Three components, all bench-validated to varying depths: - applet/: CSA Aliro v1.0 Java Card applet for J3R180. AUTH0 + AUTH1 expedited-standard flow end-to-end green via PC/SC bench reader (aliro-bench-test). Userland AES-256-GCM and HMAC-SHA-256 layered on top of J3R180's primitives because the card lacks both natively. P-256 curve params seeded explicitly per J3R180's quirk. - harness/: Python orchestrator (aliro-trustgen, aliro-personalize, aliro-bench-test) for trust-bundle generation, card personalization via PersonalizationApplet, and PC/SC AUTH0+AUTH1 transactions. 126 pytest cases passing. - reader/STM32CubeExpansion_ALIRO_V1_0_0/: ST X-CUBE-ALIRO V1.0.0 with our NFC10A1 port (NUCLEO-U545RE-Q + X-NUCLEO-NFC10A1, ST25R200 shared with NFC09A1). nfc10-only/ project, NFC10A1 BSP shim, ALIRO_TRUST_OVERRIDE include into vendor's provisioning.c, and an ALIRO_APDU_TRACE wrapper around demoTransceiveBlocking. Boots, detects the J3R180, completes SELECT + AUTH0; AUTH1 currently fails with RFAL ERR_PROTO (0xB) — under investigation, see docs/plans/2026-04-20-nucleo-nfc10a1-port.md and bench-notes/. Excluded: x-cube-aliro.zip vendor archive, harness/.venv, build dirs, generated aliro_trust.h (contains private reader scalar), all PEMs. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
88 lines
2.7 KiB
Python
88 lines
2.7 KiB
Python
"""Tests for the C header emitted from a TrustBundle."""
|
|
|
|
from cryptography.hazmat.primitives.asymmetric import ec
|
|
|
|
from aliro_harness.trustgen.header import TrustBundle, render_trust_header
|
|
|
|
|
|
def _bundle():
|
|
return TrustBundle(
|
|
issuer_public_key=ec.generate_private_key(ec.SECP256R1()).public_key(),
|
|
reader_private_key=ec.generate_private_key(ec.SECP256R1()),
|
|
reader_group_id=bytes(range(16)),
|
|
reader_group_sub_id=bytes(range(16, 32)),
|
|
)
|
|
|
|
|
|
def test_header_has_include_guard():
|
|
text = render_trust_header(_bundle())
|
|
assert "#ifndef ALIRO_TRUST_H_" in text
|
|
assert "#define ALIRO_TRUST_H_" in text
|
|
assert "#endif" in text
|
|
|
|
|
|
def test_header_marks_file_as_autogenerated():
|
|
text = render_trust_header(_bundle())
|
|
assert "AUTO-GENERATED" in text
|
|
assert "DO NOT EDIT" in text
|
|
|
|
|
|
def test_header_defines_reader_private_key_as_32_bytes():
|
|
text = render_trust_header(_bundle())
|
|
assert "#define ALIRO_READER_PRIVATE_KEY" in text
|
|
assert text.count("0x", text.index("ALIRO_READER_PRIVATE_KEY")) >= 32
|
|
|
|
|
|
def test_header_defines_reader_public_key_as_x_y_concatenated_64_bytes():
|
|
text = render_trust_header(_bundle())
|
|
assert "#define ALIRO_READER_PUBLIC_KEY" in text
|
|
|
|
|
|
def test_header_defines_issuer_pub_x_y_and_concatenated():
|
|
text = render_trust_header(_bundle())
|
|
assert "#define ALIRO_ISSUER_PUB_X" in text
|
|
assert "#define ALIRO_ISSUER_PUB_Y" in text
|
|
assert "#define ALIRO_ISSUER_PUB" in text
|
|
|
|
|
|
def test_header_defines_issuer_kid():
|
|
text = render_trust_header(_bundle())
|
|
assert "#define ALIRO_ISSUER_KID" in text
|
|
|
|
|
|
def test_header_defines_reader_group_ids():
|
|
text = render_trust_header(_bundle())
|
|
assert "#define ALIRO_READER_GROUP_ID" in text
|
|
assert "#define ALIRO_READER_GROUP_SUB_ID" in text
|
|
|
|
|
|
def test_reader_private_key_bytes_match_input():
|
|
bundle = _bundle()
|
|
text = render_trust_header(bundle)
|
|
|
|
expected = bundle.reader_private_key.private_numbers().private_value.to_bytes(32, "big")
|
|
first_byte_hex = f"0x{expected[0]:02x}"
|
|
last_byte_hex = f"0x{expected[-1]:02x}"
|
|
|
|
priv_block_start = text.index("ALIRO_READER_PRIVATE_KEY")
|
|
priv_block_end = text.index("#define", priv_block_start + 1)
|
|
block = text[priv_block_start:priv_block_end]
|
|
|
|
assert first_byte_hex in block
|
|
assert last_byte_hex in block
|
|
|
|
|
|
def test_issuer_kid_matches_compute_issuer_kid():
|
|
from aliro_harness.issuer.kid import compute_issuer_kid
|
|
|
|
bundle = _bundle()
|
|
text = render_trust_header(bundle)
|
|
|
|
expected_kid = compute_issuer_kid(bundle.issuer_public_key)
|
|
kid_start = text.index("ALIRO_ISSUER_KID")
|
|
kid_end = text.index("\n", kid_start)
|
|
kid_line = text[kid_start:kid_end]
|
|
|
|
for b in expected_kid:
|
|
assert f"0x{b:02x}" in kid_line
|