Commit Graph
4622 Commits
Author SHA1 Message Date
Iceman b24dad31c4 Merge pull request #3625 from nieldk/master
Fix ble name resolution and hitag dump (ble)
2026-09-14 23:17:32 +07:00
iceman1001 e51ef6caff fix defines 2026-09-14 17:24:31 +02:00
iceman1001 fd292048a8 fix redundant definition of ARRAYLEN 2026-09-14 16:58:42 +02:00
Niel Nielsen d7fb9654d3 fix(hitag): only one reply_ng on reader/writer abort path
ReaderHitag() and WriterHitag() double-replied on the abort path: when a
new command arrives mid-loop, data_available() sets checked = -1 and breaks,
then the out: block calls reply_ng(PM3_ESOFT) *and* falls through to a second
reply_ng(PM3_SUCCESS/EFAILED) — two NG responses for one command.

USB tolerates the stray frame, but over the BLE/FPC bridge the extra
unsolicited response desyncs the pipeline and the device appears to stop
responding until reconnect (reproducible with `lf hitag dump --pwd` on empty
air, then any following command over BLE).

Gate the final reply_ng behind an else so each command yields exactly one
response on every path: abort -> PM3_ESOFT, otherwise -> PM3_SUCCESS/EFAILED.

Signed-off-by: Niel Nielsen <nieldk@gmail.com>
2026-09-14 16:23:38 +02:00
iceman1001andClaude Opus 5 (1M context) 3e98b2dfe4 hf legic: stop eload losing everything after its first packet
'hf legic eload' writes emulator memory as a burst of back-to-back
packets. CMD_HF_LEGIC_ESET called FpgaDownloadAndGo(FPGA_BITSTREAM_HF)
on every one of them, and when that actually had a bitstream to download
the device stopped servicing USB for long enough that the packets already
in flight behind it were dropped.

Reproducible, and it only shows after a command that left a different
bitstream loaded, which is why it has gone unnoticed:

    hf iclass eload ...      # loads FPGA_BITSTREAM_HF_15
    hf legic eload -f x.bin  # first packet downloads FPGA_BITSTREAM_HF
    hf legic esave --1024    # 404 bytes of 1024 come back as zeros

The boundary is always 619, which is max_cmd_data_size minus
sizeof(legic_packet_t) -- exactly one packet. Back to back a second time
it works, because the bitstream is then already loaded. The 'fast push
mode' in legic_seteml() is not involved: block_after_ACK only applies to
OLD frames and these are NG.

So the handler does no FPGA work at all now. The comment it used to carry
-- 'if it is called later, it might destroy the Emulator Memory' -- was
aiming at a real problem but solving it at the wrong end. init_tag() in
legicrfsim.c is where the bitstream is genuinely needed, and it was using
the plain variant twelve lines above 'legic_mem = BigBuf_get_EM_addr()',
so 'hf legic sim' was wiping the image it was about to serve. That one
becomes _keep_EM.

Five sibling handlers carry the same copy-pasted comment and the same
wipe-before-use pattern and are switched to _keep_EM as well:
CMD_LF_EM4X50_SIM (em4x50_sim reads its tag out of emulator memory),
CMD_LF_EM4X50_ESET, CMD_HF_ISO15693_EML_SETMEM, EML_GETMEM and
CMD_HF_MIFARE_EML_MEMCLR. Only the LEGIC path has a reproducer; the rest
is the same fix applied where the same mistake is visible.

Verified on an RDV4: the reproducer above now loses 0 bytes over three
runs, 'hf legic sim' reports the MCD/MSN of the uploaded image, and
eload/esave still round-trips byte-identical for MIFARE Classic 4K,
iso15693 and iCLASS.

Co-Authored-By: Claude Opus 5 (1M context)
2026-09-14 15:05:31 +02:00
iceman1001andClaude Opus 5 (1M context) 616ec198f0 BigBuf: raise emulator memory to 8192 bytes
A MIFARE Classic 4K fills 4096 of emulator memory exactly, so at that
size it was fully committed and nothing larger could be simulated at
all.

The 4096 comes out of BigBuf, which is 33272 bytes on AT91, so it is
4096 that traces and LF samples do not get. The largest allocation any
tag simulation makes alongside emulator memory is 10459 bytes, which
leaves 18.7 kB of trace at the new size. LF acquisition is unaffected
either way: lfops.c calls BigBuf_free(), which drops emulator memory
entirely, so the two never coexist.

The device already reports this size to the client in capabilities_t, so
no client change is needed and both the client and device side download
clamps pick up the new value on their own.

This increased reserved space for emulator memory is intended pave the way for MIFARE DESfire simulation better.

Verified on an RDV4: eload/esave round trips byte-identical for MIFARE
Classic 4K, Ultralight, iso15693, iCLASS and LEGIC MIM1024; ST25TA
simulation starts and runs; lf read still gets 33271 samples; both
clamps now truncate at 8192.

Co-Authored-By: Claude Opus 5 (1M context)
2026-09-14 14:50:23 +02:00
iceman1001andClaude Opus 5 (1M context) 5b909402b5 BigBuf: stop narrowing sizes, and size the 14a modulation buffer to fit
Three things that all cost memory or correctness once BigBuf is larger
than 64KB, which it already is on PM5.

BigBuf_max_traceLen() returned a uint16_t while s_bigbuf_hi is a
uint32_t. At 33272 on AT91 that is harmless; on AT32, where BigBuf runs
to several hundred kbyte, it truncates and LF sampling asks for a
fraction of the buffer that is there. Widened, along with the four
callers that assigned it straight back into a uint16_t.

BigBuf_malloc() and BigBuf_calloc() took a uint16_t chunksize, so a
request of exactly 65536 arrived as 0 and anything above wrapped. It
returned NULL for the 65536 case by accident, not by design. Both take a
uint32_t now and the guard tests the upper bound explicitly, so an
oversized request fails like any other allocation that does not fit.

The 14a tag simulation allocated its dynamic modulation buffer as a flat
512, or 4096 for ST25TA. prepare_tag_modulation() memcpy's the encoded
answer out of the ToSend buffer and tosend_stuffbit() hard caps that at
TOSEND_BUFFER_SIZE, so 1788 of ST25TA's 4096 could never be reached --
it was the largest single allocation of any tag simulation for nothing.
Meanwhile 512 is 68 bytes short of what a full 64 byte response encodes
to, at 9 bytes per byte plus 4, so those answers were refused at
modulation time.

Both are now derived from the response size and capped at what ToSend
can hold: 580 for the default tag types, 2308 for ST25TA. That also
fixes the reason the 4096 never helped -- all six call sites passed the
512 macro as max_buffer_size rather than the size actually allocated, so
ST25TA allocated 4096 and then bounds checked against 512.

Worst case for a simulation that also holds emulator memory drops from
12247 bytes of BigBuf to 10459.

Built for client, RDV4 and PM3GENERIC. Not yet run on hardware.

Co-Authored-By: Claude Opus 5 (1M context)
2026-09-14 13:06:14 +02:00
iceman1001 8f5fd048d3 improve emulator downloads with out of bounds checks 2026-09-14 12:27:06 +02:00
iceman1001 9caa6d6117 minor change we device now reports back EMULATOR memory size to the client. Had to bump capability version number to 11. 2026-09-14 12:16:51 +02:00
iceman1001andClaude Opus 5 (1M context) e19c6755fe hf mf: stop a refused nested auth from hanging autopwn and eating the keys
MifareNested collected nonces in 'while (target_nt[i] == 0)' with no
attempt counter. When the tag NAKs the nested authentication the loop
re-sent the identical frame forever, so the client's 2s wait expired and
autopwn returned PM3_ETIMEOUT — throwing away every key recovered up to
that point. Reported on a card whose sector 16 refuses the standard MFC
EV1 keys: 32 keys cracked, nothing saved.

A NAK is a refusal, not a glitch, so the device now gives up on it and
reports PM3_EWRONGANSWER. autopwn names the sector it skipped and carries
on, and a timeout falls through to the key table and the dump whenever
anything was recovered.

Co-Authored-By: Claude Opus 5 (1M context)
2026-09-13 15:56:41 +02:00
iceman1001andClaude Opus 5 (1M context) 43fe6c3eb8 fpga_compress: pick the LZ4 block size by consumer, not by file count
The 1 MB block branch exists for the ARM .data section: start.c's
uncompress_data_section() reads one 4-byte length and does one
LZ4_decompress_safe(), so .data has to arrive as a single block. It was
selected by 'num_infiles == 1', which is not what tells the two callers apart.

A build that skips LF, FeliCa and ISO15693 leaves FPGA_BITSTREAMS holding just
fpga_pm3_hf.bit, so the bitstream took that same branch and was packed as one
42 kB block. get_from_fpga_combined_stream() decompresses into a
FPGA_RING_BUFFER_BYTES buffer, 16 kB since 83c3f81b1:

  [#] inflate returned: -13247
  [#] reset_fpga_stream failed

Before 83c3f81b1 the copy was clamped with MIN(FPGA_RING_BUFFER_BYTES, ...)
whatever buffer_size said, so the blocks came out at 30 kB and the 30 kB ring
buffer still took them. That is why the commit looks like the cause - it only
removed the clamp that was covering for the wrong branch.

Add -s for the single block case and let the FPGA path always chop at
FPGA_RING_BUFFER_BYTES, however many bitstreams went in:

  4 bitstreams   169344 in -> 106933 out, byte identical to before
  1 bitstream     42172 in ->  28718 out, 3 blocks 13265/13206/2247,
                                          was 1 block of 27627
  .data  (-s)     14944 in ->   8786 out, byte identical to the
                                          obj/fullimage.data.bin.z in tree

Also hand the ring buffer back when reset_fpga_stream() fails. The early
return left it allocated for the rest of the session, which is the reporter's

  [#]   BigBuf_size............. 48116
  [#]   Available memory........ 31732

48116 - 31732 is 16384, exactly FPGA_RING_BUFFER_BYTES.

No CAPABILITIES_VERSION bump: fpga_all.bit.z is objcopy'd into the same
fullimage as the decompressor that reads it, so nothing here is client facing.

Reported and correctly diagnosed by @ewangsoft.

Fixes #3599

Co-Authored-By: Claude Opus 5 (1M context)
2026-09-13 08:14:43 +02:00
iceman1001andClaude Opus 5 (1M context) 971c318d78 smart raw: make --t1 switch the card to T=1 by itself
A card runs the protocol its TD1 names until a PPS changes it. --t1 only
picked the module's T=1 send opcode, so on a card whose ATR offers T=0 first
the APDU went out as T=1 blocks to a card still speaking T=0 and got no
answer at all:

  smart raw --t1 -s -d 00a4040007a000000004101000
  [!] smart card response failed

'smart pps --t1' in the same client session made it work, which is what the
help for 'smart pps' already promised was unnecessary:

  Note 'smart raw --t1' already switches a card to T=1 by itself when
  the ATR offers it; this is for negotiating Fi/Di explicitly.

Do it for real. SmartCardRaw() now runs the PPS when T=1 is asked for and
nothing has selected it yet, taking the ATR it needs first because PPS is
only legal in that window. It fires once per activation: a second --t1 apdu
sees the protocol already in force and sends straight away. A card that does
not offer T=1 is left alone and the apdu still goes out, as before.

Also fix the flag names in the docs and in the error path. 'smart raw's
first example and both 'Choose either' messages said -0 / -1, which have
never existed. tools/pm3_online_tests.sh had copied the example, so its T=0
checks failed with 'invalid option' on every run; its T=1 checks needed no
change beyond dropping the now unnecessary reset.

Co-Authored-By: Claude Opus 5 (1M context)
2026-09-12 23:54:39 +02:00
iceman1001andClaude Opus 5 (1M context) 255576fa43 make hf 14a antifuzz actually reach a reader
Every answer was modulated after the reader's frame arrived, landing
~1812 carrier periods late against the 1172 the FDT allows, so readers
timed out before any of it mattered. All answers are now precomputed the
way hf 14a sim does it, and a phone answers at 1172 exactly.

Cascade mode sent a cascade tag at every level, which a conforming reader
rejects in the last level its ATQA announced - it dropped the card before
ever sending a SELECT. The cascade tag now appears only below that level;
it is the SAK that lies about the UID being incomplete, and that is what
walks a reader up to cascade level 7.

A bit oriented ANTICOLLISION was answered with the whole UID instead of
the bits the reader still lacked, handing it a frame of the wrong length.
One encoder now builds any tail, with or without collisions in it.

--coll leaves the first UID byte clean and collides every bit after it, so
a reader resolves 24 bits one round trip at a time, is then given a BCC
that checks out, and is cascaded into the same again - 183 answers per
poll against the 3 a real card needs. Colliding byte 0 as well only
produced a UID of all ones, which readers drop before asking for the BCC.

Reader frames that go unanswered are traced instead of silently dropped,
LED B marks an attempt in progress and LED C flips on each step deeper,
and the closing line reports rounds run and how far a reader got.

trace list -t 14a decodes SEL 0x99..0x9F, shows how many UID bits a bit
oriented ANTICOLL claims, and no longer flags those CRC-less frames as
bad CRC.

Co-Authored-By: Claude Opus 5 (1M context)
2026-09-12 21:18:26 +02:00
iceman1001 baea4014c1 fix cident overflows 2026-09-12 20:35:35 +02:00
iceman1001andClaude Opus 5 (1M context) 4d7d49e089 stop an FPGA bitstream download from eating the emulator memory
FpgaDownloadAndGoEx() with keep_em false does BigBuf_free() plus
BigBuf_Clear_ext(): the emulator memory pointer is nulled and all of BigBuf is
zeroed.  iso14443a_setup() calls that variant, and Mifare1ksim(),
SimulateIso14443aTagEx() and SimulateIso14443aTagAID() build their precompiled
anticollision responses in BigBuf first.  CMD_HF_MIFARE_EML_MEMGET had it the
other way round - it downloaded, then read the memory it had just wiped, so
'hf mf eview' and 'hf mf esave' returned their own zeros after any lf hitag,
hf iclass or hf 15 command.  A download already cached early-returns, so which
image the FPGA held decided whether any of this happened.

All five now call FpgaDownloadAndGo_keep_EM() before any BigBuf allocation.
Free-BigBuf floor at download time goes 16384 -> 20480 (ring plus the 4096 byte
emulator block); BigBuf measures 29084..31420 across all standalone configs on
RDV4 and 40120 on a PM3 Easy.

The sim paths also clear the trace before taking their modulation buffer -
BigBuf_malloc() refuses memory a stale trace holds, and MifareSimInit() ignored
the NULL, leaving prepare_tag_modulation() to memcpy 571 bytes over the vector
table at address 0.

'hf mf eload' now zeroes emulator memory device side: CMD_HF_MIFARE_EML_MEMSET
takes a flags byte, set on the first chunk only, so 'hf mf esetblk' and every
other partial write still touch only their own blocks.  That byte is why
CAPABILITIES_VERSION goes 9 -> 10; mismatched client and firmware refuse to
connect rather than write everything one byte offset.

Reported in #2836, whose USB drop is separately addressed by bc289cf43.

Builds clean for PM3RDV4, PM5 and the client; astyle clean.  Not yet verified on
hardware.

Co-Authored-By: Claude Opus 5 (1M context)
2026-09-12 18:49:24 +02:00
iceman1001andClaude Opus 5 (1M context) 05137e825a hold the spiffs file open across an upload
SPIFFS has no directory.  SPIFFS_open() by name walks the object lookup page of
every block and reads the header of each index page it meets to strcmp the name,
so reopening per packet makes an upload cost packets x filesystem size.  On a 2MB
part one open reads about 120KB of flash - storing a 512KB file spent 16MB of
reads finding the same file 131 times over, and 249MB back when a packet was one
256 byte flash page.

append_to_spiffs() now keeps the descriptor when the next packet names the same
file.  Everything else calls spiffs_close_cached() on entry, so a held descriptor
is closed, and its writes flushed, before any other operation can look at the
file - all 15 direct SPIFFS_* call sites in this file are covered.  No protocol
change: the CMD_SPIFFS_UNMOUNT the client already sends at the end of an upload
closes it, as does any other SPIFFS command.  rdv40_spiffs_unmount() closes
before SPIFFS_unmount() since descriptors do not survive a mount, and the close
checks the mount state so a dead handle is dropped rather than passed on.

Flash reads to store a file, measured on a host build of this filesystem:

  2MB fs, 512KB file, 4029 byte packets   16302 KB -> 371 KB
  2MB fs, 512KB file,  256 byte packets  249415 KB -> 914 KB
  2MB fs, 256KB file, 4029 byte packets    7834 KB -> 313 KB
  256KB fs, 80KB file, 589 byte packets    1483 KB ->  82 KB

Written bytes are unchanged; only the searching went away.

Verified on the host against an order sensitive pattern - content byte identical,
size right, SPIFFS_check clean - both for a straight upload and for one with a
stat and an fsinfo landing mid transfer, which is the case that catches a missed
invalidation.  Then on hardware: 80KB uploaded, 'mem spiffs tree' in between to
force a flush, downloaded again, byte identical.

Co-Authored-By: Claude Opus 5 (1M context)
2026-09-12 15:54:40 +02:00
iceman1001 e87343dbef add missing ManchesterDecoding_Thinfilm decl 2026-09-12 15:29:23 +02:00
iceman1001 a878043061 fix missing appmain changes 2026-09-12 15:24:46 +02:00
iceman1001andClaude Opus 5 (1M context) 696b8357b6 add hf thinfilm sniff, and hold the tag's real frame period
hf thinfilm sniff passively records the frames a Kovio tag beams at a reader.
Kovio is tag-talks-first and the reader never sends a command, so only the tag
side is decoded - use 'hf 14a sniff' to watch a reader's poll loop.  Same DMA
loop, overrun recovery and nibble de-interleave as SniffIso14443a().

ManchesterDecoding_Thinfilm() is no longer static and takes non_real_time, the
same way ManchesterDecodingEx() does.  A DMA sniff loop cannot timestamp with
GetCountSspClk(); the clock has run on past the frame by the time the samples
are processed.

Only the decoder is RAMFUNC (724 bytes), not the sniff loop, since dropping the
Miller decode roughly halves the per sample work.  The loop counts overrun
recoveries and DMA stalls separately, so a lossy capture says so instead of
looking like a quiet tag.

With that, the sim's frame period could be measured instead of guessed.  A
genuine tag repeats every 65536 carrier periods - 2**16, it clocks a 16 bit
counter off the carrier - holding that to within 65520..65920.  So 25% duty
cycle, not the continuous beam assumed when the gap was shortened to 500us in
a96756033.  Revert to the tag's real rate.

SimulateThinFilm() now waits on the previous frame start rather than delaying a
fixed amount, so the field poll comes out of the gap instead of adding on top of
it, and the period stays right if the poll cost ever changes.  Measured back
with a second pm3 sniffing: 65561 carrier periods against the genuine tag's
65588, inside the tag's own jitter.

Rig: pm3 simulating, second pm3 sniffing, Pixel 9a reading, all three at once.
Builds clean for PM3RDV4 and PM5.

Co-Authored-By: Claude Opus 5 (1M context)
2026-09-12 15:09:53 +02:00
iceman1001andClaude Opus 5 (1M context) 9a8e179266 fix spiffs downloads >= 64K, and stop losing flash errors
CMD_SPIFFS_DOWNLOAD read the whole file into BigBuf first.  BigBuf_calloc()
takes a uint16_t while the size is a uint32_t, so a 64K file allocated zero
bytes and anything larger wrapped to a short buffer the file was then read
straight past the end of.  rdv40_spiffs_read_stream() opens the file once and
hands out one frame at a time, so the size never reaches the allocator, and the
SPIFFS path now honours start_index.  Verified with an 80K round trip: upload,
download, byte identical.

The same BigBuf_calloc(filesize) wrap was in copy_in_spiffs(); it now copies in
SPIFFS_WRITE_CHUNK_SIZE chunks.

Separately, every flash failure was invisible.  SPIFFS_CHECK_RES() only treats a
negative result as an error and the HAL hooks returned 128/129/130, so SPIFFS
saw success.  The erase path was worst: Flash_Erase4k() only reports that the
command was sent, both Flash_CheckBusy() results were discarded, and
'return (SPIFFS_OK == erased)' yields 1 on failure.  A flash dump from a device
that hit this showed one block written without being erased - its object index
header held '0x14000 & 0x10000', and the filename ANDed away to empty.  Erases
are now read back and retried, and the HAL returns real SPIFFS error codes.

Flash_Write() returned len unconditionally even after a rejected page, which
also defeated the 'res == payload->len' check in CMD_FLASHMEM_WRITE.

Feedback, so none of this is silent again: CMD_SPIFFS_WRITE answers with the
SPIFFS result, the client aborts on the first refusal and names the byte it
stopped at, dl_it() checks the terminator status, and both transfer directions
print inline progress.

Co-Authored-By: Claude Opus 5 (1M context)
2026-09-12 14:58:08 +02:00
iceman1001andClaude Opus 5 (1M context) a967560335 hf thinfilm sim - shorter frame gap
The inter frame delay was 3600us for a 128 bit payload and 2400us for 256 bit,
sized so that either one holds a constant 4.8ms repeat period.  That is the wrong
target.  A Kovio tag is never transacted with - the reader captures it during a
poll slot and hands the bytes up as an activation, see
nfa_dm_disc_handle_kovio_activation() in libnfc-nci, which reads the barcode
straight out of rf_tech_param.param.pk.uid - so the only thing that matters is how often a frame is on the air.

Measured repeat period before today was 8.66ms, ie 14% duty cycle.  A fixed 500us
gap takes a 128 bit payload to roughly 2.2ms.  The gap cannot go to zero, a reader
needs unmodulated carrier to find the frame start and our own demod wants three
quiet bytes, but 500us is an order of magnitude clear of that.

Also drop the 'not correct' caveat from 'hf thinfilm list', the sim side traces
properly now.

Tested on RDV4 against an Android reader.  Builds clean for PM3RDV4 and PM5.

Co-Authored-By: Claude Opus 5 (1M context)
2026-09-12 14:17:13 +02:00
Iceman a7c6116258 Merge pull request #3620 from nieldk/master
Add BWM set BLE name
2026-09-12 19:03:24 +07:00
iceman1001andClaude Opus 5 (1M context) 91f5f7e9a2 fix hf thinfilm sim
SimulateThinFilm() set the SSC up with FPGA_MAJOR_MODE_HF_READER but wrote a conf
word for FPGA_MAJOR_MODE_HF_ISO14443A | TAGSIM_MOD.  On the HF bitstream
FpgaIs16BitMsbMode() picks 16 bit frames for HF_READER, so every 8 bit SEC_D /
SEC_E went on air as 0x00 followed by the symbol, ie half the symbol rate with an
unmodulated gap before each one.  No reader decodes that and nothing errors.

Broken since e144c793f (2020-07-02) added the argument and the 16 bit branch.
thinfilm.c has passed HF_READER since 2019, when FpgaSetupSsc() took no argument
and was always 8 bit.  Every other tag sim in the tree passes HF_SIMULATOR or
HF_ISO14443A and was unaffected.

The send loop also called ReadReaderField() between every frame.  That is
AdcRssiAvg(), 32 conversions each paying a 42.7us ADC startup and a 40us sample
and hold, about 3.8ms - more than the deliberate inter frame delay sitting next
to it.  Measured repeat period was 8.66ms against the 4.8ms the delays were
written for, ie 14% duty cycle.  Poll with 4 samples, keep 32 for the one off
baseline.

The sim now enables tracing and logs each beamed frame, so 'hf thinfilm list'
works on the sim side too, and the coded buffer hexdump is behind DBG_DEBUG
instead of printing 8 lines every run.  It also read 16 bytes per line
unconditionally, so an odd length payload over read the buffer.

Tested on RDV4.  Builds clean for PM3RDV4 and PM5.

Co-Authored-By: Claude Opus 5 (1M context)
2026-09-12 13:58:39 +02:00
Niel Nielsen e2cefcff3a Refine OTA command and timeout configurations
Updated OTA command definitions and timeout settings.

Signed-off-by: Niel Nielsen <nieldk@gmail.com>
2026-09-12 13:29:52 +02:00
Niel Nielsen 423ede5d29 Update print statement from 'Hello' to 'Goodbye'
Signed-off-by: Niel Nielsen <nieldk@gmail.com>
2026-09-12 13:29:30 +02:00
Niel Nielsen 407d9d7474 Add BLE name handling for GET and SET commands
Signed-off-by: Niel Nielsen <nieldk@gmail.com>
2026-09-12 13:27:34 +02:00
Niel Nielsen 9d587e3dcc Update OTA command definitions and BLE functions
Signed-off-by: Niel Nielsen <nieldk@gmail.com>
2026-09-12 13:20:53 +02:00
Niel Nielsen 2b98c126a7 Update print statement from 'Hello' to 'Goodbye'
Signed-off-by: Niel Nielsen <nieldk@gmail.com>
2026-09-12 13:20:24 +02:00
iceman1001 df68cf72e0 hf mf: match the isOK status locals to reply_ng() 2026-09-12 11:47:03 +02:00
iceman1001andClaude Opus 5 (1M context) 50a2b0ca37 hf mf autopwn: recover the crypto1 session when a read is denied
A read the card NAKs aborts the crypto1 session, so after the first
denied block every later read in that sector came back with len 0 and
the retry loop spun on it. One unreadable block cost the whole sector,
and the dump only recovered when the next sector did a fresh select.

MifareECardLoad also only fell back to key B when the *auth* failed,
never when the *read* was denied, so a sector whose access conditions
allow a read with B but not with A was lost even though both keys were
known. That is the gap between this and the client side 'hf mf dump',
which picks the key per block.

Re-select and re-authenticate after a NAK, and retry the block with the
other key first. If it reads, stay on that key for the rest of the
sector; if it does not, re-auth with the original key so the remaining
blocks still read instead of collapsing. The backdoor key path has no
counterpart key to swap to, so it only clears bd_authenticated to force
a re-select on the next sector.

On an MFC EV1 with two sectors that deny key A reads, this takes the
dump from PARTIAL with 96 spurious len-0 errors to complete on the first
pass.

Co-Authored-By: Claude Opus 5 (1M context)
2026-09-12 11:24:32 +02:00
iceman1001 03fed51af5 fix isOK size 2026-09-12 11:10:38 +02:00
Niel Nielsen 711b6ebcd6 Merge branch 'RfidResearchGroup:master' into master 2026-09-12 10:44:42 +02:00
iceman1001andClaude Opus 5 (1M context) 6341f40b4c hf mf hardnested: fix the nonce reply length, 9 bytes per pair not 4 per nonce
Thanks @TheArchitect0880 for pointing it out and suggested a first fix.

MifareAcquireEncryptedNonces packs two 4 byte encrypted nonces plus one
byte holding both their encrypted parity nibbles into every entry, but
the reply declared num_nonces * 4 bytes. The client walks that buffer 9
bytes at a time, so on RDV4 it read 612 bytes out of a 544 byte payload
and handed roughly 15 of every 136 nonces to add_nonce() from stale
packet buffer content. Those fake nonces went into the .bin nonce file
too.

Count pairs instead of bytes. num_nonces now reports whole pairs only,
so a button abort or a static nonce bailout part way through a pair
drops the dangling nonce rather than shipping a half built entry whose
parity nibble was never filled in.

MFC_NONCE_PAIR_SIZE and MFC_MAX_NONCE_PAIRS document the layout next to
mf_nonces_resp_t so the 9 vs 4 confusion cannot come back, and the
client now refuses a reply too short for the nonce count it carries.

Both acquisition functions collect straight into the reply buffer rather
than a second PM3_CMD_DATA_SIZE stack array, which halves the stack used
per call. MifareAcquireNonces also returned isOK = 2 on button press,
which is not a PM3_* status; that is PM3_EOPABORTED now.

Co-Authored-By: Claude Opus 5 (1M context)
2026-09-12 10:44:00 +02:00
Niel Nielsen ac7a3f3c5a Improve RGB LED state handling on power source change
Add acknowledgment check for RGB LED state change.

Signed-off-by: Niel Nielsen <nieldk@gmail.com>
2026-09-12 10:31:32 +02:00
Iceman aef0a76409 Merge pull request #3600 from Antiklesys/master
Faster i2c comms
2026-09-08 15:29:25 +07:00
Antiklesys 4633805268 Update i2c.h 2026-09-08 16:07:15 +08:00
Antiklesys b412b9c167 Merge branch 'master' of https://github.com/Antiklesys/proxmark3 2026-09-08 16:04:48 +08:00
Antiklesys 9785461f17 Faster i2c comms 2026-09-08 16:04:45 +08:00
kormaxandmxcdoam 1ecbcb74be Add ISO14443-3 Type A timeslot support to 'hf 14a info' and 'hf 14a reader'
Co-authored-by: mxcdoam <72457810+mxcdoam@users.noreply.github.com>
2026-09-07 22:55:24 +03:00
Iceman 9f641c3ced Merge pull request #3427 from Sanduuz/feature/st25ta_ndef_sim
Added support for emulating ST25TA tag (IKEA Rothult) with custom NDEF response
2026-09-07 15:38:46 +07:00
xilni 342cc37cca docs(bwm): fix stale hw bwm command references 2026-09-07 00:07:07 -04:00
Iceman 2da575ab36 Merge branch 'master' into master
Signed-off-by: Iceman <iceman@iuse.se>
2026-09-06 21:25:31 +07:00
Antiklesys b2ae468bf9 Update i2c.h 2026-09-06 13:53:46 +08:00
dxl fc355df050 Added IO test capabilities to the factory QC for PM5. 2026-09-05 18:09:46 +02:00
dxl 93983ed82f PM5 unit test logic updated. 2026-09-05 18:09:46 +02:00
dxl ea5485b4b8 Rename CMD_PM5_QC_TEST to CMD_PM5_QC_TEST_HW
and delete repeated def: CMD_PM5_BWM_SET_CAP
2026-09-05 18:09:46 +02:00
dxl c21ddfdb74 Power consumption testing has been added for pm5. 2026-09-05 18:09:46 +02:00
Antiklesys 57a42e3ce9 Stability fix for sc-bigbuf traces 2026-09-05 22:31:52 +08:00
Antiklesys ceb77de7fe Merge branch 'master' of https://github.com/Antiklesys/proxmark3 2026-09-05 17:30:52 +08:00
Antiklesys a96e3e8c18 Update sam_sc.c
Fix implemented: ARM RF-off now bypasses SAM initialization, saving 330ms from operations.
2026-09-05 17:30:42 +08:00