Skip to content

SE050Sim: add the SE052F applet personality - #18

Merged
LinuxJedi merged 2 commits into
wolfSSL:mainfrom
LinuxJedi:se052f-personality
Aug 27, 2026
Merged

SE050Sim: add the SE052F applet personality#18
LinuxJedi merged 2 commits into
wolfSSL:mainfrom
LinuxJedi:se052f-personality

Conversation

@LinuxJedi

Copy link
Copy Markdown
Member

Summary

Adds a fourth applet personality to SE050Sim for the SE052F (IoT applet
7.2.22), bench-characterized against real silicon. Selected with
SE050_SIM_APPLET=f / 52f / se052f / 7.2.22. The suffix rules are
checked before the leading-digit rule, so 3f selects the SE052F just as
3e selects the SE050E.

GetFreeMemory is U32 on this family

This is the substantive change, and it corrects the shape of an earlier
assumption rather than just adding data.

Se05x_API_GetFreeMemory picks its parser from SE05X_CHECK_52F_VERSION,
which tests (applet_version >> 8) & 0xFF for the range 0x10..=0x1F.
Because applet_version is major<<24 | minor<<16 | patch<<8, that byte is
the applet patch number, which NXP overloads to mark the SE052 family.
Applet 7.2.22 (patch 0x16) therefore takes the tlvGet_U32 branch, while
3.1.1 / 7.2.0 / SE050E (patch 0x00) take tlvGet_U16.

The two parsers reject each other's lengths outright, so a mismatched width
fails the host call rather than degrading quietly. free_memory_bytes now
carries u32 values internally and emits 2 or 4 bytes according to the new
free_memory_is_u32() predicate.

Memory type SE052F
PERSISTENT 86336
TRANSIENT_RESET 1157
TRANSIENT_DESELECT 1152

PERSISTENT does not fit in a u16 at all, which is precisely why the U32
path exists. The other three personalities keep their 2-byte replies
unchanged.

Other modelled behaviour

All measured on silicon over Platform SCP03:

Behavior SE051 7.2.0 SE052F 7.2.22
GetVersion blob 07 02 00 3f ff ff ff 07 02 16 26 f2 ff ff
GetFreeMemory width 2 bytes 4 bytes
GetRandom cap 1018 1003
ReadType, P-521 pair 0x31 0x31 (same)
Duplicate CreateECCurve 0x6985, curve intact same
Ed25519 / X25519 keygen works 0x6985
RSA-2048 CRT keygen + sign works works
RSA-1024 CRT keygen works 0x6985
RSA public key import works 0x6A80

appletConfig 0x26f2 clears EDDSA (0x0004), DH_MONT (0x0008), DES
(0x0100), MIFARE (0x0800) and RFU1 (0x1000) relative to the SE051's
0x3fff, while keeping both RSA bits. The RSA size and format restrictions
are not visible in appletConfig at all -- they only show up on the wire.

The GetRandom figure of 1003 was measured over SCP03, which is the only
channel a real SE052F serves: the part ships locked and refuses plain
GetRandom, so its plain-channel cap could not be measured. R-MAC/R-ENC
overhead is the likely reason it sits below the 1018 the other 7.2 parts
allow in plain mode.

handle_write_ec_key now takes the applet version so it can gate the 25519
curves. That is the only signature change.

Deliberately not modelled

  • The factory restricted mode. Real SE052F parts refuse everything but
    GetVersion until an SCP03 session exists. Enabling that by default would
    make the personality unusable for anyone not driving SCP03. The mechanism
    already exists if it is ever wanted: the object store's scp_required
    flag plus SetPlatformSCPRequest.
  • The P-256-only factory curve list. The simulator deliberately
    pre-provisions P-192/P-224/P-256/P-384/P-521 for every personality so
    hosts that never create curves keep working; the SE051 and SE050E factory
    lists differ from that default too, and neither is modelled.
  • RSA key format. The SE052F refuses RAW-format generation with 0x6A80
    while accepting CRT, but the simulator does not distinguish the two
    formats for any personality.

Test plan

  • cargo test -- --test-threads=1: 121 pass (93 lib + 14 + 14).
  • New tests cover the GetFreeMemory reply width per personality (including
    the exact 00 01 51 40 byte pattern and that 86336 exceeds u16::MAX),
    the token parsing including the 3f / 3e precedence cases, the 25519
    refusals with the other personalities still serving those curves, and the
    RSA size and public-import restrictions.
  • Integration suite (full T=1 -> APDU -> dispatch -> driver stack) run under
    each personality. Default and 3.1.1 are 14/14; SE050E shows its usual 4
    RSA failures, unchanged. Under SE050_SIM_APPLET=52f five tests fail, and
    each is the modelled silicon behaviour rather than a regression: all four
    RSA tests use 1024-bit keys, which a real SE052F refuses, and the fifth is
    Ed25519 keygen. test_get_free_memory passes under 52f, confirming the
    4-byte reply survives the whole stack.
  • CI runs without SE050_SIM_APPLET, so the default personality is what is
    exercised there.

Bench-characterized an SE052F (IoT applet 7.2.22) and added it as a
fourth personality, selected with SE050_SIM_APPLET=f / 52f / se052f /
7.2.22. The suffix rules are checked before the leading-digit rule, so
"3f" selects the SE052F just as "3e" selects the SE050E.

The important part is the GetFreeMemory reply width.
Se05x_API_GetFreeMemory picks its parser from SE05X_CHECK_52F_VERSION,
which tests (applet_version >> 8) & 0xFF for 0x10..=0x1F. Since
applet_version is major<<24 | minor<<16 | patch<<8, that byte is the
applet patch number, which NXP overloads to mark the SE052 family.
Applet 7.2.22 (patch 0x16) therefore takes the tlvGet_U32 branch while
3.1.1 / 7.2.0 / SE050E (patch 0x00) take tlvGet_U16. Each parser
rejects the other's length outright, so a mismatched width fails the
host call rather than degrading quietly.

free_memory_bytes now carries u32 values internally and emits 2 or 4
bytes per the new free_memory_is_u32 predicate. The SE052F reports
86336 / 1157 / 1152; PERSISTENT does not fit in a u16 at all, which is
why the U32 path exists in the first place.

Also modelled, all measured on silicon over Platform SCP03:

* version blob 07 02 16 26 f2 ff ff. appletConfig 0x26f2 clears EDDSA,
  DH_MONT, DES, MIFARE and RFU1 relative to the SE051's 0x3fff, but
  keeps both RSA bits.
* GetRandom cap 1003. Measured over SCP03, which is the only channel a
  real SE052F serves - the part ships locked and refuses plain
  GetRandom, so its plain-channel cap could not be measured.
* Duplicate CreateECCurve refused 0x6985 with the curve left intact,
  matching the other 7.2 parts.
* Ed25519 and X25519 key writes refused 0x6985 (supports_25519).
* RSA below 2048 bits refused 0x6985 (rsa_min_key_bits) and RSA
  public-key import refused 0x6A80 (supports_rsa_public_import). RSA
  2048 CRT generation and RSASign work.

handle_write_ec_key takes the applet version so it can gate the 25519
curves; that is the only signature change.

Deliberately not modelled: the factory restricted mode (real parts
refuse everything but GetVersion until an SCP03 session exists - the
object store's scp_required flag and SetPlatformSCPRequest already
provide the mechanism if it is ever wanted), the P-256-only factory
curve list (the simulator pre-provisions five curves for every
personality, and the SE051/SE050E factory lists differ from that
default too), and RSA key format, which the simulator does not
distinguish for any personality.

Tests cover the reply width per personality including the exact byte
pattern for the SE052F, the token parsing, the 25519 refusals with the
other personalities still serving those curves, and the RSA size and
import restrictions.
Copilot AI lite review requested due to automatic review settings August 27, 2026 11:32

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

Adds a new SE050Sim “applet personality” for the SE052F (applet 7.2.22), including bench-validated behavioral differences (notably GetFreeMemory U32 width, 25519 curve disablement, and RSA restrictions) and corresponding unit tests.

Changes:

  • Introduces AppletVersion::V7_2_22F and selection logic (SE050_SIM_APPLET token parsing, version bytes, feature predicates, GetRandom cap, GetFreeMemory width/values).
  • Gates Ed25519/X25519 key handling based on applet version and models SE052F RSA restrictions (min key size + public-key import refusal).
  • Expands tests across management/EC/RSA behavior to validate SE052F-specific wire behavior and selection precedence.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
SE050Sim/se050-sim/src/handlers/rsa.rs Adds SE052F RSA restrictions + tests (min key size, public import refusal).
SE050Sim/se050-sim/src/handlers/management.rs Updates tests for SE052F GetRandom cap, version bytes, and GetFreeMemory U32 replies.
SE050Sim/se050-sim/src/handlers/ec.rs Adds applet-version gating to refuse 25519 curves on SE052F + tests; updates handler signature.
SE050Sim/se050-sim/src/handlers/curve.rs Extends “duplicate CreateECCurve” behavior to include SE052F.
SE050Sim/se050-sim/src/dispatch.rs Wires applet version through dispatch into EC handler.
SE050Sim/se050-sim/src/applet.rs Adds SE052F personality metadata, selection parsing, feature predicates, and GetFreeMemory width/value logic + tests.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread SE050Sim/se050-sim/src/handlers/rsa.rs Outdated
Comment thread SE050Sim/se050-sim/src/applet.rs Outdated
Two fixes from review feedback on the SE052F personality.

from_token matched the version token with starts_with("7.2.22"), so
"7.2.220" and "7.2.22e" also selected the SE052F. Made it an exact
match; the "*f" suffix forms are unchanged, and "7.2.22e" now falls
through to the ends-with-"e" rule as it should. Both cases are pinned
in the token test.

The SE052F public-import refusal keyed only on the P1 key-part bits, so
an APDU carrying modulus and exponent with those bits clear still
created a public key object. Now an APDU that carries a whole public
key -- modulus and exponent with no private component -- is refused as
well, since it is the same operation reached through a different
encoding.

The private-key import path is deliberately untouched. The wolfCrypt
port imports (E, D, N) across three separate APDUs, so no single APDU
there carries modulus and exponent together without private material,
and none of them sets the public key part. Refusing on the mere
presence of a public component would have broken that flow at its first
APDU, so there is a regression test walking the three steps against the
SE052F personality.
@LinuxJedi
LinuxJedi merged commit ee28091 into wolfSSL:main Aug 27, 2026
24 checks passed
@LinuxJedi
LinuxJedi deleted the se052f-personality branch August 27, 2026 12:33
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