Files
aliro-project/harness/tests/test_reader_step_up.py
michael 9081990b0e feat(harness): aliro-bench-test --step-up + INSTALL.md install-recovery notes
Adds a PC/SC verification path for Step-Up Milestone 1 so M1 can be
validated against a personalized card without depending on Nucleo /
X-CUBE-ALIRO bring-up. Verdict run on J3R452 04555A4A0B2190 with M1
CAP installed: AUTH1 OK (3.4s), EXCHANGE 0xC9 OK, ENVELOPE 0xC3 OK
with response decrypting under StepUpSKDevice to the spec 0xA0 ack.

- crypto.py: derive_step_up_session_keys (HKDF parity with
  AliroCrypto.deriveStepUpSessionKeys)
- transaction.py: expose step_up_sk on TransactionResult
- step_up.py: verify_step_up_m1 -- SELECT 5502 + GCM-encrypted
  C9/C3 round-trip, IVs per StepUpApplet (0x00*8 || counter
  reader-side; 0x00*7 || 0x01 || counter device-side)
- cli.py: --step-up flag on aliro-bench-test
- tests: stdlib-RFC-5869 cross-check on the new KDF (122/122 green)
- INSTALL.md: fix multi-place PKG AID typo (missing 02 version byte),
  document partial-install recovery, document package-static
  credential store (aliro-personalize success !=> 5501/5502 installed)
2026-06-17 12:55:16 -07:00

40 lines
1.3 KiB
Python

"""Smoke test for step-up key derivation parity with the applet."""
import hashlib
import hmac
from aliro_harness.reader.crypto import derive_step_up_session_keys
def _hkdf_manual(ikm: bytes, salt: bytes, info: bytes, length: int) -> bytes:
"""Bare-stdlib RFC 5869 reference. Independent of `cryptography` so the
cross-check actually catches a wrong-info / wrong-salt regression in
derive_step_up_session_keys."""
use_salt = salt if salt else b"\x00" * 32
prk = hmac.new(use_salt, ikm, hashlib.sha256).digest()
out = b""
t = b""
counter = 1
while len(out) < length:
t = hmac.new(prk, t + info + bytes([counter]), hashlib.sha256).digest()
out += t
counter += 1
return out[:length]
def test_derive_step_up_session_keys_matches_rfc5869():
# Same IKM as AliroCryptoTest.deriveStepUpSessionKeysMatchesManualHkdf:
# bytes 0xC0..0xDF -- so this Python test pins the same vector the
# applet test pins.
step_up_sk = bytes(range(0xC0, 0xE0))
sk_device, sk_reader = derive_step_up_session_keys(step_up_sk)
assert len(sk_device) == 32
assert len(sk_reader) == 32
assert sk_device != sk_reader
assert sk_device != step_up_sk
assert sk_device == _hkdf_manual(step_up_sk, b"", b"SKDevice", 32)
assert sk_reader == _hkdf_manual(step_up_sk, b"", b"SKReader", 32)