Merge branch 'wip_protocol_refresh'

* wip_protocol_refresh: (38 commits)
  CI for releases
  changelog
  build_firmware.yml: fetch depth=0 to be able to build proper version strings
  Deduce APP_FW_VER from git tag
  bump app version
  style
  colors
  Increase initial button wakeup from 4 to 8 seconds
  Adding MIFARE Ultralight reading, wip
  hf14a_raw: use @expect_response and fix tests
  Fix shadow mode not being preserved. Breaking change: nfc_tag_mf1_write_mode_t has one new mode SHADOW_REQ. Client can set SHADOW or SHADOW_REQ, internally it will be transformed to SHADOW_REQ. When it's time to save data, if SHADOW_REQ, the fw will change it to SHADOW and still allow to save the data before acting as shadow. Breaking: when client reads back MF1 write mode just after settings SHADOW and before saving config, it will receive SHADOW_REQ and must be ready to handle this new enum value.
  MF1_DETECT_SUPPORT: remove redundant data
  Breaking change: DATA_CMD_GET_DEVICE_MODEL to match chameleon_device_type_t
  hw 14a raw: closer to pm3 syntax, removed bit_frame,...
  use field LED also in reader mode
  fix changelog
  new tag_specific_type_t enum, new slotConfig struct. FW will take care of existing slots. Disruptive changes: see below
  Implemented hf 14a raw
  Fixed initialization bugs and added raw command implementation functions.
  Update the table of MFC attack support levels.
  ...
This commit is contained in:
Philippe Teuwen
2023-09-26 09:51:25 +02:00
59 changed files with 3901 additions and 2279 deletions
+2
View File
@@ -23,6 +23,7 @@ jobs:
uses: actions/checkout@v3
with:
ref: ${{ inputs.checkout-sha == null && github.sha || inputs.checkout-sha }}
fetch-depth: 0
- name: ghcr.io login
uses: docker/login-action@v2
with:
@@ -56,6 +57,7 @@ jobs:
uses: actions/checkout@v3
with:
ref: ${{ inputs.checkout-sha == null && github.sha || inputs.checkout-sha }}
fetch-depth: 0
- name: Build firmware
env:
repo: ${{ github.repository }}
+30 -1
View File
@@ -13,7 +13,7 @@ jobs:
client_pipeline:
name: Build Firmware
uses: ./.github/workflows/build_client.yml
create_release:
create_dev_release:
permissions:
contents: write
name: Create dev pre-release with artifacts
@@ -49,3 +49,32 @@ jobs:
run: |
git tag -f dev
git push --tags -f
create_release:
permissions:
contents: write
name: Create tagged release with artifacts
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/v')
needs:
- firmware_pipeline
- client_pipeline
steps:
- name: Check out the repo
uses: actions/checkout@v3
- name: Download release artifacts
uses: actions/download-artifact@v3
with:
name: release-artifacts
path: release-artifacts
- name: Upload to tagged release
uses: softprops/action-gh-release@v1
with:
body: |
Auto-Generated DFU packages for Release ${{ github.ref_name }}
Built from commit ${{ github.sha }}
name: Release ${{ github.ref_name }}
draft: false
target_commitish: ${{ github.sha }}
generate_release_notes: true
append_body: true
files: release-artifacts/*
+28 -1
View File
@@ -3,7 +3,34 @@ All notable changes to this project will be documented in this file.
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
## [unreleased][unreleased]
- Added `hf settings blepair` command to get and set ble pairing enable state, and default disable ble pair. (@xianglin1998)
## [v2.0.0][2023-09-26]
- Changed APP_FW_VER now deduced from git tag vx.y.z (@doegox)
- Changed initial button wakeup from 4 to 8 seconds (@aramova)
- Added MIFARE Ultralight reading features (@FlUxIuS & @doegox)
- Fixed MF1 write mode SHADOW was not preserved properly (@doegox)
- Changed field LED now active also in reader mode to indicate that reader is powering the field (@doegox)
- Changed slot enabled logic: now we have separate enabled_hf and enabled_lf, changed GET_ENABLED_SLOTS and SET_SLOT_ENABLE (@doegox)
- Changed tag type enum to be ready for new types, changed stored slotConfig and GET_SLOT_INFO (@doegox)
- Added HF14A_RAW and its support in `hf 14a raw` (@xianglin1998)
- Removed MF1_DETECT_DARKSIDE (@doegox)
- Added MF1_STATIC_NESTED_ACQUIRE and its support in `hf mf nested` (@xianglin1998)
- Changed `hf 14a scan`: Automatically send RATS to 14443-4a tags (@augustozanellato)
- Changed Darkside: use LEDs for visual feedback of attack progression (@doegox)
- Changed Darkside: longer RF field off for reset and longer CLI timeout (@doegox)
- Fixed Darkside: parity byte-to-array bug made it low probability to succeed (@doegox)
- Changed `hw detection decrypt` show progression and remove duplicate keys (@doegox)
- Changed dynamic cmd_map_init() by static cmd_map initialization (@doegox)
- Changed `hf slot list` to add clarity and colors (@doegox)
- Changed `hf mf sim` and `hf mf info` to support ATS (still to be used in actual emulation) (@doegox)
- Changed `hf mf eload` and `hf mf eread`: uploads/downloads are now 30x faster (@doegox)
- Changed CLI HF14AInfo logic merged inside HF14AScan for more consistent display of the results (@doegox)
- Added guessed type information for NXP tags, and reorganization of HF information part. (@FlUxIuS)
- Changed `hw raw` to detail status message (@doegox)
- Changed CLI to query capabilities on connect, not on every single command if device does not support get_device_capabilities (@doegox)
- Changed CLI to not instanciate ChameleonCMD on every single command (@doegox)
- Changed massively the protocol and its handlers for more consistency and easier maintenance and future dev (@doegox)
- Added `hf settings blepair` command to get and set ble pairing enable state, and default disable ble pair (@xianglin1998)
- Added `hf mf info` command to get UID/SAK/ATQA from slot (@Foxushka)
- Added `hw raw` to send raw command to Chameleon (@Foxushka)
- Added command to fetch all available commands from Chameleon and test if Chameleon supports it (@Foxushka)
+4
View File
@@ -345,3 +345,7 @@ Limitations:
* SWO pin is shared with... SWO so when e.g. reflashing the device, garbage may appear on the monitoring terminal.
* SWO pin is also shared with the blue channel of the RGB slot LEDs, so faint blue may appear briefly when logs are sent and LED might not work properly when supposed to be blue.
# Resources
* [nRF52840 Objective Product Specification v0.5.1](https://infocenter.nordicsemi.com/pdf/nRF52840_OPS_v0.5.1.pdf)
+5
View File
@@ -0,0 +1,5 @@
all:
pdflatex --shell-escape protocol-packet.tex
clean:
rm *.aux *.log *.pdf
Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 8.5 KiB

+24
View File
@@ -0,0 +1,24 @@
\documentclass[border=10pt,png]{standalone}
\usepackage{bytefield}
\usepackage{xcolor}
\begin{document}
\definecolor{lightcyan}{rgb}{0.85,1,1}
\definecolor{lightgreen}{rgb}{0.85,1,0.85}
\definecolor{lightred}{rgb}{1,0.85,0.85}
\begin{bytefield}[bitwidth=1.1em]{32}
\bitbox{8}[bgcolor=lightcyan]{SOF} &
\bitbox{8}[bgcolor=lightcyan]{LRC1} &
\bitbox{16}[bgcolor=lightgreen]{CMD} \\
\bitbox{16}[bgcolor=lightgreen]{STATUS} &
\bitbox{16}[bgcolor=lightgreen]{LEN} \\
\bitbox{8}[bgcolor=lightgreen]{LRC2} &
\bitbox[tlr]{24}[bgcolor=lightred]{} \\
\wordbox[lr]{1}[bgcolor=lightred]{DATA} \\
\wordbox[lr]{1}[bgcolor=lightred]{$\cdots$} \\
\bitbox[blr]{24}[bgcolor=lightred]{} &
\bitbox{8}[bgcolor=lightred]{LRC3}
\end{bytefield}
\end{document}
+374 -15
View File
@@ -2,28 +2,387 @@
**WIP**
## Packets format
## Frame format
The communication with the application is not the easiest but is structured as follows:
The communication between the firmware and the client is made of frames structured as follows:
![](images/protocol-packet.png)
- **SOF**: `1 Byte`, the "Magic Byte" represent the start of a packet, must be `0x11`.
- **LRC1**: `1 Byte`, the LRC ([**L**ongitudinal **R**edundancy **C**heck](https://en.wikipedia.org/wiki/Longitudinal_redundancy_check)) of the `SOF`, must be `0xEF`.
- **CMD**: `2 Bytes` in unsigned [Big Endian](https://en.wikipedia.org/wiki/Endianness) format, each command have been assigned a unique number (e.g. `factoryReset(1020)`), this is what you are sending to the device.
- **STATUS**: `2 Bytes` in unsigned [Big Endian](https://en.wikipedia.org/wiki/Endianness) format. If the direction is from APP to hardware, the status is always `0x0000`. If the direction is from hardware to APP, the status is the result of the command.
- **LEN**: `2 Bytes` in unsigned [Big Endian](https://en.wikipedia.org/wiki/Endianness) format, the length of the data, maximum is `512`.
- **LRC2**: `1 Byte`, the LRC ([**L**ongitudinal **R**edundancy **C**heck](https://en.wikipedia.org/wiki/Longitudinal_redundancy_check)) of the `CMD`, `STATUS` and `LEN`.
- **DATA**: `LEN Bytes`, the data to send or receive, maximum is `512 Bytes`. This could be anything, for example you should sending key type, block number, and the card keys when reading a block.
- **LRC3**: `1 Byte`, the LRC ([**L**ongitudinal **R**edundancy **C**heck](https://en.wikipedia.org/wiki/Longitudinal_redundancy_check)) of the `DATA`.
- **SOF**: `1 byte`, "**S**tart-**O**f-**F**rame byte" represents the start of a packet, and must be equal to `0x11`.
- **LRC1**: `1 byte`, LRC over `SOF` byte, therefore must be equal to `0xEF`.
- **CMD**: `2 bytes`, each command have been assigned a unique number (e.g. `DATA_CMD_SET_SLOT_TAG_NICK` = `1007`).
- **STATUS**: `2 bytes`.
- From client to firmware, the status is always `0x0000`.
- From firmware to client, the status is the result of the command.
- **LEN**: `2 bytes`, length of the `DATA` field, maximum is `512`.
- **LRC2**: `1 byte`, LRC over `CMD|STATUS|LEN` bytes.
- **DATA**: `LEN bytes`, data to be sent or received, maximum is `512 bytes`. This payload depends on the exact command or response to command being used. See [Packet payloads](#packet-payloads) below.
- **LRC3**: `1 byte`, LRC over `DATA` bytes.
The total length of the packet is `LEN + 10` Bytes. For receiving, it is the exact same format.
Note: LRC2 and LRC3 can be computed equally as covering either the frame from its first byte or from the byte following the previous LRC, because previous LRC nullifies previous bytes LRC computation.
Notes:
* The same frame format is used for commands and for responses.
* All values are **unsigned** values, and if more than one byte, in **network byte order**, aka [Big Endian](https://en.wikipedia.org/wiki/Endianness) byte order.
* The total length of the packet is `LEN + 10` bytes, therefore it is between `10` and `522` bytes.
* The LRC ([**L**ongitudinal **R**edundancy **C**heck](https://en.wikipedia.org/wiki/Longitudinal_redundancy_check)) is the 8-bit two's-complement value of the sum of all bytes modulo $2^8$.
* LRC2 and LRC3 can be computed equally as covering either the frame from its first byte or from the byte following the previous LRC, because previous LRC nullifies previous bytes LRC computation.
E.g. LRC3(DATA) == LRC3(whole frame)
## Packet payloads
## Data payloads
Each command and response have their own payload formats.
TODO:
Standard response status is `STATUS_DEVICE_SUCCESS` for general commands, `HF_TAG_OK` for HF commands and `LF_TAG_OK` for LF commands.
See [Guidelines](#new-data-payloads-guidelines-for-developers) for more info.
* **TODO:** num_to_bytes bytes_to_num
* **FIXME:** mf1_get_emulator_config with bits -> bytes (5) with 4 bools <> mf1_get_detection_log with bitfield (2)...
Beware, slots in protocol count from 0 to 7 (and from 1 to 8 in the CLI...).
In the following list, "CLI" refers to one typical CLI command using the described protocol command. But it's not a 1:1 match, there can be other protocol commands used by the CLI command and there can be other CLI commands using the same protocol command...
### 1000: GET_APP_VERSION
* Command: no data
* Response: 2 bytes: `version_major|version_minor`
* CLI: cf `hw version`
### 1001: CHANGE_DEVICE_MODE
* Command: 1 byte. `0x00`=emulator mode, `0x01`=reader mode
* Response: no data
* CLI: cf `hw mode set`
### 1002: GET_DEVICE_MODE
* Command: no data
* Response: data: 1 byte. `0x00`=emulator mode, `0x01`=reader mode
* CLI: cf `hw mode get`
### 1003: SET_ACTIVE_SLOT
* Command: 1 byte. `slot_number` between 0 and 7
* Response: no data
* CLI: cf `hw slot change`
### 1004: SET_SLOT_TAG_TYPE
* Command: 3 bytes. `slot_number|tag_type[2]` with `slot_number` between 0 and 7 and `tag_type` according to `tag_specific_type_t` enum, U16 in Network byte order.
* Response: no data
* CLI: cf `hw slot type`
### 1005: SET_SLOT_DATA_DEFAULT
* Command: 3 bytes. `slot_number|tag_type[2]` with `slot_number` between 0 and 7 and `tag_type` U16 according to `tag_specific_type_t` enum, U16 in Network byte order.
* Response: no data
* CLI: cf `hw slot init`
### 1006: SET_SLOT_ENABLE
* Command: 3 bytes. `slot_number|sense_type|enable` with `slot_number` between 0 and 7, `sense_type` according to `tag_sense_type_t` enum and `enable` = `0x01` to enable, `0x00` to disable
* Response: no data
* CLI: cf `hw slot enable`
### 1007: SET_SLOT_TAG_NICK
* Command: 2+N bytes. `slot_number|sense_type|name[N]` with `slot_number` between 0 and 7, `sense_type` according to `tag_sense_type_t` enum and `name` a UTF-8 encoded string of max 32 bytes, no null terminator.
* Response: no data
* CLI: cf `hw slot nick set`
### 1008: GET_SLOT_TAG_NICK
* Command: 2 bytes. `slot_number|sense_type` with `slot_number` between 0 and 7 and `sense_type` according to `tag_sense_type_t` enum.
* Response: a UTF-8 encoded string of max 32 bytes, no null terminator. If no nick name has been recorded in Flash, response status is `STATUS_FLASH_READ_FAIL`.
* CLI: cf `hw slot nick get`
### 1009: SLOT_DATA_CONFIG_SAVE
* Command: no data
* Response: no data
* CLI: cf `hw slot update`
### 1010: ENTER_BOOTLOADER
* Command: no data
* Response: this special command does not return and will interrupt the communication link while rebooting in bootloader mode, needed for DFU.
* CLI: cf `hw dfu`
### 1011: GET_DEVICE_CHIP_ID
* Command: no data
* Response: 8 bytes. nRF `DEVICEID[8]` U64 in Network byte order.
* CLI: cf `hw chipid get`
### 1012: GET_DEVICE_ADDRESS
* Command: no data
* Response: 6 bytes. nRF `DEVICEADDR[6]` U48 in Network byte order. First 2 MSBits forced to `0b11` to match BLE static address.
* CLI: cf `hw address get`
### 1013: SAVE_SETTINGS
* Command: no data
* Response: no data
* CLI: cf `hw settings store`
### 1014: RESET_SETTINGS
* Command: no data
* Response: no data
* CLI: cf `hw settings reset`
### 1015: SET_ANIMATION_MODE
* Command: 1 byte, according to `settings_animation_mode_t` enum.
* Response: no data
* CLI: cf `hw settings animation set`
### 1016: GET_ANIMATION_MODE
* Command: no data
* Response: 1 byte, according to `settings_animation_mode_t` enum.
* CLI: cf `hw settings animation get`
### 1017: GET_GIT_VERSION
* Command: no data
* Response: n bytes, a UTF-8 encoded string, no null terminator.
* CLI: cf `hw version`
### 1018: GET_ACTIVE_SLOT
* Command: no data
* Response: 1 byte
* CLI: cf `hw slot list`
### 1019: GET_SLOT_INFO
* Command: no data
* Response: 32 bytes, 8 tuples `hf_tag_type[2]|lf_tag_type[2]` according to `tag_specific_type_t` enum, for slots from 0 to 7, U16 in Network byte order.
* CLI: cf `hw slot list`
### 1020: WIPE_FDS
* Command: no data
* Response: no data. Status is `STATUS_DEVICE_SUCCESS` or `STATUS_FLASH_WRITE_FAIL`. The device will reboot shortly after this command.
* CLI: cf `hw factory_reset`
### 1023: GET_ENABLED_SLOTS
* Command: no data
* Response: 16 bytes, 8*2 bool = `0x00` or `0x01`, 2 bytes for each slot from 0 to 7, as `enabled_hf|enabled_lf`
### 1024: DELETE_SLOT_SENSE_TYPE
* Command: 2 bytes. `slot_number|sense_type` with `slot_number` between 0 and 7 and `sense_type` according to `tag_sense_type_t` enum.
* Response: no data
* CLI: cf `hw factory_reset`
### 1025: GET_BATTERY_INFO
* Command: no data
* Response: 3 bytes, `voltage[2]|percentage`. Voltage: U16 in Network byte order.
* CLI: cf `hw battery`
### 1026: GET_BUTTON_PRESS_CONFIG
* Command: 1 byte. Char `A` or `B` (`a`/`b` tolerated too)
* Response: 1 byte, `button_function` according to `settings_button_function_t` enum.
* CLI: cf `hw settings btnpress get`
### 1027: SET_BUTTON_PRESS_CONFIG
* Command: 2 bytes. `button|button_function` with `button` char `A` or `B` (`a`/`b` tolerated too) and `button_function` according to `settings_button_function_t` enum.
* Response: no data
* CLI: cf `hw settings btnpress set`
### 1028: GET_LONG_BUTTON_PRESS_CONFIG
* Command: 1 byte. Char `A` or `B` (`a`/`b` tolerated too)
* Response: 1 byte, `button_function` according to `settings_button_function_t` enum.
* CLI: cf `hw settings btnpress get`
### 1029: SET_LONG_BUTTON_PRESS_CONFIG
* Command: 2 bytes. `button|button_function` with `button` char `A` or `B` (`a`/`b` tolerated too) and `button_function` according to `settings_button_function_t` enum.
* Response: no data
* CLI: cf `hw settings btnpress set`
### 1030: SET_BLE_PAIRING_KEY
* Command: 6 bytes. 6 ASCII-encoded digits.
* Response: no data
* CLI: cf `hw settings blekey`
### 1031: GET_BLE_PAIRING_KEY
* Command: no data
* Response: 6 bytes. 6 ASCII-encoded digits.
* CLI: cf `hw settings blekey`
### 1032: DELETE_ALL_BLE_BONDS
* Command: no data
* Response: no data
* CLI: cf `hw ble bonds clear`
### 1033: GET_DEVICE_MODEL
* Command: no data
* Response: 1 byte. `hw_version` aka `NRF_DFU_HW_VERSION` according to `chameleon_device_type_t` enum (0=Ultra, 1=Lite)
* CLI: cf `hw version`
### 1034: GET_DEVICE_SETTINGS
* Command: no data
* Response: 14 bytes
* `settings_current_version` = `5`
* `animation_mode`, cf [GET_ANIMATION_MODE](#1016-get_animation_mode)
* `btn_press_A`, cf [GET_BUTTON_PRESS_CONFIG](#1026-get_button_press_config)
* `btn_press_B`, cf [GET_BUTTON_PRESS_CONFIG](#1026-get_button_press_config)
* `btn_long_press_A`, cf [GET_LONG_BUTTON_PRESS_CONFIG](#1028-get_long_button_press_config)
* `btn_long_press_B`, cf [GET_LONG_BUTTON_PRESS_CONFIG](#1028-get_long_button_press_config)
* `ble_pairing_enable`, cf [GET_BLE_PAIRING_ENABLE](#1036-get_ble_pairing_enable)
* `ble_pairing_key[6]`, cf [GET_BLE_PAIRING_KEY](#1031-get_ble_pairing_key)
* CLI: unused
### 1035: GET_DEVICE_CAPABILITIES
* Command: no data
* Response: 2*n bytes, a list of supported commands IDs.
* CLI: used internally on connect
### 1036: GET_BLE_PAIRING_ENABLE
* Command: no data
* Response: 1 byte, bool = `0x00` or `0x01`
* CLI: cf `hw settings blepair`
### 1037: SET_BLE_PAIRING_ENABLE
* Command: 1 byte, bool = `0x00` or `0x01`
* Response: no data
* CLI: cf `hw settings blepair`
### 2000: HF14A_SCAN
* Command: no data
* Response: N bytes: `tag1_data|tag2_data|...` with each tag: `uidlen|uid[uidlen]|atqa[2]|sak|atslen|ats[atslen]`. UID, ATQA, SAK and ATS as bytes.
* CLI: cf `hf 14a scan`
Notes:
* remind that if no tag is present, status will be `HF_TAG_NO` and Response empty.
* at the moment, the firmware supports only one tag, but get your client ready for more!
* `atslen` must not be confused with `ats[0]`==`TL`. So `atslen|ats` = `00` means no ATS while `0100` would be an empty ATS.
### 2001: MF1_DETECT_SUPPORT
* Command: no data
* Response: 1 byte, bool = `0x00` or `0x01`
* CLI: cf `hf 14a info`
### 2002: MF1_DETECT_PRNG
* Command: no data
* Response: 1 byte, according to `mf1_nested_type_t` enum
* CLI: cf `hf 14a info`
### 2003: MF1_STATIC_NESTED_ACQUIRE
* Command: 10 bytes: `type_known|block_known|key_known[6]|type_target|block_target`. Key as 6 bytes.
* Response: 4+N*8 bytes: `uid[4]` followed by N tuples of `nt[4]|nt_enc[4]`. All values as U32.
* CLI: cf `hf mf nested` on static nonce tag
### 2004: MF1_DARKSIDE_ACQUIRE
* Command: 4 bytes: `type_target|block_target|first_recover|sync_max`
* Response: 1 byte if Darkside failed, according to `mf1_darkside_status_t` enum,
else 33 bytes `darkside_status|uid[4]|nt1[4]|par[8]|ks1[8]|nr[4]|ar[4]`
* `darkside_status`
* `uid[4]` U32 (format expected by `darkside` tool)
* `nt1[4]` U32
* `par[8]` U64
* `ks1[8]` U64
* `nr[4]` U32
* `ar[4]` U32
* CLI: cf `hf mf darkside`
### 2005: MF1_DETECT_NT_DIST
* Command: 8 bytes: `type_known|block_known|key_known[6]`. Key as 6 bytes.
* Response: 8 bytes: `uid[4]|dist[4]`
* `uid[4]` U32 (format expected by `nested` tool)
* `dist[4]` U32
* CLI: cf `hf mf nested`
### 2006: MF1_NESTED_ACQUIRE
* Command: 10 bytes: `type_known|block_known|key_known[6]|type_target|block_target`. Key as 6 bytes.
* Response: N*9 bytes: N tuples of `nt[4]|nt_enc[4]|par`
* `nt[4]` U32
* `nt_enc[4]` U32
* `par`
* CLI: cf `hf mf nested`
### 2007: MF1_AUTH_ONE_KEY_BLOCK
* Command: 8 bytes: `type|block|key[6]`. Key as 6 bytes.
* Response: no data
* Status will be `HF_TAG_OK` if auth succeeded, else `MF_ERR_AUTH`
* CLI: cf `hf mf nested`
### 2008: MF1_READ_ONE_BLOCK
* Command: 8 bytes: `type|block|key[6]`. Key as 6 bytes.
* Response: 16 bytes: `block_data[16]`
* CLI: cf `hf mf rdbl`
### 2009: MF1_WRITE_ONE_BLOCK
* Command: 24 bytes: `type|block|key[6]|block_data[16]`. Key as 6 bytes.
* Response: no data
* CLI: cf `hf mf wrbl`
### 2010: HF14A_RAW
* Command: : 5+N bytes: `options|resp_timeout_ms[2]|bitlen[2]` followed by data to be transmitted, with `options` a 1-byte BigEndian bitfield, so starting from MSB:
* `activate_rf_field`:1
* `wait_response`:1
* `append_crc`:1
* `auto_select`:1
* `keep_rf_field`:1
* `check_response_crc`:1
* `reserved`:2
* Response: data sent by the card
* CLI: cf `hf 14a raw`
### 3000: EM410X_SCAN
* Command: no data
* Response: 5 bytes. `id[5]`. ID as 5 bytes.
* CLI: cf `lf em read`
### 3001: EM410X_WRITE_TO_T55XX
* Command: 9+N*4 bytes: `id[5]|new_key[4]|old_key1[4]|old_key2[4]|...` (N>=1). . ID as 5 bytes. Keys as 4 bytes.
* Response: no data
* CLI: cf `lf em write`
### 4000: MF1_WRITE_EMU_BLOCK_DATA
* Command: 1+N*16 bytes: `block_start|block_data1[16]|block_data2[16]|...` (1<=N<=31)
* Response: no data
* CLI: cf `hf mf eload`
### 4001: HF14A_SET_ANTI_COLL_DATA
* Command: N bytes: `uidlen|uid[uidlen]|atqa[2]|sak|atslen|ats[atslen]`. UID, ATQA, SAK and ATS as bytes.
* Response: no data
* CLI: cf `hf mf sim`
### 4004: MF1_SET_DETECTION_ENABLE
* Command: 1 byte, bool = `0x00` or `0x01`
* Response: no data
* CLI: cf `hf detection enable`
### 4005: MF1_GET_DETECTION_COUNT
* Command: no data
* Response: 4 bytes, `count[4]`, U32 in Network byte order.
* CLI: cf `hf detection count`
### 4006: MF1_GET_DETECTION_LOG
* Command: 4 bytes, `index`, U32 in Network byte order.
* Response: N*18 bytes. 0<=N<=28
* `block`
* `...|is_nested|is_key_b` 1-byte bitfield, starting from LSB
* `uid[4]` ?
* `nt[4]` ?
* `nr[4]` ?
* `ar[4]` ?
* CLI: cf `hf detection decrypt`
### 4007: MF1_GET_DETECTION_ENABLE
* Command: no data
* Response: 1 byte, bool = `0x00` or `0x01`
* CLI: cf `hw slot list`
### 4008: MF1_READ_EMU_BLOCK_DATA
* Command: 2 bytes: `block_start|block_count` with 1<=`block_count` <=32
* Response: `block_count`*16 bytes
* CLI: cf `hf mf eread`
### 4009: MF1_GET_EMULATOR_CONFIG
* Command: no data
* Response: 5 bytes
* `detection`, cf [MF1_GET_DETECTION_ENABLE](#4007-mf1_get_detection_enable)
* `gen1a_mode`, cf [MF1_GET_GEN1A_MODE](#4010-mf1_get_gen1a_mode)
* `gen2_mode`, cf [MF1_GET_GEN2_MODE](#4012-mf1_get_gen2_mode)
* `block_anti_coll_mode`, cf [MF1_GET_BLOCK_ANTI_COLL_MODE](#4014-mf1_get_block_anti_coll_mode)
* `write_mode`, cf [MF1_GET_WRITE_MODE](#4016-mf1_get_write_mode)
* CLI: cf `hw slot list`
### 4010: MF1_GET_GEN1A_MODE
* Command: no data
* Response: 1 byte, bool = `0x00` or `0x01`
* CLI: unused
### 4011: MF1_SET_GEN1A_MODE
* Command: 1 byte, bool = `0x00` or `0x01`
* Response: no data
* CLI: cf `hf mf settings`
### 4012: MF1_GET_GEN2_MODE
* Command: no data
* Response: 1 byte, bool = `0x00` or `0x01`
* CLI: unused
### 4013: MF1_SET_GEN2_MODE
* Command: 1 byte, bool = `0x00` or `0x01`
* Response: no data
* CLI: cf `hf mf settings`
### 4014: MF1_GET_BLOCK_ANTI_COLL_MODE
* Command: no data
* Response: 1 byte, bool = `0x00` or `0x01`
* CLI: unused
### 4015: MF1_SET_BLOCK_ANTI_COLL_MODE
* Command: 1 byte, bool = `0x00` or `0x01`
* Response: no data
* CLI: cf `hf mf settings`
### 4016: MF1_GET_WRITE_MODE
* Command: no data
* Response: 1 byte, according to `nfc_tag_mf1_write_mode_t` aka `MifareClassicWriteMode` enum
* CLI: unused
### 4017: MF1_SET_WRITE_MODE
* Command: 1 byte, according to `nfc_tag_mf1_write_mode_t` aka `MifareClassicWriteMode` enum
* Response: no data
* CLI: cf `hf mf settings`
### 4018: HF14A_GET_ANTI_COLL_DATA
* Command: no data
* Response: no data or N bytes: `uidlen|uid[uidlen]|atqa[2]|sak|atslen|ats[atslen]`. UID, ATQA, SAK and ATS as bytes.
* CLI: cf `hf mf info`
### 5000: EM410X_SET_EMU_ID
* Command: 5 bytes. `id[5]`. ID as 5 bytes.
* Response: no data
* CLI: cf `lf em sim set`
### 5001: EM410X_GET_EMU_ID
* Command: no data
* Response: 5 bytes. `id[5]`. ID as 5 bytes.
* CLI: cf `lf em sim get`
## New data payloads: guidelines for developers
If you need to define new payloads for new commands, try to follow these guidelines.
### Guideline: Verbose and explicit
Be verbose, explicit and reuse conventions, in order to enhance code maintainability and understandability for the other contributors
### Guideline: Structs
- Define C `struct` for cmd/resp data greater than a single byte, use and abuse of `struct.pack`/`struct.unpack` in Python. So one can understand the payload format at a simple glimpse. Exceptions to `C` struct are when the formats are of variable length (but Python `struct` is still flexible enough to cope with such formats!)
- Avoid hardcoding offsets, use `sizeof()`, `offsetof(struct, field)` in C and `struct.calcsize()` in Python
- For complex bitfield structs, exceptionally you can use ctypes in Python. Beware ctypes.BigEndianStructure bitfield will be parsed in the firmware in the reverse order, from LSB to MSB.
### Guideline: Status
If single byte of data to return, still use a 1-byte `data`, not `status`. Standard response status is `STATUS_DEVICE_SUCCESS` for general commands, `HF_TAG_OK` for HF commands and `LF_TAG_OK` for LF commands. If the response status is different than those, the response data is empty. Response status are generic and cover things like tag disappearance or tag non-conformities with the ISO standard. If a command needs more specific response status, it is added in the first byte of the data, to avoid cluttering the 1-byte general status enum with command-specific statuses. See e.g. [MF1_DARKSIDE_ACQUIRE](#2004-mf1_darkside_acquire).
### Guideline: unambiguous types
- Use unambiguous types such as `uint16_t`, not `int` or `enum`. Cast explicitly `int` and `enum` to `uint_t` of proper size
- Use Network byte order for 16b and 32b integers
- Macros `U16NTOHS`, `U32NTOHL` must be used on reception of a command payload.
- Macros `U16HTONS`, `U32HTONL` must be used on creation of a response payload.
- In Python, use the modifier `!` with all `struct.pack`/`struct.unpack`
### Guideline: payload parsing in handlers
- Concentrate payload parsing in the handlers, avoid further parsing in their callers. Callers should not care about the protocol. This is true for the firmware and the client.
- In cmd_processor handlers: don't reuse input `length`/`data` parameters for creating the response content
### Guideline: Naming conventions
- Use the exact same command and fields names in firmware and in client, use function names matching the command names for their handlers unless there is a very good reason not to do so. This helps grepping around. Names must start with a letter, not a number, because some languages require it (e.g. `14a_scan` not possible in Python)
- Respect commands order in `m_data_cmd_map`, `data_cmd.h` and `chameleon_cmd.py` definitions
- Even if a command is not yet implemented in firmware or in client but a command number is allocated, add it to `data_cmd.h` and `chameleon_cmd.py` with some `FIXME: to be implemented` comment
### Guideline: Validate status and data
- Validate response status in client before parsing data.
- Validate data before using it.
+121 -102
View File
@@ -5,58 +5,67 @@
# ChameleonUltra
Why not keep using ATXMEGA128?
First of all, it is difficult to buy chips because the lead time for the main chip is too long, and because the price has skyrocketed. Secondly, because the interaction speed of the ATXMEGA, emulation is slow, the decryption performance of the READER mode cannot meet the needs, and the LF support cannot be added, so we have been trying to upgrade it, such as using the latest ARM to replace the AVR framework, and the performance will definitely be greatly improved.
First of all, it is difficult to buy chips because the lead time for the main chip is too long, and because the price
has skyrocketed. Secondly, because the interaction speed of the ATXMEGA, emulation is slow, the decryption performance
of the READER mode cannot meet the needs, and the LF support cannot be added, so we have been trying to upgrade it, such
as using the latest ARM to replace the AVR framework, and the performance will definitely be greatly improved.
# Why nRF52840?
NRF52840 has a built-in NFC Tag-A module, but no one seems to care about it. After playing with HydraNFC's TRF7970A and FlipperZero's ST25R3916, the developers found that they can only emulate MIFARE Classic with a very high FDT.
We accidentally tested the NFC of nRF52840, and found that it is not only surprisingly easy to emulate a complete MIFARE Classic card, but also has very good emulation performance, friendly data flow interaction, and very fast response, unlike the former which is limited by the SPI bus clock rate. We also found that it has ultra-low power consumption, ultra-small size, 256kb/1M large RAM and Flash, also has BLE5.0 and USB2.0 FS, super CortexM4F, most importantly, it is very cheap! This is undoubtedly a treasure discovery for us!
NRF52840 has a built-in NFC Tag-A module, but no one seems to care about it. After playing with HydraNFC's TRF7970A and
FlipperZero's ST25R3916, the developers found that they can only emulate MIFARE Classic with a very high FDT.
We accidentally tested the NFC of nRF52840, and found that it is not only surprisingly easy to emulate a complete MIFARE
Classic card, but also has very good emulation performance, friendly data flow interaction, and very fast response,
unlike the former which is limited by the SPI bus clock rate. We also found that it has ultra-low power consumption,
ultra-small size, 256kb/1M large RAM and Flash, also has BLE5.0 and USB2.0 FS, super CortexM4F, most importantly, it is
very cheap! This is undoubtedly a treasure discovery for us!
Below we will explain in detail how we exploited the performance of the NRF52840, and what seemingly impossible functions have been realized with it!
Below we will explain in detail how we exploited the performance of the NRF52840, and what seemingly impossible
functions have been realized with it!
# Supported functions
## High Frequency Attack
| Attack Type | Tag Type | Whether the hardware supports | Does the software support | Whether the application layer supports | Note |
|--------------|:-------------:|------------------------------:|---------------------------|:--------------------------------------:|------------------------:|
| Sniffing | No | No | No | No | |
| Attack Type | Tag Type | Whether the hardware supports | Does the software support | Whether the application layer supports | Note |
|--------------|:--------------:|------------------------------:|---------------------------|:--------------------------------------:|-------------------------:|
| Sniffing | No | No | No | No | |
| MFKEY32 V2 | MIFARE Classic | Support | Support | Support | MIFARE Classic Detection |
| Darkside | MIFARE Classic | Support | Support | Support | Encrypted 4 bit NAck |
| Nested | MIFARE Classic | Support | Support | Support | PRNG(Distance guess) |
| StaticNested | MIFARE Classic | Support | Support | Not yet implemented | PRNG(2NT Fast Decrypt) |
| HardNested | MIFARE Classic | Support | Support | Not yet implemented | No |
| Relay attack | ISO14443A | Support | Support | Not yet implemented | No |
| Darkside | MIFARE Classic | Support | Support | Support | Encrypted 4 bit NAck |
| Nested | MIFARE Classic | Support | Support | Support | PRNG(Distance guess) |
| StaticNested | MIFARE Classic | Support | Support | Support | PRNG(2NT Fast Decrypt) |
| HardNested | MIFARE Classic | Support | Support | Not yet implemented | No |
| Relay attack | ISO14443A | Support | Support | Not yet implemented | No |
## High Frequency emulation
| Card Type | Encoding Type | Whether the hardware supports | Does the software support | Whether the application layer supports | Note |
|-------------------------------|:--------------------:|------------------------------:|---------------------------|:--------------------------------------:|-----------------------------------------:|
| Other than ISO14443A | No | No | No | No | [NRF52 NFC Module][nrf52_nfc_module_doc] |
| NTAG 21x (210-218) | ISO14443A/106 kbit/s | Support | Support | Not yet implemented | |
| MIFARE Ultralight | ISO14443A/106 kbit/s | Support | Support | Not yet implemented | |
| MIFARE Ultralight Ev1 | ISO14443A/106 kbit/s | Support | Support | Not yet implemented | |
| MIFARE Ultralight C | ISO14443A/106 kbit/s | Support | Support | Not yet implemented | |
| Card Type | Encoding Type | Whether the hardware supports | Does the software support | Whether the application layer supports | Note |
|--------------------------------|:--------------------:|------------------------------:|---------------------------|:--------------------------------------:|-----------------------------------------:|
| Other than ISO14443A | No | No | No | No | [NRF52 NFC Module][nrf52_nfc_module_doc] |
| NTAG 21x (210-218) | ISO14443A/106 kbit/s | Support | Support | Not yet implemented | |
| MIFARE Ultralight | ISO14443A/106 kbit/s | Support | Support | Not yet implemented | |
| MIFARE Ultralight Ev1 | ISO14443A/106 kbit/s | Support | Support | Not yet implemented | |
| MIFARE Ultralight C | ISO14443A/106 kbit/s | Support | Support | Not yet implemented | |
| MIFARE Classic1K/2K/4K (4B/7B) | ISO14443A/106 kbit/s | Support | Support | Support | |
| MIFARE DESFire | ISO14443A High Rate | Only supported Low rate | Only supported Low rate | Not yet implemented | |
| MIFARE DESFire EV1 | ISO14443A High rate | Only supported Low rate | Only supported Low rate | Not yet implemented | Backward compatible |
| MIFARE DESFire EV2 | ISO14443A High rate | Only supported Low rate | Only supported Low rate | Not yet implemented | |
| MIFARE Plus | ISO14443A High rate | Only supported Low rate | Only supported Low rate | Not yet implemented | |
| MIFARE DESFire | ISO14443A High Rate | Only supported Low rate | Only supported Low rate | Not yet implemented | |
| MIFARE DESFire EV1 | ISO14443A High rate | Only supported Low rate | Only supported Low rate | Not yet implemented | Backward compatible |
| MIFARE DESFire EV2 | ISO14443A High rate | Only supported Low rate | Only supported Low rate | Not yet implemented | |
| MIFARE Plus | ISO14443A High rate | Only supported Low rate | Only supported Low rate | Not yet implemented | |
## High Frequency Reader
| Card Type | Encoding Type | Whether the hardware supports | Does the software support | Whether the application layer supports | Note |
|-------------------------------|:--------------------:|---------------------------------------------:|----------------------------------------------|:--------------------------------------:|-------------------------------------------:|
| Non <13.56MHz or ISO14443A> | No | No | No | No | [NXP RC522 Datasheet][nxp_rc522_datasheet] |
| NTAG 21x (210-218) | ISO14443A/106 kbit/s | Support | Support | Not yet implemented | |
| MIFARE Ultralight | ISO14443A/106 kbit/s | Support | Support | Not yet implemented | |
| MIFARE Ultralight Ev1 | ISO14443A/106 kbit/s | Support | Support | Not yet implemented | |
| MIFARE Ultralight C | ISO14443A/106 kbit/s | Support | Support | Not yet implemented | |
| Card Type | Encoding Type | Whether the hardware supports | Does the software support | Whether the application layer supports | Note |
|---------------------------------|:--------------------:|---------------------------------------------:|----------------------------------------------|:--------------------------------------:|-------------------------------------------:|
| Non <13.56MHz or ISO14443A> | No | No | No | No | [NXP RC522 Datasheet][nxp_rc522_datasheet] |
| NTAG 21x (210-218) | ISO14443A/106 kbit/s | Support | Support | Not yet implemented | |
| MIFARE Ultralight | ISO14443A/106 kbit/s | Support | Support | Not yet implemented | |
| MIFARE Ultralight Ev1 | ISO14443A/106 kbit/s | Support | Support | Not yet implemented | |
| MIFARE Ultralight C | ISO14443A/106 kbit/s | Support | Support | Not yet implemented | |
| MIFARE Classic 1K/2K/4K (4B/7B) | ISO14443A/106 kbit/s | Support | Support | Support | |
| MIFARE DESFire | ISO14443A High Rate | Supports low rates, or possibly higher rates | Supports low rates, or possibly higher rates | Not yet implemented | |
| MIFARE DESFire EV1 | ISO14443A High rate | Supports low rates, or possibly higher rates | Supports low rates, or possibly higher rates | Not yet implemented | Backward compatible |
| MIFARE DESFire EV2 | ISO14443A High rate | Supports low rates, or possibly higher rates | Supports low rates, or possibly higher rates | Not yet implemented | |
| MIFARE Plus | ISO14443A High rate | Supports low rates, or possibly higher rates | Supports low rates, or possibly higher rates | Not yet implemented | |
| MIFARE DESFire | ISO14443A High Rate | Supports low rates, or possibly higher rates | Supports low rates, or possibly higher rates | Not yet implemented | |
| MIFARE DESFire EV1 | ISO14443A High rate | Supports low rates, or possibly higher rates | Supports low rates, or possibly higher rates | Not yet implemented | Backward compatible |
| MIFARE DESFire EV2 | ISO14443A High rate | Supports low rates, or possibly higher rates | Supports low rates, or possibly higher rates | Not yet implemented | |
| MIFARE Plus | ISO14443A High rate | Supports low rates, or possibly higher rates | Supports low rates, or possibly higher rates | Not yet implemented | |
## Low Frequency Attack
@@ -67,103 +76,113 @@ Below we will explain in detail how we exploited the performance of the NRF52840
## Low Frequency emulation
| Card Type | Encoding Type | Whether the hardware supports | Does the software support | Whether the application layer supports | Note |
|--------------------------|:-------------:|------------------------------:|---------------------------|:--------------------------------------:|----------------------------------------------:|
| Card Type | Encoding Type | Whether the hardware supports | Does the software support | Whether the application layer supports | Note |
|---------------------------------|:-------------:|------------------------------:|---------------------------|:--------------------------------------:|----------------------------------------------:|
| Other than <125KHz/ASK/PSK/FSK> | No | No | No | No | Only 125 khz RF, Modulation ASK, FSK and PSK. |
| EM410x | ASK | Support | Support | Support | EM4100 is support(AD 64bit) |
| T5577 | ASK | Support | Support | Not yet implemented | |
| EM4306 | ASK | Support | Support | Not yet implemented | |
| HID Prox | FSK | Support | Support | Not yet implemented | |
| Indala | PSK | Support | Support | Not yet implemented | |
| FDX-B | ASK | Support | Support | Not yet implemented | |
| Paradox | FSK | Support | Support | Not yet implemented | |
| Keri | PSK | Support | Support | Not yet implemented | |
| AWD | FSK | Support | Support | Not yet implemented | |
| ioProx | FSK | Support | Support | Not yet implemented | |
| securakey | ASK | Support | Support | Not yet implemented | |
| gallagher | ASK | Support | Support | Not yet implemented | |
| PAC/Stanley | ASK | Support | Support | Not yet implemented | |
| Presco | ASK | Support | Support | Not yet implemented | |
| Visa2000 | ASK | Support | Support | Not yet implemented | |
| Viking | ASK | Support | Support | Not yet implemented | |
| Noralsy | ASK | Support | Support | Not yet implemented | |
| NexWatch | PSK | Support | Support | Not yet implemented | |
| Jablotron | ASK | Support | Support | Not yet implemented | |
| EM410x | ASK | Support | Support | Support | EM4100 is support(AD 64bit) |
| T5577 | ASK | Support | Support | Not yet implemented | |
| EM4305 | ASK | Support | Support | Not yet implemented | |
| HID Prox | FSK | Support | Support | Not yet implemented | |
| Indala | PSK | Support | Support | Not yet implemented | |
| FDX-B | ASK | Support | Support | Not yet implemented | |
| Paradox | FSK | Support | Support | Not yet implemented | |
| Keri | PSK | Support | Support | Not yet implemented | |
| AWD | FSK | Support | Support | Not yet implemented | |
| ioProx | FSK | Support | Support | Not yet implemented | |
| securakey | ASK | Support | Support | Not yet implemented | |
| gallagher | ASK | Support | Support | Not yet implemented | |
| PAC/Stanley | ASK | Support | Support | Not yet implemented | |
| Presco | ASK | Support | Support | Not yet implemented | |
| Visa2000 | ASK | Support | Support | Not yet implemented | |
| Viking | ASK | Support | Support | Not yet implemented | |
| Noralsy | ASK | Support | Support | Not yet implemented | |
| NexWatch | PSK | Support | Support | Not yet implemented | |
| Jablotron | ASK | Support | Support | Not yet implemented | |
## Low Frequency Reader
| Card Type | Encoding Type | Whether the hardware supports | Does the software support | Whether the application layer supports | Note |
|--------------------------|:-------------:|------------------------------:|---------------------------|:--------------------------------------:|----------------------------------------------:|
| Card Type | Encoding Type | Whether the hardware supports | Does the software support | Whether the application layer supports | Note |
|---------------------------------|:-------------:|------------------------------:|---------------------------|:--------------------------------------:|----------------------------------------------:|
| Other than <125KHz/ASK/PSK/FSK> | No | No | No | No | Only 125 khz RF, Modulation ASK, FSK and PSK. |
| EM410x | ASK | Support | Support | Support | |
| T5577 | ASK | Support | Support | Support(Write) | |
| EM4305 | ASK | Support | Support | Not yet implemented | |
| HID Prox | FSK | Support | Support | Not yet implemented | |
| Indala | PSK | Support | Support | Not yet implemented | |
| FDX-B | ASK | Support | Support | Not yet implemented | |
| Paradox | FSK | Support | Support | Not yet implemented | |
| Keri | PSK | Support | Support | Not yet implemented | |
| AWD | FSK | Support | Support | Not yet implemented | |
| ioProx | FSK | Support | Support | Not yet implemented | |
| securakey | ASK | Support | Support | Not yet implemented | |
| gallagher | ASK | Support | Support | Not yet implemented | |
| PAC/Stanley | ASK | Support | Support | Not yet implemented | |
| Presco | ASK | Support | Support | Not yet implemented | |
| Visa2000 | ASK | Support | Support | Not yet implemented | |
| Viking | ASK | Support | Support | Not yet implemented | |
| Noralsy | ASK | Support | Support | Not yet implemented | |
| NexWatch | PSK | Support | Support | Not yet implemented | |
| Jablotron | ASK | Support | Support | Not yet implemented | |
| EM410x | ASK | Support | Support | Support | |
| T5577 | ASK | Support | Support | Support(Write) | |
| EM4305 | ASK | Support | Support | Not yet implemented | |
| HID Prox | FSK | Support | Support | Not yet implemented | |
| Indala | PSK | Support | Support | Not yet implemented | |
| FDX-B | ASK | Support | Support | Not yet implemented | |
| Paradox | FSK | Support | Support | Not yet implemented | |
| Keri | PSK | Support | Support | Not yet implemented | |
| AWD | FSK | Support | Support | Not yet implemented | |
| ioProx | FSK | Support | Support | Not yet implemented | |
| securakey | ASK | Support | Support | Not yet implemented | |
| gallagher | ASK | Support | Support | Not yet implemented | |
| PAC/Stanley | ASK | Support | Support | Not yet implemented | |
| Presco | ASK | Support | Support | Not yet implemented | |
| Visa2000 | ASK | Support | Support | Not yet implemented | |
| Viking | ASK | Support | Support | Not yet implemented | |
| Noralsy | ASK | Support | Support | Not yet implemented | |
| NexWatch | PSK | Support | Support | Not yet implemented | |
| Jablotron | ASK | Support | Support | Not yet implemented | |
## Low Frequency Modulation
| Modulation Type | wav |
|-----------------|----------------------------:|
| Modulation Type | wav |
|-----------------|------------------------------------:|
| PSK | ![PSK WAV](images/measured-psk.png) |
| FSK | ![FSK WAV](images/measured-fsk.png) |
| ASK | ![ASK WAV](images/measured-ask.png) |
# Ultra-low power consumption
It integrates a high-performance and low-power NFC module inside. When the NFC unit is turned on, the total current of the chip is only 5mA@3.3V.
It integrates a high-performance and low-power NFC module inside. When the NFC unit is turned on, the total current of
the chip is only 5mA@3.3V.
The underlying interaction is done independently by the NFC unit and does not occupy the CPU.
In addition, the nRF52840 itself is a high-performance low-power BLE chip, and the encryption and calculation process is only 7mA@3.3V. It can greatly reduce the battery volume and prolong the working time. That is to say, the 35mAh 10mm*40mm button lithium battery can guarantee to be charged once every half a year under the working condition of swiping the card 8 times a day for 3 seconds each time. Full potential for everyday use.
In addition, the nRF52840 itself is a high-performance low-power BLE chip, and the encryption and calculation process is
only 7mA@3.3V. It can greatly reduce the battery volume and prolong the working time. That is to say, the 35mAh 10mm*
40mm button lithium battery can guarantee to be charged once every half a year under the working condition of swiping
the card 8 times a day for 3 seconds each time. Full potential for everyday use.
# Not just UID, but a real and complete MIFARE Classic emulation
We can easily and completely emulate all data and password verification of all sectors, and can customize SAK, ATQA, ATS, etc. Similar to an open CPU card development platform, 14A interaction of various architectures can be easily realized.
We can easily and completely emulate all data and password verification of all sectors, and can customize SAK, ATQA,
ATS, etc. Similar to an open CPU card development platform, 14A interaction of various architectures can be easily
realized.
# Super compatibility with low-power locks using batteries
The structure of the old Chameleon AVR is slow to start during emulation. Faced with a battery-powered low-power lock and an integrated lock on the door, it will be frequently interrupted, and the verification interaction cannot be completed completely, resulting in no response when swiping the card.
The structure of the old Chameleon AVR is slow to start during emulation. Faced with a battery-powered low-power lock
and an integrated lock on the door, it will be frequently interrupted, and the verification interaction cannot be
completed completely, resulting in no response when swiping the card.
In order to reduce power consumption, the battery lock will send out a field signal as short as possible when searching for a card, which is no problem for the original card, but it is fatal for the MCU emulated card. Cards or mobile smart bracelets emulated by the MCU cannot wake up and respond in such a short time, so many battery locks cannot open the door, which greatly reduces the user experience.
In order to reduce power consumption, the battery lock will send out a field signal as short as possible when searching
for a card, which is no problem for the original card, but it is fatal for the MCU emulated card. Cards or mobile smart
bracelets emulated by the MCU cannot wake up and respond in such a short time, so many battery locks cannot open the
door, which greatly reduces the user experience.
This project specially optimizes the start-up and interaction logic and antenna for low-power reading heads. After testing a variety of common low-power reading heads, they can open the door perfectly by swiping the card.
This project specially optimizes the start-up and interaction logic and antenna for low-power reading heads. After
testing a variety of common low-power reading heads, they can open the door perfectly by swiping the card.
# Ultra-fast response speed and low interaction delay(MIFARE Classic)
| Tag/Emulation | FDT | "**_FDT_**" Rating |
|----------------------|:---------------------------:|:--------------------------------------------------------------------------------:|
| Standard MIFARE Card | ![Standard_m1_s50](images/fdt_standard_s50.png) | &#x2B50;&#x2B50;&#x2B50;&#x2B50;&#x2B50;&#x2B50;&#x2B50;&#x2B50;&#x2B50;&#x2B50; |
| Chameleon Ultra | ![Chameleon Ultra](images/fdt_chameleon_ultra.png) | &#x2B50;&#x2B50;&#x2B50;&#x2B50;&#x2B50;&#x2B50;&#x2B50;&#x2B50; |
| Proxmark3 Rdv4.01 | ![Proxmark3_Rdv4_RRG_(Firmware build at 20201026)](images/fdt_pm3_rdv401.png) | &#x2B50;&#x2B50;&#x2B50;&#x2B50; |
| RedMi K30 | ![Xiaomi_k30u_smartkey](images/fdt_redmi_k30.png) | &#x2B50;&#x2B50;&#x2B50;&#x2B50;&#x2B50;&#x2B50; |
| Chameleon Tiny | ![Chameleon Tiny](images/fdt_chameleon_tiny.png) | &#x2B50;&#x2B50;&#x2B50;&#x2B50;&#x2B50; |
| Flipper Zero | ![Flipper Zero](images/fdt_flipper_zero.png) | &#x2B50;&#x2B50; |
| Tag/Emulation | FDT | "**_FDT_**" Rating |
|----------------------|:-----------------------------------------------------------------------------:|:--------------------------------------------------------------------------------:|
| Standard MIFARE Card | ![Standard_m1_s50](images/fdt_standard_s50.png) | &#x2B50;&#x2B50;&#x2B50;&#x2B50;&#x2B50;&#x2B50;&#x2B50;&#x2B50;&#x2B50;&#x2B50; |
| Chameleon Ultra | ![Chameleon Ultra](images/fdt_chameleon_ultra.png) | &#x2B50;&#x2B50;&#x2B50;&#x2B50;&#x2B50;&#x2B50;&#x2B50;&#x2B50; |
| Proxmark3 Rdv4.01 | ![Proxmark3_Rdv4_RRG_(Firmware build at 20201026)](images/fdt_pm3_rdv401.png) | &#x2B50;&#x2B50;&#x2B50;&#x2B50; |
| RedMi K30 | ![Xiaomi_k30u_smartkey](images/fdt_redmi_k30.png) | &#x2B50;&#x2B50;&#x2B50;&#x2B50;&#x2B50;&#x2B50; |
| Chameleon Tiny | ![Chameleon Tiny](images/fdt_chameleon_tiny.png) | &#x2B50;&#x2B50;&#x2B50;&#x2B50;&#x2B50; |
| Flipper Zero | ![Flipper Zero](images/fdt_flipper_zero.png) | &#x2B50;&#x2B50; |
# 256kB super large RAM cooperates with RC522 to enable attacks
| Attack Type | CLI |
|--------------|:------------------------------:|
| MFKEY32 V2 | ![attack_MIFARE_mfkey32](images/cli_mfkey32v2.png) |
| Darkside | ![attack_MIFARE_darkside](images/cli_darkside.png) |
| Nested | ![attack_MIFARE_nested](images/cli_nested.png) |
| StaticNested | Coming Soon |
| HardNested | Coming Soon |
| Relay attack | Coming Soon |
| Attack Type | CLI |
|--------------|:----------------------------------------------------------:|
| MFKEY32 V2 | ![attack_MIFARE_mfkey32](images/cli_mfkey32v2.png) |
| Darkside | ![attack_MIFARE_darkside](images/cli_darkside.png) |
| Nested | ![attack_MIFARE_nested](images/cli_nested.png) |
| StaticNested | ![attack_MIFARE_staticnested](images/cli_staticnested.jpg) |
| HardNested | Coming Soon |
| Relay attack | Coming Soon |
# Hardware frame diagram
+4 -1
View File
@@ -26,7 +26,10 @@ CHAMELEON_LITE := lite
CURRENT_DEVICE_TYPE ?= ${CHAMELEON_ULTRA}
# Versioning information
GIT_VERSION := "$(shell git describe --abbrev=7 --dirty --always --tags)"
GIT_VERSION := $(shell git describe --abbrev=7 --dirty --always --tags)
APP_FW_SEMVER := $(subst v,,$(shell git describe --tags --abbrev=0 --match "v*.*"))
APP_FW_VER_MAJOR := $(word 1,$(subst ., ,$(APP_FW_SEMVER)))
APP_FW_VER_MINOR := $(word 2,$(subst ., ,$(APP_FW_SEMVER)))
# Enable NRF_LOG on SWO pin as UART TX
NRF_LOG_UART_ON_SWO_ENABLED := 0
+7
View File
@@ -401,6 +401,13 @@ CFLAGS += -fno-builtin -fshort-enums
# Versioning flags
CFLAGS += -DGIT_VERSION=\"$(GIT_VERSION)\"
ifndef APP_FW_VER_MAJOR
$(error APP_FW_VER_MAJOR is not defined, please define it)
endif
ifndef APP_FW_VER_MINOR
$(error APP_FW_VER_MINOR is not defined, please define it)
endif
CFLAGS += -DAPP_FW_VER_MAJOR=$(APP_FW_VER_MAJOR) -DAPP_FW_VER_MINOR=$(APP_FW_VER_MINOR)
# C++ flags common to all targets
CXXFLAGS += $(OPT)
File diff suppressed because it is too large Load Diff
-1
View File
@@ -15,6 +15,5 @@ typedef struct {
} cmd_data_map_t;
void on_data_frame_received(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data);
void cmd_map_init();
#endif
+5 -2
View File
@@ -2,8 +2,11 @@
// version code, 1byte, max = 0 -> 255
#define APP_FW_VER_MAJOR 1
#define APP_FW_VER_MINOR 0
//#define APP_FW_VER_MAJOR 2
//#define APP_FW_VER_MINOR 0
#if !(defined APP_FW_VER_MAJOR && defined APP_FW_VER_MINOR)
#error You need to define APP_FW_VER_MAJOR and APP_FW_VER_MINOR
#endif
// Merge major and minor version code to U16 value.
#define FW_VER_NUM VER_CODE_TO_NUM(APP_FW_VER_MAJOR, APP_FW_VER_MINOR)
+12 -9
View File
@@ -250,7 +250,7 @@ static void system_off_enter(void) {
if (g_is_low_battery_shutdown) {
// Don't create too complex animations, just blink LED1 three times.
rgb_marquee_stop();
set_slot_light_color(0);
set_slot_light_color(RGB_RED);
for (uint8_t i = 0; i <= 3; i++) {
nrf_gpio_pin_set(LED_1);
bsp_delay_ms(100);
@@ -570,8 +570,8 @@ static void btn_fn_copy_ic_uid(void) {
uint8_t id_buffer[5] = { 0x00 };
// get 14a tag res buffer;
uint8_t slot_now = tag_emulation_get_slot();
tag_specific_type_t tag_type[2];
tag_emulation_get_specific_type_by_slot(slot_now, tag_type);
tag_slot_specific_type_t tag_types;
tag_emulation_get_specific_types_by_slot(slot_now, &tag_types);
nfc_tag_14a_coll_res_entity_t *antres;
@@ -584,7 +584,7 @@ static void btn_fn_copy_ic_uid(void) {
NRF_LOG_INFO("Start reader mode to offline copy.")
}
switch (tag_type[1]) {
switch (tag_types.tag_lf) {
case TAG_TYPE_EM410X:
status = PcdScanEM410X(id_buffer);
@@ -599,7 +599,7 @@ static void btn_fn_copy_ic_uid(void) {
offline_status_error();
}
break;
case TAG_TYPE_UNKNOWN:
case TAG_TYPE_UNDEFINED:
// empty LF slot, nothing to do, move on to HF
break;
default:
@@ -607,8 +607,8 @@ static void btn_fn_copy_ic_uid(void) {
offline_status_error();
}
tag_data_buffer_t *buffer = get_buffer_by_tag_type(tag_type[0]);
switch (tag_type[0]) {
tag_data_buffer_t *buffer = get_buffer_by_tag_type(tag_types.tag_hf);
switch (tag_types.tag_hf) {
case TAG_TYPE_MIFARE_Mini:
case TAG_TYPE_MIFARE_1024:
case TAG_TYPE_MIFARE_2048:
@@ -626,7 +626,7 @@ static void btn_fn_copy_ic_uid(void) {
break;
}
case TAG_TYPE_UNKNOWN:
case TAG_TYPE_UNDEFINED:
// empty HF slot, nothing to do
goto exit;
@@ -648,11 +648,15 @@ static void btn_fn_copy_ic_uid(void) {
status = pcd_14a_reader_scan_auto(&tag);
if (status == HF_TAG_OK) {
// copy uid
antres->size = tag.uid_len;
memcpy(antres->uid, tag.uid, tag.uid_len);
// copy atqa
memcpy(antres->atqa, tag.atqa, 2);
// copy sak
antres->sak[0] = tag.sak;
// copy ats
antres->ats.length = tag.ats_len;
memcpy(antres->ats.data, tag.ats, tag.ats_len);
NRF_LOG_INFO("Offline HF uid copied")
offline_status_ok();
} else {
@@ -771,7 +775,6 @@ static void ble_passkey_init(void) {
*/
int main(void) {
hw_connect_init(); // Remember to initialize the pins first
cmd_map_init(); // Set function in CMD map for DATA_CMD_GET_DEVICE_CAPABILITIES
fds_util_init(); // Initialize fds tool
settings_load_config(); // Load settings from flash
+1 -12
View File
@@ -13,18 +13,7 @@
#define HF_ERR_BCC (0x05) // IC card BCC error
#define MF_ERR_AUTH (0x06) // MF card verification failed
#define HF_ERR_PARITY (0x07) // IC card parity error
/////////////////////////////////////////////////////////////////////
// MIFARE status
/////////////////////////////////////////////////////////////////////
#define DARKSIDE_CANT_FIXED_NT (0x20) // Darkside, the random number cannot be fixed, this situation may appear on the UID card
#define DARKSIDE_LUCK_AUTH_OK (0x21) // Darkside, the direct verification is successful, maybe the key is just empty
#define DARKSIDE_NACK_NO_SEND (0x22) // Darkside, the card does not respond to NACK, it may be a card that fixes Nack logic vulnerabilities
#define DARKSIDE_TAG_CHANGED (0x23) // Darkside, card switching in the process of running DARKSIDE, May is the two cards quickly switched
#define NESTED_TAG_IS_STATIC (0x24) // Nested, the random number of the card response is fixed
#define NESTED_TAG_IS_HARD (0x25) // Nested, the random number of the card response is unpredictable
#define HF_ERR_ATS (0x08) // ATS should be present but card NAKed
/////////////////////////////////////////////////////////////////////
// lf status
+3 -3
View File
@@ -106,8 +106,8 @@ static ble_opt_t m_static_pin_option;
* @details This function will set up the ble connect passkey.
*/
void set_ble_connect_key(uint8_t *key) {
static uint8_t passkey[BLE_CONNECT_KEY_LEN_MAX];
memcpy(passkey, key, BLE_CONNECT_KEY_LEN_MAX);
static uint8_t passkey[BLE_PAIRING_KEY_LEN];
memcpy(passkey, key, BLE_PAIRING_KEY_LEN);
m_static_pin_option.gap_opt.passkey.p_passkey = passkey;
// NRF_LOG_RAW_HEXDUMP_INFO(passkey, 6);
APP_ERROR_CHECK(sd_ble_opt_set(BLE_GAP_OPT_PASSKEY, &m_static_pin_option));
@@ -331,7 +331,7 @@ static void services_init(void) {
bas_init_obj.bl_cccd_wr_sec = SEC_OPEN;
bas_init_obj.bl_report_rd_sec = SEC_OPEN;
}
err_code = ble_bas_init(&m_bas, &bas_init_obj);
APP_ERROR_CHECK(err_code);
}
+35 -34
View File
@@ -10,7 +10,7 @@
#define DATA_CMD_GET_APP_VERSION (1000)
#define DATA_CMD_CHANGE_DEVICE_MODE (1001)
#define DATA_CMD_GET_DEVICE_MODE (1002)
#define DATA_CMD_SET_SLOT_ACTIVATED (1003)
#define DATA_CMD_SET_ACTIVE_SLOT (1003)
#define DATA_CMD_SET_SLOT_TAG_TYPE (1004)
#define DATA_CMD_SET_SLOT_DATA_DEFAULT (1005)
#define DATA_CMD_SET_SLOT_ENABLE (1006)
@@ -28,6 +28,7 @@
#define DATA_CMD_GET_ACTIVE_SLOT (1018)
#define DATA_CMD_GET_SLOT_INFO (1019)
#define DATA_CMD_WIPE_FDS (1020)
#define DATA_CMD_GET_ENABLED_SLOTS (1023)
#define DATA_CMD_DELETE_SLOT_SENSE_TYPE (1024)
#define DATA_CMD_GET_BATTERY_INFO (1025)
@@ -35,11 +36,11 @@
#define DATA_CMD_SET_BUTTON_PRESS_CONFIG (1027)
#define DATA_CMD_GET_LONG_BUTTON_PRESS_CONFIG (1028)
#define DATA_CMD_SET_LONG_BUTTON_PRESS_CONFIG (1029)
#define DATA_CMD_SET_BLE_CONNECT_KEY_CONFIG (1030)
#define DATA_CMD_GET_BLE_CONNECT_KEY_CONFIG (1031)
#define DATA_CMD_SET_BLE_PAIRING_KEY (1030)
#define DATA_CMD_GET_BLE_PAIRING_KEY (1031)
#define DATA_CMD_DELETE_ALL_BLE_BONDS (1032)
#define DATA_CMD_GET_DEVICE (1033)
#define DATA_CMD_GET_SETTINGS (1034)
#define DATA_CMD_GET_DEVICE_MODEL (1033)
#define DATA_CMD_GET_DEVICE_SETTINGS (1034)
#define DATA_CMD_GET_DEVICE_CAPABILITIES (1035)
#define DATA_CMD_GET_BLE_PAIRING_ENABLE (1036)
#define DATA_CMD_SET_BLE_PAIRING_ENABLE (1037)
@@ -53,16 +54,18 @@
// Range from 2000 -> 2999
// ******************************************************************
//
#define DATA_CMD_SCAN_14A_TAG (2000)
#define DATA_CMD_MF1_SUPPORT_DETECT (2001)
#define DATA_CMD_MF1_NT_LEVEL_DETECT (2002)
#define DATA_CMD_MF1_DARKSIDE_DETECT (2003)
#define DATA_CMD_HF14A_SCAN (2000)
#define DATA_CMD_MF1_DETECT_SUPPORT (2001)
#define DATA_CMD_MF1_DETECT_PRNG (2002)
#define DATA_CMD_MF1_STATIC_NESTED_ACQUIRE (2003)
#define DATA_CMD_MF1_DARKSIDE_ACQUIRE (2004)
#define DATA_CMD_MF1_NT_DIST_DETECT (2005)
#define DATA_CMD_MF1_DETECT_NT_DIST (2005)
#define DATA_CMD_MF1_NESTED_ACQUIRE (2006)
#define DATA_CMD_MF1_CHECK_ONE_KEY_BLOCK (2007)
#define DATA_CMD_MF1_AUTH_ONE_KEY_BLOCK (2007)
#define DATA_CMD_MF1_READ_ONE_BLOCK (2008)
#define DATA_CMD_MF1_WRITE_ONE_BLOCK (2009)
#define DATA_CMD_HF14A_RAW (2010)
//
// ******************************************************************
@@ -72,8 +75,8 @@
// Range from 3000 -> 3999
// ******************************************************************
//
#define DATA_CMD_SCAN_EM410X_TAG (3000)
#define DATA_CMD_WRITE_EM410X_TO_T5577 (3001)
#define DATA_CMD_EM410X_SCAN (3000)
#define DATA_CMD_EM410X_WRITE_TO_T55XX (3001)
//
// ******************************************************************
@@ -83,25 +86,23 @@
// Range from 4000 -> 4999
// ******************************************************************
//
#define DATA_CMD_LOAD_MF1_EMU_BLOCK_DATA (4000)
#define DATA_CMD_SET_MF1_ANTI_COLLISION_RES (4001)
#define DATA_CMD_SET_MF1_ANTI_COLLISION_INFO (4002)
#define DATA_CMD_SET_MF1_ATS_RESOURCE (4003)
#define DATA_CMD_SET_MF1_DETECTION_ENABLE (4004)
#define DATA_CMD_GET_MF1_DETECTION_COUNT (4005)
#define DATA_CMD_GET_MF1_DETECTION_RESULT (4006)
#define DATA_CMD_GET_MF1_DETECTION_STATUS (4007)
#define DATA_CMD_READ_MF1_EMU_BLOCK_DATA (4008)
#define DATA_CMD_GET_MF1_EMULATOR_CONFIG (4009)
#define DATA_CMD_GET_MF1_GEN1A_MODE (4010)
#define DATA_CMD_SET_MF1_GEN1A_MODE (4011)
#define DATA_CMD_GET_MF1_GEN2_MODE (4012)
#define DATA_CMD_SET_MF1_GEN2_MODE (4013)
#define DATA_CMD_GET_MF1_USE_FIRST_BLOCK_COLL (4014)
#define DATA_CMD_SET_MF1_USE_FIRST_BLOCK_COLL (4015)
#define DATA_CMD_GET_MF1_WRITE_MODE (4016)
#define DATA_CMD_SET_MF1_WRITE_MODE (4017)
#define DATA_CMD_GET_MF1_ANTI_COLL_DATA (4018)
#define DATA_CMD_MF1_WRITE_EMU_BLOCK_DATA (4000)
#define DATA_CMD_HF14A_SET_ANTI_COLL_DATA (4001)
#define DATA_CMD_MF1_SET_DETECTION_ENABLE (4004)
#define DATA_CMD_MF1_GET_DETECTION_COUNT (4005)
#define DATA_CMD_MF1_GET_DETECTION_LOG (4006)
#define DATA_CMD_MF1_GET_DETECTION_ENABLE (4007)
#define DATA_CMD_MF1_READ_EMU_BLOCK_DATA (4008)
#define DATA_CMD_MF1_GET_EMULATOR_CONFIG (4009)
#define DATA_CMD_MF1_GET_GEN1A_MODE (4010)
#define DATA_CMD_MF1_SET_GEN1A_MODE (4011)
#define DATA_CMD_MF1_GET_GEN2_MODE (4012)
#define DATA_CMD_MF1_SET_GEN2_MODE (4013)
#define DATA_CMD_MF1_GET_BLOCK_ANTI_COLL_MODE (4014)
#define DATA_CMD_MF1_SET_BLOCK_ANTI_COLL_MODE (4015)
#define DATA_CMD_MF1_GET_WRITE_MODE (4016)
#define DATA_CMD_MF1_SET_WRITE_MODE (4017)
#define DATA_CMD_HF14A_GET_ANTI_COLL_DATA (4018)
//
// ******************************************************************
@@ -114,7 +115,7 @@
//
// ******************************************************************
#define DATA_CMD_SET_EM410X_EMU_ID (5000)
#define DATA_CMD_GET_EM410X_EMU_ID (5001)
#define DATA_CMD_EM410X_SET_EMU_ID (5000)
#define DATA_CMD_EM410X_GET_EMU_ID (5001)
#endif
@@ -617,7 +617,7 @@ void nfc_tag_14a_event_callback(nrfx_nfct_evt_t const *p_event) {
g_is_tag_emulating = true;
g_usb_led_marquee_enable = false;
set_slot_light_color(1);
set_slot_light_color(RGB_GREEN);
TAG_FIELD_LED_ON()
NRF_LOG_INFO("HF FIELD DETECTED");
@@ -661,7 +661,7 @@ void nfc_tag_14a_event_callback(nrfx_nfct_evt_t const *p_event) {
break;
}
case NRFX_NFCT_EVT_RX_FRAMEEND: {
set_slot_light_color(1);
set_slot_light_color(RGB_GREEN);
TAG_FIELD_LED_ON()
// NRF_LOG_INFO("RX FRAMEEND.\n");

Some files were not shown because too many files have changed in this diff Show More