Merge pull request #10677 from dgarske/realtek_huk

Add RealTek AmebaPro2 (RTL8735B) HUK crypto-callback port
This commit is contained in:
Zackery
2026-07-09 18:09:37 -06:00
committed by GitHub
14 changed files with 2849 additions and 4 deletions
+1 -1
View File
@@ -24,7 +24,7 @@ jobs:
check_filenames: true
check_hidden: true
# Add comma separated list of words that occur multiple times that should be ignored (sorted alphabetically, case sensitive)
ignore_words_list: adin,aNULL,brunch,carryIn,chainG,ciph,cLen,cliKs,dout,haveA,inCreated,inOut,inout,larg,LEAPYEAR,Merget,optionA,parm,parms,repid,rIn,userA,ser,siz,te,Te,HSI,failT,toLen,
ignore_words_list: adin,ameba,aNULL,brunch,carryIn,chainG,ciph,cLen,cliKs,dout,haveA,inCreated,inOut,inout,larg,LEAPYEAR,Merget,optionA,parm,parms,repid,rIn,userA,ser,siz,te,Te,HSI,failT,toLen,
# The exclude_file contains lines of code that should be ignored. This is useful for individual lines which have non-words that can safely be ignored.
exclude_file: '.codespellexcludelines'
# To skip files entirely from being processed, add it to the following list:
+96
View File
@@ -0,0 +1,96 @@
name: RealTek RTL8735B (AmebaPro2) HUK port Tests
# START OF COMMON SECTION
on:
push:
branches: [ 'release/**' ]
pull_request:
types: [opened, synchronize, reopened, ready_for_review]
branches: [ '*' ]
# Weekday-morning cron seeds the master-scoped ccache that PR runs restore
# read-only (see ccache-setup).
schedule:
- cron: '27 10 * * 1-5'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
# END OF COMMON SECTION
jobs:
# Compile + helper-KAT gate for the RTL8735B HUK crypto-callback port.
# --enable-rtl8735b sets WOLFSSL_RTL8735B_HOST_TEST, which swaps the vendor HAL
# headers for rtl8735b_shim.h (sentinel stubs, no real crypto). Two levels:
# (1) build-only matrix -- exercises crypto-callback dispatch, info-struct
# field access, compile guards, and build wiring across algo/guard combos
# and both WOLFSSL_SMALL_STACK branches, via parallel-make-check.py.
# (2) one config runs testwolfcrypt, which calls wc_Rtl8735b_HukSelfTest() --
# real KATs of the silicon-independent helpers (BE/LE word conversion, CTR
# counter increment, HMAC accumulator growth/overflow/cap, bounce
# alignment). No fake-crypto shim path is asserted as "correct".
# Functional crypto correctness (AES/GCM/ECDSA on silicon) is validated on
# RTL8735B hardware, NOT here (see the port README).
build:
name: build + helper KATs (--enable-rtl8735b)
if: ${{ (github.repository_owner == 'wolfssl') && (github.event_name != 'pull_request' || github.event.pull_request.draft == false) }}
runs-on: ubuntu-24.04
timeout-minutes: 15
steps:
- uses: actions/checkout@v5
name: Checkout wolfSSL
- name: Install dependencies
uses: ./.github/actions/install-apt-deps
with:
packages: autoconf automake libtool build-essential
ghcr-debs-tag: ubuntu-24.04-minimal
- name: Set up ccache
uses: ./.github/actions/ccache-setup
with:
workflow-id: rtl8735b
read-only: ${{ github.event_name == 'pull_request' }}
max-size: 100M
- name: Build all configs (compile-only, out-of-tree)
run: |
cat > "$RUNNER_TEMP/rtl8735b-configs.json" <<'EOF'
[
{"name": "full-smallstack", "minutes": 2,
"comment": "All port paths (AES-GCM/ECB/CBC/CTR, HMAC-SHA256, ECDSA P-256) with WOLFSSL_SMALL_STACK -> exercises the heap branch of the HW-ECDSA mp_int helpers.",
"configure": ["--enable-rtl8735b", "--enable-cryptocb", "--enable-ecc",
"--enable-aesgcm", "--enable-aesctr", "--enable-aescbc",
"CPPFLAGS=-DWOLFSSL_SMALL_STACK"]},
{"name": "full", "minutes": 2,
"comment": "Same algo coverage without WOLFSSL_SMALL_STACK -> exercises the on-stack (array) branch of the HW-ECDSA mp_int helpers.",
"configure": ["--enable-rtl8735b", "--enable-cryptocb", "--enable-ecc",
"--enable-aesgcm", "--enable-aesctr", "--enable-aescbc"]},
{"name": "min", "minutes": 2,
"comment": "Minimal: no ECC (HW/SW ECDSA sign code compiled out), AES + HMAC only -> exercises the non-ECC compile guards.",
"configure": ["--enable-rtl8735b", "--enable-cryptocb"]}
]
EOF
.github/scripts/parallel-make-check.py --build-only \
"$RUNNER_TEMP/rtl8735b-configs.json"
- name: Run helper KATs on host (testwolfcrypt self-test)
run: |
./autogen.sh
./configure --enable-rtl8735b --enable-cryptocb --enable-ecc \
--enable-aesgcm --enable-aesctr --enable-aescbc
make -j"$(nproc)"
./wolfcrypt/test/testwolfcrypt
- name: ccache stats
if: always()
run: ccache -s || true
- name: Upload logs on failure
if: failure()
uses: actions/upload-artifact@v6
with:
retention-days: 7
name: rtl8735b-logs
path: |
build-*/config.log
if-no-files-found: ignore
+1
View File
@@ -690,6 +690,7 @@ WC_RNG_BANK_NO_DEFAULT_SUPPORT
WC_RNG_BLOCKING
WC_RSA_NONBLOCK_TIME
WC_RSA_NO_FERMAT_CHECK
WC_RTL8735B_NO_DERIVE_CACHE
WC_RWLOCK_OPS_INLINE
WC_SHE_SW_DEFAULT
WC_SKIP_INCLUDED_C_FILES
+29 -1
View File
@@ -3347,6 +3347,32 @@ case "$ENABLED_STSAFE" in
esac
# RealTek AmebaPro2 (RTL8735B) HUK crypto-callback port.
# On-target the application supplies the AmebaPro2 HAL include path. This option
# is a host compile-test of the port: it swaps the HAL headers for a shim
# (WOLFSSL_RTL8735B_HOST_TEST) so the cryptocb dispatch and wiring build without
# the vendor SDK. It forces crypto callbacks on (see the cryptocb block).
# Example: "./configure --enable-rtl8735b"
ENABLED_RTL8735B="no"
AC_ARG_ENABLE([rtl8735b],
[AS_HELP_STRING([--enable-rtl8735b],
[Enable RealTek AmebaPro2 (RTL8735B) HUK crypto-callback port (host compile-test).])],
[ ENABLED_RTL8735B=$enableval ],
[ ENABLED_RTL8735B=no ])
if test "x$ENABLED_RTL8735B" != "xno"
then
# HAVE_AES_ECB is required: the port chains AES-CBC/CTR over single-block
# secure-key ECB ops, so enabling the port implies AES-ECB for the build.
# NOTE: this enables the (public, unauthenticated) AES-ECB API build-wide,
# not just for the port -- a deliberate, documented side effect.
AC_MSG_NOTICE([--enable-rtl8735b also enables AES-ECB build-wide (HAVE_AES_ECB)])
# WOLF_CRYPTO_CB_COPY/FREE: the HUK HMAC hangs its accumulation buffer on the
# inner SHA-256 devCtx and relies on the cryptocb copy/free ops (see the port).
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_RTL8735B_HUK -DWOLFSSL_RTL8735B_HOST_TEST -DHAVE_AES_ECB -DWOLF_CRYPTO_CB_COPY -DWOLF_CRYPTO_CB_FREE"
fi
# NXP SE050
# Example: "./configure --with-se050=/home/pi/simw_top"
ENABLED_SE050="no"
@@ -10899,7 +10925,7 @@ AC_ARG_ENABLE([cryptocb-sw-test],
[ ENABLED_CRYPTOCB_SW_TEST=yes ]
)
if test "x$ENABLED_PKCS11" = "xyes" || test "x$ENABLED_WOLFTPM" = "xyes" || test "$ENABLED_CAAM" != "no"
if test "x$ENABLED_PKCS11" = "xyes" || test "x$ENABLED_WOLFTPM" = "xyes" || test "$ENABLED_CAAM" != "no" || test "x$ENABLED_RTL8735B" != "xno"
then
ENABLED_CRYPTOCB=yes
fi
@@ -12677,6 +12703,7 @@ AM_CONDITIONAL([BUILD_IOTSAFE],[test "x$ENABLED_IOTSAFE" = "xyes"])
AM_CONDITIONAL([BUILD_IOTSAFE_HWRNG],[test "x$ENABLED_IOTSAFE_HWRNG" = "xyes"])
AM_CONDITIONAL([BUILD_SE050],[test "x$ENABLED_SE050" = "xyes"])
AM_CONDITIONAL([BUILD_STSAFE],[test "x$ENABLED_STSAFE" != "xno"])
AM_CONDITIONAL([BUILD_RTL8735B],[test "x$ENABLED_RTL8735B" != "xno"])
AM_CONDITIONAL([BUILD_TROPIC01],[test "x$ENABLED_TROPIC01" = "xyes"])
AM_CONDITIONAL([BUILD_KDF],[test "x$ENABLED_KDF" = "xyes"])
AM_CONDITIONAL([BUILD_HMAC],[test "x$ENABLED_HMAC" = "xyes"])
@@ -13272,6 +13299,7 @@ echo " * IoT-Safe: $ENABLED_IOTSAFE"
echo " * IoT-Safe HWRNG: $ENABLED_IOTSAFE_HWRNG"
echo " * NXP SE050: $ENABLED_SE050"
echo " * STMicro STSAFE: $ENABLED_STSAFE"
echo " * RealTek RTL8735B HUK: $ENABLED_RTL8735B"
echo " * TROPIC01: $ENABLED_TROPIC01"
echo " * Maxim Integrated MAXQ10XX: $ENABLED_MAXQ10XX"
echo " * PSA: $ENABLED_PSA"
+7
View File
@@ -122,6 +122,9 @@ EXTRA_DIST += wolfcrypt/src/port/ti/ti-aes.c \
wolfcrypt/src/port/st/README.md \
wolfcrypt/src/port/st/STM32MP13.md \
wolfcrypt/src/port/st/STM32MP25.md \
wolfcrypt/src/port/realtek/rtl8735b.c \
wolfcrypt/src/port/realtek/rtl8735b_shim.h \
wolfcrypt/src/port/realtek/README.md \
wolfcrypt/src/port/tropicsquare/tropic01.c \
wolfcrypt/src/port/tropicsquare/README.md \
wolfcrypt/src/port/af_alg/afalg_aes.c \
@@ -261,6 +264,10 @@ if BUILD_TROPIC01
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/tropicsquare/tropic01.c
endif
if BUILD_RTL8735B
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/realtek/rtl8735b.c
endif
if BUILD_PSA
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/psa/psa.c
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/psa/psa_hash.c
+445
View File
@@ -0,0 +1,445 @@
# RealTek AmebaPro2 (RTL8735B) HUK Port
Binds wolfCrypt keys to the RTL8735B silicon Hardware Unique Key (HUK) through
the AmebaPro2 HAL crypto engine, via the wolfCrypt crypto-callback (CryptoCb)
framework. A 256-bit "seed" is run through the HAL HKDF key-ladder against the
HUK to land a device-bound working key in a secure key-storage slot; AES
(GCM/ECB/CBC/CTR) then runs from that slot and the working key never enters
software. It is a pure crypto-callback device and adds no wolfSSL core API or
struct fields: AES reads its seed from the standard `aes->devKey`, and ECDSA
reads a `wc_Rtl8735b_EccKey` (the HUK-wrapped scalar + seed) the caller attaches
via the standard `ecc_key->devCtx`. This mirrors the device pattern the STM32
DHUK port (`wc_Stm32_DhukRegister`) also uses.
## Hardware
RTL8735B / AmebaPro2 security blocks used by this port (from the
`Ameba-AIoT/nuwa_hal_realtek` SDK, `rtl8735b` branch, headers under
`ameba/amebapro2/source/fwlib/rtl8735b/include/`):
- HUK in OTP: `SB_OTP_HIGH_VAL_HUK1` (0x21), `HUK2` (0x22), `HUK_RMA` (0x2F).
- HKDF key-ladder in secure RAM: `hal_hkdf_hmac_sha256_secure_init`,
`hal_hkdf_extract_secure_all`, `hal_hkdf_expand_secure_all` -- derive the HUK
into a secure key-storage slot without exposing the key to software.
- AES secure-key ops that reference the derived slot by number:
`hal_crypto_aes_ecb_sk_init`, `hal_crypto_aes_gcm_sk_init` (key never leaves
hardware).
- Secure-key HMAC-SHA256 (`hal_crypto_hmac_sha2_256_sk_init` /
`hal_crypto_hmac_sha2_256_update` / `_sk_final`) MAC'ing over the HUK-derived
slot, so the HMAC key also never enters software.
- HUK-bound ECDSA sign has two backends: software sign after an AES secure-key
unwrap of the wrapped scalar (default), or the HW ECDSA engine (`hal_ecdsa.h`)
with the private scalar either unwrapped (INPUT PRK) or OTP-resident via
`hal_ecdsa_select_prk` (`ECDSA_OTP_PRK_1/2`, scalar never in software).
- Secure TRNG (`hal_trng_sec.h`, `hal_trng_sec_init` / `hal_trng_sec_get_rand`) exposed as the
crypto-callback SEED source. The plain TRNG (`hal_trng.h`) is also available; the
`ameba-zephyr-pro2-platform` repo provides a Zephyr entropy driver
(`entropy_rtl8735b.c`, DT `realtek,amebapro2-trng`) that feeds wolfCrypt's
`wc_GenerateSeed` via `sys_rand_get`.
## Enabling
```c
#define WOLFSSL_RTL8735B_HUK /* enable the AmebaPro2 HUK device */
#define WOLF_CRYPTO_CB /* required -- HUK routes through crypto callbacks */
```
Set these in `user_settings.h`. The application/board CMake must add
the AmebaPro2 HAL include directory (e.g.
`.../fwlib/rtl8735b/include/`) to the wolfSSL library include path so this port
can include `hal_crypto.h` and `hal_hkdf.h`.
Two build implications to be aware of when enabling the port:
- It requires AES-ECB (the CBC/CTR modes chain over single-block secure-key ECB
operations), so `--enable-rtl8735b` adds `-DHAVE_AES_ECB` to the whole build;
define `HAVE_AES_ECB` yourself when configuring via `user_settings.h`.
- For multi-threaded use the port relies on the wolfCrypt HW mutex to serialize
the shared HW key slot and the derivation cache. Defining `WOLFSSL_RTL8735B_HUK`
auto-enables `WOLFSSL_CRYPT_HW_MUTEX` (via `wc_port.h`), so this is handled for
you; it does require the wolfCrypt mutex/threading primitives for your RTOS to
be present.
Configurable (override in `user_settings.h` before including wolfSSL):
| Macro | Default | Meaning |
|--------------------------------|---------|--------------------------------------|
| `WC_HUK_DEVID` | 810 | CryptoCb device id (STM32 uses 807-809) |
| `WC_RTL8735B_HUK_SK_IDX` | 0xC | Key-storage slot holding the HUK (KEY_STG_HUK1) |
| `WC_RTL8735B_HKDF_PRK_IDX` | 3 | Intermediate HKDF PRK slot |
| `WC_RTL8735B_DERIVED_WB_IDX` | 4 | Derived working-key slot (AES uses it) |
| `WC_RTL8735B_HKDF_CRYPTO_SEL` | 0 | `crypto_sel` for the secure HKDF init |
| `WC_RTL8735B_MAX_WRAPPED` | 96 | Max wrapped-scalar blob the ECDSA sign path unwraps |
## API
```c
#include <wolfssl/wolfcrypt/port/realtek/rtl8735b.h>
/* One-time: register the AmebaPro2 HUK crypto-callback device. */
wc_Rtl8735b_HukRegister(WC_HUK_DEVID);
/* AES / GCM: enable via devId at init, then pass the 256-bit seed as the key.
* The seed is HKDF input that diversifies the HUK -- it is NOT the AES key. */
Aes aes;
byte seed[32]; /* per-purpose derivation seed (need not be secret) */
wc_AesInit(&aes, NULL, WC_HUK_DEVID);
wc_AesGcmSetKey(&aes, seed, 32);
wc_AesGcmEncrypt(&aes, ct, pt, ptSz, iv, 12, tag, tagSz, aad, aadSz); /* full GCM */
wc_AesFree(&aes);
/* AES-ECB / AES-CBC follow the same pattern (wc_AesSetKey + wc_AesEcb*/
/* wc_AesCbc* with devId = WC_HUK_DEVID). */
wc_Rtl8735b_HukUnRegister(WC_HUK_DEVID);
```
The seed maps to a device-bound working key as:
HUK (slot `WC_RTL8735B_HUK_SK_IDX`) -> `hal_hkdf_extract_secure_all` -> PRK slot
-> `hal_hkdf_expand_secure_all` -> working key in `WC_RTL8735B_DERIVED_WB_IDX`
-> `hal_crypto_aes_gcm_sk_init` / `hal_crypto_aes_ecb_sk_init`. The derive and
the AES op run under one crypto-mutex hold; the working key never enters
software. Identical seed -> identical working key (deterministic, so GMAC
verifies and AES round-trips); a wrong seed yields a different key (GCM decrypt
returns `AES_GCM_AUTH_E`).
HUK-bound ECDSA sign (Stage 3, wrapped-scalar): point the key's crypto-callback
context at a `wc_Rtl8735b_EccKey` (the scalar AES-GCM-wrapped under a HUK-derived
key -- ciphertext + iv + tag -- plus its 32-byte seed) -- no dedicated wolfSSL
import API:
```c
#include <wolfssl/wolfcrypt/port/realtek/rtl8735b.h>
wc_Rtl8735b_EccKey hk = { seed, 32, wrapped, plainLen, plainLen,
0, 0, iv, 12, tag, 16 };
ecc_key key;
wc_ecc_init_ex(&key, NULL, WC_HUK_DEVID);
wc_ecc_set_curve(&key, plainLen, ECC_SECP256R1);
key.devCtx = &hk; /* borrowed; must outlive the key */
wc_ecc_sign_hash(hash, hashSz, sig, &sigSz, rng, &key);
```
At sign time the port derives the slot key from the seed, AES-GCM decrypt-verifies
the scalar into a short-lived buffer, signs, and scrubs it. Because the unwrap is
authenticated, a tampered, corrupted, or wrong-device blob fails at unwrap
(`AES_GCM_AUTH_E`) rather than yielding a garbage scalar. The wrapped blob is
device-bound (it only unwraps on the silicon whose HUK produced the slot key). The
scalar is briefly in software during the sign; an OTP-resident model
(`hal_ecdsa_select_prk`, scalar never in software) and routing the sign itself
through the HW ECDSA engine (`hal_ecdsa`) are follow-ons. (The GCM unwrap makes
the ECDSA sign path require `HAVE_AESGCM`.)
### Additional HUK operations
HMAC-SHA256 under the HUK (the 32-byte key is the HKDF seed; the MAC runs over
the HUK-derived secure-key slot):
```c
Hmac hmac;
byte seed[32];
wc_HmacInit(&hmac, NULL, WC_HUK_DEVID);
wc_HmacSetKey(&hmac, WC_SHA256, seed, 32);
wc_HmacUpdate(&hmac, msg, msgSz);
wc_HmacFinal(&hmac, mac); /* MAC produced one-shot at final under the HUK */
wc_HmacFree(&hmac);
```
HW-seeded RNG (entropy from the secure TRNG via the crypto-callback SEED source,
no `CUSTOM_RAND_GENERATE_SEED` wiring needed):
```c
WC_RNG rng;
wc_InitRng_ex(&rng, NULL, WC_HUK_DEVID);
wc_RNG_GenerateBlock(&rng, buf, sizeof(buf));
wc_FreeRng(&rng);
```
To route ECDSA sign through the HW engine instead of the software-after-unwrap
path, set `hk.useHwEngine = 1` (validated on the RTL8735B); to sign from an
OTP-resident key (scalar never in software) set `hk.otpPrkSel` to `1`/`2`
(`ECDSA_OTP_PRK_1/2`) and leave `seed`/`wrapped` unused (that OTP path is
implemented but unexercised -- it needs an OTP key provisioned).
## Notes / limitations
- The HAL GCM path assumes a 96-bit (12-byte) IV (standard J0). A non-12-byte
IV returns a hard error (not a software fallback, which would key off the seed
rather than the device-bound key).
- AES-CBC and AES-CTR chain in software over single-block
`hal_crypto_aes_ecb_sk_*` calls because the HAL exposes no CBC/CTR secure-key
variant; the key still stays in hardware. CTR maintains the wolfCrypt counter
state (`aes->reg`/`tmp`/`left`) so partial blocks continue across calls.
- The HAL crypto engine DMAs its buffers on 32-byte (cache-line) boundaries and
rejects an unaligned GCM iv/aad. The port stages key/iv/aad/tag on aligned
temporaries and bounces unaligned in/out through aligned buffers, so callers
need not align.
- Each operation derives the working key from the Aes' own `devKey` seed under
the crypto mutex (no shared port global), so concurrent `Aes` objects are safe.
- Only a 32-byte seed is HUK-bound. A 16/24-byte AES key falls back to ordinary
software AES (the bytes become the literal key, no device binding, no error),
so AES-128/192 are not HUK-bound -- treat AES-256 as the HUK path.
- HUK HMAC-SHA256 is one-shot: it buffers the whole message on the heap and MACs
at final (suits bounded/short MAC / KDF inputs). `WC_RTL8735B_HMAC_MAX_MSG`
caps the buffered length (`BUFFER_E` past it); default 64 KB, set 0 for
unbounded or raise it to MAC larger messages.
- The HMAC key buffer (the HUK seed passed to `wc_HmacSetKey`) is borrowed via
`hmac->keyRaw` and re-read at `wc_HmacFinal`/`wc_HmacFree`, so it must stay
valid and unmodified through all Update/Final/Free calls (same borrowed-buffer
contract as the ECDSA `devCtx`).
- `--enable-rtl8735b` is a host compile + helper-KAT gate: it swaps the HAL
headers for `rtl8735b_shim.h` (sentinel stubs, no real crypto) to build the
crypto-callback dispatch and wiring without the vendor SDK.
`.github/workflows/rtl8735b.yml` builds several algo/guard + `WOLFSSL_SMALL_STACK`
combinations and runs `testwolfcrypt`, which calls `wc_Rtl8735b_HukSelfTest()`
-- real KATs of the silicon-independent helpers (BE/LE word conversion, CTR
counter increment, HMAC accumulator growth/overflow/cap, bounce alignment;
these need no HAL crypto). What the shim CANNOT check -- AES/GCM/ECDSA crypto
correctness on the silicon engine -- is validated on RTL8735B hardware (the
wolfssl-examples HUK app + test/benchmark example), never asserted through the
stubs.
## Status
Validated on RTL8735B silicon (both the RealTek FreeRTOS SDK app and a Zephyr
image): registration; AES-GCM (encrypt / deterministic tag / decrypt-verify /
round-trip / wrong-seed -> `AES_GCM_AUTH_E` / unaligned buffers / non-12-byte-IV
reject); AES-ECB; AES-CBC (incl. in-place, multi-call); AES-CTR; HMAC-SHA256;
HUK-bound ECDSA (P-256) sign; and HW ECDSA verify (good signature accepted,
tampered digest rejected) -- all pass.
Caveats worth knowing:
- ECDSA sign defaults to software-after-HUK-unwrap (`useHwEngine = 0`). The HW
`hal_ecdsa` engine path is opt-in; its INPUT / HUK-wrapped-scalar mode is
validated, but the OTP-resident mode (`otpPrkSel`) is implemented and
compile-tested only -- it needs an OTP key provisioned (never burned in test).
- The HW engine also serves a general (non-HUK) sign/verify offload: an `ecc_key`
with `devId = WC_HUK_DEVID` and no `devCtx` signs/verifies with its own
key, so a stock `wolfcrypt_benchmark` drives the engine via
`WC_USE_DEVID = WC_HUK_DEVID`.
- Host CI is build-only (shim, no real crypto); functional validation is on
hardware (see the host-test note above).
## Benchmarks (software crypto baseline)
`wolfcrypt_test` (full self-test, all PASS) and `wolfcrypt_benchmark` were run on
the RTL8735B EVB to validate the core library and toolchain on this target. The
figures below are **pure software wolfCrypt** -- they are NOT the HUK device
(which routes AES through the silicon engine for HUK-derived keys); they serve as
a reference baseline and to size the benefit of hardware offload.
- Target: RTL8735B "KM4" Arm Cortex-M33 (ARMv8-M Mainline, TrustZone + DSP) at
500 MHz (`CPU_CLK`); DDR at 533 MHz.
- Toolchain / build: RealTek ASDK 10.3.0 (GCC 10.3.0), SDK default `-Os`,
FreeRTOS, `WOLFCRYPT_ONLY`, `SINGLE_THREADED`, big-integer math via the generic
`WOLFSSL_SP_MATH_ALL` (portable C, no Cortex-M assembly), `BENCH_EMBEDDED`.
- Build options live with the example, not the wolfSSL tree: the
`wolfssl-examples` repo `rtl8735b/test/{user_settings.h, wolfcrypt_test.cmake,
main.c}`, copied into the AmebaPro2 FreeRTOS SDK as
`component/example/wolfcrypt_test`. One `-DRTL_BENCH_MODE=N` switch selects the
backend: 1 = pure C (this baseline), 2 = Thumb-2 / SP Cortex-M (the asm tables
below), 3 = RealTek HW (the hardware-offload table below). The RNG is seeded
from the SDK `rtw_get_random_bytes`; `current_time()` uses
`hal_read_systime_us()`.
Symmetric / hash (higher is better):
| Algorithm | Throughput |
|---------------------|------------|
| AES-128-CBC enc/dec | 9.55 / 9.67 MiB/s |
| AES-256-CBC enc/dec | 7.25 / 7.02 MiB/s |
| AES-128-GCM enc/dec | 5.35 / 5.33 MiB/s |
| AES-256-GCM enc/dec | 4.53 / 4.52 MiB/s |
| AES-128-CTR | 9.75 MiB/s |
| AES-128-ECB enc/dec | 10.42 / 10.56 MiB/s |
| AES-CCM enc/dec | 4.73 / 4.65 MiB/s |
| GMAC (4-bit table) | 13.43 MiB/s |
| AES-128-CMAC | 8.84 MiB/s |
| ChaCha20 | 24.79 MiB/s |
| ChaCha20-Poly1305 | 15.83 MiB/s |
| Poly1305 | 64.77 MiB/s |
| SHA-1 | 29.19 MiB/s |
| SHA-256 | 10.94 MiB/s |
| SHA-512 | 7.29 MiB/s |
| SHA3-256 | 6.61 MiB/s |
| HMAC-SHA256 | 10.85 MiB/s |
Public key (higher is better):
| Operation | Rate |
|-----------------------|------|
| RSA-2048 public | 214.7 ops/s |
| RSA-2048 private | 6.14 ops/s |
| RSA-2048 key gen | 0.40 ops/s |
| DH-2048 key gen/agree | 17.67 / 15.23 ops/s |
| ECDSA P-256 sign/verify | 40.03 / 29.81 ops/s |
| ECDHE P-256 agree | 40.69 ops/s |
| Curve25519 key gen/agree | 414.8 / 419.4 ops/s |
| Ed25519 sign/verify | 788.3 / 397.0 ops/s |
The tables above are the portable-C baseline. The assembly backends below raise
these substantially. Curve25519/Ed25519 already use the dedicated
`curve25519.c`/`ed25519.c` fast code.
## Optimizations (measured on RTL8735B @ 500 MHz, -Os)
Two wolfCrypt assembly backends apply to this Cortex-M33 and were validated on
hardware (both keep `wolfcrypt_test` all-PASS). Neither needs wolfSSL source
changes -- they are build-config selections plus adding the relevant asm files.
### 1. Public key -- `sp_cortexm.c` (Thumb-2/DSP single-precision)
Enable with `WOLFSSL_SP_ARM_CORTEX_M_ASM` + `WOLFSSL_HAVE_SP_RSA` +
`WOLFSSL_HAVE_SP_ECC` + `WOLFSSL_HAVE_SP_DH`, and add `wolfcrypt/src/sp_cortexm.c`
to the build (alongside the generic `sp_int.c` for sizes without an asm path).
| Operation | Generic C | sp_cortexm | Speedup |
|------------------------|-----------|------------|---------|
| ECC P-256 key gen | 40.7 | 541.2 ops/s | 13.3x |
| ECDSA P-256 sign | 40.0 | 427.6 ops/s | 10.7x |
| ECDSA P-256 verify | 29.8 | 292.7 ops/s | 9.8x |
| ECDHE P-256 agree | 40.7 | 318.1 ops/s | 7.8x |
| RSA-2048 public | 214.7 | 618.4 ops/s | 2.9x |
| RSA-2048 private | 6.14 | 19.0 ops/s | 3.1x |
| DH-2048 agree | 15.2 | 38.3 ops/s | 2.5x |
### 2. Symmetric -- Thumb-2 asm (`port/arm/thumb2-*-asm.S`)
Enable with `WOLFSSL_ARMASM` + `WOLFSSL_ARMASM_THUMB2` +
`WOLFSSL_ARMASM_NO_HW_CRYPTO` + `WOLFSSL_ARMASM_NO_NEON` + `WOLFSSL_ARM_ARCH=7`,
and add `thumb2-aes-asm.S`, `thumb2-sha256-asm.S`, `thumb2-sha512-asm.S`,
`thumb2-sha3-asm.S`, `thumb2-chacha-asm.S`, `thumb2-poly1305-asm.S`.
`WOLFSSL_ARMASM` is a global switch, so provide the `.S` for every covered
module. (Curve25519/Ed25519 also have Thumb-2 asm but their `ge_operations.c`
integration assumes 64-bit and was left on the C path here.)
| Algorithm | Generic C | Thumb-2 asm | Speedup |
|---------------------|-----------|-------------|---------|
| AES-128-CBC enc | 9.55 | 20.85 MiB/s | 2.2x |
| AES-128-ECB enc | 10.42 | 20.82 MiB/s | 2.0x |
| AES-128-CTR | 9.75 | 20.47 MiB/s | 2.1x |
| AES-128-GCM enc | 5.35 | 10.30 MiB/s | 1.9x |
| GMAC | 13.43 | 20.81 MiB/s | 1.5x |
| AES-128-CMAC | 8.84 | 14.67 MiB/s | 1.7x |
| ChaCha20 | 24.79 | 46.44 MiB/s | 1.9x |
| ChaCha20-Poly1305 | 15.83 | 25.38 MiB/s | 1.6x |
| SHA-256 | 10.94 | 17.83 MiB/s | 1.6x |
| SHA3-256 | 6.61 | 8.64 MiB/s | 1.3x |
| HMAC-SHA256 | 10.85 | 17.66 MiB/s | 1.6x |
### 3. Hardware offload -- the HUK crypto-callback device (`hal_crypto` / `hal_ecdsa`)
Measured on the same `wolfcrypt_benchmark` with `WC_USE_DEVID = WC_HUK_DEVID`
(the test/benchmark example's mode 3, `RTL_BENCH_MODE=3`). The benchmark prints
a software and a hardware row per op; the software column here is the pure-C
`sp_int.c` baseline, the hardware column is this port driving the silicon engine.
The ECDSA rows exercise the port's general HW sign/verify offload (a benchmark
key with `devId = WC_HUK_DEVID` and no HUK context -- the engine signs with the
key's own scalar and verifies with its own public point).
| Operation | Pure C | HW (engine) | Speedup |
|------------------------|-----------|-------------|---------|
| AES-256-ECB enc/dec | 7.73/7.76 | 48.87/48.69 MiB/s | 6.3x |
| AES-256-GCM enc/dec | 4.52 | 38.44/38.18 MiB/s | 8.5x |
| AES-256-GCM no_AAD | 4.55 | 41.73/41.34 MiB/s | 9.1x |
| HMAC-SHA256 | 10.63 | 42.03 MiB/s | 4.0x |
| ECDSA P-256 sign | 39.81 | 272.05 ops/s | 6.8x |
| ECDSA P-256 verify | 29.39 | 275.13 ops/s | 9.4x |
Caveats, all expected from the port's design:
- **AES-256-CBC / -CTR are slower on the engine** (2.28 MiB/s vs ~7.2 software):
the port chains those in software over single-block secure-key ECB calls, so
per-block HAL overhead dominates. AES-256-GCM and -ECB use the engine's native
block path and are the real symmetric wins; for bulk CBC/CTR the software
(especially Thumb-2) path is faster.
- **AES-128/192 fall back to software** -- the HUK-derived working key is 256-bit.
- **RSA, DH, ECDH, hashing and key generation fall back to software** (hardware
row ~= software row) -- the device only advertises AES, HMAC-SHA256 and ECDSA
P-256 sign/verify; everything else returns `CRYPTOCB_UNAVAILABLE` and the core
runs it in software.
- The HW ECDSA **sign** (272 ops/s) is actually slower than the `sp_cortexm.c`
software sign (427.6 ops/s above): the engine's value is binding to the HUK and
offloading the CPU, not beating hand-tuned Thumb-2 P-256 latency. HW verify
(275) is on par with the `sp_cortexm.c` verify (292.7).
So the recommended posture: take `sp_cortexm.c` for public-key math unconditionally
(no silicon dependency), use the engine for AES-256-GCM/ECB bulk throughput and
HUK-bound ECDSA, and keep the Thumb-2 symmetric asm as the portable fallback for
the cipher modes the engine does not accelerate well.
#### Full benchmark output (hardware mode)
Part: RealTek RTL8735B (AmebaPro2), "KM4" Arm Cortex-M33 @ 500 MHz (`CPU_CLK`),
DDR @ 533 MHz. Toolchain: RealTek ASDK 10.3.0 (GCC 10.3.0), SDK default `-Os`,
FreeRTOS, `WOLFCRYPT_ONLY`, `SINGLE_THREADED`, `BENCH_EMBEDDED`. Generic `sp_int.c`
big-integer math (the HW base is the pure-C backend, so the `SW` rows are the
pure-C baseline). The HUK device is registered and `WC_USE_DEVID = WC_HUK_DEVID`,
so `wolfcrypt_benchmark` prints a software (`SW`) and a hardware (`HW`) row per op;
ops the engine does not accelerate show `HW` ~= `SW` (software fallback).
Symmetric / hash throughput (MiB/s; enc / dec where both apply):
| Algorithm | SW | HW |
|-----------|----|----|
| RNG SHA-256 DRBG | 2.94 | - |
| AES-128-CBC | 9.54 / 9.64 | 9.42 / 9.53 |
| AES-192-CBC | 8.24 / 8.30 | 8.15 / 8.22 |
| AES-256-CBC | 7.24 / 7.01 | 2.28 / 2.23 |
| AES-128-GCM | 5.35 / 5.35 | 5.27 / 5.27 |
| AES-192-GCM | 4.90 / 4.90 | 4.84 / 4.84 |
| AES-256-GCM | 4.52 / 4.52 | 38.44 / 38.18 |
| AES-128-GCM no_AAD | 5.38 / 5.38 | 5.31 / 5.31 |
| AES-192-GCM no_AAD | 4.93 / 4.93 | 4.87 / 4.87 |
| AES-256-GCM no_AAD | 4.55 / 4.55 | 41.73 / 41.34 |
| GMAC (4-bit table) | 13.42 | - |
| AES-128-ECB | 10.41 / 10.56 | 10.27 / 10.42 |
| AES-192-ECB | 8.88 / 8.98 | 8.78 / 8.88 |
| AES-256-ECB | 7.73 / 7.76 | 48.87 / 48.69 |
| AES-128-CTR | 9.67 | 9.44 |
| AES-192-CTR | 8.34 | 8.16 |
| AES-256-CTR | 7.32 | 2.28 |
| AES-CCM | 4.73 / 4.65 | 4.71 / 4.62 |
| AES-CCM no_AAD | 4.74 / 4.65 | 4.71 / 4.62 |
| ChaCha20 | 24.79 | - |
| ChaCha20-Poly1305 | 15.82 | - |
| Poly1305 | 64.78 | - |
| SHA-1 | 29.13 | 28.07 |
| SHA-224 | 10.73 | 10.58 |
| SHA-256 | 10.73 | 10.58 |
| SHA-384 | 7.28 | 7.21 |
| SHA-512 | 7.28 | 7.21 |
| SHA-512/224 | 7.28 | 7.21 |
| SHA-512/256 | 7.28 | 7.21 |
| SHA3-224 | 7.00 | 6.94 |
| SHA3-256 | 6.61 | 6.55 |
| SHA3-384 | 5.10 | 5.07 |
| SHA3-512 | 3.57 | 3.55 |
| AES-128-CMAC | 8.85 | 8.75 |
| AES-256-CMAC | 6.56 | 6.50 |
| HMAC-SHA1 | 28.83 | 26.64 |
| HMAC-SHA224 | 10.63 | 10.33 |
| HMAC-SHA256 | 10.63 | 42.03 |
| HMAC-SHA384 | 7.16 | 7.02 |
| HMAC-SHA512 | 7.16 | 7.02 |
Public key (ops/s):
| Operation | SW | HW |
|-----------|----|----|
| RSA-2048 key gen | 0.130 | 0.150 |
| RSA-3072 key gen | 0.043 | 0.015 |
| RSA-2048 public | 213.4 | 213.4 |
| RSA-2048 private | 6.13 | 6.13 |
| DH-2048 key gen | 17.66 | 17.66 |
| DH-2048 agree | 15.28 | 15.34 |
| ECC P-256 key gen | 40.58 | 40.48 |
| ECDHE P-256 agree | 41.13 | 40.25 |
| ECDSA P-256 sign | 39.81 | 272.05 |
| ECDSA P-256 verify | 29.39 | 275.13 |
| RNG-256 SHA256 Init/Free | 2052.9 | - |
HW differs from SW only on the engine-accelerated rows: AES-256-GCM/ECB and
HMAC-SHA256 (big wins), ECDSA P-256 sign/verify (big wins), and AES-256-CBC/CTR
(slower -- software-chained over single-block ECB). Every other row is software
fallback (HW ~= SW).
File diff suppressed because it is too large Load Diff
+187
View File
@@ -0,0 +1,187 @@
/* rtl8735b_shim.h
*
* Copyright (C) 2006-2026 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL 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.
*
* wolfSSL 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
*/
/* Host compile-test stand-in for the slice of the RealTek AmebaPro2 HAL that
* wolfcrypt/src/port/realtek/rtl8735b.c references. Compiled ONLY under
* WOLFSSL_RTL8735B_HOST_TEST (set by --enable-rtl8735b). It lets the
* crypto-callback dispatch, field access, and compile-time guards be exercised
* on a host without the customer SDK. Every stub returns a success sentinel; it
* performs NO real crypto -- so the host build is a compile gate, plus the
* silicon-independent helper KATs in wc_Rtl8735b_HukSelfTest() (which need no
* HAL crypto). Cipher / GCM / ECDSA correctness is validated on RTL8735B
* hardware, never through these stubs. On target this header is NOT used -- the
* real HAL headers (hal_crypto.h, hal_hkdf.h) are included instead, supplied via
* the application/board include path.
*
* The prototypes here intentionally mirror the real HAL signatures from
* nuwa_hal_realtek (rtl8735b branch),
* ameba/amebapro2/source/fwlib/rtl8735b/include/. Keep this in sync with the
* HAL calls in rtl8735b.c (add a stub here when the port starts calling a new
* HAL function under host test).
*/
#ifndef _WOLFPORT_RTL8735B_SHIM_H_
#define _WOLFPORT_RTL8735B_SHIM_H_
#ifdef WOLFSSL_RTL8735B_HOST_TEST
/* HAL scalar types (the real HAL pulls these from its basic_types header). */
#ifndef _RTL8735B_TYPES_SHIMMED_
#define _RTL8735B_TYPES_SHIMMED_
typedef unsigned char u8;
typedef unsigned int u32;
#endif
/* hal_status_t / success sentinel. */
typedef int hal_status_t;
#ifndef HAL_OK
#define HAL_OK 0
#endif
/* ---- Engine + AES secure-key ops (hal_crypto.h) ---- */
static inline int hal_crypto_engine_init(void) { return 0; }
static inline int hal_crypto_aes_gcm_sk_init(u8 key_num, const u32 keylen)
{ (void)key_num; (void)keylen; return 0; }
static inline int hal_crypto_aes_gcm_encrypt(const u8* msg, const u32 msglen,
const u8* iv, const u8* aad, const u32 aadlen, u8* pResult, u8* pTag)
{ (void)msg; (void)msglen; (void)iv; (void)aad; (void)aadlen;
(void)pResult; (void)pTag; return 0; }
static inline int hal_crypto_aes_gcm_decrypt(const u8* msg, const u32 msglen,
const u8* iv, const u8* aad, const u32 aadlen, u8* pResult, u8* pTag)
{ (void)msg; (void)msglen; (void)iv; (void)aad; (void)aadlen;
(void)pResult; (void)pTag; return 0; }
static inline int hal_crypto_aes_ecb_sk_init(u8 key_num, const u32 keylen)
{ (void)key_num; (void)keylen; return 0; }
static inline int hal_crypto_aes_ecb_encrypt(const u8* msg, const u32 msglen,
const u8* iv, const u32 ivlen, u8* pResult)
{ (void)msg; (void)msglen; (void)iv; (void)ivlen; (void)pResult; return 0; }
static inline int hal_crypto_aes_ecb_decrypt(const u8* msg, const u32 msglen,
const u8* iv, const u32 ivlen, u8* pResult)
{ (void)msg; (void)msglen; (void)iv; (void)ivlen; (void)pResult; return 0; }
/* ---- Secure-key HMAC-SHA256 (hal_crypto.h) ---- */
#if !defined(NO_HMAC) && !defined(NO_SHA256)
static inline u32 hal_crypto_hmac_sha2_256_get_sk_cfg(const u8 sk_op,
const u8 sk_idx, const u8 wb_op, const u8 wb_idx)
{ (void)sk_op; (void)sk_idx; (void)wb_op; (void)wb_idx; return 0; }
static inline int hal_crypto_hmac_sha2_256_sk_init(const u8* key,
const u32 sk_cfg)
{ (void)key; (void)sk_cfg; return 0; }
static inline int hal_crypto_hmac_sha2_256_update(const u8* message,
const u32 msglen)
{ (void)message; (void)msglen; return 0; }
static inline int hal_crypto_hmac_sha2_256_sk_final(u8* pDigest)
{ (void)pDigest; return 0; }
#endif /* !NO_HMAC && !NO_SHA256 */
/* ---- HKDF secure key-ladder (hal_hkdf.h) ---- */
static inline hal_status_t hal_hkdf_hmac_sha256_secure_init(const u8 crypto_sel)
{ (void)crypto_sel; return HAL_OK; }
static inline hal_status_t hal_hkdf_extract_secure_all(const u8 sk_idx,
const u8 wb_idx, const u8* msg_buf)
{ (void)sk_idx; (void)wb_idx; (void)msg_buf; return HAL_OK; }
static inline hal_status_t hal_hkdf_expand_secure_all(const u8 sk_idx,
const u8 wb_idx, const u8* nonce)
{ (void)sk_idx; (void)wb_idx; (void)nonce; return HAL_OK; }
/* ---- Secure TRNG (hal_trng_sec.h) ---- */
#ifndef WC_NO_RNG
static inline hal_status_t hal_trng_sec_init(void) { return HAL_OK; }
static inline u32 hal_trng_sec_get_rand(void) { return 0x5A5A5A5Au; }
#endif /* WC_NO_RNG */
/* ---- HW ECDSA engine (hal_ecdsa.h) ---- */
#if defined(HAVE_ECC) && defined(HAVE_ECC_SIGN)
typedef int HAL_Status;
typedef unsigned char ecdsa_curve_t;
typedef unsigned char ecdsa_mode_t;
typedef unsigned char ecdsa_basic_func_t;
typedef unsigned char ecdsa_bit_num_t;
typedef unsigned char ecdsa_sel_prk_t;
#ifndef ECDSA_P256
#define ECDSA_P256 0x1
#endif
#ifndef ECDSA_SIGN
#define ECDSA_SIGN 0x1
#endif
#ifndef ECDSA_VERI
#define ECDSA_VERI 0x0
#endif
#ifndef ECDSA_NONE
#define ECDSA_NONE 0x5
#endif
#ifndef ECDSA_256_BIT
#define ECDSA_256_BIT 0x0
#endif
#ifndef ECDSA_INPUT_PRK
#define ECDSA_INPUT_PRK 0x0
#define ECDSA_OTP_PRK_1 0x1
#define ECDSA_OTP_PRK_2 0x2
#endif
typedef struct hal_ecdsa_adapter_s { int dummy; } hal_ecdsa_adapter_t;
typedef struct hal_ecdsa_curve_table_s {
u32* ppoint_x;
u32* ppoint_y;
u32* pa_adr;
u32* pprime;
u32* porder_n;
} hal_ecdsa_curve_table_t;
typedef void (*ecdsa_irq_user_cb_t)(void*);
static inline HAL_Status hal_ecdsa_init(hal_ecdsa_adapter_t* a)
{ (void)a; return 0; }
static inline HAL_Status hal_ecdsa_deinit(hal_ecdsa_adapter_t* a)
{ (void)a; return 0; }
static inline u32 hal_ecdsa_get_err_sta(hal_ecdsa_adapter_t* a)
{ (void)a; return 0; }
static inline void hal_ecdsa_cb_handler(hal_ecdsa_adapter_t* a,
ecdsa_irq_user_cb_t cb, void* arg) { (void)a; (void)cb; (void)arg; }
static inline void hal_ecdsa_set_curve(hal_ecdsa_adapter_t* a, ecdsa_curve_t c,
hal_ecdsa_curve_table_t* t, ecdsa_bit_num_t b)
{ (void)a; (void)c; (void)t; (void)b; }
static inline void hal_ecdsa_set_mode(hal_ecdsa_adapter_t* a, ecdsa_mode_t m,
ecdsa_basic_func_t f) { (void)a; (void)m; (void)f; }
static inline void hal_ecdsa_select_prk(hal_ecdsa_adapter_t* a,
ecdsa_sel_prk_t s) { (void)a; (void)s; }
static inline void hal_ecdsa_signature(hal_ecdsa_adapter_t* a, u32* pk, u32* k)
{ (void)a; (void)pk; (void)k; }
static inline void hal_ecdsa_hash(hal_ecdsa_adapter_t* a, u32* h)
{ (void)a; (void)h; }
static inline void hal_ecdsa_get_rs(hal_ecdsa_adapter_t* a, u32* r, u32* s)
{ (void)a; (void)r; (void)s; }
#ifdef HAVE_ECC_VERIFY
typedef struct hal_ecdsa_veri_input_s {
u32* ppub_key_x;
u32* ppub_key_y;
u32* pr_adr;
u32* ps_adr;
} hal_ecdsa_veri_input_t;
static inline void hal_ecdsa_verify(hal_ecdsa_adapter_t* a,
hal_ecdsa_veri_input_t* in) { (void)a; (void)in; }
static inline u32 hal_ecdsa_get_veri_result(hal_ecdsa_adapter_t* a)
{ (void)a; return 0; }
static inline u32 hal_ecdsa_get_veri_err_sta(hal_ecdsa_adapter_t* a)
{ (void)a; return 0; }
#endif /* HAVE_ECC_VERIFY */
#endif /* HAVE_ECC && HAVE_ECC_SIGN */
#endif /* WOLFSSL_RTL8735B_HOST_TEST */
#endif /* _WOLFPORT_RTL8735B_SHIM_H_ */
+5
View File
@@ -2277,12 +2277,17 @@ int wolfSSL_CryptHwMutexLock(void)
}
int wolfSSL_CryptHwMutexUnLock(void)
{
#ifndef WOLFSSL_MUTEX_INITIALIZER
if (wcCryptHwMutexInit) {
return wc_UnLockMutex(&wcCryptHwMutex);
}
else {
return BAD_MUTEX_E;
}
#else
/* statically initialized (no runtime init flag) -- always valid to unlock */
return wc_UnLockMutex(&wcCryptHwMutex);
#endif
}
#endif /* WOLFSSL_CRYPT_HW_MUTEX */
+10
View File
@@ -473,6 +473,9 @@ static const byte const_byte_array[] = "A+Gd\0\0\0";
#if defined(WOLFSSL_MAX3266X) || defined(WOLFSSL_MAX3266X_OLD)
#include <wolfssl/wolfcrypt/port/maxim/max3266x-cryptocb.h>
#endif
#ifdef WOLFSSL_RTL8735B_HOST_TEST
#include <wolfssl/wolfcrypt/port/realtek/rtl8735b.h>
#endif
#endif
#ifdef _MSC_VER
@@ -3365,6 +3368,13 @@ options: [-s max_relative_stack_bytes] [-m max_relative_heap_memory_bytes]\n\
TEST_PASS("crypto callback test passed!\n");
#endif
#ifdef WOLFSSL_RTL8735B_HOST_TEST
if ( (ret = wc_Rtl8735b_HukSelfTest()) != 0)
TEST_FAIL("RTL8735B HUK self-test failed!\n", ret);
else
TEST_PASS("RTL8735B HUK self-test passed!\n");
#endif
#ifdef WOLFSSL_CERT_PIV
if ( (ret = certpiv_test()) != 0)
TEST_FAIL("cert piv test failed!\n", ret);
+1
View File
@@ -111,6 +111,7 @@ noinst_HEADERS+= \
wolfssl/wolfcrypt/port/silabs/silabs_random.h \
wolfssl/wolfcrypt/port/st/stm32.h \
wolfssl/wolfcrypt/port/st/stsafe.h \
wolfssl/wolfcrypt/port/realtek/rtl8735b.h \
wolfssl/wolfcrypt/port/tropicsquare/tropic01.h \
wolfssl/wolfcrypt/port/Espressif/esp-sdk-lib.h \
wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h \
+204
View File
@@ -0,0 +1,204 @@
/* rtl8735b.h
*
* Copyright (C) 2006-2026 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL 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.
*
* wolfSSL 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
*/
/* RealTek AmebaPro2 (RTL8735B) HUK (Hardware Unique Key) crypto-callback port.
*
* Binds keys to the silicon HUK via the AmebaPro2 HAL crypto engine: a 256-bit
* "seed" is run through the HAL HKDF key-ladder against the HUK to land a
* device-bound working key in a secure key-storage slot; AES (GCM/ECB/CBC/CTR)
* then runs from that slot without the key ever entering software. ECDSA sign
* binds a HUK-wrapped private scalar. The port is a pure crypto-callback device:
* it adds no wolfSSL core API or struct fields -- AES reads its seed from the
* standard aes->devKey, and ECDSA reads a wc_Rtl8735b_EccKey (below) the caller
* attaches via the standard ecc_key->devCtx. Only a 32-byte seed is HUK-bound:
* a 16/24-byte AES key falls back to ordinary software AES (the bytes become the
* literal key, no device binding, no error), so AES-128/192 are not HUK-bound.
*
* The HW ECDSA P-256 engine (hal_ecdsa) is also used as a general sign/verify
* offload, independent of the HUK: an ecc_key with devId = WC_HUK_DEVID and no
* devCtx routes wc_ecc_sign_hash through the engine using the key's own scalar,
* and wc_ecc_verify_hash through the engine using the key's own public point
* (no HUK context needed for verify). This lets a standard wolfCrypt benchmark
* exercise the HW engine just by setting WC_USE_DEVID = WC_HUK_DEVID.
*/
#ifndef _WOLFPORT_RTL8735B_H_
#define _WOLFPORT_RTL8735B_H_
#include <wolfssl/wolfcrypt/types.h>
#ifdef WOLFSSL_RTL8735B_HUK
/* Transparent HUK crypto flows through the crypto-callback framework. */
#if !defined(WOLF_CRYPTO_CB)
#error "WOLFSSL_RTL8735B_HUK requires WOLF_CRYPTO_CB (crypto callback dispatch)"
#endif
/* Crypto-callback device id for transparent HUK crypto. Must not collide with
* the STM32 DHUK device ids (807 SAES, 808 DHUK, 809 DHUK-wrapped) if both ports
* are enabled in one build. Override before include if it collides. */
#ifndef WC_HUK_DEVID
#define WC_HUK_DEVID 810
#endif
/* Secure key-storage slot indices for the key ladder (KEY_STG_* values from
* rtl8735b_crypto_ctrl.h, NOT the hkdf_key_storage_e enum in rtl8735b_hkdf.h):
* the HUK source is HUK1 (0xC); slots 0..7 are general. The PRK and the derived
* working key each take a general slot -- the working-key slot is the one
* AES/HMAC *_sk_init reference. All overridable from user_settings. */
#ifndef WC_RTL8735B_HUK_SK_IDX
#define WC_RTL8735B_HUK_SK_IDX 0xC /* KEY_STG_HUK1 */
#endif
#ifndef WC_RTL8735B_HKDF_PRK_IDX
#define WC_RTL8735B_HKDF_PRK_IDX 3 /* KEY_STG_IDX3 */
#endif
#ifndef WC_RTL8735B_DERIVED_WB_IDX
#define WC_RTL8735B_DERIVED_WB_IDX 4 /* KEY_STG_IDX4 */
#endif
/* crypto_sel for hal_hkdf_hmac_sha256_secure_init: HKDF_CRYPTO_HW_SEL_EN. */
#ifndef WC_RTL8735B_HKDF_CRYPTO_SEL
#define WC_RTL8735B_HKDF_CRYPTO_SEL 0
#endif
/* Secure-key HMAC-SHA256 config selectors (rtl8735b crypto key-storage roles,
* passed to hal_crypto_hmac_sha2_256_get_sk_cfg): source the HMAC key from the
* secure slot (KEY_STG_SKTYPE_LD_SK) and emit the digest to the output buffer
* with no slot write-back (KEY_STG_WBTYPE_WB_ONLY_BUF). The key slot used is
* WC_RTL8735B_DERIVED_WB_IDX (the HUK-derived working key). All overridable. */
#ifndef WC_RTL8735B_HMAC_SK_OP
#define WC_RTL8735B_HMAC_SK_OP 1 /* KEY_STG_SKTYPE_LD_SK */
#endif
#ifndef WC_RTL8735B_HMAC_WB_OP
#define WC_RTL8735B_HMAC_WB_OP 0 /* KEY_STG_WBTYPE_WB_ONLY_BUF */
#endif
#ifndef WC_RTL8735B_HMAC_WB_IDX
#define WC_RTL8735B_HMAC_WB_IDX 0 /* unused when WB_ONLY_BUF */
#endif
/* HUK HMAC-SHA256 is one-shot: wc_HmacUpdate chunks are buffered on the heap and
* the MAC runs at wc_HmacFinal, so heap use grows with the total message. It is
* intended for bounded/short HUK MAC / KDF inputs. WC_RTL8735B_HMAC_MAX_MSG caps
* the buffered length: past it, accumulation returns BUFFER_E. The default 64 KB
* bounds runaway growth while clearing typical benchmark/KDF use; set to 0 for
* unbounded, or raise it if you MAC larger messages under the HUK.
* IMPORTANT: the HMAC key buffer (the HUK seed, passed to wc_HmacSetKey) is
* borrowed via hmac->keyRaw and re-read at wc_HmacFinal / wc_HmacFree, so it must
* stay valid and unmodified through all Update/Final/Free calls on the Hmac. */
#ifndef WC_RTL8735B_HMAC_MAX_MSG
#define WC_RTL8735B_HMAC_MAX_MSG 65536
#endif
/* Max wrapped-scalar blob the HUK ECDSA sign path will unwrap (a multiple of 16
* covering up to P-521: 66 padded to 80, plus headroom). */
#ifndef WC_RTL8735B_MAX_WRAPPED
#define WC_RTL8735B_MAX_WRAPPED 96
#endif
/* Bounded spin waiting for the HW ECDSA finish IRQ -- only a safety bound so a
* wedged engine returns WC_HW_E instead of hanging. An ITERATION count, not a
* wall-clock timeout (so it scales with CPU clock / optimization, intentionally
* generous). Default sized for the RTL8735B "KM4" Cortex-M33 at 500 MHz (a P-256
* sign/verify finishes in a few ms). Tune for a different part/toolchain. */
#ifndef WC_RTL8735B_ECDSA_SPIN
#define WC_RTL8735B_ECDSA_SPIN 2000000L
#endif
/* Hook called once per ECDSA wait-loop iteration. The wait runs while the global
* crypto mutex is held, so on an RTOS a busy spin blocks other crypto threads;
* define this to a cooperative yield (e.g. taskYIELD() on FreeRTOS, k_yield() on
* Zephyr) so the core is released while the engine finishes. Default: no-op. */
#ifndef WC_RTL8735B_ECDSA_YIELD
#define WC_RTL8735B_ECDSA_YIELD() do {} while (0)
#endif
/* HUK-bound ECC private key context for the ECDSA sign path. Instead of a new
* wolfSSL core API, the caller attaches one of these to a WC_HUK_DEVID ecc_key
* via the standard crypto-callback context pointer (key->devCtx) before signing:
*
* wc_Rtl8735b_EccKey hk = { seed, 32, wrapped, plainLen, plainLen,
* 0, 0, iv, 12, tag, 16 };
* wc_ecc_init_ex(&key, NULL, WC_HUK_DEVID);
* wc_ecc_set_curve(&key, plainLen, curveId);
* key.devCtx = &hk;
* wc_ecc_sign_hash(...); (unwraps + signs under the HUK)
*
* The pointed-at buffers must stay valid for the key's lifetime (borrowed, not
* copied). seed is the 256-bit HKDF input. The private scalar is AUTHENTICATED-
* wrapped with AES-GCM under the HUK-derived key: wrapped is the ciphertext
* (wrappedLen == plainLen, no block padding, <= WC_RTL8735B_MAX_WRAPPED), iv the
* 12-byte nonce, tag the 16-byte auth tag; plainLen is the scalar size (32 for
* P-256). GCM means a tampered, corrupted, or wrong-device blob fails at unwrap
* (AES_GCM_AUTH_E) instead of silently yielding a garbage scalar. Requires
* HAVE_AESGCM.
*
* By default the sign runs in software after the HUK GCM-unwrap. Set useHwEngine
* to route the sign through the HW ECDSA engine (hal_ecdsa, P-256 only). With
* otpPrkSel != 0 the private scalar is sourced from OTP via hal_ecdsa_select_prk
* and never enters software -- seed/wrapped/iv/tag/plainLen are then unused and
* may be zero/NULL. (The HW-engine INPUT/HUK-wrapped path is validated on
* silicon; the OTP-resident path is implemented but unexercised.) */
typedef struct wc_Rtl8735b_EccKey {
const byte* seed;
word32 seedSz;
const byte* wrapped; /* AES-GCM ciphertext of the scalar (== plainLen) */
word32 wrappedLen;
word32 plainLen;
/* --- HW ECDSA engine extensions (appended; zero keeps legacy behavior) --- */
byte useHwEngine; /* 1: sign via the HW ECDSA engine (hal_ecdsa) */
byte otpPrkSel; /* HW private-key source: 0 = unwrapped INPUT scalar,
* 1 = ECDSA_OTP_PRK_1, 2 = ECDSA_OTP_PRK_2 (scalar
* never in software; seed/wrapped may be NULL) */
/* --- AES-GCM wrap parameters (authenticated unwrap) --- */
const byte* iv; /* 12-byte GCM nonce for the wrapped scalar */
word32 ivSz;
const byte* tag; /* 16-byte GCM auth tag */
word32 tagSz;
} wc_Rtl8735b_EccKey;
#ifdef __cplusplus
extern "C" {
#endif
/* Register / unregister the AmebaPro2 HUK device. After registering at
* WC_HUK_DEVID, set an object's devId to it at init (e.g.
* wc_AesInit(&aes, NULL, WC_HUK_DEVID)) to route transparently to the HUK
* crypto engine. Both return 0 on success; unregister returns a mutex-lock
* error if it could not scrub the derivation cache / TRNG-init state (the device
* is still unregistered in that case). */
WOLFSSL_API int wc_Rtl8735b_HukRegister(int devId);
WOLFSSL_API int wc_Rtl8735b_HukUnRegister(int devId);
#ifdef WOLFSSL_RTL8735B_HOST_TEST
/* Host-only KAT of the port's silicon-independent helpers (BE/LE word conversion,
* CTR counter increment, HMAC accumulator growth/overflow/cap, bounce alignment).
* A build/CI aid for the --enable-rtl8735b compile-test -- NOT shipped production
* API. Returns 0 on success, negative on the first failing check. */
WOLFSSL_API int wc_Rtl8735b_HukSelfTest(void);
#endif
#ifdef __cplusplus
}
#endif
#endif /* WOLFSSL_RTL8735B_HUK */
#endif /* _WOLFPORT_RTL8735B_H_ */
+4 -2
View File
@@ -920,10 +920,12 @@ WOLFSSL_LOCAL void wolfSSL_RefWithMutexDec_IfEquals(wolfSSL_RefWithMutex* ref,
#endif
/* Enable crypt HW mutex for Freescale MMCAU, PIC32MZ or STM32 */
/* Enable crypt HW mutex for Freescale MMCAU, PIC32MZ, STM32, MAX3266X or
* RTL8735B */
#if defined(FREESCALE_MMCAU) || defined(WOLFSSL_MICROCHIP_PIC32MZ) || \
defined(STM32_CRYPTO) || defined(STM32_HASH) || defined(STM32_RNG) || \
defined(WOLFSSL_MAX3266X) || defined(WOLFSSL_MAX3266X_OLD)
defined(WOLFSSL_MAX3266X) || defined(WOLFSSL_MAX3266X_OLD) || \
defined(WOLFSSL_RTL8735B_HUK)
#ifndef WOLFSSL_CRYPT_HW_MUTEX
#define WOLFSSL_CRYPT_HW_MUTEX 1
#endif
+1
View File
@@ -131,6 +131,7 @@ if(CONFIG_WOLFSSL)
zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/port/psa/psa_hash.c)
zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/port/psa/psa_pkcbs.c)
zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/port/st/stm32.c)
zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/port/realtek/rtl8735b.c)
if(CONFIG_WOLFCRYPT_ARMASM)
# tested with board: "qemu_kvm_arm64"