Repository navigation
Conversation
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>
There was a problem hiding this comment.
🟡 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
| 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()) { |
There was a problem hiding this comment.
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(); |
There was a problem hiding this comment.
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>
|
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 |


Adds
HKDFExtractAndExpand(AN12543 4.15.1.1): RFC 5869 HKDF with an HMACKey object as the input keying material, which never leaves the SE.TAG_7).POLICY_OBJ_ALLOW_KDFwhen it has a policy.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