Files
pm3py/tests/test_hf_14a.py
michael 820701511c fix(14a): NG struct for sim (+ tagtype, enables MFU/NTAG sim), NG for sniff
14a.sim sent a MIX frame but the handler is NG casting a packed {tagtype,u16 flags,uid[10],exitAfter,rats[20],ulauth...} struct -> whole struct garbled, flags never arrived. Rewrite to send_ng with the exact struct and expose tagtype (2=Ultralight,7=NTAG) so Ultralight/NTAG sim works. 14a.sniff sent MIX (args stripped -> empty asBytes); send NG with the 1-byte param. Pre-existing, independent of rebase.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-05 00:08:40 -07:00

69 lines
2.7 KiB
Python

import struct
import asyncio
from unittest.mock import AsyncMock
from pm3py.core.protocol import Cmd
from pm3py.core.transport import PM3Response
from pm3py.core.hf_iso14a import HF14ACommands
def test_14a_scan():
t = AsyncMock()
hf14a = HF14ACommands(t)
# Build iso14a_card_select_t response
uid = b"\x04\x01\x02\x03\x04\x05\x06"
card = uid + b"\x00" * 3 # uid[10]
card += bytes([7]) # uidlen
card += b"\x44\x00" # atqa
card += bytes([0x08]) # sak
card += bytes([0]) # ats_len
card += b"\x00" * 256 # ats
resp = PM3Response(cmd=Cmd.ACK, status=0, reason=0, ng=False,
data=card, oldarg=[1, 0, 0])
t.send_mix.return_value = resp
result = asyncio.get_event_loop().run_until_complete(hf14a.scan())
assert result["uid"] == "04010203040506"
assert result["uid_len"] == 7
assert result["sak"] == 0x08
def test_14a_sim_packs_ng_struct():
t = AsyncMock()
hf14a = HF14ACommands(t)
t.send_ng.return_value = PM3Response(cmd=Cmd.HF_ISO14443A_SIMULATE, status=0,
reason=0, ng=True, data=b"", oldarg=[])
uid = b"\x04\x01\x02\x03"
result = asyncio.get_event_loop().run_until_complete(
hf14a.sim(tagtype=7, uid=uid, exit_after=3))
assert result["status"] == 0
args, kwargs = t.send_ng.call_args
assert args[0] == Cmd.HF_ISO14443A_SIMULATE
payload = kwargs["payload"]
assert len(payload) == 69 # PACKED firmware struct size
tagtype, flags = struct.unpack_from("<BH", payload, 0)
assert tagtype == 7
assert flags & 0x0030 == 0x0010 # FLAG_4B_UID_IN_DATA
assert payload[3:7] == uid # uid[10] field, first 4 bytes
assert payload[13] == 3 # exitAfter
def test_14a_sim_no_uid_uses_emul_flag():
t = AsyncMock()
hf14a = HF14ACommands(t)
t.send_ng.return_value = PM3Response(cmd=Cmd.HF_ISO14443A_SIMULATE, status=0,
reason=0, ng=True, data=b"", oldarg=[])
asyncio.get_event_loop().run_until_complete(hf14a.sim(tagtype=1))
payload = t.send_ng.call_args.kwargs["payload"]
_, flags = struct.unpack_from("<BH", payload, 0)
assert flags & 0x0030 == 0x0000 # FLAG_UID_IN_EMUL
def test_14a_sniff_sends_ng_param_byte():
t = AsyncMock()
hf14a = HF14ACommands(t)
t.send_ng.return_value = PM3Response(cmd=Cmd.HF_ISO14443A_SNIFF, status=0,
reason=0, ng=True, data=b"", oldarg=[])
result = asyncio.get_event_loop().run_until_complete(hf14a.sniff(2))
assert result["status"] == 0
args, kwargs = t.send_ng.call_args
assert args[0] == Cmd.HF_ISO14443A_SNIFF
assert kwargs["payload"] == bytes([2])