Merge pull request #575 from dgarske/amebapro2-huk-example

Add RealTek AmebaPro2 (RTL8735B) HUK wolfCrypt example
pull/318/merge
Zackery 2026-07-10 14:13:48 -06:00 committed by GitHub
commit bf7fb899af
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 1808 additions and 0 deletions

87
rtl8735b/README.md 100644
View File

@ -0,0 +1,87 @@
# wolfCrypt on RealTek AmebaPro2 (RTL8735B) -- Hardware Unique Key (HUK)
This example demonstrates wolfCrypt AES-GCM, AES-ECB, AES-CBC, AES-CTR, HMAC-SHA256 and ECDSA P-256 bound to the RealTek RTL8735B silicon **Hardware Unique Key (HUK)** through the wolfCrypt crypto-callback (CryptoCb) framework. A 256-bit "seed" is run through the AmebaPro2 HAL secure HKDF key-ladder against the HUK to derive a per-purpose working key inside a secure key-storage slot; that working key never enters software. The application just sets the seed as the key and uses the normal wolfCrypt APIs -- the RealTek HUK crypto-callback device does the rest.
It is built inside the RealTek AmebaPro2 FreeRTOS SDK (which provides the startup, HAL, and the `elf2bin`/`uartfwburn` image+flash tooling).
## What it shows
- Registering the HUK crypto-callback device: `wc_Rtl8735b_HukRegister(WC_HUK_DEVID)`.
- AES-GCM (full payload), AES-ECB, AES-CBC and AES-CTR run under the HUK-derived key (init an `Aes` with `devId = WC_HUK_DEVID`, then use the usual `wc_AesGcmSetKey`/`wc_AesGcmEncrypt`, `wc_AesSetKey`/`wc_AesEcb*`/`wc_AesCbc*`, `wc_AesSetKeyDirect`/`wc_AesCtrEncrypt`).
- The key is device-bound and deterministic: the same seed yields the same key (so GMAC verifies and AES round-trips), and a different seed yields a different key (GCM decrypt returns `AES_GCM_AUTH_E`).
- The port tolerates unaligned caller buffers (it bounces them to satisfy the HAL's 32-byte alignment); the example includes an explicitly-unaligned GCM check.
- HMAC-SHA256 under the HUK (`wc_HmacInit` with `devId = WC_HUK_DEVID`, then `wc_HmacSetKey`/`wc_HmacUpdate`/`wc_HmacFinal`): the MAC is deterministic for a given seed and differs for a wrong seed.
- HUK-bound ECDSA P-256 sign: a key is generated in software, its private scalar is wrapped under the HUK (ECB-encrypted with the HUK device), and signing then goes through the HUK device (unwrap + sign); the signature verifies against the software public key.
- HW ECDSA P-256 verify offload: the same signature is then verified through the HW engine (the public point is imported into a `WC_HUK_DEVID` key so `wc_ecc_verify_hash` dispatches to `hal_ecdsa`), and a tampered digest is shown to be rejected. No HUK context is needed to verify -- any P-256 public key.
## Prerequisites
- RealTek AmebaPro2 FreeRTOS SDK: https://github.com/Ameba-AIoT/ameba-rtos-pro2
- RealTek ASDK 10.3.0 toolchain (GCC 10.3.0): https://github.com/Ameba-AIoT/ameba-toolchain (tag `V10.3.0-ameba-rtos-pro2`). The stock system `arm-none-eabi-gcc` does not build the SDK (newlib/lwip header clashes); use the ASDK toolchain.
- wolfSSL with the RealTek HUK port (`wolfcrypt/src/port/realtek/rtl8735b.c` and `wolfssl/wolfcrypt/port/realtek/rtl8735b.h`). Enable with `WOLFSSL_RTL8735B_HUK` and `WOLF_CRYPTO_CB`.
## Files
- `main.c` -- the example application (a FreeRTOS task that registers the HUK device and runs the AES-GCM/ECB/CBC/CTR checks plus unaligned-buffer GCM, in-place/multi-call CBC, non-12-byte-IV rejection, HMAC-SHA256, and HUK-bound ECDSA sign + HW verify checks).
- `user_settings.h` -- a lean wolfCrypt configuration for this example.
- `wolfcrypt_huk.cmake` -- wiring that adds wolfCrypt + the RealTek HUK port to the SDK app build.
- `test/` -- a separate `wolfcrypt_test` + `wolfcrypt_benchmark` example for this target with three backend modes (pure C, Thumb-2 / SP Cortex-M, and RealTek hardware offload); see `test/README.md`.
## Build
1. Copy this directory into the SDK as an example component:
`cp -r rtl8735b <SDK>/component/example/wolfcrypt_huk`
2. Install the example `main()` as the project app:
`cp <SDK>/component/example/wolfcrypt_huk/main.c <SDK>/project/realtek_amebapro2_v0_example/src/main.c`
3. Configure and build with the ASDK toolchain on PATH, pointing `WOLFSSL_ROOT` at your wolfSSL tree:
```
export PATH=<asdk>/asdk-10.3.0/linux/newlib/bin:$PATH
cd <SDK>/project/realtek_amebapro2_v0_example/GCC-RELEASE
mkdir -p build && cd build
cmake .. -G"Unix Makefiles" -DCMAKE_TOOLCHAIN_FILE=../toolchain.cmake \
-DBUILD_FPGA=OFF -DBUILD_PXP=OFF \
-DEXAMPLE=wolfcrypt_huk -DWOLFSSL_ROOT=<path-to-wolfssl>
make flash -j8
```
The output image is `build/flash_ntz.bin`.
## Flash and run
Put the board in download mode (J27 jumper + reset), then flash over UART with the SDK `uartfwburn` tool (from the SDK `tools/Pro2_PG_tool*` directory, which also holds `boot_recover.bin`, `flash_loader_nor.bin`, `flash_control_info.bin`):
```
./uartfwburn.linux -p <COM_PORT> -f <build>/flash_ntz.bin -b 3000000 -U
```
Remove the J27 jumper and reset to boot. The console (UART, 115200) prints:
```
=== wolfCrypt AmebaPro2 (RTL8735B) HUK example ===
[PASS] wolfCrypt_Init
[PASS] wc_Rtl8735b_HukRegister
== AES-GCM (full payload) under HUK-derived key ==
[PASS] AesInit(devId=WC_HUK_DEVID)
[PASS] AesGcmSetKey(seed,32)
[PASS] AesGcmEncrypt
[PASS] deterministic tag
[PASS] AesGcmDecrypt verifies
[PASS] plaintext round-trips
[PASS] wrong seed -> AES_GCM_AUTH_E
== AES-ECB under HUK-derived key == ... round-trip PASS
== AES-CBC under HUK-derived key == ... round-trip PASS
== AES-CTR under HUK-derived key == ... round-trip PASS
== AES-GCM with UNALIGNED buffers (port bounces) == ... round-trip PASS
== AES-CBC in-place + multi-call under HUK-derived key == ... round-trip PASS
== AES-GCM non-12-byte IV must hard-fail == ... 16-byte IV rejected PASS
== HMAC-SHA256 under HUK-derived key == ... deterministic / wrong-seed PASS
== ECDSA P-256 under HUK-derived key ==
[PASS] HUK ECDSA sign
[PASS] verify with software public key
[PASS] HW ECDSA verify (good sig)
[PASS] HW ECDSA verify (tampered -> reject)
=== done ===
```
## Notes
- The AmebaPro2 HAL crypto engine DMAs its key/IV/AAD/tag buffers on 32-byte boundaries; the port stages and bounces buffers as needed, so callers need not align (the example aligns its buffers anyway, and adds an explicitly-unaligned GCM case to exercise the bounce path).
- The seed is HKDF input, not the AES key itself -- it diversifies the HUK into a working key. Keep the seed stable for a given purpose to get a stable derived key.
- HUK-bound ECDSA P-256 signing: this example sets `hk.useHwEngine = 1` to drive the HW ECDSA engine (validated on the RTL8735B); set it to 0 for the software-after-unwrap path (the port default). `hk.otpPrkSel` can instead select an OTP-resident key (scalar never in software; needs an OTP key provisioned).
- Port internals (the HKDF key-ladder, slot configuration macros such as `WC_HUK_DEVID`, `WC_RTL8735B_*`) are documented in `wolfssl/wolfcrypt/port/realtek/rtl8735b.h` and `wolfcrypt/src/port/realtek/README.md` in the wolfSSL tree.

612
rtl8735b/main.c 100644
View File

@ -0,0 +1,612 @@
/* wolfCrypt AmebaPro2 (RTL8735B) HUK example -- built inside the RealTek
* FreeRTOS SDK. Registers the wolfCrypt HUK crypto-callback device and runs
* AES-GCM (full payload) / AES-ECB / AES-CBC / AES-CTR, HMAC-SHA256, and ECDSA
* P-256 under a key derived from the silicon Hardware Unique Key; the working
* key never enters software. The 256-bit "seed" passed as the key is HKDF input
* diversifying the HUK. It also runs regression checks: unaligned-buffer GCM
* (port bounce path), in-place multi-call CBC, and a non-12-byte GCM IV that
* must hard-fail (no silent software fallback).
*
* Build: configure with -DEXAMPLE=wolfcrypt_huk (see wolfcrypt_huk.cmake).
*/
#include <string.h>
#include "platform_stdlib.h"
#include "FreeRTOS.h"
#include "task.h"
#include "device_lock.h"
#include "hal_trng_sec.h"
#include <wolfssl/wolfcrypt/settings.h>
#include <wolfssl/wolfcrypt/wc_port.h>
#include <wolfssl/wolfcrypt/aes.h>
#include <wolfssl/wolfcrypt/hmac.h>
#include <wolfssl/wolfcrypt/ecc.h>
#include <wolfssl/wolfcrypt/random.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/port/realtek/rtl8735b.h>
/* ForceZero (used to scrub key material below). Inline the misc helpers the same
* way wolfCrypt's own test.c/benchmark.c do; misc.c provides ForceZero only as an
* inline, so a plain extern reference would not link. */
#ifdef NO_INLINE
#include <wolfssl/wolfcrypt/misc.h>
#else
#define WOLFSSL_MISC_INCLUDED
#include <wolfcrypt/src/misc.c>
#endif
#define STACKSIZE 8192
#define CHECK(label, cond) \
dbg_printf("[%s] %s\r\n", (cond) ? "PASS" : "FAIL", (label))
/* wolfCrypt RNG seed hook (user_settings: CUSTOM_RAND_GENERATE_SEED). Fills from
* the AmebaPro2 secure (self-tested) hardware TRNG -- the same source the HUK
* port exposes as a crypto-callback SEED. (Using the secure TRNG directly also
* avoids the non-secure hal_trng wrapper, whose C-cut path references a ROM
* symbol not resolvable in a from-source SDK build.) */
int rtl8735b_rand_seed(unsigned char* output, unsigned int sz)
{
static int inited = 0;
unsigned int i, n;
u32 r;
if (inited == 0) {
if (hal_trng_sec_init() != 0) {
return -1;
}
inited = 1;
}
for (i = 0; i < sz; ) {
r = hal_trng_sec_get_rand();
n = (sz - i) < 4u ? (sz - i) : 4u;
memcpy(output + i, &r, n);
i += n;
}
return 0;
}
static void huk_gcm_test(void)
{
Aes aes;
/* HAL crypto engine requires 32-byte-aligned key/iv/aad/tag buffers. */
byte seed[32] __attribute__((aligned(32)));
byte iv[12] __attribute__((aligned(32)));
byte aad[16] __attribute__((aligned(32)));
byte pt[32] __attribute__((aligned(32)));
byte ct[32] __attribute__((aligned(32)));
byte dec[32] __attribute__((aligned(32)));
byte tag[16] __attribute__((aligned(32)));
byte tag2[16] __attribute__((aligned(32)));
int ret;
memset(seed, 0xA5, sizeof(seed)); memset(iv, 0x11, sizeof(iv));
memset(aad, 0x22, sizeof(aad)); memset(pt, 0x33, sizeof(pt));
dbg_printf("\r\n== AES-GCM (full payload) under HUK-derived key ==\r\n");
ret = wc_AesInit(&aes, NULL, WC_HUK_DEVID);
CHECK("AesInit(devId=WC_HUK_DEVID)", ret == 0);
if (ret != 0) {
return;
}
ret = wc_AesGcmSetKey(&aes, seed, sizeof(seed));
CHECK("AesGcmSetKey(seed,32)", ret == 0);
if (ret != 0) {
wc_AesFree(&aes);
return;
}
ret = wc_AesGcmEncrypt(&aes, ct, pt, sizeof(pt), iv, sizeof(iv),
tag, sizeof(tag), aad, sizeof(aad));
CHECK("AesGcmEncrypt", ret == 0);
if (ret != 0) {
wc_AesFree(&aes);
return;
}
memset(tag2, 0, sizeof(tag2));
ret = wc_AesGcmEncrypt(&aes, ct, pt, sizeof(pt), iv, sizeof(iv),
tag2, sizeof(tag2), aad, sizeof(aad));
CHECK("deterministic tag", ret == 0 && memcmp(tag, tag2, 16) == 0);
ret = wc_AesGcmDecrypt(&aes, dec, ct, sizeof(ct), iv, sizeof(iv),
tag, sizeof(tag), aad, sizeof(aad));
CHECK("AesGcmDecrypt verifies", ret == 0);
CHECK("plaintext round-trips", memcmp(dec, pt, sizeof(pt)) == 0);
seed[0] ^= 0xFF;
ret = wc_AesGcmSetKey(&aes, seed, sizeof(seed));
CHECK("AesGcmSetKey(wrong seed)", ret == 0);
ret = wc_AesGcmDecrypt(&aes, dec, ct, sizeof(ct), iv, sizeof(iv),
tag, sizeof(tag), aad, sizeof(aad));
CHECK("wrong seed -> AES_GCM_AUTH_E", ret == AES_GCM_AUTH_E);
wc_AesFree(&aes);
ForceZero(seed, sizeof(seed)); /* scrub key material before return */
}
static void huk_ecb_cbc_test(void)
{
Aes aes;
byte seed[32] __attribute__((aligned(32)));
byte iv[16] __attribute__((aligned(32)));
byte pt[32] __attribute__((aligned(32)));
byte ct[32] __attribute__((aligned(32)));
byte dec[32] __attribute__((aligned(32)));
int ret;
memset(seed, 0x5A, sizeof(seed)); memset(iv, 0x44, sizeof(iv));
memset(pt, 0x77, sizeof(pt));
dbg_printf("\r\n== AES-ECB under HUK-derived key ==\r\n");
ret = wc_AesInit(&aes, NULL, WC_HUK_DEVID);
CHECK("AesInit(devId=WC_HUK_DEVID)", ret == 0);
if (ret != 0) {
return;
}
ret = wc_AesSetKey(&aes, seed, sizeof(seed), NULL, AES_ENCRYPTION);
CHECK("AesSetKey(ECB enc)", ret == 0);
if (ret != 0) {
wc_AesFree(&aes);
return;
}
ret = wc_AesEcbEncrypt(&aes, ct, pt, sizeof(pt));
CHECK("AesEcbEncrypt", ret == 0);
ret = wc_AesSetKey(&aes, seed, sizeof(seed), NULL, AES_DECRYPTION);
CHECK("AesSetKey(ECB dec)", ret == 0);
ret = wc_AesEcbDecrypt(&aes, dec, ct, sizeof(ct));
CHECK("AesEcb round-trip", ret == 0 && memcmp(dec, pt, sizeof(pt)) == 0);
wc_AesFree(&aes);
dbg_printf("\r\n== AES-CBC under HUK-derived key ==\r\n");
ret = wc_AesInit(&aes, NULL, WC_HUK_DEVID);
CHECK("AesInit(devId=WC_HUK_DEVID)", ret == 0);
if (ret != 0) {
return;
}
ret = wc_AesSetKey(&aes, seed, sizeof(seed), iv, AES_ENCRYPTION);
CHECK("AesSetKey(CBC enc)", ret == 0);
ret = wc_AesCbcEncrypt(&aes, ct, pt, sizeof(pt));
CHECK("AesCbcEncrypt", ret == 0);
ret = wc_AesSetKey(&aes, seed, sizeof(seed), iv, AES_DECRYPTION);
CHECK("AesSetKey(CBC dec)", ret == 0);
ret = wc_AesCbcDecrypt(&aes, dec, ct, sizeof(ct));
CHECK("AesCbc round-trip", ret == 0 && memcmp(dec, pt, sizeof(pt)) == 0);
wc_AesFree(&aes);
ForceZero(seed, sizeof(seed)); /* scrub key material before return */
}
static void huk_ctr_test(void)
{
Aes aes;
byte seed[32] __attribute__((aligned(32)));
byte iv[16] __attribute__((aligned(32)));
byte pt[20] __attribute__((aligned(32))); /* non-block-multiple: partial */
byte ct[20] __attribute__((aligned(32)));
byte dec[20] __attribute__((aligned(32)));
int ret;
memset(seed, 0x5A, sizeof(seed)); memset(iv, 0x66, sizeof(iv));
memset(pt, 0x99, sizeof(pt));
dbg_printf("\r\n== AES-CTR under HUK-derived key ==\r\n");
ret = wc_AesInit(&aes, NULL, WC_HUK_DEVID);
CHECK("AesInit(devId=WC_HUK_DEVID)", ret == 0);
if (ret != 0) {
return;
}
ret = wc_AesSetKeyDirect(&aes, seed, sizeof(seed), iv, AES_ENCRYPTION);
CHECK("AesSetKeyDirect(CTR)", ret == 0);
if (ret != 0) {
wc_AesFree(&aes);
return;
}
ret = wc_AesCtrEncrypt(&aes, ct, pt, sizeof(pt));
CHECK("AesCtrEncrypt", ret == 0);
CHECK("CTR ciphertext != plaintext", memcmp(ct, pt, sizeof(pt)) != 0);
wc_AesFree(&aes);
/* CTR is its own inverse with the same key+IV */
ret = wc_AesInit(&aes, NULL, WC_HUK_DEVID);
CHECK("AesInit(devId=WC_HUK_DEVID)", ret == 0);
if (ret != 0) {
return;
}
ret = wc_AesSetKeyDirect(&aes, seed, sizeof(seed), iv, AES_ENCRYPTION);
CHECK("AesSetKeyDirect(CTR round-trip)", ret == 0);
ret = wc_AesCtrEncrypt(&aes, dec, ct, sizeof(ct));
CHECK("AesCtr round-trip", ret == 0 && memcmp(dec, pt, sizeof(pt)) == 0);
wc_AesFree(&aes);
ForceZero(seed, sizeof(seed)); /* scrub key material before return */
}
static void huk_gcm_unaligned_test(void)
{
Aes aes;
/* 32-byte-aligned backing; the +1 views below are deliberately unaligned so
* the port's bounce-to-aligned path is exercised. */
byte buf[7][48] __attribute__((aligned(32)));
byte* seed = buf[0] + 1;
byte* iv = buf[1] + 1;
byte* aad = buf[2] + 1;
byte* pt = buf[3] + 1;
byte* ct = buf[4] + 1;
byte* dec = buf[5] + 1;
byte* tag = buf[6] + 1;
int ret;
memset(seed, 0xA5, 32); memset(iv, 0x11, 12);
memset(aad, 0x22, 16); memset(pt, 0x33, 32);
dbg_printf("\r\n== AES-GCM with UNALIGNED buffers (port bounces) ==\r\n");
ret = wc_AesInit(&aes, NULL, WC_HUK_DEVID);
CHECK("AesInit(devId=WC_HUK_DEVID)", ret == 0);
if (ret != 0) {
return;
}
ret = wc_AesGcmSetKey(&aes, seed, 32);
CHECK("AesGcmSetKey (unaligned seed)", ret == 0);
if (ret != 0) {
wc_AesFree(&aes);
return;
}
ret = wc_AesGcmEncrypt(&aes, ct, pt, 32, iv, 12, tag, 16, aad, 16);
CHECK("AesGcmEncrypt (unaligned)", ret == 0);
ret = wc_AesGcmDecrypt(&aes, dec, ct, 32, iv, 12, tag, 16, aad, 16);
CHECK("AesGcmDecrypt (unaligned) verifies", ret == 0);
CHECK("unaligned round-trip", memcmp(dec, pt, 32) == 0);
wc_AesFree(&aes);
ForceZero(seed, 32); /* scrub key material before return */
}
/* In-place CBC decrypt (in == out) across two chained calls -- regression for
* the in-place chaining / IV-advance fix. */
static void huk_cbc_inplace_test(void)
{
Aes aes;
byte seed[32] __attribute__((aligned(32)));
byte iv[16] __attribute__((aligned(32)));
byte pt[48] __attribute__((aligned(32))); /* 3 blocks */
byte buf[48] __attribute__((aligned(32))); /* encrypted then decrypted in place */
int ret, i;
memset(seed, 0x5A, sizeof(seed)); memset(iv, 0x44, sizeof(iv));
for (i = 0; i < (int)sizeof(pt); i++) {
pt[i] = (byte)i;
}
memcpy(buf, pt, sizeof(pt));
dbg_printf("\r\n== AES-CBC in-place + multi-call under HUK-derived key ==\r\n");
ret = wc_AesInit(&aes, NULL, WC_HUK_DEVID);
CHECK("AesInit(devId=WC_HUK_DEVID)", ret == 0);
if (ret != 0) {
return;
}
ret = wc_AesSetKey(&aes, seed, sizeof(seed), iv, AES_ENCRYPTION);
CHECK("AesSetKey(CBC enc)", ret == 0);
ret = wc_AesCbcEncrypt(&aes, buf, buf, sizeof(buf)); /* in == out */
CHECK("CBC in-place encrypt", ret == 0);
wc_AesFree(&aes);
/* Decrypt in place across two calls (32 then 16 bytes) -- the 2nd call relies
* on aes->reg having been advanced to the correct last-ciphertext block. */
ret = wc_AesInit(&aes, NULL, WC_HUK_DEVID);
CHECK("AesInit(devId=WC_HUK_DEVID)", ret == 0);
if (ret != 0) {
return;
}
ret = wc_AesSetKey(&aes, seed, sizeof(seed), iv, AES_DECRYPTION);
CHECK("AesSetKey(CBC dec)", ret == 0);
ret = wc_AesCbcDecrypt(&aes, buf, buf, 32);
if (ret == 0) {
ret = wc_AesCbcDecrypt(&aes, buf + 32, buf + 32, 16);
}
CHECK("CBC in-place multi-call decrypt", ret == 0);
CHECK("CBC in-place round-trip", memcmp(buf, pt, sizeof(pt)) == 0);
wc_AesFree(&aes);
ForceZero(seed, sizeof(seed)); /* scrub key material before return */
}
/* A non-12-byte GCM IV must hard-fail, NOT silently fall back to software GCM
* keyed on the seed -- regression for the IV hard-error fix. */
static void huk_gcm_badiv_test(void)
{
Aes aes;
byte seed[32] __attribute__((aligned(32)));
byte iv[16] __attribute__((aligned(32))); /* 16 bytes, not the supported 12 */
byte pt[16] __attribute__((aligned(32)));
byte ct[16] __attribute__((aligned(32)));
byte tag[16] __attribute__((aligned(32)));
int ret;
memset(seed, 0xA5, sizeof(seed)); memset(iv, 0x11, sizeof(iv));
memset(pt, 0x33, sizeof(pt));
dbg_printf("\r\n== AES-GCM non-12-byte IV must hard-fail ==\r\n");
ret = wc_AesInit(&aes, NULL, WC_HUK_DEVID);
CHECK("AesInit(devId=WC_HUK_DEVID)", ret == 0);
if (ret != 0) {
return;
}
ret = wc_AesGcmSetKey(&aes, seed, sizeof(seed));
CHECK("AesGcmSetKey(seed,32)", ret == 0);
if (ret != 0) {
wc_AesFree(&aes);
return;
}
ret = wc_AesGcmEncrypt(&aes, ct, pt, sizeof(pt), iv, sizeof(iv),
tag, sizeof(tag), NULL, 0);
CHECK("16-byte IV rejected (no silent SW fallback)", ret != 0);
wc_AesFree(&aes);
ForceZero(seed, sizeof(seed)); /* scrub key material before return */
}
/* HMAC-SHA256 under the HUK-derived key: same seed -> same MAC (deterministic),
* a different seed -> different MAC. The 32-byte seed is the HMAC key; the port
* runs the MAC over the HUK-derived secure-key slot (key never in software). */
static void huk_hmac_test(void)
{
Hmac hmac;
byte seed[32] __attribute__((aligned(32)));
byte msg[40] __attribute__((aligned(32)));
byte mac1[WC_SHA256_DIGEST_SIZE];
byte mac2[WC_SHA256_DIGEST_SIZE];
byte mac3[WC_SHA256_DIGEST_SIZE];
int ret;
memset(seed, 0x5A, sizeof(seed));
memset(msg, 0x33, sizeof(msg));
dbg_printf("\r\n== HMAC-SHA256 under HUK-derived key ==\r\n");
ret = wc_HmacInit(&hmac, NULL, WC_HUK_DEVID);
CHECK("HmacInit(devId=WC_HUK_DEVID)", ret == 0);
if (ret != 0) {
return;
}
ret = wc_HmacSetKey(&hmac, WC_SHA256, seed, sizeof(seed));
CHECK("HmacSetKey(seed,32)", ret == 0);
if (ret == 0) {
ret = wc_HmacUpdate(&hmac, msg, sizeof(msg));
}
if (ret == 0) {
ret = wc_HmacFinal(&hmac, mac1);
}
CHECK("HmacFinal", ret == 0);
wc_HmacFree(&hmac);
if (ret != 0) {
return;
}
/* Same seed + message -> identical MAC. */
ret = wc_HmacInit(&hmac, NULL, WC_HUK_DEVID);
if (ret == 0) {
ret = wc_HmacSetKey(&hmac, WC_SHA256, seed, sizeof(seed));
}
if (ret == 0) {
ret = wc_HmacUpdate(&hmac, msg, sizeof(msg));
}
if (ret == 0) {
ret = wc_HmacFinal(&hmac, mac2);
}
wc_HmacFree(&hmac);
CHECK("deterministic MAC", ret == 0 &&
memcmp(mac1, mac2, sizeof(mac1)) == 0);
/* Different seed -> different MAC. */
seed[0] ^= 0xFF;
ret = wc_HmacInit(&hmac, NULL, WC_HUK_DEVID);
if (ret == 0) {
ret = wc_HmacSetKey(&hmac, WC_SHA256, seed, sizeof(seed));
}
if (ret == 0) {
ret = wc_HmacUpdate(&hmac, msg, sizeof(msg));
}
if (ret == 0) {
ret = wc_HmacFinal(&hmac, mac3);
}
wc_HmacFree(&hmac);
CHECK("wrong seed -> different MAC", ret == 0 &&
memcmp(mac1, mac3, sizeof(mac1)) != 0);
ForceZero(seed, sizeof(seed)); /* scrub key material before return */
}
/* HUK-bound ECDSA P-256 sign. A key is generated in software, its private
* scalar wrapped under the HUK (ECB-encrypted with the HUK device using the
* seed), then signing goes through the HUK device (which unwraps under the HUK
* and signs). The signature is checked against the software public key. To
* exercise the HW ECDSA engine instead of the software-after-unwrap path, set
* hk.useHwEngine = 1 (requires on-silicon validation). */
static void huk_ecdsa_test(void)
{
Aes aes;
ecc_key key;
ecc_key huk;
ecc_key hwpub;
WC_RNG rng;
wc_Rtl8735b_EccKey hk;
byte seed[32] __attribute__((aligned(32)));
byte d[32] __attribute__((aligned(32)));
byte wrapped[32] __attribute__((aligned(32)));
byte wrapIv[12] __attribute__((aligned(32))); /* GCM nonce for the wrap */
byte wrapTag[16] __attribute__((aligned(32))); /* GCM auth tag */
byte hash[32] __attribute__((aligned(32)));
byte qx[32];
byte qy[32];
byte sig[80];
word32 dLen = sizeof(d);
word32 qxLen = sizeof(qx);
word32 qyLen = sizeof(qy);
word32 sigLen = sizeof(sig);
int ret;
int verified = 0;
int hwVerified = 0;
int rngOk = 0;
memset(seed, 0x6B, sizeof(seed));
memset(hash, 0x42, sizeof(hash));
memset(d, 0, sizeof(d));
/* Zero the key structs up front so the single cleanup can wc_ecc_free them
* safely even if an earlier step fails before they are initialized. */
memset(&key, 0, sizeof(key));
memset(&huk, 0, sizeof(huk));
memset(&hwpub, 0, sizeof(hwpub));
dbg_printf("\r\n== ECDSA P-256 under HUK-derived key ==\r\n");
ret = wc_InitRng(&rng);
CHECK("InitRng", ret == 0);
if (ret != 0) {
goto cleanup;
}
rngOk = 1;
ret = wc_ecc_init(&key);
if (ret == 0) {
ret = wc_ecc_make_key(&rng, 32, &key);
}
CHECK("ecc_make_key (P-256)", ret == 0);
if (ret != 0) {
goto cleanup;
}
ret = wc_ecc_export_private_only(&key, d, &dLen);
CHECK("export private scalar (32B)", ret == 0 && dLen == 32);
if (ret != 0 || dLen != 32) {
goto cleanup;
}
/* Wrap the scalar under the HUK: AES-GCM-encrypt with the HUK device + seed
* so the blob is authenticated (a tampered/wrong blob fails at unwrap). */
memset(wrapIv, 0x24, sizeof(wrapIv)); /* demo nonce; use a fresh one/provision */
ret = wc_AesInit(&aes, NULL, WC_HUK_DEVID);
if (ret == 0) {
ret = wc_AesGcmSetKey(&aes, seed, sizeof(seed));
}
if (ret == 0) {
ret = wc_AesGcmEncrypt(&aes, wrapped, d, sizeof(d), wrapIv, sizeof(wrapIv),
wrapTag, sizeof(wrapTag), NULL, 0);
}
wc_AesFree(&aes);
CHECK("wrap scalar under HUK (GCM)", ret == 0);
if (ret != 0) {
goto cleanup;
}
/* Sign via the HUK-bound key (GCM-unwraps under the HUK, then signs). */
memset(&hk, 0, sizeof(hk));
hk.seed = seed; hk.seedSz = sizeof(seed);
hk.wrapped = wrapped; hk.wrappedLen = 32;
hk.plainLen = 32;
hk.iv = wrapIv; hk.ivSz = sizeof(wrapIv);
hk.tag = wrapTag; hk.tagSz = sizeof(wrapTag);
/* Route the sign through the HW ECDSA engine (hal_ecdsa, validated on the
* RTL8735B). Set 0 for the software-after-unwrap path (the port default).
* hk.otpPrkSel can instead select an OTP-resident key (scalar never in
* software); see wolfcrypt/src/port/realtek/README.md. */
hk.useHwEngine = 1;
ret = wc_ecc_init_ex(&huk, NULL, WC_HUK_DEVID);
if (ret == 0) {
ret = wc_ecc_set_curve(&huk, 32, ECC_SECP256R1);
}
if (ret == 0) {
huk.devCtx = &hk;
ret = wc_ecc_sign_hash(hash, sizeof(hash), sig, &sigLen, &rng, &huk);
}
CHECK("HUK ECDSA sign", ret == 0);
if (ret == 0) {
ret = wc_ecc_verify_hash(sig, sigLen, hash, sizeof(hash), &verified,
&key);
}
CHECK("verify with software public key", ret == 0 && verified == 1);
/* Verify the same signature through the HW ECDSA engine (general verify
* offload): import the public point into a WC_HUK_DEVID key so the verify
* dispatches to hal_ecdsa. A good signature -> res = 1; a tampered hash
* must -> res = 0 (and still return 0, since a bad signature is not an
* error). No HUK context is needed for verify -- any P-256 public key. */
ret = wc_ecc_export_public_raw(&key, qx, &qxLen, qy, &qyLen);
CHECK("export public point", ret == 0);
if (ret == 0) {
ret = wc_ecc_init_ex(&hwpub, NULL, WC_HUK_DEVID);
}
if (ret == 0) {
ret = wc_ecc_import_unsigned(&hwpub, qx, qy, NULL, ECC_SECP256R1);
}
if (ret == 0) {
hwVerified = 0;
ret = wc_ecc_verify_hash(sig, sigLen, hash, sizeof(hash), &hwVerified,
&hwpub);
}
CHECK("HW ECDSA verify (good sig)", ret == 0 && hwVerified == 1);
if (ret == 0) {
hash[0] ^= 0xFF; /* tamper the digest */
hwVerified = 1;
ret = wc_ecc_verify_hash(sig, sigLen, hash, sizeof(hash), &hwVerified,
&hwpub);
hash[0] ^= 0xFF; /* restore */
}
CHECK("HW ECDSA verify (tampered -> reject)", ret == 0 && hwVerified == 0);
cleanup:
wc_ecc_free(&hwpub);
wc_ecc_free(&huk);
wc_ecc_free(&key);
if (rngOk != 0) {
wc_FreeRng(&rng);
}
/* Scrub the plaintext private scalar, its wrapped form, and the HKDF seed
* (zero secrets with ForceZero, not memset, per wolfSSL convention). */
ForceZero(d, sizeof(d));
ForceZero(wrapped, sizeof(wrapped));
ForceZero(seed, sizeof(seed));
}
static void wolf_huk_thread(void* param)
{
int ret;
(void)param;
dbg_printf("\r\n=== wolfCrypt AmebaPro2 (RTL8735B) HUK example ===\r\n");
device_mutex_lock(RT_DEV_LOCK_CRYPTO);
ret = wolfCrypt_Init();
CHECK("wolfCrypt_Init", ret == 0);
if (ret == 0) {
ret = wc_Rtl8735b_HukRegister(WC_HUK_DEVID);
CHECK("wc_Rtl8735b_HukRegister", ret == 0);
}
if (ret == 0) {
huk_gcm_test();
huk_ecb_cbc_test();
huk_ctr_test();
huk_gcm_unaligned_test();
huk_cbc_inplace_test();
huk_gcm_badiv_test();
huk_hmac_test();
huk_ecdsa_test();
wc_Rtl8735b_HukUnRegister(WC_HUK_DEVID);
}
wolfCrypt_Cleanup();
device_mutex_unlock(RT_DEV_LOCK_CRYPTO);
dbg_printf("\r\n=== done ===\r\n");
vTaskDelete(NULL);
}
int main(void)
{
if (xTaskCreate(wolf_huk_thread, "wolf_huk", STACKSIZE, NULL,
tskIDLE_PRIORITY + 1, NULL) != pdPASS) {
dbg_printf("xTaskCreate failed\r\n");
}
else {
vTaskStartScheduler();
}
while (1) {
}
}

View File

@ -0,0 +1,38 @@
# wolfCrypt test + benchmark on RealTek AmebaPro2 (RTL8735B)
Runs the standard `wolfcrypt_test` self-test and `wolfcrypt_benchmark` on the RTL8735B "KM4" Arm Cortex-M33 inside the RealTek AmebaPro2 FreeRTOS SDK. It validates the wolfCrypt build and toolchain on this target and reports per-algorithm throughput in three backend modes, selected with `-DRTL_BENCH_MODE=N` at configure time:
| Mode | `RTL_BENCH_MODE` | Backend |
|------|------------------|---------|
| Pure C | `1` | Generic `sp_int.c` big-integer math + C symmetric/hash. The portable reference baseline (no assembly). |
| Thumb-2 / SP Cortex-M | `2` (default) | `sp_cortexm.c` for public-key math (Thumb-2/DSP UMAAL) + `thumb2-*-asm.S` for AES/SHA/ChaCha/Poly1305. |
| RealTek HW | `3` | The HUK crypto-callback device over the silicon engine (`hal_crypto` / `hal_ecdsa`): AES, HMAC-SHA256 and ECDSA P-256 sign/verify run in hardware (via `WC_USE_DEVID`). Benchmark only -- see note below. |
Modes 1 and 2 run the self-test then the benchmark. Mode 3 runs the benchmark only: the HUK device derives its working key from the "key" bytes (an HKDF seed), so the standard known-answer test vectors do not apply to it. Mode 3 routes every benchmark op through the HUK device id; ops the device does not accelerate (RSA, DH, ChaCha, hashing, key generation, ECDH) fall back to software automatically, so they show their software (mode-1) rates while the accelerated ops (AES, HMAC-SHA256, ECDSA P-256 sign/verify) show the hardware rates.
## Files
- `main.c` -- a FreeRTOS task that initializes wolfCrypt and runs the test/benchmark (registering the HUK device in mode 3). Provides the RNG seed (`rtw_get_random_bytes`), the benchmark time source (`hal_read_systime_us`), and a fixed wall clock for X.509 date checks.
- `user_settings.h` -- the wolfCrypt configuration; the `RTL_BENCH_MODE` switch selects the backend defines.
- `wolfcrypt_test.cmake` -- SDK app wiring; the `RTL_BENCH_MODE` switch selects the backend sources.
## Build and run
1. Copy this directory into the SDK as an example component:
`cp -r rtl8735b/test <SDK>/component/example/wolfcrypt_test`
2. Install the example `main()` as the project app:
`cp <SDK>/component/example/wolfcrypt_test/main.c <SDK>/project/realtek_amebapro2_v0_example/src/main.c`
3. Configure and build with the ASDK toolchain on PATH, pointing `WOLFSSL_ROOT` at your wolfSSL tree and choosing a mode:
```
export PATH=<asdk>/asdk-10.3.0/linux/newlib/bin:$PATH
cd <SDK>/project/realtek_amebapro2_v0_example/GCC-RELEASE
mkdir -p build && cd build
cmake .. -G"Unix Makefiles" -DCMAKE_TOOLCHAIN_FILE=../toolchain.cmake \
-DBUILD_FPGA=OFF -DBUILD_PXP=OFF \
-DEXAMPLE=wolfcrypt_test -DRTL_BENCH_MODE=2 \
-DWOLFSSL_ROOT=<path-to-wolfssl>
make flash -j8
```
The output image is `build/flash_ntz.bin`. Flash it the same way as the HUK example (J27 download jumper + `uartfwburn`), then reset to boot; the console (UART, 115200) prints the test and benchmark results.
The measured numbers for all three modes are tabulated in the wolfSSL tree at `wolfcrypt/src/port/realtek/README.md`.

View File

@ -0,0 +1,130 @@
/* wolfcrypt_test + wolfcrypt_benchmark on the AmebaPro2 (RTL8735B), built inside
* the RealTek FreeRTOS SDK.
*
* Modes 1 (pure C) and 2 (Thumb-2 / SP Cortex-M asm) run the full wolfCrypt
* self-test then the benchmark over software crypto -- validating the core
* library and toolchain on this Cortex-M33 and reporting per-algorithm
* throughput. Mode 3 registers the HUK crypto-callback device over the silicon
* engine and runs the benchmark only (AES / HMAC-SHA256 / ECDSA P-256 in
* hardware via WC_USE_DEVID); the self-test is skipped because the HUK device
* derives its key from the "key" bytes, so the standard known-answer vectors do
* not apply to it.
*
* Build: configure with -DEXAMPLE=wolfcrypt_test -DRTL_BENCH_MODE=N (see
* wolfcrypt_test.cmake; N defaults to 2).
*/
#include "platform_stdlib.h"
#include "FreeRTOS.h"
#include "task.h"
#include "osdep_service.h" /* rtw_get_random_bytes */
#include "hal_timer.h" /* hal_read_systime_us */
#include <wolfssl/wolfcrypt/settings.h>
#include <wolfssl/wolfcrypt/wc_port.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfcrypt/test/test.h>
#include <wolfcrypt/benchmark/benchmark.h>
#if defined(WOLFSSL_RTL8735B_HUK)
#include <wolfssl/wolfcrypt/port/realtek/rtl8735b.h>
#endif
#define STACKSIZE 16384 /* words (FreeRTOS) -> 64 KB */
typedef struct func_args {
int argc;
char** argv;
int return_code;
} func_args;
/* wolfCrypt RNG seed hook (user_settings: CUSTOM_RAND_GENERATE_SEED). Uses the
* SDK's rtw_get_random_bytes (the high-level entropy API used by the SDK's own
* TLS examples); it fills from the hardware-seeded PRNG and always links in the
* non-TrustZone image. */
int amebapro2_rand_seed(unsigned char* output, unsigned int sz)
{
/* Fail closed: propagate a non-zero entropy-source error so wolfCrypt's DRBG
* seeding fails rather than using the unfilled buffer. (The SDK's FreeRTOS
* implementation returns 0 on success.) */
if (rtw_get_random_bytes(output, sz) != 0) {
return -1;
}
return 0;
}
/* benchmark time source (user_settings: WOLFSSL_USER_CURRTIME). Free-running
* microsecond system timer, returned as fractional seconds. */
double current_time(int reset)
{
(void)reset;
return (double)hal_read_systime_us() / 1000000.0;
}
/* wolfCrypt wall-clock (user_settings: XTIME). The EVB has no RTC set; return a
* fixed, plausible time so X.509 validity-period checks in wolfcrypt_test pass. */
time_t amebapro2_time(time_t* t)
{
time_t now = (time_t)1781222400; /* 2026-06-12T00:00:00Z */
if (t != NULL) {
*t = now;
}
return now;
}
static void wolf_test_thread(void* param)
{
func_args args;
(void)param;
args.argc = 0;
args.argv = NULL;
args.return_code = 0;
if (wolfCrypt_Init() != 0) {
printf("wolfCrypt_Init failed\r\n");
vTaskDelete(NULL);
return;
}
#if defined(WOLFSSL_RTL8735B_HUK)
/* Mode 3: register the HUK crypto-callback device at WC_HUK_DEVID. The
* benchmark's WC_USE_DEVID routes AES / HMAC / ECDSA through it; everything
* else falls back to software. */
if (wc_Rtl8735b_HukRegister(WC_HUK_DEVID) != 0) {
printf("wc_Rtl8735b_HukRegister failed\r\n");
wolfCrypt_Cleanup();
vTaskDelete(NULL);
return;
}
printf("\r\n=== wolfCrypt Benchmark (RTL8735B, HUK hardware) ===\r\n");
benchmark_test(&args);
printf("benchmark_test: return code %d\r\n", args.return_code);
wc_Rtl8735b_HukUnRegister(WC_HUK_DEVID);
#else
printf("\r\n=== wolfCrypt Test (RTL8735B) ===\r\n");
wolfcrypt_test(&args);
printf("wolfcrypt_test: return code %d\r\n", args.return_code);
printf("\r\n=== wolfCrypt Benchmark (RTL8735B) ===\r\n");
args.return_code = 0;
benchmark_test(&args);
printf("benchmark_test: return code %d\r\n", args.return_code);
#endif
wolfCrypt_Cleanup();
printf("\r\n=== done ===\r\n");
vTaskDelete(NULL);
}
int main(void)
{
if (xTaskCreate(wolf_test_thread, "wolf_test", STACKSIZE, NULL,
tskIDLE_PRIORITY + 1, NULL) != pdPASS) {
printf("xTaskCreate failed\r\n");
}
else {
vTaskStartScheduler(); /* only start the scheduler if the task exists */
}
while (1) {
}
}

View File

@ -0,0 +1,169 @@
/* user_settings.h -- wolfCrypt config for the AmebaPro2 (RTL8735B)
* wolfcrypt_test + wolfcrypt_benchmark app, built inside the RealTek FreeRTOS
* SDK.
*
* Three build modes select the crypto backend, chosen with -DRTL_BENCH_MODE=N
* at configure time (see wolfcrypt_test.cmake), so the same sources produce all
* three of the benchmarks documented in the port README:
*
* RTL_BENCH_MODE = 1 pure C portable big-integer + C symmetric/hash
* (no assembly): the reference baseline.
* RTL_BENCH_MODE = 2 Thumb-2 / SP Cortex-M assembly: sp_cortexm.c for the
* Cortex-M public key math + thumb2-*-asm symmetric
* and hash. (default)
* RTL_BENCH_MODE = 3 RealTek HW the HUK crypto-callback device over the
* silicon engine (hal_crypto / hal_ecdsa):
* AES, HMAC-SHA256 and ECDSA P-256
* sign/verify run in hardware. Set globally
* via WC_USE_DEVID; main.c registers the
* device. Mode 3 runs the benchmark only --
* the HUK device derives its key from the
* "key" bytes (HKDF seed), so the standard
* wolfcrypt_test known-answer vectors do not
* apply to it. */
#ifndef AMEBAPRO2_TEST_USER_SETTINGS_H
#define AMEBAPRO2_TEST_USER_SETTINGS_H
#ifdef __cplusplus
extern "C" {
#endif
#ifndef RTL_BENCH_MODE
#define RTL_BENCH_MODE 2
#endif
/* ---- platform / RTOS ---- */
#define WOLFSSL_GENERAL_ALIGNMENT 4
#define SIZEOF_LONG_LONG 8
#define SINGLE_THREADED
#define NO_FILESYSTEM
#define NO_WRITEV
#define NO_MAIN_DRIVER /* we call wolfcrypt_test/benchmark_test */
#define WOLFCRYPT_ONLY /* no TLS layer */
#define WOLFSSL_SMALL_STACK
#define WOLFSSL_IGNORE_FILE_WARN
/* ---- single-precision math backend ----
* Modes 1 and 3 use only the generic sp_int.c big-integer math (portable C, no
* per-size fast paths). Mode 2 adds the Cortex-M assembly specific paths
* (sp_cortexm.c: sp_RsaPublic_2048, sp_ecc_sign_256, ...) for RSA-2048/3072,
* ECC P-256 and DH-2048; WOLFSSL_HAVE_SP_* select those and so only apply in
* mode 2 (they need an SP-specific provider, which sp_int.c is not). */
#define WOLFSSL_SP_MATH_ALL
#define SP_WORD_SIZE 32
#if RTL_BENCH_MODE == 2
#define WOLFSSL_HAVE_SP_RSA
#define WOLFSSL_HAVE_SP_ECC
#define WOLFSSL_HAVE_SP_DH
/* Thumb-2/DSP UMAAL single-precision; sizes without an asm path fall back
* to the generic sp_int.c. */
#define WOLFSSL_SP_ARM_CORTEX_M_ASM
#endif
/* ---- Thumb-2 assembly for AES / SHA / ChaCha / Poly1305 (mode 2 only) ----
* Cortex-M33 is ARMv8-M but runs the Thumb-2 (ARMv7-style, no NEON, no ARMv8-A
* crypto extension) asm. WOLFSSL_ARMASM is a global switch, so every symmetric
* module it covers gets its thumb2-*-asm.S in the source list. */
#if RTL_BENCH_MODE == 2
#define WOLFSSL_ARMASM
#define WOLFSSL_ARMASM_THUMB2
#define WOLFSSL_ARMASM_NO_HW_CRYPTO
#define WOLFSSL_ARMASM_NO_NEON
#define WOLFSSL_ARM_ARCH 7
#endif
/* ---- mode 3: RealTek HUK crypto-callback device over the silicon engine ---- */
#if RTL_BENCH_MODE == 3
#define WOLFSSL_RTL8735B_HUK
#define WOLF_CRYPTO_CB
/* The HUK device id (the port header honors a pre-defined WC_HUK_DEVID).
* Route every benchmark op through it by default; ops the device does not
* accelerate fall back to software automatically. Defined numerically here
* to avoid pulling the port header into settings.h include order. */
#define WC_HUK_DEVID 810
#define WC_USE_DEVID WC_HUK_DEVID
#endif
/* ---- RNG / DRBG (seeded from the SDK TRNG, see main.c) ---- */
#define HAVE_HASHDRBG
#define CUSTOM_RAND_GENERATE_SEED amebapro2_rand_seed
#ifndef __ASSEMBLER__
#include <stddef.h>
int amebapro2_rand_seed(unsigned char* output, unsigned int sz);
#endif
/* ---- AES (all modes) ---- */
#define HAVE_AES_CBC
#define HAVE_AESGCM
#define GCM_TABLE_4BIT
#define HAVE_AESCCM
#define HAVE_AES_ECB
#define WOLFSSL_AES_DIRECT
#define WOLFSSL_AES_COUNTER
#define WOLFSSL_AES_128
#define WOLFSSL_AES_192
#define WOLFSSL_AES_256
#define WOLFSSL_CMAC
/* ---- ChaCha20 / Poly1305 ---- */
#define HAVE_CHACHA
#define HAVE_POLY1305
/* ---- hashing ---- */
#define WOLFSSL_SHA224
#define WOLFSSL_SHA384
#define WOLFSSL_SHA512
#define WOLFSSL_SHA3
#define HAVE_HKDF
/* ---- public key: ECC (P-256/P-384), Curve/Ed25519, RSA, DH ---- */
#define HAVE_ECC
#define ECC_USER_CURVES
#define HAVE_ECC256
#define HAVE_ECC384
#define ECC_SHAMIR
#define HAVE_ECC_SIGN
#define HAVE_ECC_VERIFY
#define HAVE_ECC_DHE
#define WOLFSSL_VALIDATE_ECC_IMPORT
#define WC_RSA_BLINDING
#define WOLFSSL_KEY_GEN /* RSA/ECC key generation tests */
#define HAVE_DH
#define HAVE_FFDHE_2048
#define WOLFSSL_DH_CONST /* avoid pow/log in DH param checks */
/* ---- ASN + in-memory test certs/keys (no filesystem) ---- */
#define USE_CERT_BUFFERS_2048
#define USE_CERT_BUFFERS_256
/* ---- benchmark: embedded sizes, no %f (ROM printf has no float) ---- */
#define BENCH_EMBEDDED
#define WOLFSSL_NO_FLOAT_FMT
#define WOLFSSL_USER_CURRTIME /* current_time() provided in main.c */
/* ---- fixed wall-clock for X.509 date validation (EVB has no RTC set) ---- */
#ifndef __ASSEMBLER__
#include <time.h>
time_t amebapro2_time(time_t* t);
#define XTIME(tl) amebapro2_time((tl))
#endif
/* ---- trims ---- */
#define NO_DES3
#define NO_RC4
#define NO_MD4
#define NO_MD5
#define NO_DSA
#define NO_PWDBASED
#define NO_PKCS12
#define NO_OLD_TLS
#define WC_NO_HARDEN
#ifdef __cplusplus
}
#endif
#endif /* AMEBAPRO2_TEST_USER_SETTINGS_H */

View File

@ -0,0 +1,102 @@
# wolfCrypt AmebaPro2 (RTL8735B) test + benchmark -- RealTek FreeRTOS SDK wiring.
#
# Install at <SDK>/component/example/wolfcrypt_test/ and select at configure:
# cmake .. -DEXAMPLE=wolfcrypt_test -DWOLFSSL_ROOT=/path/to/wolfssl \
# -DRTL_BENCH_MODE=N ...
# (also copy main.c to <SDK>/project/realtek_amebapro2_v0_example/src/main.c)
#
# RTL_BENCH_MODE selects the crypto backend (matches user_settings.h):
# 1 pure C generic sp_int.c + C symmetric/hash (baseline)
# 2 Thumb-2 / SP sp_cortexm.c + thumb2-*-asm.S (default)
# 3 RealTek HW HUK crypto-callback over the silicon engine (sp_int.c base
# + cryptocb.c + the RealTek port); benchmark only.
# Locate the wolfSSL tree: -DWOLFSSL_ROOT=..., or $WOLFSSL_ROOT, else a guess.
if(NOT DEFINED WOLFSSL_ROOT OR WOLFSSL_ROOT STREQUAL "")
if(DEFINED ENV{WOLFSSL_ROOT})
set(WOLFSSL_ROOT $ENV{WOLFSSL_ROOT})
else()
set(WOLFSSL_ROOT ${CMAKE_CURRENT_LIST_DIR}/../../../../wolfssl)
endif()
endif()
if(NOT EXISTS ${WOLFSSL_ROOT}/wolfcrypt/src/aes.c)
message(FATAL_ERROR
"WOLFSSL_ROOT='${WOLFSSL_ROOT}' is not a wolfSSL tree. "
"Pass -DWOLFSSL_ROOT=/path/to/wolfssl.")
endif()
if(NOT DEFINED RTL_BENCH_MODE OR RTL_BENCH_MODE STREQUAL "")
set(RTL_BENCH_MODE 2)
endif()
message(STATUS "wolfcrypt_test example: WOLFSSL_ROOT=${WOLFSSL_ROOT} "
"RTL_BENCH_MODE=${RTL_BENCH_MODE}")
### header search paths ###
list(APPEND app_example_inc_path
${WOLFSSL_ROOT}
${CMAKE_CURRENT_LIST_DIR} # user_settings.h
)
### compile definitions (become -D...) ###
list(APPEND app_example_flags
WOLFSSL_USER_SETTINGS
RTL_BENCH_MODE=${RTL_BENCH_MODE}
)
### source files (backend-independent) ###
list(APPEND app_example_sources
# --- symmetric ---
${WOLFSSL_ROOT}/wolfcrypt/src/aes.c
${WOLFSSL_ROOT}/wolfcrypt/src/cmac.c
${WOLFSSL_ROOT}/wolfcrypt/src/chacha.c
${WOLFSSL_ROOT}/wolfcrypt/src/chacha20_poly1305.c
${WOLFSSL_ROOT}/wolfcrypt/src/poly1305.c
# --- hashing ---
${WOLFSSL_ROOT}/wolfcrypt/src/sha.c
${WOLFSSL_ROOT}/wolfcrypt/src/sha256.c
${WOLFSSL_ROOT}/wolfcrypt/src/sha512.c
${WOLFSSL_ROOT}/wolfcrypt/src/sha3.c
${WOLFSSL_ROOT}/wolfcrypt/src/hash.c
${WOLFSSL_ROOT}/wolfcrypt/src/hmac.c
${WOLFSSL_ROOT}/wolfcrypt/src/kdf.c
# --- public key ---
${WOLFSSL_ROOT}/wolfcrypt/src/rsa.c
${WOLFSSL_ROOT}/wolfcrypt/src/dh.c
${WOLFSSL_ROOT}/wolfcrypt/src/ecc.c
# --- math (generic single-precision always present) ---
${WOLFSSL_ROOT}/wolfcrypt/src/sp_int.c
${WOLFSSL_ROOT}/wolfcrypt/src/wolfmath.c
# --- encoding / support ---
${WOLFSSL_ROOT}/wolfcrypt/src/asn.c
${WOLFSSL_ROOT}/wolfcrypt/src/coding.c
${WOLFSSL_ROOT}/wolfcrypt/src/random.c
${WOLFSSL_ROOT}/wolfcrypt/src/memory.c
${WOLFSSL_ROOT}/wolfcrypt/src/wc_port.c
${WOLFSSL_ROOT}/wolfcrypt/src/wc_encrypt.c
${WOLFSSL_ROOT}/wolfcrypt/src/error.c
${WOLFSSL_ROOT}/wolfcrypt/src/logging.c
${WOLFSSL_ROOT}/wolfcrypt/src/signature.c
# --- the test + benchmark drivers ---
${WOLFSSL_ROOT}/wolfcrypt/test/test.c
${WOLFSSL_ROOT}/wolfcrypt/benchmark/benchmark.c
)
### mode 2: Cortex-M / Thumb-2 assembly fast paths ###
if(RTL_BENCH_MODE EQUAL 2)
list(APPEND app_example_sources
${WOLFSSL_ROOT}/wolfcrypt/src/sp_cortexm.c
${WOLFSSL_ROOT}/wolfcrypt/src/port/arm/thumb2-aes-asm.S
${WOLFSSL_ROOT}/wolfcrypt/src/port/arm/thumb2-chacha-asm.S
${WOLFSSL_ROOT}/wolfcrypt/src/port/arm/thumb2-poly1305-asm.S
${WOLFSSL_ROOT}/wolfcrypt/src/port/arm/thumb2-sha256-asm.S
${WOLFSSL_ROOT}/wolfcrypt/src/port/arm/thumb2-sha512-asm.S
${WOLFSSL_ROOT}/wolfcrypt/src/port/arm/thumb2-sha3-asm.S
)
endif()
### mode 3: RealTek HUK crypto-callback device (silicon engine) ###
if(RTL_BENCH_MODE EQUAL 3)
list(APPEND app_example_sources
${WOLFSSL_ROOT}/wolfcrypt/src/cryptocb.c
${WOLFSSL_ROOT}/wolfcrypt/src/port/realtek/rtl8735b.c
)
endif()

View File

@ -0,0 +1,57 @@
# RTL8735B (AmebaPro2) HUK-in-TLS example
In-memory TLS 1.2 ECDHE-ECDSA handshake (client + server in one firmware, no
networking) where the server's certificate ECDSA P-256 signature is produced on
the RTL8735B HW ECDSA engine via the wolfCrypt HUK crypto-callback port. The
ECDHE key agreement and record-layer AES-GCM run in software. Proves
HUK/HW-accelerated server authentication in a real TLS handshake.
Validated on RTL8735B silicon:
```
== TLS 1.2 ECDHE-ECDSA (server auth on HUK) ==
[PASS] TLS handshake completed
cipher: ECDHE-ECDSA-AES128-GCM-SHA256
[PASS] client write
[PASS] server read == client msg
```
## Key design point: use a PK sign callback, NOT a whole-CTX devId
Do NOT `wolfSSL_CTX_SetDevId(ctx, WC_HUK_DEVID)` for a TLS CTX. The HUK device
treats a 32-byte HMAC/AES key as a *HUK seed* (HKDF input), but TLS legitimately
uses 32-byte keys in its own crypto -- e.g. the P-256 ECDHE pre-master secret is
32 bytes and TLS 1.2's PRF computes `master_secret = HMAC-SHA256(pre_master,...)`
with it. Routing that PRF HMAC to the HUK derives the wrong master secret ->
wrong session keys -> the peer's Finished fails (`VERIFY_MAC_ERROR`, -305).
Instead, route ONLY the server's certificate signature to the HUK with a PK ECC
sign callback (`wolfSSL_CTX_SetEccSignCb`). Inside it, sign with a temporary
`ecc_key` whose `devId = WC_HUK_DEVID`, so only that ECDSA sign dispatches to the
HW engine while the PRF/HMAC, record AES, and ECDHE stay in software. See
`huk_ecc_sign_cb` in `main.c`. Requires `HAVE_PK_CALLBACKS`.
## Build
Install this directory at `<SDK>/component/example/wolfcrypt_huk_tls/` and select
it in the RealTek AmebaPro2 FreeRTOS SDK build:
```
cmake .. -DEXAMPLE=wolfcrypt_huk_tls -DWOLFSSL_ROOT=/path/to/wolfssl ...
```
(also copy `main.c` to `<SDK>/project/realtek_amebapro2_v0_example/src/main.c`).
See the `amebapro2-flash` build/flash flow used by the sibling `wolfcrypt_huk`
example.
## Notes
- P-256 test certificates come from wolfSSL's `certs_test.h` (`USE_CERT_BUFFERS_256`:
`serv_ecc_der_256`, `ecc_key_der_256`, `ca_ecc_cert_der_256`).
- `NO_ASN_TIME` is set (the board has no RTC, so certificate date checks are
skipped) -- do not use that in production without a real time source.
- `WOLFSSL_USER_IO` + `WOLFSSL_NO_SOCK`: the transport is two in-memory buffers
via custom `SetIORecv`/`SetIOSend` callbacks; no sockets are used.
- Model shown is the general HW-offload key (a plain P-256 server key signed on
the engine). A device-bound HUK-wrapped server key is a follow-on (the sign
callback would use a `wc_Rtl8735b_EccKey` via the key's `devCtx`).

301
rtl8735b/tls/main.c 100644
View File

@ -0,0 +1,301 @@
/* wolfCrypt AmebaPro2 (RTL8735B) HUK-in-TLS example -- built inside the RealTek
* FreeRTOS SDK. Runs an in-memory TLS 1.2 ECDHE-ECDSA handshake (client + server
* in one firmware, no networking) where the server's ECDSA P-256 authentication
* routes through the HUK crypto-callback device (wolfSSL_CTX_SetDevId), i.e. the
* server signature is produced on the RTL8735B HW ECDSA engine. The ECDHE key
* agreement and record-layer AES run in software (the engine has no arbitrary
* scalar-mult path; see the port README). Proves HUK-accelerated server auth in
* a real TLS handshake.
*
* Two server-key models (RTL_TLS_KEY_MODEL):
* 1 = general HW offload: a plain P-256 server key loaded from certs_test.h;
* with devId set, its handshake ECDSA sign dispatches to the HW engine.
* 2 = device-bound HUK-wrapped key (follow-on; see README).
*
* Build: configure with -DEXAMPLE=wolfcrypt_huk_tls (see wolfcrypt_huk_tls.cmake).
*/
#include <string.h>
#include "platform_stdlib.h"
#include "FreeRTOS.h"
#include "task.h"
#include "device_lock.h"
#include "hal_trng_sec.h"
#include <wolfssl/wolfcrypt/settings.h>
#include <wolfssl/ssl.h>
#include <wolfssl/certs_test.h>
#include <wolfssl/wolfcrypt/port/realtek/rtl8735b.h>
#ifndef RTL_TLS_KEY_MODEL
#define RTL_TLS_KEY_MODEL 1
#endif
#define STACKSIZE (16 * 1024)
#define BUFFER_SIZE 2048
#define CHECK(label, cond) \
dbg_printf("[%s] %s\r\n", (cond) ? "PASS" : "FAIL", (label))
/* wolfCrypt RNG seed hook (user_settings: CUSTOM_RAND_GENERATE_SEED), from the
* AmebaPro2 secure hardware TRNG. */
int rtl8735b_rand_seed(unsigned char* output, unsigned int sz)
{
static int inited = 0;
unsigned int i, n;
u32 r;
if (inited == 0) {
if (hal_trng_sec_init() != 0) {
return -1;
}
inited = 1;
}
for (i = 0; i < sz; ) {
r = hal_trng_sec_get_rand();
n = (sz - i) < 4u ? (sz - i) : 4u;
memcpy(output + i, &r, n);
i += n;
}
return 0;
}
/* In-memory transport: two shared buffers with WANT_READ/WANT_WRITE semantics.
* client -> server via server_buffer; server -> client via client_buffer. */
static unsigned char client_buffer[BUFFER_SIZE];
static int client_buffer_sz = 0;
static unsigned char server_buffer[BUFFER_SIZE];
static int server_buffer_sz = 0;
static int recv_client(WOLFSSL* ssl, char* buff, int sz, void* ctx)
{
(void)ssl; (void)ctx;
if (client_buffer_sz > 0) {
if (sz > client_buffer_sz) {
sz = client_buffer_sz;
}
memcpy(buff, client_buffer, sz);
if (sz < client_buffer_sz) {
memmove(client_buffer, client_buffer + sz, client_buffer_sz - sz);
}
client_buffer_sz -= sz;
return sz;
}
return WOLFSSL_CBIO_ERR_WANT_READ;
}
static int send_client(WOLFSSL* ssl, char* buff, int sz, void* ctx)
{
(void)ssl; (void)ctx;
if (server_buffer_sz < BUFFER_SIZE) {
if (sz > BUFFER_SIZE - server_buffer_sz) {
sz = BUFFER_SIZE - server_buffer_sz;
}
memcpy(server_buffer + server_buffer_sz, buff, sz);
server_buffer_sz += sz;
return sz;
}
return WOLFSSL_CBIO_ERR_WANT_WRITE;
}
static int recv_server(WOLFSSL* ssl, char* buff, int sz, void* ctx)
{
(void)ssl; (void)ctx;
if (server_buffer_sz > 0) {
if (sz > server_buffer_sz) {
sz = server_buffer_sz;
}
memcpy(buff, server_buffer, sz);
if (sz < server_buffer_sz) {
memmove(server_buffer, server_buffer + sz, server_buffer_sz - sz);
}
server_buffer_sz -= sz;
return sz;
}
return WOLFSSL_CBIO_ERR_WANT_READ;
}
static int send_server(WOLFSSL* ssl, char* buff, int sz, void* ctx)
{
(void)ssl; (void)ctx;
if (client_buffer_sz < BUFFER_SIZE) {
if (sz > BUFFER_SIZE - client_buffer_sz) {
sz = BUFFER_SIZE - client_buffer_sz;
}
memcpy(client_buffer + client_buffer_sz, buff, sz);
client_buffer_sz += sz;
return sz;
}
return WOLFSSL_CBIO_ERR_WANT_WRITE;
}
/* RNG for the ECDSA sign callback (the PK callback passes no rng). */
static WC_RNG g_signRng;
/* ECC sign PK callback: route ONLY the server's cert signature to the HUK HW
* ECDSA engine. A temp ecc_key with devId=WC_HUK_DEVID makes wc_ecc_sign_hash
* dispatch to the port's general HW offload (signs with the key's own scalar);
* the rest of TLS (PRF/HMAC, record AES, ECDHE) stays in software. */
static int huk_ecc_sign_cb(WOLFSSL* ssl, const byte* in, word32 inSz,
byte* out, word32* outSz, const byte* keyDer, word32 keySz, void* ctx)
{
ecc_key key;
word32 idx = 0;
int ret;
(void)ssl; (void)ctx;
ret = wc_ecc_init_ex(&key, NULL, WC_HUK_DEVID);
if (ret == 0) {
ret = wc_EccPrivateKeyDecode(keyDer, &idx, &key, keySz);
if (ret == 0) {
ret = wc_ecc_sign_hash(in, inSz, out, outSz, &g_signRng, &key);
}
wc_ecc_free(&key);
}
return ret;
}
static void huk_tls_test(void)
{
WOLFSSL_CTX* cctx = NULL;
WOLFSSL_CTX* sctx = NULL;
WOLFSSL* cssl = NULL;
WOLFSSL* sssl = NULL;
const char msg[] = "hello from HUK TLS client";
char rx[64];
int cdone = 0, sdone = 0;
int i, ret;
dbg_printf("\r\n== TLS 1.2 ECDHE-ECDSA (server auth on HUK) ==\r\n");
sctx = wolfSSL_CTX_new(wolfTLSv1_2_server_method());
cctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method());
CHECK("CTX_new (client+server)", sctx != NULL && cctx != NULL);
if (sctx == NULL || cctx == NULL) {
goto cleanup;
}
/* RNG for the sign callback's nonce. */
ret = wc_InitRng(&g_signRng);
CHECK("sign-callback RNG init", ret == 0);
/* Route ONLY the server's cert ECDSA sign to the HUK HW engine (PK callback);
* TLS's own HMAC/PRF, record AES and ECDHE stay in software. */
wolfSSL_CTX_SetEccSignCb(sctx, huk_ecc_sign_cb);
/* Restrict to ECDHE-ECDSA + AES-GCM so server auth uses ECDSA (HUK). */
wolfSSL_CTX_set_cipher_list(sctx, "ECDHE-ECDSA-AES128-GCM-SHA256");
wolfSSL_CTX_set_cipher_list(cctx, "ECDHE-ECDSA-AES128-GCM-SHA256");
/* Server: P-256 cert + key (model 1: general HW offload). */
ret = wolfSSL_CTX_use_certificate_buffer(sctx, serv_ecc_der_256,
sizeof_serv_ecc_der_256, WOLFSSL_FILETYPE_ASN1);
CHECK("server use_certificate", ret == WOLFSSL_SUCCESS);
ret = wolfSSL_CTX_use_PrivateKey_buffer(sctx, ecc_key_der_256,
sizeof_ecc_key_der_256, WOLFSSL_FILETYPE_ASN1);
CHECK("server use_PrivateKey", ret == WOLFSSL_SUCCESS);
/* Client: trust the CA that signed the server cert. */
ret = wolfSSL_CTX_load_verify_buffer(cctx, ca_ecc_cert_der_256,
sizeof_ca_ecc_cert_der_256, WOLFSSL_FILETYPE_ASN1);
if (ret != WOLFSSL_SUCCESS) {
dbg_printf("load_verify ret=%d\r\n", ret);
}
CHECK("client load_verify (CA)", ret == WOLFSSL_SUCCESS);
wolfSSL_SetIORecv(sctx, recv_server);
wolfSSL_SetIOSend(sctx, send_server);
wolfSSL_SetIORecv(cctx, recv_client);
wolfSSL_SetIOSend(cctx, send_client);
sssl = wolfSSL_new(sctx);
cssl = wolfSSL_new(cctx);
CHECK("wolfSSL_new (client+server)", sssl != NULL && cssl != NULL);
if (sssl == NULL || cssl == NULL) {
goto cleanup;
}
/* Drive the handshake: interleave connect/accept until both complete. */
for (i = 0; i < 20 && (cdone == 0 || sdone == 0); i++) {
if (cdone == 0) {
ret = wolfSSL_connect(cssl);
if (ret == WOLFSSL_SUCCESS) {
cdone = 1;
}
else if (wolfSSL_get_error(cssl, ret) != WOLFSSL_ERROR_WANT_READ &&
wolfSSL_get_error(cssl, ret) != WOLFSSL_ERROR_WANT_WRITE) {
dbg_printf("client err %d\r\n", wolfSSL_get_error(cssl, ret));
break;
}
}
if (sdone == 0) {
ret = wolfSSL_accept(sssl);
if (ret == WOLFSSL_SUCCESS) {
sdone = 1;
}
else if (wolfSSL_get_error(sssl, ret) != WOLFSSL_ERROR_WANT_READ &&
wolfSSL_get_error(sssl, ret) != WOLFSSL_ERROR_WANT_WRITE) {
dbg_printf("server err %d\r\n", wolfSSL_get_error(sssl, ret));
break;
}
}
}
CHECK("TLS handshake completed", cdone == 1 && sdone == 1);
if (cdone == 1 && sdone == 1) {
dbg_printf("cipher: %s\r\n", wolfSSL_get_cipher(sssl));
/* Exchange one application record client -> server. */
ret = wolfSSL_write(cssl, msg, (int)sizeof(msg));
CHECK("client write", ret == (int)sizeof(msg));
memset(rx, 0, sizeof(rx));
ret = wolfSSL_read(sssl, rx, sizeof(rx) - 1);
CHECK("server read == client msg",
ret == (int)sizeof(msg) && memcmp(rx, msg, sizeof(msg)) == 0);
}
cleanup:
if (cssl != NULL) wolfSSL_free(cssl);
if (sssl != NULL) wolfSSL_free(sssl);
if (cctx != NULL) wolfSSL_CTX_free(cctx);
if (sctx != NULL) wolfSSL_CTX_free(sctx);
wc_FreeRng(&g_signRng);
}
static void wolf_tls_thread(void* param)
{
int ret;
(void)param;
dbg_printf("\r\n=== wolfCrypt AmebaPro2 (RTL8735B) HUK-in-TLS example ===\r\n");
device_mutex_lock(RT_DEV_LOCK_CRYPTO);
ret = wolfSSL_Init();
CHECK("wolfSSL_Init", ret == WOLFSSL_SUCCESS);
if (ret == WOLFSSL_SUCCESS) {
ret = wc_Rtl8735b_HukRegister(WC_HUK_DEVID);
CHECK("wc_Rtl8735b_HukRegister", ret == 0);
}
if (ret == 0) {
huk_tls_test();
wc_Rtl8735b_HukUnRegister(WC_HUK_DEVID);
}
wolfSSL_Cleanup();
device_mutex_unlock(RT_DEV_LOCK_CRYPTO);
dbg_printf("\r\n=== done ===\r\n");
vTaskDelete(NULL);
}
int main(void)
{
if (xTaskCreate(wolf_tls_thread, "wolf_tls", STACKSIZE, NULL,
tskIDLE_PRIORITY + 1, NULL) != pdPASS) {
dbg_printf("xTaskCreate failed\r\n");
}
else {
vTaskStartScheduler();
}
while (1) {
}
}

View File

@ -0,0 +1,101 @@
/* user_settings.h -- wolfSSL config for the AmebaPro2 (RTL8735B) HUK-in-TLS
* example (RealTek FreeRTOS SDK). In-memory TLS 1.2 ECDHE-ECDSA handshake with
* the server's ECDSA P-256 auth routed to the HUK crypto-callback device. */
#ifndef RTL8735B_HUK_TLS_USER_SETTINGS_H
#define RTL8735B_HUK_TLS_USER_SETTINGS_H
#ifdef __cplusplus
extern "C" {
#endif
/* ---- HUK crypto-callback device (our RealTek port) ---- */
#define WOLFSSL_RTL8735B_HUK
#define WOLF_CRYPTO_CB
#define WOLF_CRYPTO_CB_COPY /* HUK HMAC buffer copy/free ops */
#define WOLF_CRYPTO_CB_FREE
/* ---- platform / RTOS ---- */
#define WOLFSSL_GENERAL_ALIGNMENT 4
#define SIZEOF_LONG_LONG 8
#define SINGLE_THREADED /* HW crypto serialized by the SDK device_lock */
#define NO_FILESYSTEM
#define NO_WRITEV
#define NO_MAIN_DRIVER
#define WOLFSSL_USER_IO /* custom SetIORecv/Send; no sockets/netinet */
#define WOLFSSL_NO_SOCK /* no built-in socket headers (bare metal) */
#define WOLFSSL_SMALL_STACK
#define WOLFSSL_IGNORE_FILE_WARN
#define NO_ERROR_STRINGS
/* ---- TLS layer: TLS 1.2 only, ECDHE-ECDSA-AES-GCM ---- */
#define NO_OLD_TLS /* TLS 1.2+ only (no SSLv3/TLS1.0/1.1) */
#define WOLFSSL_TLS13 /* harmless; harness uses TLSv1_2 methods */
#define HAVE_TLS_EXTENSIONS
#define HAVE_SUPPORTED_CURVES /* ECDHE curve negotiation */
#define HAVE_EXTENDED_MASTER
#define HAVE_ENCRYPT_THEN_MAC
#define HAVE_HKDF /* TLS 1.3 key schedule (kdf.c) */
#define WOLFSSL_NO_TLS12_RENEGOTIATION
#define NO_SESSION_CACHE /* save RAM (no resumption cache) */
#define WOLFSSL_AEAD_ONLY /* AES-GCM suites only (no CBC-HMAC) */
#define HAVE_PK_CALLBACKS /* route ONLY the server ECDSA sign to the HUK
* (whole-CTX devId would send TLS's own 32-byte
* HMAC/PRF + record AES to the HUK too, whose
* key==HUK-seed semantics break TLS) */
/* ---- test certificate buffers (serv_ecc/ecc_key/ca_ecc, P-256) ---- */
#define USE_CERT_BUFFERS_256
#define NO_ASN_TIME /* no RTC on the board -> skip cert date checks */
/* ---- AES modes: GCM for TLS records; ECB/CBC/CTR for the HUK device ---- */
#define HAVE_AESGCM
#define WOLFSSL_AES_DIRECT
#define HAVE_AES_ECB
#define HAVE_AES_CBC
#define WOLFSSL_AES_COUNTER
#define WOLFSSL_AES_256
#define WOLFSSL_AES_128
#define GCM_TABLE_4BIT
/* ---- hashing + DRBG ---- */
#undef NO_SHA256
#define WOLFSSL_SHA256
#define WOLFSSL_SHA384 /* some TLS sigalg/PRF paths */
#define HAVE_HASHDRBG
/* ---- ECC / ECDSA / ECDHE (P-256) ---- */
#define HAVE_ECC
#define HAVE_ECC_SIGN
#define HAVE_ECC_VERIFY
#define HAVE_ECC_DHE /* ECDHE key agreement (software) */
#define ECC_USER_CURVES
#define HAVE_ECC256 /* P-256 only */
#define ECC_TIMING_RESISTANT
#define WOLFSSL_SP_MATH_ALL
#define HAVE_SUPPORTED_CURVES
/* ---- trims ---- */
#define NO_RSA
#define NO_DSA
#define NO_DH
#define NO_DES3
#define NO_RC4
#define NO_MD4
#define NO_MD5
#define NO_PWDBASED
#define NO_PKCS12
#define NO_PKCS8
/* ---- custom RNG seed hook (provided in main.c via the SDK TRNG) ---- */
#define CUSTOM_RAND_GENERATE_SEED rtl8735b_rand_seed
#ifndef __ASSEMBLER__
#include <stddef.h>
int rtl8735b_rand_seed(unsigned char* output, unsigned int sz);
#endif
#ifdef __cplusplus
}
#endif
#endif /* RTL8735B_HUK_TLS_USER_SETTINGS_H */

View File

@ -0,0 +1,73 @@
# wolfCrypt AmebaPro2 (RTL8735B) HUK-in-TLS example -- RealTek FreeRTOS SDK wiring.
#
# Install at <SDK>/component/example/wolfcrypt_huk_tls/ and select with:
# cmake .. -DEXAMPLE=wolfcrypt_huk_tls -DWOLFSSL_ROOT=/path/to/wolfssl ...
# (also copy main.c to <SDK>/project/realtek_amebapro2_v0_example/src/main.c)
#
# Adds the wolfCrypt sources + the wolfSSL TLS layer + the RealTek HUK port,
# this example's include path, and -DWOLFSSL_USER_SETTINGS to the SDK app build.
if(NOT DEFINED WOLFSSL_ROOT OR WOLFSSL_ROOT STREQUAL "")
if(DEFINED ENV{WOLFSSL_ROOT})
set(WOLFSSL_ROOT $ENV{WOLFSSL_ROOT})
else()
set(WOLFSSL_ROOT ${CMAKE_CURRENT_LIST_DIR}/../../../../wolfssl)
endif()
endif()
if(NOT EXISTS "${WOLFSSL_ROOT}/wolfcrypt/src/aes.c")
message(FATAL_ERROR
"WOLFSSL_ROOT='${WOLFSSL_ROOT}' is not a wolfSSL tree. "
"Pass -DWOLFSSL_ROOT=/path/to/wolfssl.")
endif()
message(STATUS "wolfCrypt HUK-TLS example: WOLFSSL_ROOT=${WOLFSSL_ROOT}")
### header search paths ###
list(APPEND app_example_inc_path
${WOLFSSL_ROOT}
${CMAKE_CURRENT_LIST_DIR} # user_settings.h
)
### compile definitions (become -D...) ###
list(APPEND app_example_flags
WOLFSSL_USER_SETTINGS
)
### source files ###
list(APPEND app_example_sources
# --- wolfCrypt ---
${WOLFSSL_ROOT}/wolfcrypt/src/aes.c
${WOLFSSL_ROOT}/wolfcrypt/src/sha256.c
${WOLFSSL_ROOT}/wolfcrypt/src/sha512.c # SHA-384/512
${WOLFSSL_ROOT}/wolfcrypt/src/sha.c # SHA-1 (TLS sigalg paths)
${WOLFSSL_ROOT}/wolfcrypt/src/hash.c
${WOLFSSL_ROOT}/wolfcrypt/src/hmac.c
${WOLFSSL_ROOT}/wolfcrypt/src/kdf.c # TLS PRF / HKDF
${WOLFSSL_ROOT}/wolfcrypt/src/random.c
${WOLFSSL_ROOT}/wolfcrypt/src/memory.c
${WOLFSSL_ROOT}/wolfcrypt/src/wc_port.c
${WOLFSSL_ROOT}/wolfcrypt/src/cryptocb.c
${WOLFSSL_ROOT}/wolfcrypt/src/error.c
${WOLFSSL_ROOT}/wolfcrypt/src/logging.c
${WOLFSSL_ROOT}/wolfcrypt/src/wc_encrypt.c
${WOLFSSL_ROOT}/wolfcrypt/src/ecc.c
${WOLFSSL_ROOT}/wolfcrypt/src/asn.c
${WOLFSSL_ROOT}/wolfcrypt/src/coding.c
${WOLFSSL_ROOT}/wolfcrypt/src/sp_int.c
${WOLFSSL_ROOT}/wolfcrypt/src/wolfmath.c
${WOLFSSL_ROOT}/wolfcrypt/src/port/realtek/rtl8735b.c
# --- wolfSSL TLS layer ---
${WOLFSSL_ROOT}/src/internal.c
${WOLFSSL_ROOT}/src/keys.c
${WOLFSSL_ROOT}/src/tls.c
${WOLFSSL_ROOT}/src/tls13.c
${WOLFSSL_ROOT}/src/wolfio.c
${WOLFSSL_ROOT}/src/ssl.c
${WOLFSSL_ROOT}/src/ssl_load.c
${WOLFSSL_ROOT}/src/ssl_certman.c
${WOLFSSL_ROOT}/src/ssl_misc.c
${WOLFSSL_ROOT}/src/ssl_sess.c
${WOLFSSL_ROOT}/src/ssl_asn1.c
${WOLFSSL_ROOT}/src/ssl_crypto.c
${WOLFSSL_ROOT}/src/x509.c
${WOLFSSL_ROOT}/src/x509_str.c
)

View File

@ -0,0 +1,81 @@
/* user_settings.h -- wolfCrypt config for the AmebaPro2 (RTL8735B) HUK example
* built inside the RealTek FreeRTOS SDK. HUK crypto-callback demo: AES
* (GCM/ECB/CBC/CTR), HMAC-SHA256, and ECDSA P-256. */
#ifndef RTL8735B_HUK_USER_SETTINGS_H
#define RTL8735B_HUK_USER_SETTINGS_H
#ifdef __cplusplus
extern "C" {
#endif
/* ---- HUK crypto-callback device (our RealTek port) ---- */
#define WOLFSSL_RTL8735B_HUK
#define WOLF_CRYPTO_CB
#define WOLF_CRYPTO_CB_COPY /* HUK HMAC buffer copy/free ops */
#define WOLF_CRYPTO_CB_FREE
/* ---- platform / RTOS ---- */
#define WOLFSSL_GENERAL_ALIGNMENT 4
#define SIZEOF_LONG_LONG 8
#define SINGLE_THREADED /* HW crypto serialized by the SDK device_lock */
#define NO_FILESYSTEM
#define NO_WRITEV
#define NO_MAIN_DRIVER
#define WOLFCRYPT_ONLY /* no TLS layer */
#define WOLFSSL_SMALL_STACK
#define WOLFSSL_IGNORE_FILE_WARN
#define NO_ERROR_STRINGS
/* ---- AES modes exercised by the HUK device ---- */
#define HAVE_AESGCM
#define WOLFSSL_AES_DIRECT
#define HAVE_AES_ECB
#define HAVE_AES_CBC
#define WOLFSSL_AES_COUNTER
#define WOLFSSL_AES_256
#define WOLFSSL_AES_128
#define GCM_TABLE_4BIT
/* ---- hashing + DRBG (seeded from the SDK TRNG, see main.c) ---- */
#undef NO_SHA256
#define WOLFSSL_SHA256
#define HAVE_HASHDRBG
/* HMAC-SHA256 is enabled by default (no NO_HMAC) for the HUK HMAC demo. */
/* ---- ECC / ECDSA P-256 (HUK-bound sign demo) ---- */
#define HAVE_ECC
#define HAVE_ECC_SIGN
#define HAVE_ECC_VERIFY
#define ECC_USER_CURVES /* limit curve tables to those enabled below */
#define HAVE_ECC256 /* P-256 only */
#define ECC_TIMING_RESISTANT
#define WOLFSSL_SP_MATH_ALL /* generic SP big-integer math backend (ECC) */
/* ---- trims ---- */
#define NO_RSA
#define NO_DSA
#define NO_DH
#define NO_DES3
#define NO_RC4
#define NO_MD4
#define NO_MD5
#define NO_SHA
#define NO_PWDBASED
#define NO_PKCS12
#define NO_PKCS8
#define NO_CERTS
#define NO_OLD_TLS
/* ---- custom RNG seed hook (provided in main.c via the SDK TRNG) ---- */
#define CUSTOM_RAND_GENERATE_SEED rtl8735b_rand_seed
#ifndef __ASSEMBLER__
#include <stddef.h>
int rtl8735b_rand_seed(unsigned char* output, unsigned int sz);
#endif
#ifdef __cplusplus
}
#endif
#endif /* RTL8735B_HUK_USER_SETTINGS_H */

View File

@ -0,0 +1,57 @@
# wolfCrypt AmebaPro2 (RTL8735B) HUK example -- RealTek FreeRTOS SDK wiring.
#
# Install this directory at <SDK>/component/example/wolfcrypt_huk/ and select it
# at configure time:
# cmake .. -DEXAMPLE=wolfcrypt_huk -DWOLFSSL_ROOT=/path/to/wolfssl ...
# (also copy main.c to <SDK>/project/realtek_amebapro2_v0_example/src/main.c)
#
# Adds the wolfCrypt sources + the RealTek HUK crypto-callback port + this
# example's include path and -DWOLFSSL_USER_SETTINGS to the SDK app build.
# Locate the wolfSSL tree: -DWOLFSSL_ROOT=..., or $WOLFSSL_ROOT, else a guess.
if(NOT DEFINED WOLFSSL_ROOT OR WOLFSSL_ROOT STREQUAL "")
if(DEFINED ENV{WOLFSSL_ROOT})
set(WOLFSSL_ROOT $ENV{WOLFSSL_ROOT})
else()
set(WOLFSSL_ROOT ${CMAKE_CURRENT_LIST_DIR}/../../../../wolfssl)
endif()
endif()
if(NOT EXISTS "${WOLFSSL_ROOT}/wolfcrypt/src/aes.c")
message(FATAL_ERROR
"WOLFSSL_ROOT='${WOLFSSL_ROOT}' is not a wolfSSL tree. "
"Pass -DWOLFSSL_ROOT=/path/to/wolfssl.")
endif()
message(STATUS "wolfCrypt HUK example: WOLFSSL_ROOT=${WOLFSSL_ROOT}")
### header search paths ###
list(APPEND app_example_inc_path
${WOLFSSL_ROOT}
${CMAKE_CURRENT_LIST_DIR} # user_settings.h
)
### compile definitions (become -D...) ###
list(APPEND app_example_flags
WOLFSSL_USER_SETTINGS
)
### source files ###
list(APPEND app_example_sources
${WOLFSSL_ROOT}/wolfcrypt/src/aes.c
${WOLFSSL_ROOT}/wolfcrypt/src/sha256.c
${WOLFSSL_ROOT}/wolfcrypt/src/hash.c
${WOLFSSL_ROOT}/wolfcrypt/src/hmac.c
${WOLFSSL_ROOT}/wolfcrypt/src/random.c
${WOLFSSL_ROOT}/wolfcrypt/src/memory.c
${WOLFSSL_ROOT}/wolfcrypt/src/wc_port.c
${WOLFSSL_ROOT}/wolfcrypt/src/cryptocb.c
${WOLFSSL_ROOT}/wolfcrypt/src/error.c
${WOLFSSL_ROOT}/wolfcrypt/src/logging.c
${WOLFSSL_ROOT}/wolfcrypt/src/wc_encrypt.c
${WOLFSSL_ROOT}/wolfcrypt/src/port/realtek/rtl8735b.c
# ECC / ECDSA P-256 (HUK sign demo) + its ASN.1 + SP big-integer math
${WOLFSSL_ROOT}/wolfcrypt/src/ecc.c
${WOLFSSL_ROOT}/wolfcrypt/src/asn.c
${WOLFSSL_ROOT}/wolfcrypt/src/coding.c
${WOLFSSL_ROOT}/wolfcrypt/src/sp_int.c
${WOLFSSL_ROOT}/wolfcrypt/src/wolfmath.c
)