Skip to content

Commit c3aeeab

Browse files
committed
Fix SE050 Ed25519 port bugs and add simulator CI workflow
- se050_ed25519_verify_msg: initialize *res = 0 at entry so failures don't leak a stale res = 1 from a prior good verify. - Ed25519 import functions: reset keyIdSet / keyId under WOLFSSL_SE050 in wc_ed25519_import_private_key_ex, wc_ed25519_import_private_only, wc_ed25519_import_public_ex so overwriting host-side key material invalidates any prior SE050 object binding. - New workflow .github/workflows/se050-sim.yml: builds wolfSSL against the NXP Plug&Trust SDK and runs the wolfCrypt tests against the SE050Sim simulator. Patches the upstream Dockerfile to use the PR's wolfSSL source. - ed25519_test SE050 adjustments: - Cap the RFC 8032 loop at 5 iters — iter 5's 1023 B msg exceeds NXP SDK SE05X_TLV_BUF_SIZE_CMD = 900. - rareEd verifies and private-only sign: expect WC_HW_E (SE050 delegates malformed-input rejection to the secure element) instead of BAD_FUNC_ARG / SIG_VERIFY_E. - Skip ed25519ctx_test / ed25519ph_test — SE050 port drops the context/prehash params so RFC 8032 ctx/ph vectors can't byte-match.
1 parent 178e10e commit c3aeeab

4 files changed

Lines changed: 135 additions & 5 deletions

File tree

.github/workflows/se050-sim.yml

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
name: SE050 simulator test
2+
3+
# START OF COMMON SECTION
4+
on:
5+
push:
6+
branches: [ 'master', 'main', 'release/**' ]
7+
pull_request:
8+
branches: [ '*' ]
9+
10+
concurrency:
11+
group: ${{ github.workflow }}-${{ github.ref }}
12+
cancel-in-progress: true
13+
# END OF COMMON SECTION
14+
15+
# Build the SE050 software simulator (https://github.com/LinuxJedi/SE050Sim),
16+
# build wolfSSL against its NXP Plug&Trust SDK + simulator bridge, and run the
17+
# wolfCrypt SE050 test binary against the simulator TCP server.
18+
#
19+
# The simulator's own Dockerfile (Dockerfile.wolfcrypt) clones wolfSSL master.
20+
# We patch it to COPY the PR checkout instead so CI reflects the PR's source.
21+
22+
env:
23+
# Pin the simulator to a known-good revision. Bump this deliberately after
24+
# validating upstream changes in a standalone PR.
25+
SE050SIM_REF: main
26+
27+
jobs:
28+
se050_sim:
29+
name: wolfCrypt against SE050 simulator
30+
if: github.repository_owner == 'wolfssl'
31+
runs-on: ubuntu-24.04
32+
timeout-minutes: 30
33+
steps:
34+
- name: Checkout wolfSSL (PR source)
35+
uses: actions/checkout@v4
36+
with:
37+
path: wolfssl-src
38+
39+
- name: Clone SE050 simulator
40+
run: |
41+
git clone https://github.com/LinuxJedi/SE050Sim se050sim
42+
cd se050sim && git checkout "$SE050SIM_REF"
43+
44+
- name: Stage PR wolfSSL into simulator build context
45+
run: mv wolfssl-src se050sim/wolfssl
46+
47+
- name: Patch Dockerfile to use PR wolfSSL instead of upstream master
48+
working-directory: se050sim
49+
run: |
50+
sed -i 's|^RUN git clone --depth 1 https://github.com/wolfSSL/wolfssl.git /app/wolfssl$|COPY wolfssl /app/wolfssl|' Dockerfile.wolfcrypt
51+
# Fail fast if the pattern drifted upstream — better a clear error
52+
# than a CI run that silently tests master.
53+
grep -q '^COPY wolfssl /app/wolfssl$' Dockerfile.wolfcrypt
54+
! grep -q 'git clone .*wolfssl\.git' Dockerfile.wolfcrypt
55+
56+
- uses: docker/setup-buildx-action@v3
57+
58+
- name: Build wolfCrypt-SE050 test image
59+
uses: docker/build-push-action@v5
60+
with:
61+
context: se050sim
62+
file: se050sim/Dockerfile.wolfcrypt
63+
push: false
64+
load: true
65+
tags: wolfssl-se050-sim:ci
66+
cache-from: type=gha
67+
cache-to: type=gha,mode=max
68+
69+
- name: Run wolfCrypt tests against simulator
70+
run: docker run --rm wolfssl-se050-sim:ci

wolfcrypt/src/ed25519.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1169,6 +1169,12 @@ int wc_ed25519_import_public_ex(const byte* in, word32 inLen, ed25519_key* key,
11691169
if (inLen < ED25519_PUB_KEY_SIZE)
11701170
return BAD_FUNC_ARG;
11711171

1172+
#ifdef WOLFSSL_SE050
1173+
/* Importing new key material invalidates any prior SE050 object binding. */
1174+
key->keyIdSet = 0;
1175+
key->keyId = 0;
1176+
#endif
1177+
11721178
/* compressed prefix according to draft
11731179
http://www.ietf.org/id/draft-koch-eddsa-for-openpgp-02.txt */
11741180
if (in[0] == 0x40 && inLen == ED25519_PUB_KEY_SIZE + 1) {
@@ -1255,6 +1261,12 @@ int wc_ed25519_import_private_only(const byte* priv, word32 privSz,
12551261
if (privSz != ED25519_KEY_SIZE)
12561262
return BAD_FUNC_ARG;
12571263

1264+
#ifdef WOLFSSL_SE050
1265+
/* Importing new key material invalidates any prior SE050 object binding. */
1266+
key->keyIdSet = 0;
1267+
key->keyId = 0;
1268+
#endif
1269+
12581270
XMEMCPY(key->k, priv, ED25519_KEY_SIZE);
12591271
key->privKeySet = 1;
12601272

@@ -1311,6 +1323,12 @@ int wc_ed25519_import_private_key_ex(const byte* priv, word32 privSz,
13111323
return BAD_FUNC_ARG;
13121324
}
13131325

1326+
#ifdef WOLFSSL_SE050
1327+
/* Importing new key material invalidates any prior SE050 object binding. */
1328+
key->keyIdSet = 0;
1329+
key->keyId = 0;
1330+
#endif
1331+
13141332
XMEMCPY(key->k, priv, ED25519_KEY_SIZE);
13151333
key->privKeySet = 1;
13161334

wolfcrypt/src/port/nxp/se050_port.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3039,6 +3039,8 @@ int se050_ed25519_verify_msg(const byte* signature, word32 signatureLen,
30393039
key, signature, signatureLen, msg, msgLen);
30403040
#endif
30413041

3042+
*res = 0;
3043+
30423044
if (cfg_se050_i2c_pi == NULL) {
30433045
return WC_HW_E;
30443046
}

wolfcrypt/test/test.c

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41340,7 +41340,16 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t ed25519_test(void)
4134041340

4134141341
#if defined(HAVE_ED25519_SIGN) && defined(HAVE_ED25519_KEY_EXPORT) && \
4134241342
defined(HAVE_ED25519_KEY_IMPORT)
41343+
#ifdef WOLFSSL_SE050
41344+
/* Iter 5 uses RFC 8032 msg4 (~1023 bytes), which exceeds the NXP
41345+
* Plug&Trust SDK's SE05X_TLV_BUF_SIZE_CMD = 900 byte APDU buffer:
41346+
* EdDSASign fails with "Not enough buffer" before the command reaches
41347+
* the secure element. Cap at 5 iterations until the SDK buffer is
41348+
* enlarged upstream. */
41349+
for (i = 0; i < 5; i++) {
41350+
#else
4134341351
for (i = 0; i < 6; i++) {
41352+
#endif
4134441353
outlen = sizeof(out);
4134541354
XMEMSET(out, 0, sizeof(out));
4134641355

@@ -41413,7 +41422,12 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t ed25519_test(void)
4141341422
#endif /* HAVE_ED25519_VERIFY */
4141441423
}
4141541424

41416-
#ifdef HAVE_ED25519_VERIFY
41425+
#if defined(HAVE_ED25519_VERIFY)
41426+
/* These cases exercise host-side signature-encoding pre-validation (e.g.,
41427+
* sig == curve order). The SE050 port delegates verify to the secure
41428+
* element, which rejects all four inputs with WC_HW_E rather than the
41429+
* BAD_FUNC_ARG / SIG_VERIFY_E the host-side path produces — so the
41430+
* expected error code differs below when built against an SE050. */
4141741431
{
4141841432
/* Run tests for some rare code paths */
4141941433
/* sig is exactly equal to the order */
@@ -41466,35 +41480,53 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t ed25519_test(void)
4146641480
if (ret != 0)
4146741481
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), cleanup);
4146841482

41483+
#ifdef WOLFSSL_SE050
41484+
#define RARE_ED_BAD_ENC_E WC_HW_E
41485+
#define RARE_ED_BAD_SIG_E WC_HW_E
41486+
#else
41487+
#define RARE_ED_BAD_ENC_E BAD_FUNC_ARG
41488+
#define RARE_ED_BAD_SIG_E SIG_VERIFY_E
41489+
#endif
41490+
4146941491
ret = wc_ed25519_verify_msg(rareEd1, sizeof(rareEd1), msgs[0], msgSz[0],
4147041492
&verify, key);
41471-
if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG))
41493+
if (ret != WC_NO_ERR_TRACE(RARE_ED_BAD_ENC_E))
4147241494
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), cleanup);
4147341495

4147441496
ret = wc_ed25519_verify_msg(rareEd2, sizeof(rareEd2), msgs[0], msgSz[0],
4147541497
&verify, key);
41476-
if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG))
41498+
if (ret != WC_NO_ERR_TRACE(RARE_ED_BAD_ENC_E))
4147741499
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), cleanup);
4147841500

4147941501
ret = wc_ed25519_verify_msg(rareEd3, sizeof(rareEd3), msgs[0], msgSz[0],
4148041502
&verify, key);
41481-
if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG))
41503+
if (ret != WC_NO_ERR_TRACE(RARE_ED_BAD_ENC_E))
4148241504
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), cleanup);
4148341505

4148441506
ret = wc_ed25519_verify_msg(rareEd4, sizeof(rareEd4), msgs[0], msgSz[0],
4148541507
&verify, key);
41486-
if (ret != WC_NO_ERR_TRACE(SIG_VERIFY_E))
41508+
if (ret != WC_NO_ERR_TRACE(RARE_ED_BAD_SIG_E))
4148741509
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), cleanup);
41510+
41511+
#undef RARE_ED_BAD_ENC_E
41512+
#undef RARE_ED_BAD_SIG_E
4148841513
}
4148941514
#endif /* HAVE_ED25519_VERIFY */
4149041515

41516+
#ifndef WOLFSSL_SE050
41517+
/* Ed25519ctx and Ed25519ph require passing a context / prehash flag
41518+
* through to the signer. The SE050 port's se050_ed25519_sign_msg /
41519+
* _verify_msg drop those parameters and always do plain Ed25519, so the
41520+
* RFC 8032 ctx/ph test vectors cannot match. Skip these variants when
41521+
* built against an SE050. */
4149141522
ret = ed25519ctx_test();
4149241523
if (ret != 0)
4149341524
goto cleanup;
4149441525

4149541526
ret = ed25519ph_test();
4149641527
if (ret != 0)
4149741528
goto cleanup;
41529+
#endif /* !WOLFSSL_SE050 */
4149841530

4149941531
#ifndef NO_ASN
4150041532
/* Try ASN.1 encoded private-only key and public key. */
@@ -41509,8 +41541,16 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t ed25519_test(void)
4150941541
sizeof(badPrivateEd25519)) == 0)
4151041542
ERROR_OUT(WC_TEST_RET_ENC_NC, cleanup);
4151141543

41544+
/* Signing with a private-only key (no public loaded yet) is rejected on
41545+
* the host with BAD_FUNC_ARG. The SE050 port instead fails inside
41546+
* sss_se05x_key_store_set_ecc_keypair and returns WC_HW_E, so accept
41547+
* that alternate error code when built against an SE050. */
4151241548
ret = wc_ed25519_sign_msg(msgs[0], msgSz[0], out, &outlen, key3);
41549+
#ifdef WOLFSSL_SE050
41550+
if (ret != WC_NO_ERR_TRACE(WC_HW_E))
41551+
#else
4151341552
if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG))
41553+
#endif
4151441554
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), cleanup);
4151541555

4151641556
/* try with a buffer size that is too large */

0 commit comments

Comments
 (0)