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_mfc import HFMFCommands def test_mf_rdbl(): t = AsyncMock() mf = HFMFCommands(t) block_data = bytes(range(16)) t.send_ng.return_value = PM3Response(cmd=Cmd.HF_MIFARE_READBL, status=0, reason=0, ng=True, data=block_data) result = asyncio.get_event_loop().run_until_complete( mf.rdbl(block=0, key="FFFFFFFFFFFF")) assert result["data"] == block_data.hex() assert len(result["raw"]) == 16 def test_mf_wrbl(): t = AsyncMock() mf = HFMFCommands(t) t.send_mix.return_value = PM3Response(cmd=Cmd.ACK, status=0, reason=0, ng=False, data=b"", oldarg=[1, 0, 0]) result = asyncio.get_event_loop().run_until_complete( mf.wrbl(block=4, key="FFFFFFFFFFFF", data="11" * 16)) assert result["success"] is True # firmware: key at asBytes[0], block_data at asBytes[10] kwargs = t.send_mix.call_args.kwargs payload = kwargs["payload"] assert len(payload) == 26 assert payload[:6] == bytes.fromhex("FFFFFFFFFFFF") assert payload[6:10] == b"\x00" * 4 assert payload[10:26] == bytes.fromhex("11" * 16) assert kwargs["arg0"] == 4 assert kwargs["arg1"] == 0 def test_mf_value_increment_in_place(): t = AsyncMock() mf = HFMFCommands(t) t.send_mix.return_value = PM3Response(cmd=Cmd.ACK, status=0, reason=0, ng=False, data=b"", oldarg=[1, 0, 0]) result = asyncio.get_event_loop().run_until_complete( mf.value(block=5, action=0, value=10, key="FFFFFFFFFFFF")) assert result == {"success": True, "block": 5} # in-place commit args, kwargs = t.send_mix.call_args.args, t.send_mix.call_args.kwargs assert args[0] == Cmd.HF_MIFARE_VALUE assert kwargs["arg0"] == 5 and kwargs["arg1"] == 0 and kwargs["arg2"] == 0 p = kwargs["payload"] assert len(p) == 34 assert p[:6] == bytes.fromhex("FFFFFFFFFFFF") # key assert p[9] == 0 # action = increment assert p[10] == 0 # transfer in place (commit to block) assert struct.unpack_from(" no nested auth def test_mf_value_transfer_cross_sector(): t = AsyncMock() mf = HFMFCommands(t) t.send_mix.return_value = PM3Response(cmd=Cmd.ACK, status=0, reason=0, ng=False, data=b"", oldarg=[1, 0, 0]) # block 4 (sector 1) restore -> block 8 (sector 2): cross-sector => nested-auth flag set result = asyncio.get_event_loop().run_until_complete( mf.value(block=4, action=2, transfer_block=8, key="A0A1A2A3A4A5")) assert result == {"success": True, "block": 8} p = t.send_mix.call_args.kwargs["payload"] assert p[9] == 2 and p[10] == 8 # restore, transfer to block 8 assert p[33] == 1 # crosses sector -> nested auth def test_mf_nested(): t = AsyncMock() mf = HFMFCommands(t) # reply: isOK=0, block=8, keytype=1, cuid, nt_a, ks_a, nt_b, ks_b reply = struct.pack("