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)
40 lines
1.3 KiB
Python
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)
|