Skip to content
Open
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
28 changes: 24 additions & 4 deletions .github/workflows/se050-sim.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,22 @@ env:

jobs:
se050_sim:
name: wolfCrypt against SE050 simulator
name: wolfCrypt against SE050 simulator (${{ matrix.name }})
if: ${{ (github.repository_owner == 'wolfssl') && (github.event_name != 'pull_request' || github.event.pull_request.draft == false) }}
runs-on: ubuntu-24.04
timeout-minutes: 30
strategy:
fail-fast: false
matrix:
include:
# Default build: every keyed operation is offloaded to the SE050.
- name: default
extra_cflags: ''
# Per-key runtime HW/SW routing. The wolfCrypt test binary runs the
# ecc/ed25519/curve25519/rsa SE050_ONLY_KEY_ID coverage (software key
# vs SE050-resident key) added to wolfcrypt/test/test.c.
- name: only-key-id
extra_cflags: '-DWOLFSSL_SE050_ONLY_KEY_ID'
steps:
- name: Checkout wolfSSL (PR source)
uses: actions/checkout@v5
Expand Down Expand Up @@ -75,9 +87,17 @@ jobs:
file: simulators/SE050Sim/Dockerfile.wolfcrypt
push: false
load: true
tags: wolfssl-se050-sim:ci
tags: wolfssl-se050-sim:ci-${{ matrix.name }}
# WOLFSSL_EXTRA_CFLAGS is appended to the wolfSSL ./configure CFLAGS by
# the simulator's Dockerfile.wolfcrypt (ARG WOLFSSL_EXTRA_CFLAGS). When
# bumping SIMULATORS_REF, keep that ARG in place so the only-key-id
# matrix leg actually defines the macro.
build-args: |
WOLFSSL_EXTRA_CFLAGS=${{ matrix.extra_cflags }}
# Only the default leg refreshes the shared cache to avoid two matrix
# legs writing the same registry ref.
cache-from: type=registry,ref=ghcr.io/wolfssl/wolfssl-sim-cache:se050
cache-to: ${{ (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') && 'type=registry,ref=ghcr.io/wolfssl/wolfssl-sim-cache:se050,mode=max' || '' }}
cache-to: ${{ ((github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') && matrix.name == 'default') && 'type=registry,ref=ghcr.io/wolfssl/wolfssl-sim-cache:se050,mode=max' || '' }}

- name: Run wolfCrypt tests against simulator
run: docker run --rm wolfssl-se050-sim:ci
run: docker run --rm wolfssl-se050-sim:ci-${{ matrix.name }}
6 changes: 4 additions & 2 deletions wolfcrypt/src/curve25519.c
Original file line number Diff line number Diff line change
Expand Up @@ -585,15 +585,17 @@ int wc_curve25519_make_key(WC_RNG* rng, int keysize, curve25519_key* key)
#endif /* WOLFSSL_ASYNC_CRYPT && WC_ASYNC_ENABLE_X25519 &&
* WOLFSSL_ASYNC_CRYPT_SW */

#ifdef WOLFSSL_SE050
#if defined(WOLFSSL_SE050) && !defined(WOLFSSL_SE050_ONLY_KEY_ID)
ret = se050_curve25519_create_key(key, keysize);
#elif defined(WC_X25519_NONBLOCK)
if (key->nb_ctx != NULL) {
ret = wc_curve25519_make_key_nb(rng, keysize, key);
}
else
#endif
#if !defined(WOLFSSL_SE050)
/* Under WOLFSSL_SE050_ONLY_KEY_ID, generate a software key (keyIdSet == 0);
* its shared-secret computation routes through software (privSet == 1). */
#if !defined(WOLFSSL_SE050) || defined(WOLFSSL_SE050_ONLY_KEY_ID)
{
ret = wc_curve25519_make_priv(rng, keysize, key->k);
if (ret == 0) {
Expand Down
58 changes: 52 additions & 6 deletions wolfcrypt/src/ecc.c
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,14 @@ ECC Curve Sizes:
#undef HAVE_ECC_VERIFY_HELPER
#define HAVE_ECC_VERIFY_HELPER
#endif
#if defined(WOLFSSL_SE050_NO_ECDSA_VERIFY) && defined(HAVE_ECC_VERIFY)
/* Compile in the software verify helper whenever SE050 hardware ECDSA verify is
* bypassed:
* - WOLFSSL_SE050_NO_ECDSA_VERIFY disables SE050 ECDSA verify outright.
* - WOLFSSL_SE050_ONLY_KEY_ID verifies software keys (keyIdSet == 0) in
* wolfCrypt; the SE050 is used at runtime only for keys resident in HW. */
#if (defined(WOLFSSL_SE050_NO_ECDSA_VERIFY) || \
(defined(WOLFSSL_SE050) && defined(WOLFSSL_SE050_ONLY_KEY_ID))) && \
defined(HAVE_ECC_VERIFY)
#define HAVE_ECC_VERIFY_HELPER
#endif

Expand Down Expand Up @@ -4716,13 +4723,15 @@ int wc_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key, byte* out,
word32* outlen)
{
int err = 0;
int privateKeyOk = 0;

#if defined(WOLFSSL_CRYPTOCELL) && !defined(WOLFSSL_ATECC508A) && \
!defined(WOLFSSL_ATECC608A) && !defined(WOLFSSL_MICROCHIP_TA100)
CRYS_ECDH_TempData_t tempBuff;
#endif

(void)err;
(void)privateKeyOk;

if (private_key == NULL || public_key == NULL || out == NULL ||
outlen == NULL) {
Expand All @@ -4745,8 +4754,16 @@ int wc_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key, byte* out,
return NO_VALID_DEVID;
#else /* !WOLF_CRYPTO_CB_ONLY_ECC */
/* type valid? */
if (private_key->type != ECC_PRIVATEKEY &&
private_key->type != ECC_PRIVATEKEY_ONLY) {
privateKeyOk = private_key->type == ECC_PRIVATEKEY ||
private_key->type == ECC_PRIVATEKEY_ONLY;
#if defined(WOLFSSL_SE050) && !defined(WOLFSSL_SE050_NO_ECDHE) && \
defined(WOLFSSL_SE050_ONLY_KEY_ID)
/* A SE050 key-id handle can represent a private key even though
* wc_ecc_use_key_id() only loads the public point into the ecc_key. */
if (private_key->keyIdSet)
privateKeyOk = 1;
#endif
if (!privateKeyOk) {
return ECC_BAD_ARG_E;
}

Expand Down Expand Up @@ -4789,6 +4806,15 @@ int wc_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key, byte* out,
err = silabs_ecc_shared_secret(private_key, public_key, out, outlen);
#elif defined(WOLFSSL_KCAPI_ECC)
err = KcapiEcc_SharedSecret(private_key, public_key, out, outlen);
#elif defined(WOLFSSL_SE050) && !defined(WOLFSSL_SE050_NO_ECDHE) && \
defined(WOLFSSL_SE050_ONLY_KEY_ID)
/* SE050-resident private key uses hardware ECDH; a software private key
* (keyIdSet == 0) uses the wolfCrypt software implementation. */
if (private_key->keyIdSet)
err = se050_ecc_shared_secret(private_key, public_key, out, outlen);
else
err = wc_ecc_shared_secret_ex(private_key, &public_key->pubkey, out,
outlen);
#elif defined(WOLFSSL_SE050) && !defined(WOLFSSL_SE050_NO_ECDHE)
err = se050_ecc_shared_secret(private_key, public_key, out, outlen);
#else
Expand Down Expand Up @@ -5869,7 +5895,8 @@ static int _ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key,
else {
err = NOT_COMPILED_IN;
}
#elif defined(WOLFSSL_SE050) && !defined(WOLFSSL_SE050_NO_ECDHE)
#elif defined(WOLFSSL_SE050) && !defined(WOLFSSL_SE050_NO_ECDHE) && \
!defined(WOLFSSL_SE050_ONLY_KEY_ID)
err = se050_ecc_create_key(key, key->dp->id, key->dp->size);
key->type = ECC_PRIVATEKEY;
#elif defined(WOLFSSL_CRYPTOCELL)
Expand Down Expand Up @@ -6969,7 +6996,14 @@ int wc_ecc_sign_hash(const byte* in, word32 inlen, byte* out, word32 *outlen,
}

/* hardware crypto */
#if defined(WOLFSSL_ATECC508A) || defined(WOLFSSL_ATECC608A) || \
#if defined(WOLFSSL_SE050) && defined(WOLFSSL_SE050_ONLY_KEY_ID)
/* Route by key location: SE050-resident keys sign in hardware, software
* keys (keyIdSet == 0) sign with the wolfCrypt software implementation. */
if (key->keyIdSet)
err = wc_ecc_sign_hash_hw(in, inlen, r, s, out, outlen, rng, key);
else
err = wc_ecc_sign_hash_ex(in, inlen, rng, key, r, s);
#elif defined(WOLFSSL_ATECC508A) || defined(WOLFSSL_ATECC608A) || \
defined(WOLFSSL_MICROCHIP_TA100) || \
defined(PLUTON_CRYPTO_ECC) || defined(WOLFSSL_CRYPTOCELL) || \
defined(WOLFSSL_SILABS_SE_ACCEL) || defined(WOLFSSL_KCAPI_ECC) || \
Expand Down Expand Up @@ -9461,8 +9495,11 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash,
#elif defined(WOLFSSL_XILINX_CRYPT_VERSAL)
byte sigRS[ECC_MAX_CRYPTO_HW_SIZE * 2];
byte hashcopy[ECC_MAX_CRYPTO_HW_SIZE] = {0};
#elif defined(WOLFSSL_SE050) && !defined(WOLFSSL_SE050_NO_ECDSA_VERIFY)
#elif defined(WOLFSSL_SE050) && !defined(WOLFSSL_SE050_NO_ECDSA_VERIFY) && \
!defined(WOLFSSL_SE050_ONLY_KEY_ID)
#else
/* Software verify helper (also used for SE050 software keys under
* WOLFSSL_SE050_ONLY_KEY_ID) needs the curve specs. */
int curveLoaded = 0;
DECLARE_CURVE_SPECS(ECC_CURVE_FIELD_COUNT);
#endif
Expand Down Expand Up @@ -9497,6 +9534,15 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash,
return err;
}

#if defined(WOLFSSL_SE050) && defined(WOLFSSL_SE050_ONLY_KEY_ID) && \
!defined(WOLFSSL_SE050_NO_ECDSA_VERIFY)
/* Key resident in the SE050: verify in hardware. Software keys fall through
* to the wolfCrypt verify helper below. */
if (key->keyIdSet) {
return se050_ecc_verify_hash_ex(hash, hashlen, r, s, key, res);
}
#endif

keySz = (word32)key->dp->size;

#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) && \
Expand Down
42 changes: 37 additions & 5 deletions wolfcrypt/src/ed25519.c
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,7 @@ int wc_ed25519_sign_msg_ex(const byte* in, word32 inLen, byte* out,
const byte* context, byte contextLen)
{
int ret;
#ifdef WOLFSSL_SE050
#if defined(WOLFSSL_SE050) && !defined(WOLFSSL_SE050_ONLY_KEY_ID)
(void)context;
(void)contextLen;
(void)type;
Expand All @@ -454,6 +454,20 @@ int wc_ed25519_sign_msg_ex(const byte* in, word32 inLen, byte* out,
return BAD_FUNC_ARG;
}

#if defined(WOLFSSL_SE050) && defined(WOLFSSL_SE050_ONLY_KEY_ID)
/* Key resident in the SE050: sign in hardware. Software keys fall through
* to the wolfCrypt software implementation below. */
if (key->keyIdSet) {
/* The SE050 performs only PureEdDSA; it cannot apply the Ed25519ctx or
* Ed25519ph variants, so reject them rather than silently signing with
* the wrong scheme. */
if (type == Ed25519ctx || type == Ed25519ph || contextLen != 0) {
return BAD_FUNC_ARG;
}
return se050_ed25519_sign_msg(in, inLen, out, outLen, key);
}
#endif

if ((type == Ed25519ph) &&
(inLen != WC_SHA512_DIGEST_SIZE))
{
Expand Down Expand Up @@ -696,7 +710,9 @@ int wc_ed25519ph_sign_msg(const byte* in, word32 inLen, byte* out,
#endif /* HAVE_ED25519_SIGN */

#ifdef HAVE_ED25519_VERIFY
#ifndef WOLFSSL_SE050
/* The software verify helpers are also needed under WOLFSSL_SE050_ONLY_KEY_ID
* so that software keys (keyIdSet == 0) can be verified in wolfCrypt. */
#if !defined(WOLFSSL_SE050) || defined(WOLFSSL_SE050_ONLY_KEY_ID)

#ifdef WOLFSSL_CHECK_VER_FAULTS
static const byte sha512_empty[] = {
Expand Down Expand Up @@ -930,7 +946,8 @@ static int ed25519_verify_msg_final_with_sha(const byte* sig, word32 sigLen,
}
#endif /* WOLFSSL_SE050 */

#if defined(WOLFSSL_ED25519_STREAMING_VERIFY) && !defined(WOLFSSL_SE050)
#if defined(WOLFSSL_ED25519_STREAMING_VERIFY) && \
(!defined(WOLFSSL_SE050) || defined(WOLFSSL_SE050_ONLY_KEY_ID))

int wc_ed25519_verify_msg_init(const byte* sig, word32 sigLen, ed25519_key* key,
byte type, const byte* context, byte contextLen) {
Expand All @@ -950,7 +967,8 @@ int wc_ed25519_verify_msg_final(const byte* sig, word32 sigLen, int* res,
key, &key->sha);
}

#endif /* WOLFSSL_ED25519_STREAMING_VERIFY && !WOLFSSL_SE050 */
#endif /* WOLFSSL_ED25519_STREAMING_VERIFY &&
* (!WOLFSSL_SE050 || WOLFSSL_SE050_ONLY_KEY_ID) */

/*
sig is array of bytes containing the signature
Expand All @@ -966,7 +984,7 @@ int wc_ed25519_verify_msg_ex(const byte* sig, word32 sigLen, const byte* msg,
byte type, const byte* context, byte contextLen)
{
int ret;
#ifdef WOLFSSL_SE050
#if defined(WOLFSSL_SE050) && !defined(WOLFSSL_SE050_ONLY_KEY_ID)
(void)type;
(void)context;
(void)contextLen;
Expand All @@ -979,6 +997,20 @@ int wc_ed25519_verify_msg_ex(const byte* sig, word32 sigLen, const byte* msg,
WC_DECLARE_VAR(sha, wc_Sha512, 1, key ? key->heap : NULL);
#endif

#if defined(WOLFSSL_SE050) && defined(WOLFSSL_SE050_ONLY_KEY_ID)
/* Key resident in the SE050: verify in hardware. Software keys fall through
* to the wolfCrypt software implementation below. */
if (key != NULL && key->keyIdSet) {
/* The SE050 performs only PureEdDSA; it cannot apply the Ed25519ctx or
* Ed25519ph variants, so reject them rather than silently verifying
* against the wrong scheme. */
if (type == Ed25519ctx || type == Ed25519ph || contextLen != 0) {
return BAD_FUNC_ARG;
}
return se050_ed25519_verify_msg(sig, sigLen, msg, msgLen, key, res);
}
#endif

/* sanity check on arguments */
if (sig == NULL || msg == NULL || res == NULL || key == NULL ||
(context == NULL && contextLen != 0))
Expand Down
29 changes: 29 additions & 0 deletions wolfcrypt/src/port/nxp/README_SE050.md
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,35 @@ offloaded to the SE050, but RSA PKCS#1 v1.5 verification (`wc_RsaSSL_Verify()`)
uses wolfCrypt software (public-key exponentiation + unpad). RSA PSS verify and
RSA key-exchange decrypt are unaffected.

**`WOLFSSL_SE050_ONLY_KEY_ID`**

Requires `WOLFSSL_SE050`. By default every keyed operation is routed to the
SE050 at compile time. When this macro is defined, routing becomes a per-key
*runtime* decision based on `key->keyIdSet`:

- A key resident in the SE050 (`keyIdSet == 1`, established via
`wc_ecc_use_key_id()`, `wc_se050_ecc_insert_private_key()`, `wc_RsaUseKeyId()`,
`wc_se050_rsa_insert_private_key()`, etc.) runs the operation on the SE050.
- A software key (`keyIdSet == 0`) runs the operation in wolfCrypt software.

Because both paths must be available, the build compiles *both* the SE050 and
the wolfCrypt software implementations (larger code size). Key generation
(`wc_ecc_make_key()`, `wc_curve25519_make_key()`, `wc_MakeRsaKey()`; Ed25519
key generation is already software-only) produces a *software* key
(`keyIdSet == 0`); it does not implicitly create a key inside the SE050.

In-scope operations: ECC sign/verify/ECDH/keygen, Ed25519 sign/verify,
Curve25519 shared-secret/keygen, and RSA sign/verify/encrypt/decrypt/keygen.
RNG (TRNG) and hashing have no key and are unaffected. AES routing continues to
be governed by `WOLFSSL_SE050_CRYPT` and the AES `useSWCrypt` flag (the SE050
AES path is opt-in and already chosen per-key at runtime).

This macro composes with the `WOLFSSL_SE050_NO_*` macros above: if a `NO_*`
macro disables an operation, that operation always uses wolfCrypt software
regardless of `keyIdSet`. The SE050 port's "import a software key into the
SE050 on first use" behavior is disabled under this macro, so a software key is
never silently moved into hardware.

## wolfSSL HostCrypto Support

The NXP SE05x Plug & Trust Middleware by default can use either OpenSSL or
Expand Down
Loading
Loading