diff --git a/rtl8735b/README.md b/rtl8735b/README.md new file mode 100644 index 00000000..69999e0b --- /dev/null +++ b/rtl8735b/README.md @@ -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 /component/example/wolfcrypt_huk` +2. Install the example `main()` as the project app: + `cp /component/example/wolfcrypt_huk/main.c /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-10.3.0/linux/newlib/bin:$PATH + cd /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= + 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 -f /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. diff --git a/rtl8735b/main.c b/rtl8735b/main.c new file mode 100644 index 00000000..ef4a358d --- /dev/null +++ b/rtl8735b/main.c @@ -0,0 +1,605 @@ +/* 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 + +#include "platform_stdlib.h" +#include "FreeRTOS.h" +#include "task.h" +#include "device_lock.h" +#include "hal_trng_sec.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +/* 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 +#else + #define WOLFSSL_MISC_INCLUDED + #include +#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 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: ECB-encrypt with the HUK device + seed. */ + ret = wc_AesInit(&aes, NULL, WC_HUK_DEVID); + if (ret == 0) { + ret = wc_AesSetKey(&aes, seed, sizeof(seed), NULL, AES_ENCRYPTION); + } + if (ret == 0) { + ret = wc_AesEcbEncrypt(&aes, wrapped, d, sizeof(d)); + } + wc_AesFree(&aes); + CHECK("wrap scalar under HUK (ECB)", ret == 0); + if (ret != 0) { + goto cleanup; + } + + /* Sign via the HUK-bound key (unwraps under the HUK, then signs). */ + memset(&hk, 0, sizeof(hk)); + hk.seed = seed; hk.seedSz = sizeof(seed); + hk.wrapped = wrapped; hk.wrappedLen = sizeof(wrapped); + hk.plainLen = 32; + /* 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) { + } +} diff --git a/rtl8735b/test/README.md b/rtl8735b/test/README.md new file mode 100644 index 00000000..5efcf79b --- /dev/null +++ b/rtl8735b/test/README.md @@ -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 /component/example/wolfcrypt_test` +2. Install the example `main()` as the project app: + `cp /component/example/wolfcrypt_test/main.c /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-10.3.0/linux/newlib/bin:$PATH + cd /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= + 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`. diff --git a/rtl8735b/test/main.c b/rtl8735b/test/main.c new file mode 100644 index 00000000..dbfe7593 --- /dev/null +++ b/rtl8735b/test/main.c @@ -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 +#include +#include +#include +#include +#if defined(WOLFSSL_RTL8735B_HUK) + #include +#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) { + } +} diff --git a/rtl8735b/test/user_settings.h b/rtl8735b/test/user_settings.h new file mode 100644 index 00000000..3fb8b2cb --- /dev/null +++ b/rtl8735b/test/user_settings.h @@ -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 + 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_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 */ diff --git a/rtl8735b/test/wolfcrypt_test.cmake b/rtl8735b/test/wolfcrypt_test.cmake new file mode 100644 index 00000000..bea69002 --- /dev/null +++ b/rtl8735b/test/wolfcrypt_test.cmake @@ -0,0 +1,102 @@ +# wolfCrypt AmebaPro2 (RTL8735B) test + benchmark -- RealTek FreeRTOS SDK wiring. +# +# Install at /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 /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() diff --git a/rtl8735b/user_settings.h b/rtl8735b/user_settings.h new file mode 100644 index 00000000..2944e71f --- /dev/null +++ b/rtl8735b/user_settings.h @@ -0,0 +1,79 @@ +/* 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 + +/* ---- 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 + int rtl8735b_rand_seed(unsigned char* output, unsigned int sz); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* RTL8735B_HUK_USER_SETTINGS_H */ diff --git a/rtl8735b/wolfcrypt_huk.cmake b/rtl8735b/wolfcrypt_huk.cmake new file mode 100644 index 00000000..02f47032 --- /dev/null +++ b/rtl8735b/wolfcrypt_huk.cmake @@ -0,0 +1,57 @@ +# wolfCrypt AmebaPro2 (RTL8735B) HUK example -- RealTek FreeRTOS SDK wiring. +# +# Install this directory at /component/example/wolfcrypt_huk/ and select it +# at configure time: +# cmake .. -DEXAMPLE=wolfcrypt_huk -DWOLFSSL_ROOT=/path/to/wolfssl ... +# (also copy main.c to /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 +)