Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -189,8 +189,12 @@

## New Features

* Added `WC_ALGO_TYPE_KEYSTORE`, a crypto callback algorithm type for lifetime operations on keys held in a hardware key store, with the public API in `wolfssl/wolfcrypt/wc_keystore.h` behind `--enable-cryptocbutils=keystore`. Seven operations - plaintext and wrapped import/export, derive, delete and get-info - address keys by an opaque device-defined reference that wolfCrypt copies through and never interprets, the same way it treats a key object's `id[]` blob. This lets a device create, wrap, derive and destroy keys that never appear in memory, which `WOLF_CRYPTO_CB_SETKEY` and `WOLF_CRYPTO_CB_EXPORT_KEY` cannot express because both are bound to a wolfCrypt key object holding material for its own use.
Comment thread
Frauschi marked this conversation as resolved.

* Added Argon2 (RFC 9106) password hashing with all three variants - Argon2d, Argon2i and Argon2id - via `--enable-argon2`. Only version 0x13 is implemented. Provides the one-shot `wc_Argon2()`/`wc_Argon2_ex()` and a reusable context API (`wc_Argon2Init`/`wc_Argon2SetParams`/`wc_Argon2DeriveTag`/`wc_Argon2Free`, plus `wc_Argon2New`/`wc_Argon2Delete` unless `WC_NO_CONSTRUCTORS`) that allocates the memory block array once for applications deriving many tags. `--enable-argon2-threads` fills the segments of a slice in parallel, which does not change the derived tag: the one-shot functions use a thread per lane, and the context API takes a count from `wc_Argon2SetThreads()`. by @SparkiDev

* Added an NXP EdgeLock (ELS + PKC) crypto callback port for the RW612 and related parts, in `wolfcrypt/src/port/nxp/els_pkc_port.c` behind `WOLFSSL_ELS_PKC`. The ELS peripheral serves SHA-256/384/512, AES (ECB/CBC/CTR), AES-GCM, CMAC, the DRBG and ECDSA on P-256 from a key slot; the PKC coprocessor serves RSA, X25519 and ECDSA on every curve. Keys resident in the ELS key store are referenced rather than exported, through the new `WC_ALGO_TYPE_KEYSTORE` operations. Configure with `--with-els-pkc=PATH --with-mcux-sdk=PATH`, or under Zephyr with `CONFIG_WOLFSSL_ELS_PKC=y`. NXP's CLNS library is linked by the application and is neither built nor vendored here.
Comment thread
Frauschi marked this conversation as resolved.

## Fixes

* **Fix (sniffer could not decrypt Encrypt-Then-MAC or X25519 sessions)**: the
Expand Down
104 changes: 104 additions & 0 deletions IDE/MCUEXPRESSO/RW612/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
# wolfSSL on NXP RW612 with EdgeLock (ELS + PKC)

This directory configures wolfSSL for the NXP RW612 with the EdgeLock crypto callback port, `wolfcrypt/src/port/nxp/els_pkc_port.c`, built from an MCUXpresso SDK project. It offloads SHA-256, AES, AES-GCM, CMAC and the DRBG to the ELS peripheral, and RSA, X25519 and ECDSA to the PKC coprocessor.

Zephyr users do not need any of this: the wolfSSL Zephyr module supplies the same port through `CONFIG_WOLFSSL_ELS_PKC=y`, and the `els_pkc` Zephyr module supplies the vendor headers. This is the path for a project that uses the MCUXpresso SDK directly.

## What els_pkc is

`els_pkc` is NXP's CLNS (Crypto Library NXP Secure) middleware. It ships as an MCUXpresso SDK component under `components/els_pkc/` and is also published at <https://github.com/NXP/els_pkc>. The Zephyr module it carries is an add-on; the SDK component is the primary form.

wolfSSL never builds or vendors CLNS. The port calls into it and the application links it, exactly as the SE050 port does. Take either route:

- build `els_pkc/src/comps` as part of your project, or
- link the prebuilt `els_pkc/static_library/rw61x/libclns.a`.

**Licensing.** els_pkc is distributed under NXP's proprietary `LA_OPT_Online Code Hosting` license, not an open source license. Clause 3.7 forbids subjecting it to a license that would require source disclosure. Fetching it at build time is fine and is what both this setup and the Zephyr module do; copying it into a wolfSSL tree is not.

## MCUXpresso IDE setup

1. Create a project for your RW612 board (for example `frdm_rw612`).
2. In the SDK component selector, add **els_pkc**. That brings in `src/comps`, the `rw61x` platform layer, and the bundled CMSIS.
3. Add the wolfSSL sources to the project. `wolfcrypt/src/port/nxp/els_pkc_port.c` is compiled like every other wolfCrypt port and gates itself on `WOLFSSL_ELS_PKC`, so it costs nothing when the port is off.
4. Copy `user_settings.h` from this directory into your project and define `WOLFSSL_USER_SETTINGS` for the build.
5. Add these include paths, all inside the els_pkc component: `src/inc`, `src/compiler`, `src/comps/*/inc`, `src/comps/*/inc/internal`, `src/platforms/rw61x`, `src/platforms/rw61x/inc`, `src/platforms/rw61x/cmsis_cortex_m_5_5_1/inc`, `includes/platform/rw61x`.

### Compiler flags that matter

| Flag | Why |
| --- | --- |
| `-mcpu=cortex-m33+nodsp` | Without `+nodsp` the vendor CMSIS `core_cm33.h` aborts the build with "Compiler generates DSP (SIMD) instructions for a device without DSP extensions". `-D__DSP_PRESENT=1` does **not** work around it. |
| `-DCPU_RW612ETA2I` | `fsl_device_registers.h` selects the register map from the part number. Use the macro matching your part; only the A2 parts appear in its selector. |
| `-mcmse` | Matches how NXP builds CLNS. |
| `-DNO_THREAD_LS` | Required on bare metal. See below. |
| `-DWOLFSSL_NO_GETPID` | Required with newlib. See below. |

### wolfCrypt_Init() returning -1000

`wolfCrypt_Init()` guards against recursive entry with a `__thread` variable whenever the toolchain advertises thread-local storage. On bare metal nothing sets the thread pointer, so that read returns garbage, the guard fires, and the call returns `DEADLOCK_AVERTED_E` (-1000) before initialising anything. Define `NO_THREAD_LS` unless your runtime really does set up TLS.

### random.c and an implicit declaration of getpid()

`--specs=nosys.specs` gives the linker a stub for every syscall, which is what
lets autoconf's link probes succeed without a board support package. It also
makes the probe for `getpid()` succeed, so `HAVE_GETPID` ends up defined even
though newlib's headers never declare the function, and `random.c` then fails
to compile on an implicit declaration. Define `WOLFSSL_NO_GETPID`; a bare metal
target has no processes to identify.

Toolchains shipping picolibc rather than newlib, such as the Zephyr SDK's
`arm-zephyr-eabi`, declare `getpid()` and do not need this.

## Building with autoconf instead

The same result from a source tarball or checkout. Note that no CI job builds this port today - it needs the vendor library and the SoC headers, neither of which the CI images carry - so a green run says nothing about it:

```sh
./autogen.sh
./configure --host=arm-none-eabi --disable-shared --enable-static \
--enable-cryptonly --enable-cryptocb \
--enable-cryptocbutils=keystore \
--enable-ecc --enable-aesgcm --enable-cmac --enable-curve25519 --enable-rsa \
--with-els-pkc=/path/to/els_pkc \
--with-mcux-sdk=/path/to/mcux-sdk-ng \
--disable-filesystem --enable-singlethreaded \
CFLAGS="-mcpu=cortex-m33+nodsp -mthumb -Os --specs=nosys.specs" \
CPPFLAGS="-DWOLFSSL_NO_SOCK -DWOLFSSL_USER_IO -DNO_WRITEV -DNO_DEV_RANDOM \
-DNO_THREAD_LS -DWOLFSSL_NO_GETPID"
make
```

`--with-mcux-sdk` wants a tree holding `devices/Wireless/RW/RW612` and `drivers/common`: your MCUXpresso SDK install, or a checkout of NXP's `mcux-sdk-ng`. The els_pkc platform layer includes `fsl_common.h`, `fsl_device_registers.h` and `fsl_ocotp.h` from it.

The resulting `libwolfssl.a` carries unresolved `mcuxCl*` references. That is correct: the application links CLNS.

To confirm the port really made it into the archive, check for its symbols rather than for the object file. The port compiles to an empty translation unit when `WOLFSSL_ELS_PKC` is missing, so a build can succeed with the port silently absent:

```sh
arm-none-eabi-nm src/.libs/libwolfssl.a | grep wc_ElsPkc
```

## Using it

`wolfCrypt_Init()` brings the port up and registers its crypto callback, so there is nothing to call by hand, and `wc_CryptoCb_DefaultDevID()` answers `WOLFSSL_ELS_PKC_DEVID`, so a context created without an explicit device is offloaded too:

```c
#include <wolfssl/wolfcrypt/port/nxp/els_pkc_port.h>

wolfCrypt_Init();

wc_Sha256 sha;
wc_InitSha256(&sha); /* offloaded */
wc_InitSha256_ex(&sha, NULL, WOLFSSL_ELS_PKC_DEVID); /* the same, explicitly */
wc_InitSha256_ex(&sha, NULL, INVALID_DEVID); /* kept in software */
```

Define `WC_NO_DEFAULT_DEVID` to switch the automatic routing off and require every context to name the device. Note it only reaches code that asks `wc_CryptoCb_DefaultDevID()` for a device: `wc_AesInit()` takes a `devId` argument directly, so pass `WOLFSSL_ELS_PKC_DEVID` there yourself.

Anything the hardware does not serve is *declined* with `CRYPTOCB_UNAVAILABLE` and completed in software, so an unsupported algorithm or key size is a performance question, never a failure.

A hardware *failure* is treated differently on purpose: the port reports the error rather than quietly finishing in software, because a caller that ignores the return would otherwise receive a confident bad result. Declining and failing are not the same thing.

`wolfCrypt_Cleanup()` unregisters the callback and releases the lock; `wc_ElsPkc_Init()` re-registers it if you need the port back afterwards.

Keys resident in the ELS key store are referenced rather than exported: attach a reference to a key with `wc_ElsPkc_EccUseSlot()`, `wc_ElsPkc_AesUseSlot()` or `wc_ElsPkc_CmacUseSlot()`. Those are the entry point - `wc_ElsPkc_MakeKeyRef()` is the primitive underneath them, and the ECC helper also pins the curve, without which the offload declines. See the port header for the key store operations and the reference format.
134 changes: 134 additions & 0 deletions IDE/MCUEXPRESSO/RW612/user_settings.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
/* 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
*/

/* wolfSSL configuration for the NXP RW612 (frdm_rw612) with the EdgeLock
* ELS + PKC crypto callback port, built from an MCUXpresso SDK project. See
* README.md for the SDK components and compiler flags. Under Zephyr none of
* this applies: the module's Kconfig generates the equivalent settings. */

#ifndef USER_SETTINGS_H
#define USER_SETTINGS_H

#ifdef __cplusplus
extern "C" {
#endif

/* ---------------------------------------------------------------------------
* Platform
* ------------------------------------------------------------------------ */

#define WOLFSSL_GENERAL_ALIGNMENT 4
#define SINGLE_THREADED

/* wolfCrypt_Init() uses a __thread recursion guard when the toolchain reports
* thread-local storage. Bare-metal startup never sets the thread pointer, so
* the guard reads garbage and the call fails with DEADLOCK_AVERTED_E (-1000)
* before doing any work. */
#define NO_THREAD_LS

/* newlib does not declare getpid(), but --specs=nosys.specs makes configure's
* link probe for it succeed, so random.c would compile against an implicit
* declaration. There are no processes here to identify. */
#define WOLFSSL_NO_GETPID
#define NO_FILESYSTEM
#define NO_WRITEV
#define WOLFSSL_NO_SOCK
#define WOLFSSL_USER_IO
#define NO_DEV_RANDOM /* entropy comes from the ELS DRBG, below */
#define WOLFCRYPT_ONLY /* drop for TLS; then supply IO and time */

/* No RTC by default on this board. Supply a real time source and remove this
* if certificate validity has to be checked. */
#define NO_ASN_TIME

/* ---------------------------------------------------------------------------
* EdgeLock (ELS + PKC) offload
* ------------------------------------------------------------------------ */

/* The single switch for the port. */
#define WOLFSSL_ELS_PKC

/* The port is a crypto callback; KEYSTORE adds the ELS key store operations.
*
* FIND matters more than it looks: with NO_DEV_RANDOM below there is no
* software seed, and wc_GenerateSeed() dispatches to a device only when the
* RNG carries a devId - which wc_InitRng() does not set. Without FIND,
* wc_InitRng() fails with WC_HW_E and nothing falls back. */
#define WOLF_CRYPTO_CB
#define WOLF_CRYPTO_CB_FIND
#define WOLF_CRYPTO_CB_KEYSTORE

/* Seed wolfCrypt's DRBG from the ELS hardware DRBG. */
#define HAVE_HASHDRBG

/* ---------------------------------------------------------------------------
* Algorithms
* ------------------------------------------------------------------------ */

/* Anything not listed here falls back to software through the normal
* CRYPTOCB_UNAVAILABLE path. */

#define WOLFSSL_SHA256
#define WOLFSSL_SHA384
#define WOLFSSL_SHA512

#define HAVE_AESGCM
#define WOLFSSL_AES_DIRECT
#define HAVE_AES_ECB
#define WOLFSSL_AES_COUNTER
#define WOLFSSL_CMAC

#define HAVE_ECC
#define ECC_USER_CURVES
#define HAVE_ECC256
#define HAVE_ECC384
#define HAVE_CURVE25519
/* Ed25519 is deliberately absent: the PKC does not serve EdDSA, so it would be
* pure software here and imply an offload that does not exist. */

/* SP math with the curves this build uses. SP_MATH is per-curve: a curve the
* SP backend was not built for fails at run time with WC_KEY_SIZE_E rather
* than at compile time, so keep this in step with the curve list above. */
#define WOLFSSL_SP_MATH_ALL
#define WOLFSSL_HAVE_SP_ECC
#define WOLFSSL_SP_384
#define WOLFSSL_HAVE_SP_RSA

#define WC_RSA_BLINDING
#define WOLFSSL_KEY_GEN

/* ---------------------------------------------------------------------------
* Size
* ------------------------------------------------------------------------ */

#define NO_DSA
#define NO_RC4
#define NO_MD4
#define NO_DES3
#define NO_PSK
#define NO_OLD_TLS
#define WOLFSSL_SMALL_STACK

#ifdef __cplusplus
}
#endif

#endif /* USER_SETTINGS_H */
Loading
Loading