diff --git a/.github/workflows/wolfboot-tz-integration.yml b/.github/workflows/wolfboot-tz-integration.yml
new file mode 100644
index 000000000..90a048103
--- /dev/null
+++ b/.github/workflows/wolfboot-tz-integration.yml
@@ -0,0 +1,165 @@
+# Nightly integration: build wolfBoot's STM32H5 TrustZone demo against
+# the latest wolfHSM main and run it under the m33mu emulator. This
+# catches drift between wolfHSM and wolfBoot main (in either direction)
+# that the pinned-submodule per-PR builds do not. The full client suite
+# runs software RSA and ECC, which is slow under the emulator, so this
+# is a nightly job rather than a per-PR gate.
+#
+# On failure it opens (or updates) a tracking issue assigned to
+# wolfSSL-Bot.
+
+name: wolfBoot TrustZone integration nightly (m33mu)
+
+on:
+ schedule:
+ # 07:00 UTC daily
+ - cron: '0 7 * * *'
+ workflow_dispatch:
+
+permissions:
+ contents: read
+ issues: write
+
+jobs:
+ wolfboot-stm32h5-tz-wolfhsm:
+ runs-on: ubuntu-latest
+ timeout-minutes: 60
+ container:
+ image: ghcr.io/wolfssl/wolfboot-ci-m33mu:latest
+
+ steps:
+ - name: Checkout wolfHSM (this repo, main)
+ uses: actions/checkout@v4
+ with:
+ path: wolfHSM
+
+ - name: Checkout wolfBoot master
+ # Switch `ref` to `master` once wolfBoot PR #769 lands; until
+ # then the STM32H5 demo only exists on that PR.
+ uses: actions/checkout@v4
+ with:
+ repository: wolfSSL/wolfBoot
+ ref: refs/pull/769/head
+ path: wolfBoot
+ # Skip lib/wolfHSM submodule init - we replace it with this
+ # checkout. Other submodules still need to come down.
+ submodules: false
+
+ - name: Initialise wolfBoot submodules (except lib/wolfHSM)
+ working-directory: wolfBoot
+ run: |
+ git config -f .gitmodules submodule.lib/wolfHSM.update none
+ git submodule update --init --recursive
+
+ - name: Point lib/wolfHSM at this checkout
+ working-directory: wolfBoot
+ run: |
+ rm -rf lib/wolfHSM
+ ln -s "$GITHUB_WORKSPACE/wolfHSM" lib/wolfHSM
+ ls -l lib/wolfHSM
+
+ - name: Build wolfBoot STM32H5 TZ demo
+ working-directory: wolfBoot/port/stmicro/stm32h5-tz-wolfhsm
+ run: make
+
+ - name: Run wolfHSM whTest_ClientConfig under m33mu
+ working-directory: wolfBoot/port/stmicro/stm32h5-tz-wolfhsm
+ run: |
+ set -o pipefail
+ mkdir -p /tmp/m33mu-wolfhsm-persist
+ cp out/wolfboot.bin out/image_v1_signed.bin /tmp/m33mu-wolfhsm-persist/
+ cd /tmp/m33mu-wolfhsm-persist
+ # m33mu timeout below the 60 min job timeout so a hung run
+ # still produces a log. Software RSA keygen dominates.
+ m33mu wolfboot.bin image_v1_signed.bin:0x60000 \
+ --persist --uart-stdout --timeout 3000 \
+ --expect-bkpt 0x7d --quit-on-faults \
+ 2>&1 | tee /tmp/m33mu-wolfhsm.log
+
+ - name: Verify wolfHSM whTest_ClientConfig
+ run: |
+ grep -q "wolfHSM whTest_ClientConfig PASSED" /tmp/m33mu-wolfhsm.log
+ grep -q "RNG DEVID=0x5748534D SUCCESS" /tmp/m33mu-wolfhsm.log
+ grep -q "AES GCM DEVID=0x5748534D SUCCESS" /tmp/m33mu-wolfhsm.log
+ grep -q "RSA SUCCESS" /tmp/m33mu-wolfhsm.log
+ grep -q "ECC ephemeral ECDH SUCCESS" /tmp/m33mu-wolfhsm.log
+ grep -q "SHA256 DEVID=0x5748534D SUCCESS" /tmp/m33mu-wolfhsm.log
+ grep -q "HKDF SUCCESS" /tmp/m33mu-wolfhsm.log
+ grep -q "\\[BKPT\\] imm=0x7d" /tmp/m33mu-wolfhsm.log
+ grep -q "\\[EXPECT BKPT\\] Success" /tmp/m33mu-wolfhsm.log
+
+ - name: Archive emulator log on failure
+ if: failure()
+ uses: actions/upload-artifact@v4
+ with:
+ name: m33mu-wolfhsm.log
+ path: /tmp/m33mu-wolfhsm.log
+
+ - name: Open or update tracking issue on failure
+ if: failure()
+ uses: actions/github-script@v7
+ with:
+ script: |
+ const runUrl = `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`;
+ const marker = 'nightly-tz-integration';
+ const title = 'Nightly wolfBoot TrustZone (m33mu) integration failed';
+ const body = [
+ 'The nightly wolfBoot STM32H5 TrustZone integration run failed.',
+ '',
+ `Run: ${runUrl}`,
+ '',
+ 'This builds wolfBoot main against wolfHSM main and runs the',
+ 'STM32H5 demo under m33mu. A failure usually means a regression',
+ 'in the NSC transport, the wolfBoot port, or a wolfHSM/wolfBoot',
+ 'API drift. The emulator log is attached to the run as an artifact.',
+ ].join('\n');
+
+ // Reuse one open tracking issue instead of opening a new one
+ // every night.
+ const existing = await github.rest.issues.listForRepo({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ state: 'open',
+ labels: marker,
+ });
+
+ if (existing.data.length > 0) {
+ await github.rest.issues.createComment({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: existing.data[0].number,
+ body: `Still failing as of ${runUrl}`,
+ });
+ return;
+ }
+
+ // Best-effort label create (ignore if it already exists).
+ try {
+ await github.rest.issues.createLabel({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ name: marker,
+ color: 'b60205',
+ });
+ } catch (e) { /* label exists */ }
+
+ try {
+ await github.rest.issues.create({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ title,
+ body,
+ labels: [marker],
+ assignees: ['wolfSSL-Bot'],
+ });
+ } catch (e) {
+ // Assignee may not be assignable; retry without it so the
+ // issue still gets filed.
+ await github.rest.issues.create({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ title,
+ body,
+ labels: [marker],
+ });
+ }
diff --git a/docs/src/5-Features.md b/docs/src/5-Features.md
index 6e06d1d1c..ff997e6d8 100644
--- a/docs/src/5-Features.md
+++ b/docs/src/5-Features.md
@@ -469,6 +469,7 @@ wolfHSM ships with several reference transports that between them cover the most
- **POSIX TCP transport** (`port/posix/posix_transport_tcp.h`): carries the packet exchange over a length-prefixed TCP stream. The server listens on a configured port and the client connects to it. This is the default transport for the POSIX server example and the recommended development transport, because the client and server can live in separate host processes — or on separate machines — without any additional platform integration.
- **POSIX shared memory transport** (`port/posix/posix_transport_shm.h`): hosts the same request/response buffer layout used by the memory buffer transport in a named POSIX shared memory object, with optional space for DMA-style buffers alongside it. This lets the client and server run as independent processes on the same host while exercising the shared-memory code paths a multi-core SoC would use in production.
- **TLS-over-TCP transport** (`port/posix/posix_transport_tls.h`): wraps the POSIX TCP transport in a wolfSSL-secured channel, with support for certificate-based authentication and PSK. It is intended for deployments where the client and server are physically separated and the link between them cannot be trusted. The packet framing above the TLS session is identical to the plain TCP transport, so higher-level code does not change between the two.
+- **ARMv8-M TrustZone NSC bridge transport** (`port/armv8m-tz/wh_transport_nsc.h`): a synchronous transport for ARMv8-M Cortex-M parts where the server runs in the secure world and clients run in the non-secure world. The non-secure client `Send` calls a single `cmse_nonsecure_entry` veneer (`wcs_wolfhsm_transmit`) the integrator provides; that veneer hands the request to the secure-side server inline and returns the response in the same call, which `Recv` then yields. There is no polling or shared-memory ring. The transport is target-agnostic across ARMv8-M parts; the veneer, flash/NVM adapter, and server init are supplied by the secure-side integration. The reference integration is the wolfBoot STM32H5 port.
Beyond the reference transports, platform ports for embedded targets typically supply hardware-specific transports — silicon mailboxes, interrupt-driven inter-core channels, vendor IPC blocks — by implementing the same callback interface. The comm-layer contract is purely "deliver one packet, in order," so a transport need only marshal bytes between the two sides.
diff --git a/port/armv8m-tz/README.md b/port/armv8m-tz/README.md
new file mode 100644
index 000000000..2b0b2910b
--- /dev/null
+++ b/port/armv8m-tz/README.md
@@ -0,0 +1,44 @@
+# ARMv8-M TrustZone NSC bridge transport
+
+A synchronous wolfHSM transport for ARMv8-M TrustZone targets that
+bridges a non-secure client to a secure-world server through a single
+Non-Secure Callable (NSC) veneer. See `wh_transport_nsc.h` for the C
+API and `docs/src/chapter08.md` for the narrative description.
+
+## How it works
+
+Client and server share a single secure-callable function. The
+non-secure side packs a wolfHSM request into a buffer, calls the
+veneer, and waits for the veneer to return with the response written
+into a second buffer. The secure side runs the wolfHSM server in the
+same process; there is no separate task, no IRQ, and no shared-memory
+ring — just a function call across the security boundary.
+
+## Host-side veneer contract
+
+The integrator provides one function with this exact shape:
+
+```c
+int wcs_wolfhsm_transmit(const uint8_t *cmd, uint32_t cmdSz,
+ uint8_t *rsp, uint32_t *rspSz);
+```
+
+declared `cmse_nonsecure_entry` from the secure side. On entry,
+`cmd[0..cmdSz)` holds the request and `*rspSz` is the maximum response
+size the client can accept; on return the function writes the
+response into `rsp[0..*rspSz)` and updates `*rspSz` to the actual
+size. Return value follows wolfHSM's `WH_ERROR_*` convention.
+
+The veneer must not block on anything outside the secure server; the
+non-secure side treats it as a synchronous call.
+
+## Known integrations
+
+- **wolfBoot STM32H5 demo app** at
+ [`port/stmicro/stm32h5-tz-wolfhsm/`](https://github.com/wolfSSL/wolfBoot/tree/main/port/stmicro/stm32h5-tz-wolfhsm)
+ in wolfBoot. Reference integration on a NUCLEO-H563ZI;
+ verified end-to-end on real silicon and on the m33mu emulator.
+
+To add a new integration, copy the veneer skeleton from wolfBoot's
+demo, wire `wh_transport_nsc.h` into the non-secure client init, and
+write a `whServerCb` table for the secure server.
diff --git a/port/armv8m-tz/wh_transport_nsc.c b/port/armv8m-tz/wh_transport_nsc.c
new file mode 100644
index 000000000..233c0d0fc
--- /dev/null
+++ b/port/armv8m-tz/wh_transport_nsc.c
@@ -0,0 +1,237 @@
+/*
+ * port/armv8m-tz/wh_transport_nsc.c
+ *
+ * Copyright (C) 2026 wolfSSL Inc.
+ *
+ * This file is part of wolfHSM.
+ *
+ * wolfHSM is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfHSM 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 wolfHSM. If not, see .
+ */
+
+#include "wolfhsm/wh_settings.h"
+
+#ifdef WOLFHSM_CFG_PORT_ARMV8M_TZ_NSC
+
+#include
+#include
+
+#include "wolfhsm/wh_comm.h"
+#include "wolfhsm/wh_error.h"
+#include "wh_transport_nsc.h"
+
+/*
+ * Resolved on the non-secure side via the wolfBoot --cmse-implib import
+ * library; on the secure side the same symbol is provided by the host's
+ * NSC veneer (wolfBoot's src/wolfhsm_callable.c). The server callbacks
+ * below never call this; --gc-sections strips client-side code from the
+ * secure image.
+ */
+extern int wcs_wolfhsm_transmit(const uint8_t* cmd, uint32_t cmdSz,
+ uint8_t* rsp, uint32_t* rspSz);
+
+
+/* ============================================================
+ * Non-secure (client) callbacks
+ * ============================================================ */
+
+static int _NscClientInit(void* context, const void* config,
+ whCommSetConnectedCb connectcb, void* connectcb_arg)
+{
+ whTransportNscClientContext* ctx = (whTransportNscClientContext*)context;
+
+ (void)config;
+
+ if (ctx == NULL) {
+ return WH_ERROR_BADARGS;
+ }
+
+ memset(ctx, 0, sizeof(*ctx));
+ ctx->initialized = 1;
+
+ /* Synchronous bridge: the secure side is always reachable once linked. */
+ if (connectcb != NULL) {
+ connectcb(connectcb_arg, WH_COMM_CONNECTED);
+ }
+ return WH_ERROR_OK;
+}
+
+static int _NscClientSend(void* context, uint16_t size, const void* data)
+{
+ whTransportNscClientContext* ctx = (whTransportNscClientContext*)context;
+ uint32_t rspSz;
+ int rc;
+
+ if (ctx == NULL || data == NULL || ctx->initialized == 0U) {
+ return WH_ERROR_BADARGS;
+ }
+ if (size == 0U || size > WH_TRANSPORT_NSC_BUFFER_SIZE) {
+ return WH_ERROR_BADARGS;
+ }
+ /* prior response must be consumed before next Send */
+ if (ctx->last_rsp_size != 0U) {
+ return WH_ERROR_NOTREADY;
+ }
+
+ rspSz = (uint32_t)WH_TRANSPORT_NSC_BUFFER_SIZE;
+ rc = wcs_wolfhsm_transmit((const uint8_t*)data, (uint32_t)size,
+ ctx->rsp_buf, &rspSz);
+ if (rc != 0) {
+ ctx->last_rsp_size = 0;
+ /* propagate known wolfHSM error codes, collapse unknowns */
+ if (rc == WH_ERROR_BADARGS || rc == WH_ERROR_NOTREADY ||
+ rc == WH_ERROR_ABORTED) {
+ return rc;
+ }
+ return WH_ERROR_ABORTED;
+ }
+ if (rspSz == 0U || rspSz > (uint32_t)WH_TRANSPORT_NSC_BUFFER_SIZE) {
+ ctx->last_rsp_size = 0;
+ return WH_ERROR_ABORTED;
+ }
+
+ ctx->last_rsp_size = (uint16_t)rspSz;
+ return WH_ERROR_OK;
+}
+
+static int _NscClientRecv(void* context, uint16_t* out_size, void* data)
+{
+ whTransportNscClientContext* ctx = (whTransportNscClientContext*)context;
+
+ if (ctx == NULL || out_size == NULL || data == NULL ||
+ ctx->initialized == 0U) {
+ return WH_ERROR_BADARGS;
+ }
+ if (ctx->last_rsp_size == 0U) {
+ return WH_ERROR_NOTREADY;
+ }
+ /* out_size is in/out capacity; reject truncation, keep cached response */
+ if (*out_size < ctx->last_rsp_size) {
+ return WH_ERROR_BADARGS;
+ }
+
+ memcpy(data, ctx->rsp_buf, ctx->last_rsp_size);
+ *out_size = ctx->last_rsp_size;
+ ctx->last_rsp_size = 0;
+ return WH_ERROR_OK;
+}
+
+static int _NscClientCleanup(void* context)
+{
+ whTransportNscClientContext* ctx = (whTransportNscClientContext*)context;
+ if (ctx == NULL) {
+ return WH_ERROR_BADARGS;
+ }
+ ctx->initialized = 0;
+ return WH_ERROR_OK;
+}
+
+const whTransportClientCb whTransportNscClient_Cb = {
+ .Init = _NscClientInit,
+ .Send = _NscClientSend,
+ .Recv = _NscClientRecv,
+ .Cleanup = _NscClientCleanup,
+};
+
+
+/* ============================================================
+ * Secure-side (server) callbacks
+ *
+ * The host's NSC veneer populates req_buf/req_size/rsp_buf/rsp_capacity
+ * and sets request_pending = 1 before calling wh_Server_HandleRequestMessage.
+ * Recv hands the request to the dispatcher; Send writes the response back
+ * into rsp_buf and stores its size for the veneer to read.
+ * ============================================================ */
+
+static int _NscServerInit(void* context, const void* config,
+ whCommSetConnectedCb connectcb, void* connectcb_arg)
+{
+ whTransportNscServerContext* ctx = (whTransportNscServerContext*)context;
+
+ (void)config;
+
+ if (ctx == NULL) {
+ return WH_ERROR_BADARGS;
+ }
+
+ memset(ctx, 0, sizeof(*ctx));
+
+ if (connectcb != NULL) {
+ connectcb(connectcb_arg, WH_COMM_CONNECTED);
+ }
+ return WH_ERROR_OK;
+}
+
+static int _NscServerRecv(void* context, uint16_t* inout_size, void* data)
+{
+ whTransportNscServerContext* ctx = (whTransportNscServerContext*)context;
+
+ if (ctx == NULL || inout_size == NULL || data == NULL) {
+ return WH_ERROR_BADARGS;
+ }
+ if (!ctx->request_pending || ctx->req_buf == NULL || ctx->req_size == 0U) {
+ return WH_ERROR_NOTREADY;
+ }
+ /* clear stale rsp_size up-front so every exit path leaves a clean state */
+ ctx->rsp_size = 0;
+
+ if (ctx->req_size > *inout_size) {
+ ctx->request_pending = 0;
+ return WH_ERROR_ABORTED;
+ }
+
+ memcpy(data, ctx->req_buf, ctx->req_size);
+ *inout_size = ctx->req_size;
+ ctx->request_pending = 0;
+ return WH_ERROR_OK;
+}
+
+static int _NscServerSend(void* context, uint16_t size, const void* data)
+{
+ /* veneer is responsible for Recv/Send pairing; Send does not enforce it */
+ whTransportNscServerContext* ctx = (whTransportNscServerContext*)context;
+
+ if (ctx == NULL || data == NULL) {
+ return WH_ERROR_BADARGS;
+ }
+ if (size == 0U || size > ctx->rsp_capacity) {
+ return WH_ERROR_BADARGS;
+ }
+ if (ctx->rsp_buf == NULL) {
+ return WH_ERROR_ABORTED;
+ }
+
+ memcpy(ctx->rsp_buf, data, size);
+ ctx->rsp_size = size;
+ return WH_ERROR_OK;
+}
+
+static int _NscServerCleanup(void* context)
+{
+ whTransportNscServerContext* ctx = (whTransportNscServerContext*)context;
+ if (ctx == NULL) {
+ return WH_ERROR_BADARGS;
+ }
+ /* clear stale NS pointers so they cannot survive reinit */
+ memset(ctx, 0, sizeof(*ctx));
+ return WH_ERROR_OK;
+}
+
+const whTransportServerCb whTransportNscServer_Cb = {
+ .Init = _NscServerInit,
+ .Recv = _NscServerRecv,
+ .Send = _NscServerSend,
+ .Cleanup = _NscServerCleanup,
+};
+
+#endif /* WOLFHSM_CFG_PORT_ARMV8M_TZ_NSC */
diff --git a/port/armv8m-tz/wh_transport_nsc.h b/port/armv8m-tz/wh_transport_nsc.h
new file mode 100644
index 000000000..c91199bc1
--- /dev/null
+++ b/port/armv8m-tz/wh_transport_nsc.h
@@ -0,0 +1,91 @@
+/*
+ * port/armv8m-tz/wh_transport_nsc.h
+ *
+ * Copyright (C) 2026 wolfSSL Inc.
+ *
+ * This file is part of wolfHSM.
+ *
+ * wolfHSM is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfHSM 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 wolfHSM. If not, see .
+ */
+
+/*
+ * Synchronous TrustZone NSC bridge transport for wolfHSM.
+ *
+ * The non-secure (client) side calls a single ARMv8-M Cortex-M
+ * cmse_nonsecure_entry veneer (`wcs_wolfhsm_transmit`) provided by the
+ * secure-side host. The veneer hands the request to the secure-side
+ * server context, runs `wh_Server_HandleRequestMessage` once inline,
+ * and returns the response in the same call. There is no polling,
+ * notify counter, or async producer/consumer — Send delivers the
+ * response, Recv just hands it back.
+ *
+ * The transport is target-agnostic across ARMv8-M TrustZone parts;
+ * the target-specific NSC veneer is provided by the host.
+ */
+
+#ifndef WH_TRANSPORT_NSC_H_
+#define WH_TRANSPORT_NSC_H_
+
+#include "wolfhsm/wh_settings.h"
+
+#ifdef WOLFHSM_CFG_PORT_ARMV8M_TZ_NSC
+
+#include
+#include "wolfhsm/wh_comm.h"
+
+#define WH_TRANSPORT_NSC_BUFFER_SIZE WH_COMM_MTU
+
+/*
+ * Non-secure (client) context. Owns the response buffer in NS .bss.
+ * Not internally thread-safe.
+ */
+typedef struct {
+ uint8_t rsp_buf[WH_TRANSPORT_NSC_BUFFER_SIZE];
+ uint16_t last_rsp_size;
+ uint8_t initialized;
+ uint8_t WH_PAD[5]; /* trailing slack */
+} whTransportNscClientContext;
+
+/* Empty config; Init accepts NULL since there is nothing to read. */
+typedef struct {
+ uint8_t WH_PAD[1];
+} whTransportNscClientConfig;
+
+/*
+ * Secure-side server context. Populated by the NSC veneer per call:
+ * before invoking `wh_Server_HandleRequestMessage` the host sets
+ * req_buf/req_size/rsp_buf/rsp_capacity; after the dispatcher returns,
+ * the host reads rsp_size to pass back to the non-secure caller.
+ */
+typedef struct {
+ const uint8_t* req_buf;
+ uint8_t* rsp_buf;
+ uint16_t req_size;
+ uint16_t rsp_capacity;
+ uint16_t rsp_size; /* set by Send, read by veneer */
+ uint8_t request_pending; /* set by veneer, cleared by Recv */
+ uint8_t WH_PAD[1];
+} whTransportNscServerContext;
+
+typedef struct {
+ uint8_t WH_PAD[1];
+} whTransportNscServerConfig;
+
+/* Pre-populated tables; callbacks are file-local in wh_transport_nsc.c */
+extern const whTransportClientCb whTransportNscClient_Cb;
+extern const whTransportServerCb whTransportNscServer_Cb;
+
+#endif /* WOLFHSM_CFG_PORT_ARMV8M_TZ_NSC */
+
+#endif /* WH_TRANSPORT_NSC_H_ */
diff --git a/port/stmicro/stm32h5-tz/README.md b/port/stmicro/stm32h5-tz/README.md
new file mode 100644
index 000000000..af828878a
--- /dev/null
+++ b/port/stmicro/stm32h5-tz/README.md
@@ -0,0 +1,11 @@
+# STM32H5 TrustZone port
+
+The STM32H5 wolfHSM TrustZone port (HAL adapter, secure-side server,
+flash/NVM backend, non-secure demo app, linker layout, and test
+harness) is maintained in
+[wolfBoot](https://github.com/wolfSSL/wolfBoot) under
+`port/stmicro/stm32h5-tz-wolfhsm/` and `test-app/wcs/`.
+
+It consumes the generic ARMv8-M TrustZone NSC bridge transport in
+`port/armv8m-tz/` of this repository. See `docs/src/chapter08.md` for
+the transport description.