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_raw_trims_to_received_length(): t = AsyncMock() hf14a = HF14ACommands(t) # firmware replies with its whole (padded) buffer; oldarg[0] = bytes actually received version = bytes.fromhex("0004040201000f03") + b"\x80\x91" # 8-byte version + 2-byte CRC t.send_mix.return_value = PM3Response(cmd=Cmd.ACK, status=0, reason=0, ng=False, data=version + b"\x00" * 30, oldarg=[10, 0, 0]) result = asyncio.get_event_loop().run_until_complete(hf14a.raw(b"\x60")) assert result["received"] == 10 assert result["raw"] == version # trimmed to the received length, not the padding assert result["data"] == version.hex() def test_14a_raw_no_response_is_empty(): t = AsyncMock() hf14a = HF14ACommands(t) # tag didn't answer: received length 0, buffer full of zeros -> must come back empty t.send_mix.return_value = PM3Response(cmd=Cmd.ACK, status=0, reason=0, ng=False, data=b"\x00" * 40, oldarg=[0, 0, 0]) result = asyncio.get_event_loop().run_until_complete(hf14a.raw(b"\x30\x99")) assert result["received"] == 0 assert result["raw"] == b"" # not 40 bytes of zeros assert result["data"] is None 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("