Skip to content

SE050Sim: support direct ECDH variant, never export HMACKey objects - #12

Merged
LinuxJedi merged 2 commits into
wolfSSL:mainfrom
LinuxJedi:se050-direct-ecdh-variant
Aug 3, 2026
Merged

SE050Sim: support direct ECDH variant, never export HMACKey objects#12
LinuxJedi merged 2 commits into
wolfSSL:mainfrom
LinuxJedi:se050-direct-ecdh-variant

Conversation

@LinuxJedi

Copy link
Copy Markdown
Member

Motivation

Testing on real SE051 applet 7.2.0 hardware settled the ECDH derive-target question with two facts the simulator (and PR #10/#11) got wrong:

  1. The applet never exports symmetric key objects. ReadObject on an HMACKey object fails with SW 0x6986 even when the object's attributes confirm an attached POLICY_OBJ_ALLOW_READ (and adding ALLOW_IMPORT_EXPORT changes nothing). The read-policy exception the simulator honored does not exist on silicon; the SE050C (applet 3.1.1) behaves identically.
  2. The direct ECDH variant is how hosts get the secret. Se05x_API_ECDHGenerateSharedSecret (no Tag7) returns the shared secret in the APDU response on the same applet, and is what sss_se05x_derive_key_dh itself uses whenever the derived key object lives in a host keystore. The simulator rejected Tag7-less requests with SW_WRONG_DATA.

wolfSSL's se050_applet72_ecdh branch now uses the direct variant on applet >= 7.2 (verified on the SE051: ECC P-256, X25519, and the wolfCrypt suite pass), so the simulator must support it for CI to run at all.

Changes

  • handle_ecdh: Tag7 is now optional. Without it (direct variant) the shared secret is returned in response Tag1 and no object is touched, in strict and lenient mode alike; Montgomery secrets are returned big endian, as on hardware (the SDK swaps around the call). With Tag7 the InObject behavior and the strict target contract are unchanged.
  • ReadObject on HMACKey objects is now always refused with SW 0x6986, regardless of any attached policy, matching hardware. The policy recorded at WriteSymmKey is kept as object-attribute bookkeeping.
  • sdk-test: the P-256 and X25519 ECDH tests now use the direct variant (with the Montgomery byte swaps), since the derive-into-object-and-read-back flow they previously modeled is impossible on real silicon; the derive-target policy globals are gone.

Validation

  • cargo test: 52 tests pass (2 new direct-variant tests, including a big-endian X25519 response check; the with-read-policy read test is inverted to match hardware).
  • Docker wolfCrypt-vs-simulator against the wolfSSL branch tip (direct APDU port): full suite passes in strict and lenient modes.
  • Docker sdk-test leg: 31/31 pass.
  • Hardware cross-check (SE051, applet 7.2.0): the same operations the simulator now models were exercised on silicon: direct ECDH P-256/X25519 pass, policy-attached HMACKey read fails 0x6986.

The wolfSSL branch CI pin (SIMULATORS_REF) should be bumped to this PR's head once merged.

Real SE051 applet 7.2.0 hardware settled two behaviors the simulator
modeled wrongly:

ReadObject on an HMACKey object fails with SW 0x6986 even when the
object's attributes confirm an attached POLICY_OBJ_ALLOW_READ, so the
read-policy exception honored since the strict-mode enforcement landed
does not exist on silicon. Refuse HMACKey reads unconditionally; the
policy recorded at WriteSymmKey stays as attribute bookkeeping.

The Tag7-less ECDHGenerateSharedSecret form is how a host obtains an
ECDH secret on applet >= 7.2: the applet returns it in the response
(big endian for Montgomery curves, byte swapped by the SDK around the
call) and touches no object. The simulator rejected Tag7-less requests
with SW_WRONG_DATA; accept them in strict and lenient mode alike, with
the strict InObject target contract unchanged for Tag7 requests.

Rewrite the sdk-test P-256 and X25519 ECDH tests to the direct variant,
since the derive-into-object-and-read-back flow they encoded is
impossible on real parts, and drop their derive-target policy globals.

Verified: 52 cargo tests; wolfCrypt-vs-simulator docker run against the
wolfSSL direct-APDU port passes in strict and lenient modes; sdk-test
31/31; hardware cross-check on SE051 applet 7.2.0 (direct ECDH passes,
policy-attached HMACKey read denied 0x6986).
Copilot AI review requested due to automatic review settings August 3, 2026 13:59

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the SE050 simulator to match observed SE05x hardware behavior around ECDH shared-secret derivation and symmetric key export restrictions, and aligns the SDK test suite accordingly so CI can exercise the real-world host flows.

Changes:

  • Add support for Tag7-less (“direct”) ECDH in handle_ecdh, returning the shared secret in the APDU response (including big-endian Montgomery behavior).
  • Make ReadObject on HMACKey objects always fail with SW_COMMAND_NOT_ALLOWED (0x6986), regardless of attached policy.
  • Update sdk-test ECDH tests to use the direct ECDH API flow instead of derive-into-object-and-read-back.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
SE050Sim/se050-sim/src/object_store/types.rs Clarifies HMACKey policy is retained as attributes but does not allow export.
SE050Sim/se050-sim/src/handlers/object_mgmt.rs Enforces “never export HMACKey via ReadObject” behavior and updates related tests.
SE050Sim/se050-sim/src/handlers/ec.rs Implements optional Tag7 to support direct ECDH response behavior; adds direct-variant tests.
SE050Sim/se050-sim/src/handlers/aes.rs Updates HMAC write documentation to reflect non-exportability regardless of policy.
SE050Sim/sdk-test/test_se050.c Switches ECDH tests to the direct APDU variant and adjusts Montgomery byte-order handling.
Suppressed comments (5)

SE050Sim/sdk-test/test_se050.c:379

  • TEST_FAILF already returns from the current test function; the extra return; is unreachable. Removing it avoids dead code.
    if (sm != SM_OK) {
        TEST_FAILF("direct ECDH failed: 0x%04x", (unsigned)sm);
        return;
    }

SE050Sim/sdk-test/test_se050.c:1431

  • TEST_FAIL already returns; the trailing return; is unreachable. Dropping it avoids dead code and keeps the error path consistent with the rest of the test helpers.
    if (pub_len < 32) { TEST_FAIL("key_b public too short"); return; }

SE050Sim/sdk-test/test_se050.c:1441

  • TEST_FAILF already returns; the extra return; is unreachable and can be removed.
    if (sm != SM_OK) {
        TEST_FAILF("direct ECDH a failed: 0x%04x", (unsigned)sm);
        return;
    }

SE050Sim/sdk-test/test_se050.c:1453

  • TEST_FAIL already returns; the trailing return; is unreachable. Dropping it avoids dead code.
    if (pub_len < 32) { TEST_FAIL("key_a public too short"); return; }

SE050Sim/sdk-test/test_se050.c:1463

  • TEST_FAILF already returns; the extra return; is unreachable and can be removed.
    if (sm != SM_OK) {
        TEST_FAILF("direct ECDH b failed: 0x%04x", (unsigned)sm);
        return;
    }

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread SE050Sim/sdk-test/test_se050.c
Comment thread SE050Sim/sdk-test/test_se050.c
Comment thread SE050Sim/sdk-test/test_se050.c
Comment thread SE050Sim/se050-sim/src/handlers/ec.rs Outdated
Zero-init the sss_key_store_get_key bit-length out-parameters for
consistency with the rest of the file, drop the unreachable returns
after TEST_FAIL/TEST_FAILF (the macros return), and extract the peer
public key in the Tag7-less unit test by TLV parsing instead of fixed
offsets.
@LinuxJedi
LinuxJedi merged commit 7e180d1 into wolfSSL:main Aug 3, 2026
21 checks passed
@LinuxJedi
LinuxJedi deleted the se050-direct-ecdh-variant branch August 3, 2026 14:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants