Repository navigation
NXP EdgeLock (ELS + PKC) crypto callback port #48
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from all commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
103b75c
nxp: add the EdgeLock crypto callback port with SHA-256 offload
Frauschi 730f8c6
nxp: offload SHA-384 and SHA-512 to the EdgeLock
Frauschi 34aa055
nxp: offload AES-ECB, CBC and CTR to the EdgeLock
Frauschi 1db2a52
nxp: offload AES-GCM to the EdgeLock
Frauschi f61ebc9
nxp: offload AES-CMAC to the EdgeLock
Frauschi 6f97d3b
nxp: offload the DRBG to the EdgeLock
Frauschi 8c915d0
nxp: offload P-256 to EdgeLock key slots
Frauschi b764c08
nxp: open a PKC session and offload RSA
Frauschi 47bd6ec
nxp: offload X25519 to the PKC
Frauschi 112044f
nxp: offload ECDSA on the PKC for curves beyond P-256
Frauschi ebd2fc4
cryptocb: let wc_KeyStore_Derive() request the key size
Frauschi e077d8a
nxp: implement the EdgeLock key store operations
Frauschi 1844c9c
nxp: derive NXP_DIE_KEK_SK instead of requiring a provisioned one
Frauschi c4d8dd3
nxp: build the EdgeLock port from autoconf
Frauschi 255dae0
nxp: document the MCUXpresso build for the EdgeLock port
Frauschi 9e3c5c2
nxp: run the Zephyr test and benchmark against the EdgeLock
Frauschi File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 */ |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.