diff --git a/embedded/efr32xg25/.gitignore b/embedded/efr32xg25/.gitignore new file mode 100644 index 000000000..5be089821 --- /dev/null +++ b/embedded/efr32xg25/.gitignore @@ -0,0 +1,3 @@ +# slc generate output +build/ +.wolfcrypt_test.local.slcp diff --git a/embedded/efr32xg25/README.md b/embedded/efr32xg25/README.md new file mode 100644 index 000000000..7a0d54427 --- /dev/null +++ b/embedded/efr32xg25/README.md @@ -0,0 +1,194 @@ +# wolfCrypt test and benchmark on EFR32xG25 + +Runs the wolfCrypt algorithm self-test and benchmark on an EFR32xG25 with crypto routed to the Secure Element through the wolfSSL crypto callback port. Builds headlessly with `slc-cli` and GNU Arm - no Simplicity Studio GUI needed. + +For the port itself, including which algorithms are offloaded and the Secure Vault key management API, see [wolfcrypt/src/port/silabs/README.md](https://github.com/wolfSSL/wolfssl/blob/master/wolfcrypt/src/port/silabs/README.md) in the wolfSSL repository. + +## wolfSSL source + +This project compiles the wolfSSL sources directly - there is no prebuilt library. `build.sh` expects a wolfSSL checkout beside `wolfssl-examples`: + +``` +GitHub/ + wolfssl/ + wolfssl-examples/embedded/efr32xg25/ +``` + +Point `WOLFSSL_ROOT` somewhere else if yours does not sit there: + +```sh +WOLFSSL_ROOT=/path/to/wolfssl ./build.sh +``` + +The Secure Element crypto callback port arrived in wolfSSL [PR 11267](https://github.com/wolfSSL/wolfssl/pull/11267); until that is in a release, use a checkout that contains it. + +## Hardware + +An xG25 radio board (BRD4270B, BRD4271A or BRD4272A) on a BRD4002A/BRD4001A mainboard. All three radio boards carry `EFR32FG25B222F1920IM56`: Series 2 Config 5, Secure Vault **High**, 1920 KB flash. Set `BOARD` if yours is not the default BRD4270B: + +```sh +BOARD=brd4271a ./build.sh +``` + +The application prints the SE firmware version and the detected Secure Vault level at startup, so a captured log records which silicon produced the numbers under it. + +## Toolchain + +Install headlessly with Silicon Labs Tool (SLT). As of SLC-CLI v6 the CLI is no longer a direct download; SLT fetches it along with the SDK, GNU Arm and Commander from a recipe: + +```sh +mkdir -p ~/silabs && cd ~/silabs +wget -O slt-cli.zip \ + "https://www.silabs.com/documents/public/software/slt-cli-1.2.1-linux-x64.zip" +unzip -o slt-cli.zip && chmod +x slt +cat > pkg.slt <<'RECIPE' +[dependency] +simplicity-sdk = "~" +slc-cli = "~" +gcc-arm-none-eabi = "~" +commander = "~" +RECIPE +./slt install +``` + +Check the current SLT version on the [command line development page](https://www.silabs.com/software-and-tools/simplicity-studio/configurator-command-line-development). `build.sh` and `flash.sh` read `~/.silabs/sdks.json` and `~/.silabs/tools.json` to locate everything, so no paths are hardcoded. Override `SDK`, `SLC`, `GCC_DIR`, `JAVA_DIR` or `COMMANDER` in the environment if your install lives elsewhere; the scripts say so by name if a registry is missing or a tool was never installed. + +Developed against Simplicity SDK 2026.6.1 (platform 6.0.0), slc-cli 6.0.23, Commander 1.24.3, GNU Arm 14.2.rel1. + +## Build and flash + +```sh +./build.sh # slc generate + make, output in ./build +./flash.sh # commander device info, flash, reset +``` + +Then read the VCOM output at 115200 8N1. On a bench running the `uart-monitor` daemon, tail its log rather than opening the port directly. + +## What to expect + +`wolfcrypt_test` must report a full PASS. Because `WOLFSSL_SILABS_CRYPTOCB` points `WC_USE_DEVID` at the SE device, every algorithm the port claims runs on the Secure Element, so a PASS is direct evidence the callback is correct against the known-answer vectors. + +The benchmark then runs each algorithm twice, labelling rows `HW` and `SW`, which gives a hardware-versus-software comparison in one run. + +## Measured results + +Captured on an **EFR32FG25B222F1920IM56** (Secure Vault High, SE firmware 2.2.0) with this project, wolfSSL 5.9.2. `wolfcrypt_test` reports a **full PASS** in both builds below; the software/Secure Element pairs are the `HW` and `SW` rows the benchmark prints in one run. + +Both builds define the `--enable-harden` options (`ECC_TIMING_RESISTANT`, `WC_RSA_BLINDING`), so these are hardened numbers. They cost nothing measurable here: this configuration routes P-256 through `WOLFSSL_SP_MATH_ALL`/`WOLFSSL_HAVE_SP_ECC`, which is already constant time, and every ECC and RSA row moved by less than 0.3% when the options were added. + +The two software columns are two builds of this project. **Software (C)** is what you get out of the box. **Software (Thumb2 asm)** additionally enables the `WOLFSSL_ARMASM` block near the top of `user_settings.h` -- flip its `#if 0` to `#if 1` to reproduce it. Both builds already use `WOLFSSL_SP_ARM_CORTEX_M_ASM` for ECC, so the ECC rows do not move. + +| Algorithm | Software (C) | Software (Thumb2 asm) | Secure Element | SE vs C | SE vs asm | +|---|---|---|---|---|---| +| RNG SHA-256 DRBG | 281 KiB/s | 408 KiB/s | **89 KiB/s** | **0.3x** | **0.2x** | +| AES-128-CBC-enc | 856 KiB/s | 986 KiB/s | **2.63 MiB/s** | **3.2x** | **2.7x** | +| AES-128-CBC-dec | 854 KiB/s | 985 KiB/s | **2.65 MiB/s** | **3.2x** | **2.8x** | +| AES-192-CBC-enc | 722 KiB/s | 826 KiB/s | **2.60 MiB/s** | **3.7x** | **3.2x** | +| AES-192-CBC-dec | 722 KiB/s | 820 KiB/s | **2.59 MiB/s** | **3.7x** | **3.2x** | +| AES-256-CBC-enc | 627 KiB/s | 710 KiB/s | **2.58 MiB/s** | **4.2x** | **3.7x** | +| AES-256-CBC-dec | 626 KiB/s | 712 KiB/s | **2.59 MiB/s** | **4.2x** | **3.7x** | +| AES-128-GCM-enc | 293 KiB/s | 629 KiB/s | **2.37 MiB/s** | **8.3x** | **3.9x** | +| AES-128-GCM-dec | 291 KiB/s | 626 KiB/s | **2.26 MiB/s** | **8.0x** | **3.7x** | +| AES-192-GCM-enc | 275 KiB/s | 558 KiB/s | **2.38 MiB/s** | **8.9x** | **4.4x** | +| AES-192-GCM-dec | 274 KiB/s | 556 KiB/s | **2.24 MiB/s** | **8.4x** | **4.1x** | +| AES-256-GCM-enc | 260 KiB/s | 502 KiB/s | **2.38 MiB/s** | **9.4x** | **4.8x** | +| AES-256-GCM-dec | 258 KiB/s | 501 KiB/s | **2.23 MiB/s** | **8.8x** | **4.6x** | +| AES-128-GCM-enc-no_AAD | 296 KiB/s | 632 KiB/s | **2.44 MiB/s** | **8.4x** | **3.9x** | +| AES-128-GCM-dec-no_AAD | 294 KiB/s | 630 KiB/s | **2.28 MiB/s** | **7.9x** | **3.7x** | +| AES-192-GCM-enc-no_AAD | 278 KiB/s | 560 KiB/s | **2.41 MiB/s** | **8.9x** | **4.4x** | +| AES-192-GCM-dec-no_AAD | 276 KiB/s | 559 KiB/s | **2.30 MiB/s** | **8.5x** | **4.2x** | +| AES-256-GCM-enc-no_AAD | 262 KiB/s | 505 KiB/s | **2.35 MiB/s** | **9.2x** | **4.8x** | +| AES-256-GCM-dec-no_AAD | 261 KiB/s | 503 KiB/s | **2.23 MiB/s** | **8.8x** | **4.5x** | +| AES-128-ECB-enc | 876 KiB/s | 992 KiB/s | **2.84 MiB/s** | **3.3x** | **2.9x** | +| AES-128-ECB-dec | 882 KiB/s | 988 KiB/s | **2.77 MiB/s** | **3.2x** | **2.9x** | +| AES-192-ECB-enc | 737 KiB/s | 824 KiB/s | **2.74 MiB/s** | **3.8x** | **3.4x** | +| AES-192-ECB-dec | 741 KiB/s | 833 KiB/s | **2.79 MiB/s** | **3.9x** | **3.4x** | +| AES-256-ECB-enc | 638 KiB/s | 711 KiB/s | **2.70 MiB/s** | **4.3x** | **3.9x** | +| AES-256-ECB-dec | 640 KiB/s | 710 KiB/s | **2.71 MiB/s** | **4.3x** | **3.9x** | +| AES-128-CTR | 852 KiB/s | 977 KiB/s | **2.63 MiB/s** | **3.2x** | n/a | +| AES-192-CTR | 720 KiB/s | 820 KiB/s | **2.62 MiB/s** | **3.7x** | n/a | +| AES-256-CTR | 625 KiB/s | 705 KiB/s | **2.63 MiB/s** | **4.3x** | n/a | +| AES-CCM-enc | 426 KiB/s | 460 KiB/s | **2.20 MiB/s** | **5.3x** | **4.9x** | +| AES-CCM-dec | 425 KiB/s | 459 KiB/s | **2.14 MiB/s** | **5.1x** | **4.8x** | +| AES-CCM-enc-no_AAD | 426 KiB/s | 460 KiB/s | **2.20 MiB/s** | **5.3x** | **4.9x** | +| AES-CCM-dec-no_AAD | 425 KiB/s | 459 KiB/s | **2.11 MiB/s** | **5.1x** | **4.7x** | +| SHA-1 | 3.91 MiB/s | 3.92 MiB/s | **3.63 MiB/s** | **0.9x** | **0.9x** | +| SHA-224 | 1.23 MiB/s | 1.99 MiB/s | **3.67 MiB/s** | **3.0x** | **1.8x** | +| SHA-256 | 1.23 MiB/s | 1.99 MiB/s | **3.67 MiB/s** | **3.0x** | **1.8x** | +| AES-128-CMAC | 793 KiB/s | 856 KiB/s | **2.45 MiB/s** | **3.2x** | **2.9x** | +| AES-256-CMAC | 593 KiB/s | 640 KiB/s | **2.40 MiB/s** | **4.1x** | **3.8x** | +| HMAC-SHA-1 | 3.87 MiB/s | 3.87 MiB/s | **3.01 MiB/s** | **0.8x** | **0.8x** | +| HMAC-SHA-224 | 1.22 MiB/s | 1.97 MiB/s | **3.04 MiB/s** | **2.5x** | **1.5x** | +| HMAC-SHA-256 | 1.22 MiB/s | 1.97 MiB/s | **3.04 MiB/s** | **2.5x** | **1.5x** | +| ECC 256 key gen | 125.4 ops/s | 125.3 ops/s | **180.6 ops/s** | **1.4x** | **1.4x** | +| ECDHE 256 agree | 65.4 ops/s | 65.4 ops/s | **179.8 ops/s** | **2.7x** | **2.7x** | +| ECDSA 256 sign | 67.8 ops/s | 67.8 ops/s | **173.4 ops/s** | **2.6x** | **2.6x** | +| ECDSA 256 verify | 41.9 ops/s | 41.9 ops/s | **163.8 ops/s** | **3.9x** | **3.9x** | + +Where the Secure Element is **slower** the numbers are reported as measured. SHA-1 and HMAC-SHA-1 are cheap enough on this Cortex-M33 that the SE round trip costs more than it saves. The **RNG** row compares asking the SE for every byte against a SHA-256 DRBG seeded once from that same SE TRNG - seeding a DRBG is the normal way to use a hardware entropy source, so the `HW` row is raw TRNG throughput rather than the cost of getting random data. **AES-GCM** gains the most, up to **9.4x**. + +The RNG row is the only one that moves appreciably between runs: the DRBG reseeds from the SE TRNG at a fixed generate count and one reseed is expensive at 89 KiB/s, so the software figure swings by roughly 15% depending on whether a reseed lands inside the one-second measurement window. + +**AES-CTR** reads `n/a` in the last column because the port deliberately declines CTR when `WOLFSSL_ARMASM` is defined -- the Thumb2 keystream remainder and the SE's do not line up -- so that build has no Secure Element CTR number. + +**RSA** and **DH** are omitted because Series 2 has no RSA hardware, so both columns run in software. **SHA-384/512** likewise, and they are always left to software (see the port README). **ChaCha20-Poly1305** has no paired row because the benchmark drives it through the one-shot `wc_ChaCha20Poly1305_Encrypt()`, which carries no `devId` and so always runs in software. The pre-keyed API the TLS record layer uses does carry one, and that path is offloaded. + +To check the software fallback path, offload a subset by adding one or more engine macros to `user_settings.h` (for example only `WOLFSSL_SILABS_CRYPTOCB_HASH`) and re-run: everything else must still pass, in software. + +## TLS 1.3 over the Secure Element + +Flip the `WOLFSSL_XG25_TLS13` block at the top of `user_settings.h` to `#if 1` +and rebuild. The application then runs `tls13_test.c` between the wolfCrypt +test and the benchmark: a client and a server, both on the device, wired +together through two in-memory byte queues, with the Secure Element `devId` set +on both. It runs the handshake once per TLS 1.3 cipher suite and then pushes +application data through the record layer. + +This covers ground the known answer vectors cannot. Handshake and record +buffers are cursors into a larger buffer, so the engines see arbitrary byte +offsets rather than aligned stack arrays, and one cipher object is reused +across many chained records, so any state the port fails to carry between calls +shows up as a decrypt failure instead of passing on a single shot. + +The three suites cover different engines. `TLS13-AES128-GCM-SHA256` drives the +key schedule and transcript hash through the Secure Element, while +`TLS13-AES256-GCM-SHA384` runs those in software, so between them they cover +the offloaded and the fallback hash path. `TLS13-CHACHA20-POLY1305-SHA256` +covers the ChaCha20-Poly1305 record cipher, which the AES suites never reach. + +Measured result on the kit: + +``` +--- TLS 1.3 over the Secure Element --- + [TLS13-AES128-GCM-SHA256] + handshake OK: TLSv1.3 TLS_AES_128_GCM_SHA256 + record layer OK: 9 payloads, 1 to 255 bytes + [TLS13-AES256-GCM-SHA384] + handshake OK: TLSv1.3 TLS_AES_256_GCM_SHA384 + record layer OK: 9 payloads, 1 to 255 bytes + [TLS13-CHACHA20-POLY1305-SHA256] + handshake OK: TLSv1.3 TLS_CHACHA20_POLY1305_SHA256 + record layer OK: 9 payloads, 1 to 255 bytes +tls13_test returned 0 (PASS) +``` + +The ChaCha suite is the one that needs the `devId` carried on the cipher +object: the record layer keys a `ChaCha` once per epoch and then calls the +pre-keyed API, so without a `devId` on that object there is nothing to route +on. Instrumenting the port's dispatch during this run counts 28 +ChaCha20-Poly1305 requests reaching the Secure Element and 28 handled there, +with no software fallback. + +The kit has no battery-backed real time clock, so `app.c` supplies a +`_gettimeofday()` seeded from the build date, overriding newlib's weak stub. +Without it `time()` returns -1, every certificate reads as not yet valid and +the CA fails to load with `ASN_BEFORE_DATE_E` (-150). That clock is good enough +for a self-contained demo and nothing more: a device that cannot tell the time +cannot tell a valid certificate from an expired one, so a real design needs an +RTC, a time server, or a provisioned time that an attacker cannot move. + +## Notes + +* The SE firmware must be recent enough for the SE Manager commands used. xG25 is Series 2 Config 5, so it takes the `s2c5` firmware package - not the `s2c1` package referenced by older wolfSSL SiLabs documentation. Check with `commander device info` and upgrade with `commander flash` if needed. +* `user_settings.h` is shared by the library and the application, as wolfSSL requires. Changing feature macros in one and not the other corrupts struct layouts at runtime. +* RSA has no hardware support on Series 2 and stays in software; the benchmark rows for it are software timings. diff --git a/embedded/efr32xg25/app.c b/embedded/efr32xg25/app.c new file mode 100644 index 000000000..7f6e86a35 --- /dev/null +++ b/embedded/efr32xg25/app.c @@ -0,0 +1,216 @@ +/* app.c + * + * Copyright (C) 2006-2026 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/* wolfCrypt test and benchmark entry point for the EFR32xG25. */ + +#include + +#include +#include +#include +#include +#ifdef WOLFSSL_XG25_TLS13 + #include +#endif + +#include +#include +#include + +#ifdef WOLFSSL_XG25_TLS13 +#include +#endif + +#ifdef WOLFSSL_XG25_TLS13 +/* The kit has no RTC and newlib's _gettimeofday is a weak stub that fails, so + * time() returns -1 and every certificate looks not-yet-valid + * (ASN_BEFORE_DATE_E). Seed a clock from the build date and let the sleep + * timer advance it, so date validation can stay on. + * + * Adequate for a self-contained demo and nothing more: a device that cannot + * tell the time cannot tell a valid certificate from an expired one. A real + * design needs an RTC or a provisioned time, not attacker-controlled. */ + +/* Days from 1970-01-01 to y-m-d, proleptic Gregorian, for y >= 1970. */ +static long xg25_days_from_civil(long y, long m, long d) +{ + long era, yoe, doy, doe; + + y -= (m <= 2); + era = ((y >= 0) ? y : (y - 399)) / 400; + yoe = y - era * 400; + doy = (153 * (m + ((m > 2) ? -3 : 9)) + 2) / 5 + d - 1; + doe = yoe * 365 + yoe / 4 - yoe / 100 + doy; + return era * 146097 + doe - 719468; +} + +/* Seconds since the epoch for __DATE__ ("Mmm dd yyyy"), midnight UTC. Derived + * from the build so it cannot drift out of the test certificates' validity + * window the way a hardcoded constant would. */ +static long xg25_build_epoch(void) +{ + static const char months[] = "JanFebMarAprMayJunJulAugSepOctNovDec"; + const char* bd = __DATE__; + long mon = 0; + long day, year; + int i; + + for (i = 0; i < 12; i++) { + if (bd[0] == months[i * 3] && + bd[1] == months[i * 3 + 1] && + bd[2] == months[i * 3 + 2]) { + mon = i + 1; + break; + } + } + if (mon == 0) { + mon = 1; + } + + day = (bd[4] == ' ') ? (bd[5] - '0') + : ((bd[4] - '0') * 10 + (bd[5] - '0')); + year = (bd[7] - '0') * 1000 + (bd[8] - '0') * 100 + + (bd[9] - '0') * 10 + (bd[10] - '0'); + + return xg25_days_from_civil(year, mon, day) * 86400L; +} + +/* Strong override of newlib's weak stub. */ +int _gettimeofday(struct timeval* tv, void* tzvp) +{ + (void)tzvp; + if (tv == NULL) { + return -1; + } + tv->tv_sec = (time_t)(xg25_build_epoch() + + (long)(sl_sleeptimer_get_tick_count64() / + sl_sleeptimer_get_timer_frequency())); + tv->tv_usec = 0; + return 0; +} +#endif /* WOLFSSL_XG25_TLS13 */ + +extern int wolfcrypt_test(void* args); +extern int benchmark_test(void* args); +#ifdef WOLFSSL_XG25_TLS13 +extern int xg25_tls13_test(void); +#endif + +/* The benchmark needs a coarse wall clock. Bench iterations are sized in + * BENCH_EMBEDDED mode, so a low resolution tick is adequate. */ +double current_time(int reset) +{ + (void)reset; + return (double)sl_sleeptimer_get_tick_count64() + / (double)sl_sleeptimer_get_timer_frequency(); +} + +/* Report the Secure Element firmware version and the part's security level, so + * a captured log says which silicon produced the numbers below it. */ +static void print_se_info(void) +{ + sl_se_command_context_t cmd = SL_SE_COMMAND_CONTEXT_INIT; + uint32_t version = 0; + + if (sl_se_get_se_version(&cmd, &version) == SL_STATUS_OK) { + printf("SE firmware : %lu.%lu.%lu\n", + (unsigned long)((version >> 16) & 0xFF), + (unsigned long)((version >> 8) & 0xFF), + (unsigned long)(version & 0xFF)); + } + else { + printf("SE firmware : unavailable\n"); + } + +#if defined(_SILICON_LABS_SECURITY_FEATURE) && \ + (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT) + printf("Secure Vault : High\n"); +#else + printf("Secure Vault : Mid (SHA-384/512, P-384/521, ChaCha20-Poly1305,\n" + " the SE KDFs and wrapped keys run in software)\n"); +#endif +} + +void app_init(void) +{ + int ret; + + printf("\n\nwolfSSL %s - EFR32xG25 Secure Element crypto callback\n", + LIBWOLFSSL_VERSION_STRING); + /* Name the software backend: it is what the benchmark's SW column + * measures, and what the SE is being compared against. */ +#ifdef WOLFSSL_ARMASM + printf("Software path: Thumb2 assembly (WOLFSSL_ARMASM)\n"); +#else + printf("Software path: C\n"); +#endif + print_se_info(); + +#ifdef DEBUG_WOLFSSL + wolfSSL_Debugging_ON(); +#endif + + /* In TLS mode init and cleanup must pair at the library layer: a + * WOLFSSL_CTX takes its own wolfCrypt reference via wolfSSL_Init(), so a + * lone wolfCrypt_Cleanup() would leak the TLS globals and one SE + * registration. */ +#ifdef WOLFSSL_XG25_TLS13 + ret = wolfSSL_Init(); + if (ret != WOLFSSL_SUCCESS) { + printf("wolfSSL_Init failed: %d\n", ret); + return; + } + ret = 0; +#else + ret = wolfCrypt_Init(); +#endif + if (ret != 0) { + printf("wolfCrypt_Init failed: %d\n", ret); + return; + } + + printf("\n--- wolfCrypt test ---\n"); + ret = wolfcrypt_test(NULL); + printf("wolfcrypt_test returned %d (%s)\n", ret, + (ret == 0) ? "PASS" : "FAIL"); + +#ifdef WOLFSSL_XG25_TLS13 + printf("\n--- TLS 1.3 over the Secure Element ---\n"); + ret = xg25_tls13_test(); + printf("tls13_test returned %d (%s)\n", ret, (ret == 0) ? "PASS" : "FAIL"); +#endif + + printf("\n--- wolfCrypt benchmark ---\n"); + printf("Rows marked HW run on the Secure Element, SW in software.\n"); + ret = benchmark_test(NULL); + printf("benchmark_test returned %d\n", ret); + +#ifdef WOLFSSL_XG25_TLS13 + wolfSSL_Cleanup(); +#else + wolfCrypt_Cleanup(); +#endif + printf("\n--- done ---\n"); +} + +void app_process_action(void) +{ +} diff --git a/embedded/efr32xg25/build.sh b/embedded/efr32xg25/build.sh new file mode 100755 index 000000000..dead280ef --- /dev/null +++ b/embedded/efr32xg25/build.sh @@ -0,0 +1,120 @@ +#!/usr/bin/env bash +# Generate and build the EFR32xG25 wolfCrypt test/benchmark project headlessly. +# Requires the Silicon Labs toolchain installed via SLT (see README.md). +set -euo pipefail + +HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +BOARD="${BOARD:-brd4270b}" +BUILD_DIR="${BUILD_DIR:-$HERE/build}" + +# wolfSSL sources are pulled in by relative path from wolfcrypt_test.slcp, which +# assumes a wolfssl checkout sitting beside wolfssl-examples. Point WOLFSSL_ROOT +# somewhere else and the project file is rewritten with absolute paths into the +# build directory, leaving the checked-in one untouched. +WOLFSSL_ROOT="${WOLFSSL_ROOT:-$HERE/../../../wolfssl}" +if [ ! -f "$WOLFSSL_ROOT/wolfcrypt/src/aes.c" ]; then + echo "No wolfSSL checkout at '$WOLFSSL_ROOT'." >&2 + echo "Clone wolfSSL beside wolfssl-examples, or set WOLFSSL_ROOT." >&2 + exit 1 +fi +WOLFSSL_ROOT="$(cd "$WOLFSSL_ROOT" && pwd -P)" + +# Resolve the SLT-managed toolchain from its own registries rather than +# hardcoding conan hash directories, which change on reinstall. +SILABS_HOME="${SILABS_HOME:-$HOME/.silabs}" +SLT_HINT="Install the toolchain with 'slt install' (see README.md), or set SDK, SLC, GCC_DIR and JAVA_DIR explicitly." + +# A missing registry, a truncated one, or a tool that was never installed all +# have the same fix, so say what it is instead of letting python traceback. +json_path() { # json_path + local out + if [ ! -r "$1" ]; then + echo "Cannot read SLT registry '$1'." >&2 + echo "$SLT_HINT" >&2 + return 1 + fi + out="$(python3 -c "import json,sys +try: + d = json.load(open(sys.argv[1])) +except ValueError as e: + sys.exit('%s: not valid JSON: %s' % (sys.argv[1], e)) +try: + print(d[sys.argv[2]][0]['path'] if isinstance(d, dict) + else d[0]['extensions'][0]['path']) +except (KeyError, IndexError, TypeError): + sys.exit('%s: no entry for %s' % (sys.argv[1], sys.argv[2]))" "$1" "$2")" || { + echo "$SLT_HINT" >&2 + return 1 + } + printf '%s\n' "$out" +} + +SDK="${SDK:-$(json_path "$SILABS_HOME/sdks.json" simplicity-sdk)}" +SLC="${SLC:-$(json_path "$SILABS_HOME/tools.json" slc-cli)/slc}" +GCC_DIR="${GCC_DIR:-$(json_path "$SILABS_HOME/tools.json" gcc-arm-none-eabi)/bin}" +JAVA_DIR="${JAVA_DIR:-$(json_path "$SILABS_HOME/tools.json" java21)/bin}" + +export PATH="$JAVA_DIR:$GCC_DIR:$PATH" +ARM_GCC_DIR="$(dirname "$GCC_DIR")" +export ARM_GCC_DIR + +echo "SDK : $SDK" +echo "slc : $SLC" +echo "gcc : $(arm-none-eabi-gcc -dumpversion)" +echo "board : $BOARD" + +# BUILD_DIR is deleted below, so refuse anything that is not clearly ours. +# It must resolve beneath this example directory: that rules out "/", $HOME, +# the repository root and any unrelated project someone points the variable at. +BUILD_PARENT="$(cd "$(dirname "$BUILD_DIR")" 2>/dev/null && pwd -P || true)" +if [ -z "$BUILD_PARENT" ]; then + echo "BUILD_DIR parent does not exist: $BUILD_DIR" >&2 + exit 1 +fi +BUILD_ABS="$BUILD_PARENT/$(basename "$BUILD_DIR")" +case "$BUILD_ABS" in + "$HERE"/?*) ;; + *) + echo "Refusing to delete '$BUILD_ABS'" >&2 + echo "BUILD_DIR must be inside $HERE" >&2 + exit 1 + ;; +esac + +rm -rf "$BUILD_ABS" +mkdir -p "$BUILD_ABS" +BUILD_DIR="$BUILD_ABS" + +# Point the project file at WOLFSSL_ROOT. slc resolves every path: entry +# relative to the .slcp itself, so a non-default root means rewriting that one +# prefix to a path relative to this directory - and the copy has to stay here, +# because app.c and user_settings.h are relative to it too. +SLCP="$HERE/wolfcrypt_test.slcp" +WOLFSSL_REL="$(realpath --relative-to="$HERE" "$WOLFSSL_ROOT")" +if [ "$WOLFSSL_REL" != "../../../wolfssl" ]; then + SLCP="$HERE/.wolfcrypt_test.local.slcp" + sed "s|\.\./\.\./\.\./wolfssl|$WOLFSSL_REL|g" \ + "$HERE/wolfcrypt_test.slcp" > "$SLCP" + echo "wolfSSL: $WOLFSSL_ROOT" +fi + +"$SLC" signature trust --sdk "$SDK" >/dev/null 2>&1 || true + +"$SLC" generate \ + --sdk "$SDK" \ + --project-file "$SLCP" \ + --output-type makefile \ + --with "$BOARD" \ + --destination "$BUILD_DIR" \ + --new-project --force + +# slc only emits include directories that live inside the project, so add the +# wolfSSL root here. Appending to the generated fragment keeps the SDK's own +# INCLUDES intact, which passing INCLUDES= on the make command line would not. +printf '\nINCLUDES += -I%s\n' "$WOLFSSL_ROOT" >> "$BUILD_DIR/wolfcrypt_test.project.mak" + +make -C "$BUILD_DIR" -f wolfcrypt_test.Makefile -j"$(nproc)" + +echo +echo "Artifacts:" +find "$BUILD_DIR" -name "*.hex" -o -name "*.s37" -o -name "*.bin" | sed 's/^/ /' diff --git a/embedded/efr32xg25/flash.sh b/embedded/efr32xg25/flash.sh new file mode 100755 index 000000000..0a2eaea50 --- /dev/null +++ b/embedded/efr32xg25/flash.sh @@ -0,0 +1,57 @@ +#!/usr/bin/env bash +# Flash the built image to an attached EFR32xG25 kit and report the device. +set -euo pipefail + +HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +BUILD_DIR="${BUILD_DIR:-$HERE/build}" +SILABS_HOME="${SILABS_HOME:-$HOME/.silabs}" + +# Resolve Commander from the SLT registry. The path goes in as an argument +# rather than being pasted into the program text, so a directory holding a +# quote is read as a path and nothing else. +TOOLS_JSON="$SILABS_HOME/tools.json" +if [ -z "${COMMANDER:-}" ]; then + if [ ! -r "$TOOLS_JSON" ]; then + echo "Cannot read SLT registry '$TOOLS_JSON'." >&2 + echo "Install the toolchain with 'slt install' (see README.md), or set COMMANDER explicitly." >&2 + exit 1 + fi + COMMANDER_DIR="$(python3 -c "import json,sys +try: + d = json.load(open(sys.argv[1])) +except ValueError as e: + sys.exit('%s: not valid JSON: %s' % (sys.argv[1], e)) +try: + print(d['commander'][0]['path']) +except (KeyError, IndexError, TypeError): + sys.exit('%s: no entry for commander' % (sys.argv[1],))" "$TOOLS_JSON")" || { + echo "Install the toolchain with 'slt install' (see README.md), or set COMMANDER explicitly." >&2 + exit 1 + } + COMMANDER="$COMMANDER_DIR/commander" +fi + +# find would end the script under set -e if the directory is not there, before +# the message below could explain why. +if [ -z "${IMAGE:-}" ]; then + if [ ! -d "$BUILD_DIR" ]; then + echo "No build directory at $BUILD_DIR - run build.sh first." >&2 + exit 1 + fi + IMAGE="$(find "$BUILD_DIR" -name '*.hex' | head -1)" +fi +if [ -z "$IMAGE" ]; then + echo "No .hex found under $BUILD_DIR - run build.sh first." >&2 + exit 1 +fi + +echo "== device ==" +"$COMMANDER" device info + +echo +echo "== flashing $IMAGE ==" +"$COMMANDER" flash "$IMAGE" + +echo +echo "== reset ==" +"$COMMANDER" device reset diff --git a/embedded/efr32xg25/tls13_test.c b/embedded/efr32xg25/tls13_test.c new file mode 100644 index 000000000..590bfe040 --- /dev/null +++ b/embedded/efr32xg25/tls13_test.c @@ -0,0 +1,305 @@ +/* tls13_test.c + * + * Copyright (C) 2006-2026 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/* TLS 1.3 handshake and record layer over an in-memory transport, run on the + * device with every crypto operation routed to the Secure Element. + * + * The wolfCrypt test proves the callbacks against known answer vectors one call + * at a time; this drives them the way a connection does - ECDHE key share, + * ECDSA certificate and CertificateVerify, the HKDF key schedule and a running + * transcript hash, then application data through the record layer. + * + * That catches what the vector tests cannot. Handshake and record buffers are + * cursors into a larger buffer, so they land on arbitrary offsets rather than + * aligned stack arrays - if an engine needs alignment or a DMA-reachable + * buffer, it shows here. One cipher object is also reused across thousands of + * chained records, so state the port fails to carry between calls fails rather + * than passing by luck on a single shot. + * + * Client and server both run in one thread, wired through two byte queues. + * Modeled on examples/tls13/tls13_memio.c, with the file-based certificates + * replaced by the compiled-in test buffers and the SE devId on both ends. + */ + +#include + +#ifdef WOLFSSL_XG25_TLS13 + +#include + +#include +#include +#include +#include + +/* Holds one handshake flight. The server's is the larger: certificate, + * CertificateVerify and Finished together stay under 2 KB with a P-256 + * chain. */ +#define XG25_TLS_BUF_SZ 4096 + +/* Handshake needs a few round trips; the cap only stops a stalled loop. */ +#define XG25_TLS_MAX_ITERS 32 + +typedef struct membuf { + unsigned char data[XG25_TLS_BUF_SZ]; + int len; +} membuf; + +static int mem_recv(WOLFSSL* ssl, char* buf, int sz, void* ctx) +{ + membuf* mb = (membuf*)ctx; + int n; + + (void)ssl; + if (mb->len == 0) { + return WOLFSSL_CBIO_ERR_WANT_READ; + } + n = (sz < mb->len) ? sz : mb->len; + XMEMCPY(buf, mb->data, (size_t)n); + XMEMMOVE(mb->data, mb->data + n, (size_t)(mb->len - n)); + mb->len -= n; + return n; +} + +static int mem_send(WOLFSSL* ssl, char* buf, int sz, void* ctx) +{ + membuf* mb = (membuf*)ctx; + + (void)ssl; + /* A write larger than the queue itself never fits, however much the peer + * drains, so fail it outright. Retrying to the iteration cap would report + * it as a stalled handshake instead. */ + if (sz < 0 || sz > XG25_TLS_BUF_SZ) { + return WOLFSSL_CBIO_ERR_GENERAL; + } + if (mb->len > XG25_TLS_BUF_SZ - sz) { + return WOLFSSL_CBIO_ERR_WANT_WRITE; + } + XMEMCPY(mb->data + mb->len, buf, (size_t)sz); + mb->len += sz; + return sz; +} + +/* Application data round trip at deliberately awkward lengths and offsets. + * Every record is sealed and opened by the SE and read back byte for byte, so + * a record layer that corrupts data fails here even after a good handshake. */ +static int xg25_tls13_echo(WOLFSSL* c, WOLFSSL* s, int payloadSz, int offset) +{ + static unsigned char out[512]; + static unsigned char in[512]; + int i; + int ret; + + if (offset + payloadSz > (int)sizeof(out)) { + return BAD_FUNC_ARG; + } + + for (i = 0; i < payloadSz; i++) { + out[offset + i] = (unsigned char)(i * 7 + payloadSz); + } + + ret = wolfSSL_write(c, out + offset, payloadSz); + if (ret != payloadSz) { + printf(" write failed: %d (err %d)\n", ret, wolfSSL_get_error(c, ret)); + return -1; + } + + XMEMSET(in, 0, sizeof(in)); + ret = wolfSSL_read(s, in + offset, payloadSz); + if (ret != payloadSz) { + printf(" read failed: %d (err %d)\n", ret, wolfSSL_get_error(s, ret)); + return -1; + } + + if (XMEMCMP(out + offset, in + offset, (size_t)payloadSz) != 0) { + printf(" payload mismatch at %d bytes, offset %d\n", + payloadSz, offset); + return -1; + } + + return 0; +} + +static int xg25_tls13_one(const char* suite) +{ + /* Static rather than automatic: two 4 KB queues plus the peer objects + * would otherwise sit on a small-stack build's stack. */ + static membuf c2s; /* client writes, server reads */ + static membuf s2c; /* server writes, client reads */ + /* Odd lengths and offsets on purpose: unaligned starts and partial final + * blocks are what an engine with an alignment or block assumption trips + * over. */ + static const int sizes[] = { 1, 15, 16, 17, 31, 63, 127, 128, 255 }; + static const int offsets[] = { 0, 1, 2, 3, 1, 2, 3, 1, 2 }; + WOLFSSL_CTX* cctx = NULL; + WOLFSSL_CTX* sctx = NULL; + WOLFSSL* c = NULL; + WOLFSSL* s = NULL; + int cdone = 0, sdone = 0; + int cret = WOLFSSL_FATAL_ERROR; + int sret = WOLFSSL_FATAL_ERROR; + int ret = -1; + int i; + + XMEMSET(&c2s, 0, sizeof(c2s)); + XMEMSET(&s2c, 0, sizeof(s2c)); + + cctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method()); + sctx = wolfSSL_CTX_new(wolfTLSv1_3_server_method()); + if (cctx == NULL || sctx == NULL) { + printf(" CTX_new failed\n"); + goto done; + } + + /* A single-suite list means a completed handshake proves that suite was + * the one used. */ + if (wolfSSL_CTX_set_cipher_list(cctx, suite) != WOLFSSL_SUCCESS || + wolfSSL_CTX_set_cipher_list(sctx, suite) != WOLFSSL_SUCCESS) { + printf(" %s: not built in, skipped\n", suite); + ret = 0; + goto done; + } + + /* The whole point: every private key operation, key schedule step, + * transcript hash and record seal below goes to the Secure Element. */ + if (wolfSSL_CTX_SetDevId(cctx, WOLFSSL_SILABS_DEVID) != WOLFSSL_SUCCESS || + wolfSSL_CTX_SetDevId(sctx, WOLFSSL_SILABS_DEVID) != WOLFSSL_SUCCESS) { + printf(" CTX_SetDevId failed\n"); + goto done; + } + + /* P-256 server certificate and its issuing CA, from the compiled-in test + * buffers. Test credentials only - never ship these. */ + if (wolfSSL_CTX_use_certificate_buffer(sctx, serv_ecc_der_256, + (long)sizeof_serv_ecc_der_256, WOLFSSL_FILETYPE_ASN1) + != WOLFSSL_SUCCESS) { + printf(" server cert load failed\n"); + goto done; + } + if (wolfSSL_CTX_use_PrivateKey_buffer(sctx, ecc_key_der_256, + (long)sizeof_ecc_key_der_256, WOLFSSL_FILETYPE_ASN1) + != WOLFSSL_SUCCESS) { + printf(" server key load failed\n"); + goto done; + } + ret = wolfSSL_CTX_load_verify_buffer(cctx, ca_ecc_cert_der_256, + (long)sizeof_ca_ecc_cert_der_256, WOLFSSL_FILETYPE_ASN1); + if (ret != WOLFSSL_SUCCESS) { + printf(" CA load failed: %d\n", ret); + ret = -1; + goto done; + } + ret = -1; + + /* Peer verification stays on: the client must actually validate the + * server's chain, which drives ECDSA verify through the SE. */ + wolfSSL_CTX_set_verify(cctx, WOLFSSL_VERIFY_PEER, NULL); + + wolfSSL_CTX_SetIORecv(cctx, mem_recv); + wolfSSL_CTX_SetIOSend(cctx, mem_send); + wolfSSL_CTX_SetIORecv(sctx, mem_recv); + wolfSSL_CTX_SetIOSend(sctx, mem_send); + + c = wolfSSL_new(cctx); + s = wolfSSL_new(sctx); + if (c == NULL || s == NULL) { + printf(" SSL_new failed\n"); + goto done; + } + + wolfSSL_SetIOReadCtx(c, &s2c); + wolfSSL_SetIOWriteCtx(c, &c2s); + wolfSSL_SetIOReadCtx(s, &c2s); + wolfSSL_SetIOWriteCtx(s, &s2c); + + for (i = 0; i < XG25_TLS_MAX_ITERS && !(cdone && sdone); i++) { + if (!cdone) { + cret = wolfSSL_connect(c); + if (cret == WOLFSSL_SUCCESS) { + cdone = 1; + } + } + if (!sdone) { + sret = wolfSSL_accept(s); + if (sret == WOLFSSL_SUCCESS) { + sdone = 1; + } + } + } + + if (!cdone || !sdone) { + printf(" handshake FAILED (client err %d, server err %d)\n", + wolfSSL_get_error(c, cret), wolfSSL_get_error(s, sret)); + goto done; + } + if (XSTRCMP(wolfSSL_get_version(c), "TLSv1.3") != 0) { + printf(" negotiated %s, expected TLSv1.3\n", wolfSSL_get_version(c)); + goto done; + } + + printf(" handshake OK: %s %s\n", + wolfSSL_get_version(c), wolfSSL_get_cipher(c)); + + for (i = 0; i < (int)(sizeof(sizes) / sizeof(sizes[0])); i++) { + if (xg25_tls13_echo(c, s, sizes[i], offsets[i]) != 0) { + goto done; + } + } + printf(" record layer OK: %d payloads, 1 to %d bytes\n", + (int)(sizeof(sizes) / sizeof(sizes[0])), + sizes[(sizeof(sizes) / sizeof(sizes[0])) - 1]); + + ret = 0; + +done: + wolfSSL_free(c); + wolfSSL_free(s); + wolfSSL_CTX_free(cctx); + wolfSSL_CTX_free(sctx); + return ret; +} + +int xg25_tls13_test(void) +{ + /* Three suites, exercising different engines. SHA-256 drives the key + * schedule and transcript hash through the SE, SHA-384 runs them in + * software, and the ChaCha suite covers a record cipher the AES suites + * never reach. */ + static const char* suites[] = { + "TLS13-AES128-GCM-SHA256", + "TLS13-AES256-GCM-SHA384", + "TLS13-CHACHA20-POLY1305-SHA256" + }; + int i; + int ret; + + for (i = 0; i < (int)(sizeof(suites) / sizeof(suites[0])); i++) { + printf(" [%s]\n", suites[i]); + ret = xg25_tls13_one(suites[i]); + if (ret != 0) { + return ret; + } + } + + return 0; +} + +#endif /* WOLFSSL_XG25_TLS13 */ diff --git a/embedded/efr32xg25/user_settings.h b/embedded/efr32xg25/user_settings.h new file mode 100644 index 000000000..37609085d --- /dev/null +++ b/embedded/efr32xg25/user_settings.h @@ -0,0 +1,162 @@ +/* user_settings.h + * + * Copyright (C) 2006-2026 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/* wolfCrypt configuration for the EFR32xG25 Secure Element crypto callback + * port. Used by both the library and the application, as required. */ + +#ifndef WOLFSSL_XG25_USER_SETTINGS_H +#define WOLFSSL_XG25_USER_SETTINGS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* ---- Silicon Labs Secure Element -------------------------------------- */ +/* Routes operations through the crypto callback framework by devId. This one + * define also turns on WOLF_CRYPTO_CB, registers the device from + * wolfCrypt_Init() and points WC_USE_DEVID at it, so the stock wolfCrypt test + * and benchmark exercise the hardware. */ +#define WOLFSSL_SILABS_CRYPTOCB + +/* Optional: TLS 1.3 handshake and record layer test. Adds a full handshake and + * application data exchange, both peers on the device, everything routed to + * the Secure Element - buffers at arbitrary offsets and one cipher object + * reused across many records, which is where alignment or carried-state + * problems show up. See tls13_test.c. + * + * Turning this on links the TLS sources, which are already in the project and + * compile to nothing while it is off. + */ +#if 0 + #define WOLFSSL_XG25_TLS13 +#endif + +/* ---- Platform ---------------------------------------------------------- */ +#ifdef WOLFSSL_XG25_TLS13 + #define WOLFSSL_TLS13 + #define WOLFSSL_NO_TLS12 + #define HAVE_TLS_EXTENSIONS + #define HAVE_SUPPORTED_CURVES + #define WOLFSSL_USER_IO + #define NO_DH + /* RSA stays compiled in for the wolfCrypt test vectors, and TLS 1.3 + * requires PSS for any RSA signature. */ + #define WC_RSA_PSS +#else + /* This project exercises wolfCrypt only; no TLS is linked. */ + #define WOLFCRYPT_ONLY +#endif +#define NO_OLD_TLS +#define WOLFSSL_GENERAL_ALIGNMENT 4 +/* newlib-nano has no strcasecmp/strncasecmp; use wolfCrypt's own. */ +#define USE_WOLF_STRCASECMP +#define USE_WOLF_STRNCASECMP +#define SINGLE_THREADED +#define NO_FILESYSTEM +#define NO_WRITEV +#define WOLFSSL_NO_SOCK +#define NO_MAIN_DRIVER +#define BENCH_EMBEDDED +#define WOLFSSL_SMALL_STACK +#define WOLFSSL_USER_CURRTIME +#define USE_CERT_BUFFERS_256 + +/* Optional: Thumb2 assembly for the symmetric and hash software paths. The SE + * handles these algorithms, so this only changes what the software fallback + * costs - and what the benchmark's SW column reports. The thumb2-*-asm_c.c + * sources are already in the project and compile to nothing while it is off. + * + * WOLFSSL_ARM_ARCH=7 selects the ARMv7-M/Thumb2 encodings the Cortex-M33 runs; + * WOLFSSL_ARMASM_NO_HW_CRYPTO is required because the M33 has no ARMv8 + * cryptography extensions and no NEON. + */ +#if 0 + #define WOLFSSL_ARMASM + #define WOLFSSL_ARMASM_THUMB2 + #define WOLFSSL_ARMASM_INLINE + #define WOLFSSL_ARMASM_NO_HW_CRYPTO + #define WOLFSSL_ARMASM_NO_NEON + #define WOLFSSL_ARM_ARCH 7 +#endif + +/* ---- Hardening --------------------------------------------------------- + * What ./configure --enable-harden turns on, and its default for good reason: + * timing-attack resistance on the paths handling private keys, at some + * software cost. The SE is unaffected, but anything it declines falls back to + * these software implementations. + * + * TFM_TIMING_RESISTANT applies only to the fastmath backend, which this + * configuration does not use (see WOLFSSL_SP_MATH_ALL below), but is set so + * the setting survives a change of math backend. + */ +#define ECC_TIMING_RESISTANT +#define WC_RSA_BLINDING +#define TFM_TIMING_RESISTANT + +/* Cortex-M33 single precision assembly for the software fallback paths. */ +#define WOLFSSL_SP_MATH_ALL +#define WOLFSSL_HAVE_SP_RSA +#define WOLFSSL_HAVE_SP_ECC +#define WOLFSSL_SP_ARM_CORTEX_M_ASM +#define WOLFSSL_SP_SMALL + +/* ---- Algorithms offloaded to the SE ------------------------------------ */ +#define HAVE_AES_ECB +#define WOLFSSL_AES_DIRECT +#define WOLFSSL_AES_COUNTER +#define HAVE_AESGCM +#define HAVE_AESCCM +#define WOLFSSL_AES_192 +#define WOLFSSL_AES_256 +#define WOLFSSL_CMAC +#define WOLFSSL_SHA224 +#define WOLFSSL_SHA384 +#define WOLFSSL_SHA512 +#define HAVE_HKDF +#define HAVE_PBKDF2 +#define HAVE_CHACHA +#define HAVE_POLY1305 +#define HAVE_ECC +#define ECC_SHAMIR +#define HAVE_ECC384 +#define HAVE_ECC521 +#define ALT_ECC_SIZE + +/* ---- Trimmed away to fit and to keep the run short --------------------- */ +#define NO_DSA +#define NO_DES3 +#define NO_RC4 +#define NO_MD4 +#define NO_MD5 +#define NO_PSK +#define NO_PWDBASED_TEST_LONG +#define WOLFSSL_NO_SHAKE128 +#define WOLFSSL_NO_SHAKE256 + +/* The Series 2 High Security Engine has no RSA hardware. RSA stays in + * software; leave it on for the test vectors but keep the key size modest. */ +#define RSA_MAX_SIZE 2048 + +#ifdef __cplusplus +} +#endif + +#endif /* WOLFSSL_XG25_USER_SETTINGS_H */ diff --git a/embedded/efr32xg25/wolfcrypt_test.slcp b/embedded/efr32xg25/wolfcrypt_test.slcp new file mode 100644 index 000000000..54dcdd3c1 --- /dev/null +++ b/embedded/efr32xg25/wolfcrypt_test.slcp @@ -0,0 +1,189 @@ +project_name: wolfcrypt_test +package: platform +quality: experimental +label: wolfSSL - wolfCrypt test and benchmark (EFR32xG25) +description: > + Runs the wolfCrypt algorithm self-test and benchmark on an EFR32xG25, with + crypto routed to the Secure Element through the wolfSSL crypto callback port + (WOLFSSL_SILABS_CRYPTOCB). Output goes to the kit VCOM. +category: Example|Platform +filter: + - name: "Device Type" + value: ["SoC"] + - name: "MCU" + value: ["32-bit MCU"] + - name: "Project Difficulty" + value: ["Advanced"] +source: + - path: app.c + - path: ../../../wolfssl/wolfcrypt/src/aes.c + - path: ../../../wolfssl/wolfcrypt/src/arc4.c + - path: ../../../wolfssl/wolfcrypt/src/ascon.c + - path: ../../../wolfssl/wolfcrypt/src/asn.c + - path: ../../../wolfssl/wolfcrypt/src/async.c + - path: ../../../wolfssl/wolfcrypt/src/blake2b.c + - path: ../../../wolfssl/wolfcrypt/src/blake2s.c + - path: ../../../wolfssl/wolfcrypt/src/camellia.c + - path: ../../../wolfssl/wolfcrypt/src/chacha.c + - path: ../../../wolfssl/wolfcrypt/src/chacha20_poly1305.c + - path: ../../../wolfssl/wolfcrypt/src/cmac.c + - path: ../../../wolfssl/wolfcrypt/src/coding.c + - path: ../../../wolfssl/wolfcrypt/src/compress.c + - path: ../../../wolfssl/wolfcrypt/src/cpuid.c + - path: ../../../wolfssl/wolfcrypt/src/cryptocb.c + - path: ../../../wolfssl/wolfcrypt/src/curve25519.c + - path: ../../../wolfssl/wolfcrypt/src/curve448.c + - path: ../../../wolfssl/wolfcrypt/src/des3.c + - path: ../../../wolfssl/wolfcrypt/src/dh.c + - path: ../../../wolfssl/wolfcrypt/src/dsa.c + - path: ../../../wolfssl/wolfcrypt/src/ecc.c + - path: ../../../wolfssl/wolfcrypt/src/eccsi.c + - path: ../../../wolfssl/wolfcrypt/src/ed25519.c + - path: ../../../wolfssl/wolfcrypt/src/ed448.c + - path: ../../../wolfssl/wolfcrypt/src/error.c + - path: ../../../wolfssl/wolfcrypt/src/falcon.c + - path: ../../../wolfssl/wolfcrypt/src/fe_448.c + - path: ../../../wolfssl/wolfcrypt/src/fe_low_mem.c + - path: ../../../wolfssl/wolfcrypt/src/fe_operations.c + - path: ../../../wolfssl/wolfcrypt/src/fips.c + - path: ../../../wolfssl/wolfcrypt/src/fips_test.c + - path: ../../../wolfssl/wolfcrypt/src/ge_448.c + - path: ../../../wolfssl/wolfcrypt/src/ge_low_mem.c + - path: ../../../wolfssl/wolfcrypt/src/ge_operations.c + - path: ../../../wolfssl/wolfcrypt/src/hash.c + - path: ../../../wolfssl/wolfcrypt/src/hmac.c + - path: ../../../wolfssl/wolfcrypt/src/hpke.c + - path: ../../../wolfssl/wolfcrypt/src/integer.c + - path: ../../../wolfssl/wolfcrypt/src/kdf.c + - path: ../../../wolfssl/wolfcrypt/src/logging.c + - path: ../../../wolfssl/wolfcrypt/src/md2.c + - path: ../../../wolfssl/wolfcrypt/src/md4.c + - path: ../../../wolfssl/wolfcrypt/src/md5.c + - path: ../../../wolfssl/wolfcrypt/src/memory.c + - path: ../../../wolfssl/wolfcrypt/src/pkcs12.c + - path: ../../../wolfssl/wolfcrypt/src/pkcs7.c + - path: ../../../wolfssl/wolfcrypt/src/poly1305.c + - path: ../../../wolfssl/wolfcrypt/src/puf.c + - path: ../../../wolfssl/wolfcrypt/src/pwdbased.c + - path: ../../../wolfssl/wolfcrypt/src/random.c + - path: ../../../wolfssl/wolfcrypt/src/rc2.c + - path: ../../../wolfssl/wolfcrypt/src/ripemd.c + - path: ../../../wolfssl/wolfcrypt/src/rng_bank.c + - path: ../../../wolfssl/wolfcrypt/src/rsa.c + - path: ../../../wolfssl/wolfcrypt/src/sakke.c + - path: ../../../wolfssl/wolfcrypt/src/selftest.c + - path: ../../../wolfssl/wolfcrypt/src/sha.c + - path: ../../../wolfssl/wolfcrypt/src/sha256.c + - path: ../../../wolfssl/wolfcrypt/src/sha3.c + - path: ../../../wolfssl/wolfcrypt/src/sha512.c + - path: ../../../wolfssl/wolfcrypt/src/signature.c + - path: ../../../wolfssl/wolfcrypt/src/siphash.c + - path: ../../../wolfssl/wolfcrypt/src/sm2.c + - path: ../../../wolfssl/wolfcrypt/src/sm3.c + - path: ../../../wolfssl/wolfcrypt/src/sm4.c + - path: ../../../wolfssl/wolfcrypt/src/sp_arm32.c + - path: ../../../wolfssl/wolfcrypt/src/sp_arm64.c + - path: ../../../wolfssl/wolfcrypt/src/sp_armthumb.c + - path: ../../../wolfssl/wolfcrypt/src/sp_c32.c + - path: ../../../wolfssl/wolfcrypt/src/sp_c64.c + - path: ../../../wolfssl/wolfcrypt/src/sp_cortexm.c + - path: ../../../wolfssl/wolfcrypt/src/sp_int.c + - path: ../../../wolfssl/wolfcrypt/src/sp_riscv64.c + - path: ../../../wolfssl/wolfcrypt/src/sp_sm2_arm32.c + - path: ../../../wolfssl/wolfcrypt/src/sp_sm2_arm64.c + - path: ../../../wolfssl/wolfcrypt/src/sp_sm2_armthumb.c + - path: ../../../wolfssl/wolfcrypt/src/sp_sm2_c32.c + - path: ../../../wolfssl/wolfcrypt/src/sp_sm2_c64.c + - path: ../../../wolfssl/wolfcrypt/src/sp_sm2_cortexm.c + - path: ../../../wolfssl/wolfcrypt/src/sp_sm2_riscv64.c + - path: ../../../wolfssl/wolfcrypt/src/sp_sm2_x86_64.c + - path: ../../../wolfssl/wolfcrypt/src/sp_x86_64.c + - path: ../../../wolfssl/wolfcrypt/src/srp.c + - path: ../../../wolfssl/wolfcrypt/src/tfm.c + - path: ../../../wolfssl/wolfcrypt/src/tsp.c + - path: ../../../wolfssl/wolfcrypt/src/wc_encrypt.c + - path: ../../../wolfssl/wolfcrypt/src/wc_frodokem.c + - path: ../../../wolfssl/wolfcrypt/src/wc_frodokem_mat.c + - path: ../../../wolfssl/wolfcrypt/src/wc_lms.c + - path: ../../../wolfssl/wolfcrypt/src/wc_lms_impl.c + - path: ../../../wolfssl/wolfcrypt/src/wc_mldsa.c + - path: ../../../wolfssl/wolfcrypt/src/wc_mlkem.c + - path: ../../../wolfssl/wolfcrypt/src/wc_mlkem_poly.c + - path: ../../../wolfssl/wolfcrypt/src/wc_pkcs11.c + - path: ../../../wolfssl/wolfcrypt/src/wc_port.c + - path: ../../../wolfssl/wolfcrypt/src/wc_she.c + - path: ../../../wolfssl/wolfcrypt/src/wc_slhdsa.c + - path: ../../../wolfssl/wolfcrypt/src/wc_xmss.c + - path: ../../../wolfssl/wolfcrypt/src/wc_xmss_impl.c + - path: ../../../wolfssl/wolfcrypt/src/wolfcrypt_first.c + - path: ../../../wolfssl/wolfcrypt/src/wolfcrypt_last.c + - path: ../../../wolfssl/wolfcrypt/src/wolfentropy.c + - path: ../../../wolfssl/wolfcrypt/src/wolfevent.c + - path: ../../../wolfssl/wolfcrypt/src/wolfmath.c + - path: ../../../wolfssl/src/internal.c + - path: ../../../wolfssl/src/keys.c + - path: ../../../wolfssl/src/ssl.c + - path: ../../../wolfssl/src/tls.c + - path: ../../../wolfssl/src/tls13.c + - path: ../../../wolfssl/src/wolfio.c + - path: tls13_test.c + - path: ../../../wolfssl/wolfcrypt/src/port/arm/thumb2-aes-asm_c.c + - path: ../../../wolfssl/wolfcrypt/src/port/arm/thumb2-sha256-asm_c.c + - path: ../../../wolfssl/wolfcrypt/src/port/arm/thumb2-sha512-asm_c.c + - path: ../../../wolfssl/wolfcrypt/src/port/arm/thumb2-chacha-asm_c.c + - path: ../../../wolfssl/wolfcrypt/src/port/arm/thumb2-poly1305-asm_c.c + - path: ../../../wolfssl/wolfcrypt/src/port/silabs/silabs_aes.c + - path: ../../../wolfssl/wolfcrypt/src/port/silabs/silabs_cb_cipher.c + - path: ../../../wolfssl/wolfcrypt/src/port/silabs/silabs_cb_cmac.c + - path: ../../../wolfssl/wolfcrypt/src/port/silabs/silabs_cb_hash.c + - path: ../../../wolfssl/wolfcrypt/src/port/silabs/silabs_cb_kdf.c + - path: ../../../wolfssl/wolfcrypt/src/port/silabs/silabs_cb_pk.c + - path: ../../../wolfssl/wolfcrypt/src/port/silabs/silabs_cb_rng.c + - path: ../../../wolfssl/wolfcrypt/src/port/silabs/silabs_cryptocb.c + - path: ../../../wolfssl/wolfcrypt/src/port/silabs/silabs_ecc.c + - path: ../../../wolfssl/wolfcrypt/src/port/silabs/silabs_hash.c + - path: ../../../wolfssl/wolfcrypt/src/port/silabs/silabs_key.c + - path: ../../../wolfssl/wolfcrypt/src/port/silabs/silabs_random.c + - path: ../../../wolfssl/wolfcrypt/test/test.c + - path: ../../../wolfssl/wolfcrypt/benchmark/benchmark.c +include: + - path: . + file_list: + - path: user_settings.h + - path: ../../../wolfssl + file_list: + - path: wolfssl/wolfcrypt/settings.h +readme: + - path: README.md +component: + - id: se_manager + - id: sl_main + - id: device_init + - id: clock_manager + - id: printf + - id: iostream_retarget_stdio + - id: iostream_recommended_stream + - id: sleeptimer + - id: sl_string + - id: status_string +requires: + - name: device_has_semailbox +configuration: + - name: SL_STATUS_STRING_ENABLE_BLUETOOTH + value: 0 + - name: SL_STATUS_STRING_ENABLE_WIFI + value: 0 + - name: SL_BOARD_ENABLE_VCOM + value: 1 + # wolfcrypt_test exercises deep call chains (ECC, RSA, ASN.1). The part has + # 512 KB of RAM and the app uses about 2 KB of static data, so spend some of it + # on stack rather than risk an overflow mid-test. + - name: SL_STACK_SIZE + value: 32768 + - name: SL_IOSTREAM_USART_VCOM_FLOW_CONTROL_TYPE + value: usartHwFlowControlNone +define: + - name: WOLFSSL_USER_SETTINGS +toolchain_settings: + - option: optimize + value: speed