Skip to content

SE050Sim: HKDFExtractAndExpand - #26

Open
mcamposv wants to merge 2 commits into
wolfSSL:mainfrom
shosoin:hkdf
Open

mcamposv wants to merge 2 commits into
wolfSSL:mainfrom
shosoin:hkdf

Conversation

@mcamposv

@mcamposv mcamposv commented Nov 1, 2026

Copy link
Copy Markdown

Adds HKDFExtractAndExpand (AN12543 4.15.1.1): RFC 5869 HKDF with an HMACKey object as the input keying material, which never leaves the SE.

  • Digest modes SHA-1/256/384/512, optional salt and info, output of 1-768 bytes.
  • The output is returned to the host, or written into an existing HMACKey/AESKey of exactly that length (TAG_7).
  • The IKM key needs POLICY_OBJ_ALLOW_KDF when it has a policy.
  • Salt taken from an HMACKey object (TAG_6) is not modelled.

We use it to keep a device root key in the SE and derive from it without exporting it. Unit tests: RFC 5869 test case 1, and the APDU path with a policy that allows KDF and one that does not. Independent of #22-#25; all existing tests pass.

🤖 Generated with Claude Code

AN12543 4.15.1.1: RFC 5869 HKDF with an HMACKey object as the input keying
material, which never leaves the SE. Digest modes SHA-1/256/384/512, optional
salt and info, output of 1-768 bytes returned to the host or written into an
existing HMACKey/AESKey of that length (TAG_7). The IKM key needs
POLICY_OBJ_ALLOW_KDF when it has a policy. Salt from an HMACKey (TAG_6) is not
modelled.

Unit tests: RFC 5869 test case 1, and the APDU path with a policy that allows
and one that does not allow KDF.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings November 1, 2026 16:48

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.

🟡 Changes recommended

Malformed TAG_7 values can cause unintended key export, while ignored TAG_6 values silently substitute a zero salt and produce the wrong derived key.

2 open issues
What changed in this PR

Adds HKDF derivation to SE050Sim, allowing callers to derive keys from a stored HMAC key without exporting the input key material.

Changes:

  • Implements SHA-1/256/384/512 HKDF with optional salt and info, enforcing the input key’s KDF policy.
  • Supports returning derived bytes or storing them in an existing compatible key object, with persistence.
  • Adds an RFC 5869 test vector and APDU policy tests.
File Description
SE050Sim/​se050-sim/​src/​object_store/​mod.rs Adds persistence support after in-place object updates.
SE050Sim/​se050-sim/​src/​handlers/​mod.rs Registers the KDF handler module.
SE050Sim/​se050-sim/​src/​handlers/​kdf.rs Implements HKDF, output handling, policy checks, and tests.
SE050Sim/​se050-sim/​src/​dispatch.rs Routes HKDF APDUs to the new handler.

Review effort: Balanced

Comment thread SE050Sim/se050-sim/src/handlers/kdf.rs Outdated
let Some(out) = out else {
return ApduResponse::error(SW_WRONG_DATA);
};
if let Some(target) = tlv::find_tlv(&tlvs, TAG_7).and_then(|t| <[u8; 4]>::try_from(t.value.as_slice()).ok()) {

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed in 39afaa0: a TAG_7 that is not a 4-byte object ID is refused with 0x6A80 and nothing is returned; the host-output path is used only when TAG_7 is absent. Covered by hkdf_refuses_salt_object_and_malformed_target.

if len == 0 || len > 768 {
return ApduResponse::error(SW_WRONG_DATA);
}
let salt = tlv::find_tlv(&tlvs, TAG_3).map(|t| t.value.clone()).unwrap_or_default();

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed in 39afaa0: until object salts are modelled, a request with TAG_6 is refused with 0x6A80 instead of silently using the zero salt. Covered by the same test.

Two fixes from review feedback on HKDFExtractAndExpand.

A TAG_7 that was not four bytes was treated as absent, so a malformed
request to derive into an object returned the derived key to the host
instead. It is now refused with 0x6A80; the host-output path is taken only
when TAG_7 is absent.

TAG_6 (salt taken from an HMACKey object) was ignored, so such a request
succeeded with the default zero salt and produced a different key than
asked for. Until object salts are modelled it is refused with 0x6A80.

Test for both refusals.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@mcamposv

mcamposv commented Nov 2, 2026

Copy link
Copy Markdown
Author

Thanks for the review. Both points are addressed in 39afaa0: a malformed TAG_7 and any TAG_6 (object salt, not modelled yet) are now refused with 0x6A80, with a test.

Verified locally with cargo test (unit, integration and SCP03 suites).

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