Skip to content

Conversation

unkernet
Copy link
Contributor

I observed unstable and incorrect behavior when using Chameleon MIFARE emulation with a city transport system.

To investigate, I wrote a Proxmark script to check card responses and determine the state after receiving incorrect or unexpected commands from a reader. I ran this script against both Chameleon and various genuine cards. The differences observed:

  • REQA / WUPA handling: Chameleon responds in all states (including Authenticated); real cards respond only in Idle state.
  • RATS handling: Chameleon responds to unencrypted RATS in both Active and Authenticated states; real cards respond only in Active state.
  • Invalid command handling: Chameleon remains in Active state; real cards return to Idle state.
  • NAK codes: Chameleon sends incorrect NAK (0x04) for wrong CRC in Authenticated state; real cards send 0x05.
  • HALT behavior: Chameleon enters Halted state when receiving an unencrypted HALT in Authenticated state; real cards do not.
  • Access bits: Chameleon does not check the currently authenticated sector or its access bits.

This PR addresses all of the above issues.
It is split into two commits for clarity:

  1. Fixes state machine reset logic.
  2. Adds proper access bits verification.

- Ensured state machine reset on CRC/parity errors and invalid operations across command handlers.
- Set `NFC_TAG_STATE_14A_PROPRIETARY` upon successful authentication to route subsequent commands only into the MF1 handler.
- Introduced `blockToSector()` and `sectorToBlock()` helpers to map between blocks and sectors.
- Added `AuthenticatedSector` to track which sector is currently authenticated.
- Fix access control table `abTrailerAccessConditions`: fixed swapped entries for access conditions.
- Prevent authentication with Key B if it is readable using Key A.
- READ and WRITE commands now verify permissions; unauthorized access are rejected.
- On trailer writes, preserved protected fields (Key A, access bits, Key B) based on access conditions if write is not permitted.
Copy link

You are welcome to add an entry to the CHANGELOG.md as well

Copy link

Built artifacts for commit 6ceefb3

Firmware

Client

Copy link
Contributor

@LupusE LupusE left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't test in the field, because in my area the public transport is not NFC based, yet. [But Other MF1 functions does not seems to be affected negative and still working.] ... It seems the code does not to compile anymore. I don't know what is different to last weeks test.
Could you check? I see missing dependencies to the nrf52_sdk. For example:

make: *** [../nrf52_sdk/components/toolchain/gcc/Makefile.common:272: ../objects/application/nfc_mf0_ntag.c.o] Fehler 127
./src/rfid/mf1_crapto1.c:142:10: fatal error: cmsis_gcc.h: No such file or directory
  142 | #include <cmsis_gcc.h>
      |          ^~~~~~~~~~~~~
compilation terminated.

I've cloned your branch directly. because there where a lot of changes in the main branch lately.

@Foxushka Foxushka mentioned this pull request Sep 2, 2025
@LupusE
Copy link
Contributor

LupusE commented Sep 7, 2025

The compilation errors seems to be caused by my environment. In a clean new approach, everything is working fine.

Nice LUA script for the PM3.
With the newest firmware (2.1.0), I am able to reproduce what you are describing. In a nutshell: The CU behaves different than a card.
So I compiled your Firmware and tested it again on my PM4. At least "with wrong CRC' answers with 05 now. But the LUA stops at Auth: with error - hf_hak.lua:265: ABORTED. Looks like a timeout.

Card details:

- Slot 3:               (active)
   HF: DB_Member       Mifare Classic 1k
      UID:                                    FF0AFFCA
      ATQA:                                   0400 (0x0004)
      SAK:                                    08
      Gen1A magic mode:                       disabled
      Gen2 magic mode:                        disabled
      Use anti-collision data from block 0:   disabled
      Write mode:                             Normal
      Log (mfkey32) mode:                     disabled

(UID redacted)

@unkernet
Copy link
Contributor Author

unkernet commented Sep 8, 2025

There are two possible issues with this test:

  1. On my PM3 Easy clone, results are very dependent on the card’s position relative to the Proxmark. I have to hold the card at a specific angle and distance, determined experimentally, otherwise the test fails.
  2. The script relies on crypto1 in the hf 14a raw command, which was introduced in this commit about a year ago. Is your Proxmark firmware up to date?

@LupusE
Copy link
Contributor

LupusE commented Sep 8, 2025

I know the position of the CU is a little picky. So I compared the latest released FW and Auth worked. I upgraded to the compiled version of your branch, and Auth stopped working. Without moving the CU.
Afterwards, as usual, I changed the position. Up do the controller, down to the other end, in the middle, 90°/180° turned, 1cm above, turned around the CU ... No luck at all. Afterwards I send my response.
Could you describe or make a photo of your best position/orientation of the CU above the antenna? This should not vary too wide from easy to RDV4. I may try hw tune, to find the sweet spot as well. I skipped this step.

My PM3 RDV4 was updated just yesterday. For reference I also checked the original card, to be sure it is not a PM3 error: OS........ Iceman/master/v4.20469-248-gd957b23f9-suspect 2025-09-07 16:37:38 2689d7032

@unkernet
Copy link
Contributor Author

unkernet commented Sep 9, 2025

I was able to reproduce the issue you describe, but only in one specific case: when attempting authentication with Key B on a sector where Key B is marked as readable. According to the datasheet, if Key B is readable in the Sector Trailer, it cannot be used for authentication. Could this be your case?

@LupusE
Copy link
Contributor

LupusE commented Sep 29, 2025

Sorry for the late answer. You know, life is always blocking development ;)

No, as far as I am aware, I am testing always with A keys... Maybe I switched this time because the key was easier to type. I'll check, when I am home next time (approx. 2 weeks, I forgot my test cards).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants