RfidResearchGroup / proxmark3

Iceman Fork - Proxmark3
http://www.icedev.se
GNU General Public License v3.0
3.63k stars 981 forks source link

`hf emrtd` implementation deadlocks UART with NG frames #2311

Open marcellp opened 4 months ago

marcellp commented 4 months ago

Describe the bug This is a continuation of #1714 with better reproducibility steps and a patch that fixes the problem, but probably introduces other problems.

The bug seems to be more general and to do with the way the packets are being sent via UART on macOS.

To Reproduce

  1. Compile latest pm3 + firmware on macOS.
  2. Flash the firmware onto the Proxmark 3.
  3. Grab a passport utilizing ISO/IEC 14443(B) as a communication standard.
  4. Run hf emrtd info.

Expected behavior Details of passport being printed.

Instead, observed behavior is:

[usb] pm3 --> hf emrtd info -m xyz
[=] ..
[=] Authentication is enforced
[=] Switching to external authentication...
[=] External authentication with BAC successful.

[=] ------------------ Basic Info ------------------
[+] Communication standard: ISO/IEC 14443(B)
[+] Authentication........: Enforced
[+] PACE..................: Available
[+] Authentication result.: Successful

[=] ----------------- EF_CardAccess ----------------
[+] PACE version..........: 2
[+] PACE algorithm........: ECDH, Generic Mapping, AES-CMAC-256
[+] PACE parameter........: NIST P-256 (secp256r1)
[=] You can cancel this operation by pressing the pm3 button
[!!] 🚨 APDU: reply timeout
[!!] 🚨 Failed to secure select 011E
[!!] 🚨 Failed to read EF_COM.

After minimum viable patch from below is applied, passport is read successfully:

[=] ..
[=] Authentication is enforced
[=] Switching to external authentication...
[=] External authentication with BAC successful.

[=] ------------------ Basic Info ------------------
[+] Communication standard: ISO/IEC 14443(B)
[+] Authentication........: Enforced
[+] PACE..................: Available
[+] Authentication result.: Successful

[=] ----------------- EF_CardAccess ----------------
[+] PACE version..........: 2
[+] PACE algorithm........: ECDH, Generic Mapping, AES-CMAC-256
[+] PACE parameter........: NIST P-256 (secp256r1)
[=] ..

[=] -------------------- EF_COM --------------------
[+] EF_DG1 ...............: Details recorded in MRZ
[+] EF_DG2 ...............: Encoded Face
[+] EF_DG14...............: Security Options
[=] ...............
[=] ..

[=] -------------------- EF_DG1 --------------------
[+] Document Type.........: Passport
[+] Document Form Factor..: TD3
[+] Issuing state.........: GBR
[+] Nationality...........: GBR
[... omitted ...]

Desktop (please complete the following information):

[usb] pm3 --> hw version

 [ Proxmark3 RFID instrument ]

 [ Client ]
  Iceman/master/v4.18218-49-g99571f328-dirty-suspect 2024-03-02 20:44:16 490a2c900
  compiled with............. Clang/LLVM Apple LLVM 15.0.0 (clang-1500.0.40.1)
  platform.................. OSX / x86_64
  Readline support.......... present
  QT GUI support............ absent
  native BT support......... absent
  Python script support..... absent
  Lua SWIG support.......... present
  Python SWIG support....... absent

 [ Proxmark3 ]
  firmware.................. PM3 GENERIC

 [ ARM ]
  bootrom: Iceman/master/v4.18218-49-g99571f328-dirty-suspect 2024-03-02 20:43:53 490a2c900
       os: Iceman/master/v4.18218-49-g99571f328-dirty-suspect 2024-03-02 20:44:01 490a2c900
  compiled with GCC 10.3.1 20210824 (release)

 [ FPGA ]
  fpga_pm3_lf.ncd image 2s30vq100 2024-02-03 15:12:10
  fpga_pm3_hf.ncd image 2s30vq100 2024-02-03 15:12:20
  fpga_pm3_felica.ncd image 2s30vq100 2024-02-03 15:12:41
  fpga_pm3_hf_15.ncd image 2s30vq100 2024-02-03 15:12:31

 [ Hardware ]
  --= uC: AT91SAM7S512 Rev A
  --= Embedded Processor: ARM7TDMI
  --= Internal SRAM size: 64K bytes
  --= Architecture identifier: AT91SAM7Sxx Series
  --= Embedded flash memory 512K bytes ( 62% used )
[#] Memory
[#]   BigBuf_size............. 41648
[#]   Available memory........ 37804
[#] Tracing
[#]   tracing ................ 1
[#]   traceLen ............... 4694
[#] Current FPGA image
[#]   mode.................... fpga_pm3_hf.ncd image 2s30vq100 2024-02-03 15:12:20
[#] LF Sampling config
[#]   [q] divisor............. 95 ( 125.00 kHz )
[#]   [b] bits per sample..... 8
[#]   [d] decimation.......... 1
[#]   [a] averaging........... yes
[#]   [t] trigger threshold... 0
[#]   [s] samples to skip..... 0
[#]
[#] LF T55XX config
[#]            [r]               [a]   [b]   [c]   [d]   [e]   [f]   [g]
[#]            mode            |start|write|write|write| read|write|write
[#]                            | gap | gap |  0  |  1  | gap |  2  |  3
[#] ---------------------------+-----+-----+-----+-----+-----+-----+------
[#] fixed bit length (default) |  31 |  20 |  18 |  50 |  15 | n/a | n/a |
[#]     long leading reference |  31 |  20 |  18 |  50 |  15 | n/a | n/a |
[#]               leading zero |  31 |  20 |  18 |  40 |  15 | n/a | n/a |
[#]    1 of 4 coding reference |  31 |  20 |  18 |  34 |  15 |  50 |  66 |
[#]
[#] HF 14a config
[#]   [a] Anticol override.... std    ( follow standard )
[#]   [b] BCC override........ std    ( follow standard )
[#]   [2] CL2 override........ std    ( follow standard )
[#]   [3] CL3 override........ std    ( follow standard )
[#]   [r] RATS override....... std    ( follow standard )
[#] Transfer Speed
[#]   Sending packets to client...
[#]   Time elapsed................... 500ms
[#]   Bytes transferred.............. 346624
[#]   Transfer Speed PM3 -> Client... 693248 bytes/s
[#] Various
[#]   Max stack usage......... 3952 / 8480 bytes
[#]   Debug log level......... 1 ( error )
[#]   ToSendMax............... 30
[#]   ToSend BUFFERSIZE....... 2308
[#]   Slow clock.............. 30537 Hz
[#] Installed StandAlone Mode
[#]   LF HID26 standalone - aka SamyRun (Samy Kamkar)
[#]

Additional context

Upon research on #2289 with three separate passports issued by different countries, I managed to trace down the issue and "fix" it.

In particular:

Then after debugging the exact communications path differences, I noticed the following:

Enabling

#define COMMS_DEBUG
#define COMMS_DEBUG_RAW

in client/src/comms.c indicated that:

After extensive debugging across the comms path on both the client-side and the device-side, it seems that:

Therefore, as receive_ng() is continuously called from the event loop in the firmware, it seems that receive_ng never passes control over to receive_ng_internal.

This led to the minium viable fix for the issue, which is:

diff --git a/armsrc/cmd.c b/armsrc/cmd.c
index ee2565cd2..fb0ea539d 100644
--- a/armsrc/cmd.c
+++ b/armsrc/cmd.c
@@ -232,7 +232,7 @@ static int receive_ng_internal(PacketCommandNG *rx, uint32_t read_ng(uint8_t *da
 int receive_ng(PacketCommandNG *rx) {

     // Check if there is a packet available
-    if (usb_poll_validate_length())
+    if (usb_check())
         return receive_ng_internal(rx, usb_read_ng, true, false);

 #ifdef WITH_FPC_USART_HOST

Unfortunately, as usb_poll_validate_length was introduced for a reason, this is likely not the correct fix, but it does cause the passport to be read correctly on macOS.

I hope this framing of the issue will make it easier to track down the cause, which now looks likely to be related to the uart implementations in the macOS POSIX SDK instead of the emrtd code path specifically.

iceman1001 commented 4 months ago

Great write-up with the communications.

iceman1001 commented 4 months ago

I believe the issue is inside uint32_t usb_read_ng(uint8_t *data, size_t len)