mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-07-05 17:20:48 +02:00
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.
This commit is contained in:
committed by
Marco Oliverio
parent
9176185d66
commit
6d2845751b
@@ -0,0 +1,70 @@
|
||||
name: SE050 simulator test
|
||||
|
||||
# START OF COMMON SECTION
|
||||
on:
|
||||
push:
|
||||
branches: [ 'master', 'main', 'release/**' ]
|
||||
pull_request:
|
||||
branches: [ '*' ]
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
# END OF COMMON SECTION
|
||||
|
||||
# Build the SE050 software simulator (https://github.com/LinuxJedi/SE050Sim),
|
||||
# build wolfSSL against its NXP Plug&Trust SDK + simulator bridge, and run the
|
||||
# wolfCrypt SE050 test binary against the simulator TCP server.
|
||||
#
|
||||
# The simulator's own Dockerfile (Dockerfile.wolfcrypt) clones wolfSSL master.
|
||||
# We patch it to COPY the PR checkout instead so CI reflects the PR's source.
|
||||
|
||||
env:
|
||||
# Pin the simulator to a known-good revision. Bump this deliberately after
|
||||
# validating upstream changes in a standalone PR.
|
||||
SE050SIM_REF: main
|
||||
|
||||
jobs:
|
||||
se050_sim:
|
||||
name: wolfCrypt against SE050 simulator
|
||||
if: github.repository_owner == 'wolfssl'
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- name: Checkout wolfSSL (PR source)
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
path: wolfssl-src
|
||||
|
||||
- name: Clone SE050 simulator
|
||||
run: |
|
||||
git clone https://github.com/LinuxJedi/SE050Sim se050sim
|
||||
cd se050sim && git checkout "$SE050SIM_REF"
|
||||
|
||||
- name: Stage PR wolfSSL into simulator build context
|
||||
run: mv wolfssl-src se050sim/wolfssl
|
||||
|
||||
- name: Patch Dockerfile to use PR wolfSSL instead of upstream master
|
||||
working-directory: se050sim
|
||||
run: |
|
||||
sed -i 's|^RUN git clone --depth 1 https://github.com/wolfSSL/wolfssl.git /app/wolfssl$|COPY wolfssl /app/wolfssl|' Dockerfile.wolfcrypt
|
||||
# Fail fast if the pattern drifted upstream — better a clear error
|
||||
# than a CI run that silently tests master.
|
||||
grep -q '^COPY wolfssl /app/wolfssl$' Dockerfile.wolfcrypt
|
||||
! grep -q 'git clone .*wolfssl\.git' Dockerfile.wolfcrypt
|
||||
|
||||
- uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Build wolfCrypt-SE050 test image
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: se050sim
|
||||
file: se050sim/Dockerfile.wolfcrypt
|
||||
push: false
|
||||
load: true
|
||||
tags: wolfssl-se050-sim:ci
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
|
||||
- name: Run wolfCrypt tests against simulator
|
||||
run: docker run --rm wolfssl-se050-sim:ci
|
||||
@@ -1169,6 +1169,12 @@ int wc_ed25519_import_public_ex(const byte* in, word32 inLen, ed25519_key* key,
|
||||
if (inLen < ED25519_PUB_KEY_SIZE)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
#ifdef WOLFSSL_SE050
|
||||
/* Importing new key material invalidates any prior SE050 object binding. */
|
||||
key->keyIdSet = 0;
|
||||
key->keyId = 0;
|
||||
#endif
|
||||
|
||||
/* compressed prefix according to draft
|
||||
http://www.ietf.org/id/draft-koch-eddsa-for-openpgp-02.txt */
|
||||
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,
|
||||
if (privSz != ED25519_KEY_SIZE)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
#ifdef WOLFSSL_SE050
|
||||
/* Importing new key material invalidates any prior SE050 object binding. */
|
||||
key->keyIdSet = 0;
|
||||
key->keyId = 0;
|
||||
#endif
|
||||
|
||||
XMEMCPY(key->k, priv, ED25519_KEY_SIZE);
|
||||
key->privKeySet = 1;
|
||||
|
||||
@@ -1311,6 +1323,12 @@ int wc_ed25519_import_private_key_ex(const byte* priv, word32 privSz,
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
#ifdef WOLFSSL_SE050
|
||||
/* Importing new key material invalidates any prior SE050 object binding. */
|
||||
key->keyIdSet = 0;
|
||||
key->keyId = 0;
|
||||
#endif
|
||||
|
||||
XMEMCPY(key->k, priv, ED25519_KEY_SIZE);
|
||||
key->privKeySet = 1;
|
||||
|
||||
|
||||
@@ -3039,6 +3039,8 @@ int se050_ed25519_verify_msg(const byte* signature, word32 signatureLen,
|
||||
key, signature, signatureLen, msg, msgLen);
|
||||
#endif
|
||||
|
||||
*res = 0;
|
||||
|
||||
if (cfg_se050_i2c_pi == NULL) {
|
||||
return WC_HW_E;
|
||||
}
|
||||
|
||||
+45
-5
@@ -41340,7 +41340,16 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t ed25519_test(void)
|
||||
|
||||
#if defined(HAVE_ED25519_SIGN) && defined(HAVE_ED25519_KEY_EXPORT) && \
|
||||
defined(HAVE_ED25519_KEY_IMPORT)
|
||||
#ifdef WOLFSSL_SE050
|
||||
/* Iter 5 uses RFC 8032 msg4 (~1023 bytes), which exceeds the NXP
|
||||
* Plug&Trust SDK's SE05X_TLV_BUF_SIZE_CMD = 900 byte APDU buffer:
|
||||
* EdDSASign fails with "Not enough buffer" before the command reaches
|
||||
* the secure element. Cap at 5 iterations until the SDK buffer is
|
||||
* enlarged upstream. */
|
||||
for (i = 0; i < 5; i++) {
|
||||
#else
|
||||
for (i = 0; i < 6; i++) {
|
||||
#endif
|
||||
outlen = sizeof(out);
|
||||
XMEMSET(out, 0, sizeof(out));
|
||||
|
||||
@@ -41413,7 +41422,12 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t ed25519_test(void)
|
||||
#endif /* HAVE_ED25519_VERIFY */
|
||||
}
|
||||
|
||||
#ifdef HAVE_ED25519_VERIFY
|
||||
#if defined(HAVE_ED25519_VERIFY)
|
||||
/* These cases exercise host-side signature-encoding pre-validation (e.g.,
|
||||
* sig == curve order). The SE050 port delegates verify to the secure
|
||||
* element, which rejects all four inputs with WC_HW_E rather than the
|
||||
* BAD_FUNC_ARG / SIG_VERIFY_E the host-side path produces — so the
|
||||
* expected error code differs below when built against an SE050. */
|
||||
{
|
||||
/* Run tests for some rare code paths */
|
||||
/* sig is exactly equal to the order */
|
||||
@@ -41466,28 +41480,45 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t ed25519_test(void)
|
||||
if (ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), cleanup);
|
||||
|
||||
#ifdef WOLFSSL_SE050
|
||||
#define RARE_ED_BAD_ENC_E WC_HW_E
|
||||
#define RARE_ED_BAD_SIG_E WC_HW_E
|
||||
#else
|
||||
#define RARE_ED_BAD_ENC_E BAD_FUNC_ARG
|
||||
#define RARE_ED_BAD_SIG_E SIG_VERIFY_E
|
||||
#endif
|
||||
|
||||
ret = wc_ed25519_verify_msg(rareEd1, sizeof(rareEd1), msgs[0], msgSz[0],
|
||||
&verify, key);
|
||||
if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG))
|
||||
if (ret != WC_NO_ERR_TRACE(RARE_ED_BAD_ENC_E))
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), cleanup);
|
||||
|
||||
ret = wc_ed25519_verify_msg(rareEd2, sizeof(rareEd2), msgs[0], msgSz[0],
|
||||
&verify, key);
|
||||
if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG))
|
||||
if (ret != WC_NO_ERR_TRACE(RARE_ED_BAD_ENC_E))
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), cleanup);
|
||||
|
||||
ret = wc_ed25519_verify_msg(rareEd3, sizeof(rareEd3), msgs[0], msgSz[0],
|
||||
&verify, key);
|
||||
if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG))
|
||||
if (ret != WC_NO_ERR_TRACE(RARE_ED_BAD_ENC_E))
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), cleanup);
|
||||
|
||||
ret = wc_ed25519_verify_msg(rareEd4, sizeof(rareEd4), msgs[0], msgSz[0],
|
||||
&verify, key);
|
||||
if (ret != WC_NO_ERR_TRACE(SIG_VERIFY_E))
|
||||
if (ret != WC_NO_ERR_TRACE(RARE_ED_BAD_SIG_E))
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), cleanup);
|
||||
|
||||
#undef RARE_ED_BAD_ENC_E
|
||||
#undef RARE_ED_BAD_SIG_E
|
||||
}
|
||||
#endif /* HAVE_ED25519_VERIFY */
|
||||
|
||||
#ifndef WOLFSSL_SE050
|
||||
/* Ed25519ctx and Ed25519ph require passing a context / prehash flag
|
||||
* through to the signer. The SE050 port's se050_ed25519_sign_msg /
|
||||
* _verify_msg drop those parameters and always do plain Ed25519, so the
|
||||
* RFC 8032 ctx/ph test vectors cannot match. Skip these variants when
|
||||
* built against an SE050. */
|
||||
ret = ed25519ctx_test();
|
||||
if (ret != 0)
|
||||
goto cleanup;
|
||||
@@ -41495,6 +41526,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t ed25519_test(void)
|
||||
ret = ed25519ph_test();
|
||||
if (ret != 0)
|
||||
goto cleanup;
|
||||
#endif /* !WOLFSSL_SE050 */
|
||||
|
||||
#ifndef NO_ASN
|
||||
/* Try ASN.1 encoded private-only key and public key. */
|
||||
@@ -41509,8 +41541,16 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t ed25519_test(void)
|
||||
sizeof(badPrivateEd25519)) == 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, cleanup);
|
||||
|
||||
/* Signing with a private-only key (no public loaded yet) is rejected on
|
||||
* the host with BAD_FUNC_ARG. The SE050 port instead fails inside
|
||||
* sss_se05x_key_store_set_ecc_keypair and returns WC_HW_E, so accept
|
||||
* that alternate error code when built against an SE050. */
|
||||
ret = wc_ed25519_sign_msg(msgs[0], msgSz[0], out, &outlen, key3);
|
||||
#ifdef WOLFSSL_SE050
|
||||
if (ret != WC_NO_ERR_TRACE(WC_HW_E))
|
||||
#else
|
||||
if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG))
|
||||
#endif
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), cleanup);
|
||||
|
||||
/* try with a buffer size that is too large */
|
||||
|
||||
Reference in New Issue
Block a user