feat(fw): implement GetUnwrappingKey DDI handler#501
Merged
Conversation
Within an open session, return the partition's RSA-2048 unwrapping public key (raw wire `n_le || e_le`) plus its vault key id, for the host to RSA-AES key-wrap a payload for RsaUnwrap. - Lazy RSA-2048 keygen via a new HsmPartitionManager:: part_ensure_unwrapping_key: the std PAL generates on first use (keygen is too slow to run at partition enable); hardware PALs generate in the background from part-init and report PendingKeyGeneration until ready, prompting the host to retry. - Derive the public key from the vault-stored private key on demand (no separate pub cached, matching the reference firmware) via a new HsmRsa::rsa_priv_pub_key that converts the PAL's vault representation (raw on hardware, DER in the std/OpenSSL PAL) into wire form; the std driver owns the big-endian->little-endian flip. - Serialize the public key straight into the response frame's reserved slot (query/alloc/use) — no intermediate buffer or copy. - Centralize the BE<->LE reverse_copy helper in drivers/mod.rs, shared by the ecc and rsa drivers. - Fix ras_gen_keypair -> rsa_gen_keypair typo. masked_key is emitted empty for now (firmware-side masking pending the unmask path). Uno PAL methods are stubbed (PendingKeyGeneration / UnsupportedCmd). Adds get_unwrapping_key smoke tests (happy path, stable-across-calls, no-session). Full smoke 53/53; std PAL unit 157/157. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Implements the MBOR GetUnwrappingKey DDI command to return a partition’s RSA-2048 unwrapping public key (wire n_le || e_le) and its vault key id, with PAL support for ensuring/deriving the key and emulator smoke tests.
Changes:
- Added core MBOR handler + type plumbing for
GetUnwrappingKeyand wired it into the dispatcher. - Added PAL APIs to (a) ensure the partition unwrapping key exists and (b) derive a wire-format public key from a vault-stored private key (std PAL implemented; Uno stubs).
- Centralized the BE↔LE byte reversal helper and added std RSA public-key wire serialization; added MBOR integration smoke tests.
Reviewed changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| fw/plat/uno/fw/pal/src/part.rs | Adds Uno stub for part_ensure_unwrapping_key (returns PendingKeyGeneration). |
| fw/plat/uno/fw/pal/src/crypto/rsa.rs | Fixes ras_gen_keypair typo to rsa_gen_keypair; adds Uno stub for rsa_priv_pub_key. |
| fw/plat/std/pal/src/rsa.rs | Implements rsa_priv_pub_key for std PAL by parsing vault DER and emitting wire `n_le |
| fw/plat/std/pal/src/part.rs | Adds std PAL lazy generation + vault persistence for the unwrapping key id. |
| fw/plat/std/pal/src/drivers/rsa.rs | Adds rsa_pub_wire helper to serialize OpenSSL public key components into wire form. |
| fw/plat/std/pal/src/drivers/mod.rs | Centralizes reverse_copy for BE↔LE component conversion shared across drivers. |
| fw/plat/std/pal/src/drivers/ecc.rs | Switches ECC driver to use centralized reverse_copy. |
| fw/pal/traits/src/part.rs | Extends HsmPartitionManager trait with part_ensure_unwrapping_key and docs. |
| fw/pal/traits/src/crypto/rsa.rs | Renames ras_gen_keypair → rsa_gen_keypair; adds rsa_priv_pub_key to HsmRsa trait. |
| fw/core/lib/src/ddi/mbor/mod.rs | Registers and dispatches the new GetUnwrappingKey handler. |
| fw/core/lib/src/ddi/mbor/get_unwrapping_key.rs | New MBOR command handler that allocates the response and writes pubkey directly into the reserved frame slot. |
| fw/core/ddi/mbor/types/src/get_unwrapping_key.rs | Marks pub_key as a framed field for correct encoding/layout. |
| ddi/mbor/types/tests/integration/get_unwrapping_key_smoke.rs | Adds integration smoke tests (happy path, stability across calls, and no-session rejection). |
| ddi/mbor/types/tests/azihsm_ddi_tests.rs | Includes the new smoke test module in the test suite. |
- part_ensure_unwrapping_key (std): close a TOCTOU race across the keygen await — re-check unwrapping_key_id while holding the mutable entry borrow before creating the vault key, so two concurrent callers on one partition can't both insert (leaking one) and return different ids. The re-check -> create -> store window is await-free, hence atomic on the single-threaded executor. - rsa_pub_wire (std driver): bound the modulus length against the fixed 512-byte scratch buffer and error out, so a malformed/oversized vault key can never panic across the PAL trust boundary. - Docs: drop the stale PartPropId::RSA_UNWRAPPING_PUB_KEY reference (no such property — the public key is derived on demand, not cached), and reword the unwrapping-key caching as the partition's current enabled incarnation (clear_enabled_state deletes it on disable/free). - Smoke test: drop the `key_id != 0` assertion — key_id is an opaque handle and the sim/mock backend (which CI runs this suite under) legitimately assigns 0; the stability test already covers id consistency. Validation: get_unwrapping_key smoke 3/3 under both mock and emu; full mock smoke 45/45; std unit 157/157; host + Uno build clean. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
vsonims
requested changes
Jun 30, 2026
Address PR feedback: follow the existing property model instead of adding a new PAL trait method for the unwrapping key. - Remove HsmPartitionManager::part_ensure_unwrapping_key. The handler now just reads the partition's RSA_UNWRAPPING_KEY_ID property via part_unwrapping_key_id; an absent id (PartPropNotFound) means generation is still pending, surfaced as PendingKeyGeneration so the host retries. This keeps the core handler PAL-agnostic — real hardware generates the key in the background at part-init and only ever exposes it through the property. - std PAL: provision the key lazily behind the property read. A new private provision_unwrapping_key runs inside part_prop_get_u16 for RSA_UNWRAPPING_KEY_ID, generating the RSA-2048 key synchronously on first read so only a GetUnwrappingKey request pays the keygen cost (never partition enable — avoids a ~19x smoke-test slowdown). The routine is await-free, so on the single-threaded executor it runs atomically: concurrent reads cannot race to generate two keys (first write wins, the rest reuse it). - Uno PAL: drop the part_ensure_unwrapping_key stub; its getter stays uniform with every other key-id property (PartPropNotFound when unset), which the handler maps to PendingKeyGeneration. Validation: get_unwrapping_key smoke 3/3 under both mock and emu; std unit 157/157; host + Uno build clean; fmt/copyright clean. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
vsonims
previously approved these changes
Jul 1, 2026
Co-authored-by: jaygmsft <22506014+jaygmsft@users.noreply.github.com>
vsonims
approved these changes
Jul 1, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Within an open session, return the partition's RSA-2048 unwrapping public key (raw wire
n_le || e_le) plus its vault key id, for the host to RSA-AES key-wrap a payload for RsaUnwrap.masked_key is emitted empty for now (firmware-side masking pending the unmask path). Uno PAL methods are stubbed (PendingKeyGeneration / UnsupportedCmd).
Adds get_unwrapping_key smoke tests (happy path, stable-across-calls, no-session). Full smoke 53/53; std PAL unit 157/157.