mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2026-10-06 05:37:28 +00:00
An enciphered read longer than one frame was answered with 91 7E, because the CRC32 covers the whole read and the code could only build that in one piece. It is one CBC run over the file data, a CRC32 behind it and zero padding, split across frames with the init vector carried from one to the next -- "if the commands are queued due to a very long data stream, the init vector for the decipherment is always updated" (M134034 7.3.7). So each frame only has to carry whole blocks, which the 96 byte chunk and the padded total both are, and the reader joins the ciphertext and deciphers the lot in one go. The read now walks a stream rather than a file extent: bytes come from the file while they last, then the CRC32, then padding. The CRC is taken up front, over the data and the status byte the last frame will carry, so it has to be built a piece at a time -- the status byte is not in the card image and the data can be a whole file, which rules out crc32_ex() and its single buffer. common/crc.h already has an incremental CRC, the one legicrf.c uses, so that is what this uses: crc_update() shifts LSB first, so the polynomial goes in already reflected with neither reflect flag set. Those parameters were checked against crc32_ex() over every length from 0 to 200 before being used. Tested against the simulation with a 128 byte file created through the reader in Full communication mode with all rights on key 0, so the file's mode actually applies rather than being forced plain by a free access right. Reads of 64, 96, 112 and 128 bytes all verify, the last three over two frames, and the content comes back as written. A wrong init vector or a wrong CRC would have failed the client's CRC32 check rather than passed quietly. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>