diff --git a/Home.md b/Home.md index b2c2b27..27c594d 100644 --- a/Home.md +++ b/Home.md @@ -6,32 +6,32 @@ This Guide is split up into multiple "subguides": ### About the device -- [[Whitepaper|technical_whitepaper]]: Discover what the Chameleon Ultra is capable of. +- [Whitepaper](./technical_whitepaper.md): Discover what the Chameleon Ultra is capable of. -- [[Hardware|hardware]]: Learn to know the hardware of your Chameleon. +- [Hardware](./hardware.md): Learn to know the hardware of your Chameleon. -- [[Firmware|firmware]]: Your Chameleon runs a firmware, learn what it can do and how to use it. +- [Firmware](./firmware.md): Your Chameleon runs a firmware, learn what it can do and how to use it. ### Interacting with the device -- [[Quickstart|quickstart]]: For the impatient people to just get you up and running with anything. +- [Quickstart](./quickstart.md): For the impatient people to just get you up and running with anything. -- [[CLI|cli]]: The official way to control your Chameleon is via the **C**ommand **L**ine **I**nterface (CLI). Learn how to install and master the CLI. +- [CLI](./cli.md): The official way to control your Chameleon is via the **C**ommand **L**ine **I**nterface (CLI). Learn how to install and master the CLI. -- [[GUIs|gui]]: Some people also develop **G**raphical **U**ser **I**nterfaces (GUIs), these may be a good start for people that do not want to deal with a CLI. +- [GUIs](./gui.md): Some people also develop **G**raphical **U**ser **I**nterfaces (GUIs), these may be a good start for people that do not want to deal with a CLI. -- [[Troubleshooting|troubleshooting]]: For when things go wrong, here are some common tips to maybe fix whatever issue you might have. +- [Troubleshooting](./troubleshooting.md): For when things go wrong, here are some common tips to maybe fix whatever issue you might have. ### For developers -- [[Development|development]]: For all developers. This covers how to build firmware from source and set up a development environment. +- [Development](./development.md): For all developers. This covers how to build firmware from source and set up a development environment. -- [[SDKs|sdk]]: SDKs for Chameleon, useful if you want to develop your own application to control Chameleon. +- [SDKs](./sdk.md): SDKs for Chameleon, useful if you want to develop your own application to control Chameleon. -- [[Protocol|protocol]]: The gory details of the communication protocol, useful if you want to develop your own client. +- [Protocol](./protocol/README.md): The gory details of the communication protocol, useful if you want to develop your own client. ### Miscellaneous -- [[Modding|modding]]: Third party moddings worth mentioning. +- [Modding](./modding.md): Third party moddings worth mentioning. -- [[FAQ|faq]]: **F**requently **A**sked **Q**uestions, if you have a question, it might already be answered here. +- [FAQ](./faq.md): **F**requently **A**sked **Q**uestions, if you have a question, it might already be answered here. \ No newline at end of file diff --git a/chameleonultragui.md b/chameleonultragui.md index f3c5bd5..4502df6 100644 --- a/chameleonultragui.md +++ b/chameleonultragui.md @@ -65,7 +65,7 @@ The *Mifare Classic emulator settings* section allows you to toggle various beha - *Gen2 Magic Mode*: behaves like a gen2 magic card, makes Block 0 writable ; - *Use UID/SAK/ATQA from 0 block*: the Chameleon Ultra stores the UID and other anti-collision data independently of the card content. Enabling this setting tells the Chameleon to derive them from card content block 0. Only for MFC with 4-byte UID ; - *Collect nonces (Mfkey32)*: it toggles nonce collection for mfkey32. When enabled you will be prompted to present the Chameleon to a reader. After you have collected nonces the *Present Chameleon to reader* message will change into a *Recover Keys from x nonces* button. Pressing this will start the recovery process ; -- *Write mode*: Please refer to the [[firmware docs|firmware]]. +- *Write mode*: Please refer to the [firmware docs](./firmware.md). ### Search dialog ![Search Dialog](./images/cugui-searchdialog.png) diff --git a/firmware.md b/firmware.md index d651739..1faab9b 100644 --- a/firmware.md +++ b/firmware.md @@ -2,7 +2,7 @@ The Chameleon flash contains several parts: the bootloader and its settings, the application, the user data and the SoftDevice. -NOTE: If you are a developer searching for the building instructions, look into [[development|development]] +NOTE: If you are a developer searching for the building instructions, look into [development](./development.md). ## The Bootloader diff --git a/gui.md b/gui.md index 59f952a..20337a5 100644 --- a/gui.md +++ b/gui.md @@ -3,6 +3,6 @@ There are multiple GUIs to control your Chameleon, two are featured in this documentation. Note that in spite of what their name may suggest, all GUIs support both the Ultra and the Lite. -- [[Chameleon Ultra GUI|chameleonultragui]] ([github](https://github.com/GameTec-live/ChameleonUltraGUI)) +- [Chameleon Ultra GUI](./chameleonultragui.md) ([github](https://github.com/GameTec-live/ChameleonUltraGUI)) - [MTools Lite for iOS](https://shop.mtoolstec.com/mifare-classic-tool-for-ios) diff --git a/protocol.md b/protocol.md deleted file mode 100644 index 4e72106..0000000 --- a/protocol.md +++ /dev/null @@ -1,580 +0,0 @@ -# Protocol description - -## Versioning - -Global firmware+CLI versions are following the [semantic versioning](https://semver.org/) logic mostly regarding the protocol version, so third party clients (GUIs, mobile apps, SDKs) can rely on firmware version to know their level of compatibility. - -Given a version number MAJOR.MINOR.PATCH, we will increment the: - -* MAJOR version when we are breaking the existing protocol format -* MINOR version when we are extending the protocol format in a backward compatible manner (new commands,...) -* PATCH version when we are releasing bugfixes not affecting the protocol description - -Besides compatibility with a given firmware version, third party clients may choose to offer to the users the possibility to follow a stable release channel (installing only tagged releases) or the development channel (installing latest commits). - -For the stable channel, a client compatible with versions X.y.z can accept any version > X.y'.z' but should refuse to work with a version X'>X. - -For the development channel, a client compatible with versions X.y.z can accept any latest commit unless a tag X'.0.0 with X'>X is present in the repo, indicating that the corresponding commit and all the commits above are incompatible with the client version. There is still a non negligible risk that breaking changes are pushed while forgetting about putting a new tag, or artefacts being built before the tag being pushed. Here be dragons... It's always a good practice for the client to validate whatever data is transmitted by the firmware, and fail gracefully in case of hiccups. - -Cf [GET_APP_VERSION](#1000-get_app_version) and [GET_GIT_VERSION](#1017-get_git_version). - -When `GET_GIT_VERSION` returns only a tag and no commit hash info (on a release tag), one can query the corresponding hash with the GitHub API, e.g. - -``` -"4747d3884d21e0df8549e3029a920ea390e0b00a" -``` - -## Frame format - -The communication between the firmware and the client is made of frames structured as follows: - -![](images/protocol-packet.png) - -```mermaid -packet -+8: "SOF" -+8: "LRC1" -+16: "CMD" -+16: "STATUS" -+16: "LEN" -+8: "LRC2" -+48: "DATA (variable length)" -+8: "LRC3" -``` - -- **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. - -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) - -## Data payloads - -Each command and response have their own payload formats. - -Standard response status is `STATUS_SUCCESS` for general commands, `STATUS_HF_TAG_OK` for HF commands and `STATUS_LF_TAG_OK` for LF commands. -See [Guidelines](#new-data-payloads-guidelines-for-developers) for more info. - -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 - -* CLI: cf `hw version` - -```mermaid ---- -title: "Command Packet" ---- -packet -+8: "SOF" -+8: "LRC1" -+16: "CMD (=1000)" -+16: "STATUS" -+16: "LEN (=0)" -+8: "LRC2" -+8: "LRC3" -``` - -* Command: no data - -```mermaid ---- -title: "Response Packet" ---- -packet -+8: "SOF" -+8: "LRC1" -+16: "CMD (=1000)" -+16: "STATUS" -+16: "LEN (=2)" -+8: "LRC2" -+8: "major version" -+8: "minor version" -+8: "LRC3" -``` - -* Response: 2 bytes: `version_major|version_minor` - -### 1001: CHANGE_DEVICE_MODE - -* CLI: cf `hw mode` - -```mermaid ---- -title: "Command Packet" ---- -packet -+8: "SOF" -+8: "LRC1" -+16: "CMD (=1001)" -+16: "STATUS" -+16: "LEN (=1)" -+8: "LRC2" -+8: "new device mode" -+8: "LRC3" -``` - -* device mode: `0x00`=emulator mode, `0x01`=reader mode - -```mermaid ---- -title: "Response Packet" ---- -packet -+8: "SOF" -+8: "LRC1" -+16: "CMD (=1001)" -+16: "STATUS" -+16: "LEN (=0)" -+8: "LRC2" -+8: "LRC3" -``` - -* Response: no data - -### 1002: GET_DEVICE_MODE -* Command: no data -* Response: data: 1 byte. `0x00`=emulator mode, `0x01`=reader mode -* CLI: cf `hw mode` -### 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`/`hw slot disable` -### 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` -### 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` -### 1009: SLOT_DATA_CONFIG_SAVE -* Command: no data -* Response: no data -* CLI: cf `hw slot store` -### 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` -### 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` -### 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` -### 1016: GET_ANIMATION_MODE -* Command: no data -* Response: 1 byte, according to `settings_animation_mode_t` enum. -* CLI: cf `hw settings animation` -### 1017: GET_GIT_VERSION -* Command: no data -* Response: n bytes, a UTF-8 encoded string, no null terminator. -* CLI: cf `hw version` - -Notes: the returned string is the output of `git describe --abbrev=7 --dirty --always --tags --match "v*.*"` so, depending on the status of the repo it can be -* a short tag, e.g. `v2.0.0` if the firmware is built from the tagged commit -* a longer tag indicating how far it is from the latest tag and 7 nibbles of its commit hash, prepended with `g`, e.g. 5 commits away from v2.0.0: `v2.0.0-5-g617d6d0` -* a long tag finishing with `-dirty` if the local repo contains changes not yet committed, e.g. `v2.0.0-5-g617d6d0-dirty` -### 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_SUCCESS` or `STATUS_FLASH_WRITE_FAIL`. The device will reboot shortly after this command. -* CLI: cf `hw factory_reset` -### 1021: DELETE_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: no data -* CLI: cf `hw slot nick` -### 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` -* CLI: cf `hw slot list` -### 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 slot delete` -### 1025: GET_BATTERY_INFO -* Command: no data -* Response: 3 bytes, `voltage[2]|percentage`. Voltage: U16 in Network byte order. -* CLI: cf `hw battery` - -Notes: wait about 5 seconds after wake-up, before querying the battery status, else the device won't be able to give a proper measure and will return zeroes. -### 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` -### 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` -### 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` -### 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` -### 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 settings bleclearbonds` -### 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 `STATUS_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`. Type=0x60 for key A, 0x61 for key B. -* 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. Type=0x60 for key A, 0x61 for key B. -* 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. Type=0x60 for key A, 0x61 for key B. -* 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. Type=0x60 for key A, 0x61 for key B. -* Response: no data -* Status will be `STATUS_HF_TAG_OK` if auth succeeded, else `STATUS_MF_ERR_AUTH` -* CLI: cf `hf mf nested` -### 2008: MF1_READ_ONE_BLOCK -* Command: 8 bytes: `type|block|key[6]`. Key as 6 bytes. Type=0x60 for key A, 0x61 for key B. -* 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. Type=0x60 for key A, 0x61 for key B. -* 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` -### 2011: MF1_MANIPULATE_VALUE_BLOCK -* Command: 21 bytes: `src_type|src_block|src_key[6]|operator|operand[4]|dst_type|dst_block|dst_key[6]`. Key as 6 bytes. Type=`0x60` for key A, `0x61` for key B. Operator=`0xC0` for decrement, `0xC1` for increment, `0xC2` for restore. Operand as I32 in Network byte order. -* Response: no data -* CLI: cf `hf mf value` -### 2012: MF1_CHECK_KEYS_OF_SECTORS -* Command: 10+N*6 bytes: `mask[10]|keys[N][6]` (1<=N<=83) - * `mask`: 40 sectors, 2 bits/sector, MSB: `0A|0B|1A|1B|...|39A|39B`. `0b1` represent to skip checking the key. -* Response: 490 bytes: `found[10]|sectorKey[40][2][6]`. - * `found`: 40 sectors, 2 bits/sector, MSB: `0A|0B|1A|1B|...|39A|39B`. `0b1` represent the key is found. - * `sectorKey`: 40 sectors, 2 keys/sector, 6 bytes/key: `key0A[6]|key0B[6]|key1A[6]|key1B[6]|...|key39A[6]|key39B[6]` -* CLI: cf `hf mf fchk` -### 3000: EM410X_SCAN -* Command: no data -* Response: 5 bytes. `id[5]`. ID as 5 bytes. -* CLI: cf `lf em 410x 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 410x write` -### 3002: HIDPROX_SCAN -* Command: no data -* Response: 13 bytes: `format[1]|facility_code[4]|card_number[5]|issue_level[1]|oem[2]`. -* CLI: cf `lf hid prox read` -### 3003: HIDPROX_WRITE_TO_T55XX -* Command: 17+N*4 bytes: `format[1]|facility_code[4]|card_number[5]|issue_level[1]|oem[2]|new_key[4]|old_key1[4]|old_key2[4]|...` (N>=1). Keys as 4 bytes. -* Response: no data -* CLI: cf `lf hid prox 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 econfig`/`hf mfu econfig` -### 4004: MF1_SET_DETECTION_ENABLE -* Command: 1 byte, bool = `0x00` or `0x01` -* Response: no data -* CLI: cf `hf mf econfig` -### 4005: MF1_GET_DETECTION_COUNT -* Command: no data -* Response: 4 bytes, `count[4]`, U32 in Network byte order. -* CLI: cf `hf mf elog` -### 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 mf elog` -### 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 `hf mf econfig` -### 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 econfig` -### 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 econfig` -### 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 econfig` -### 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 econfig` -### 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 `hw slot list`/`hf mf econfig`/`hf mfu econfig` -### 4019: MF0_NTAG_GET_UID_MAGIC_MODE -* Command: no data -* Response: 1 byte where a non-zero value indicates that UID magic mode is enabled for the current slot. -* CLI: cf `hf mfu econfig` -### 4020: MF0_NTAG_SET_UID_MAGIC_MODE -* Command: 1 byte where a non-zero value indicates that UID magic mode should be enabled for the current slot, otherwise disabled. -* Response: no data -* CLI: cf `hf mfu econfig --enable-uid-magic`/`hf mfu econfig --disable-uid-magic` -### 4021: MF0_NTAG_READ_EMU_PAGE_DATA -* Command: 2 bytes: one for first page index, one for count of pages to be read. -* Response: `4 * n` bytes where `n` is the number if pages to be read -* CLI: cf `hf mfu eview` -### 4022: MF0_NTAG_WRITE_EMU_PAGE_DATA -* Command: 2 + `n * 4` bytes: one for first page index, one for count of pages to be read, `n * 4` for `n` pages data. -* Response: no data -* CLI: unused -### 4023: MF0_NTAG_GET_VERSION_DATA -* Command: no data -* Response: 8 version data bytes. -* CLI: cf `hf mfu econfig` -### 4024: MF0_NTAG_SET_VERSION_DATA -* Command: 8 version data bytes. -* Response: no data -* CLI: cf `hf mfu econfig --set-version ` -### 4025: MF0_NTAG_GET_SIGNATURE_DATA -* Command: no data -* Response: 32 signature data bytes. -* CLI: cf `hf mfu econfig` -### 4026: MF0_NTAG_SET_SIGNATURE_DATA -* Command: 32 signature data bytes. -* Response: no data -* CLI: cf `hf mfu econfig --set-signature ` -### 4027: MF0_NTAG_GET_COUNTER_DATA -* Command: 1 byte for the counter index -* Response: 3 bytes for the counter value (big-endian) + 1 byte for tearing where `0xBD` means tearing flag is not set. -* CLI: cf `hf mfu ercnt` -### 4028: MF0_NTAG_SET_COUNTER_DATA -* Command: 1 byte where the lower 7 bits are the counter index and the top bit indicates whether tearing event flag should be reset + 3 bytes of the counter value (big-endian). -* Response: no data -* CLI: cf `hf mfu ewcnt` -### 4029: MF0_NTAG_RESET_AUTH_CNT -* Command: no data -* Response: 1 byte for the old value of the unsuccessful auth counter. -* CLI: cf `hf mfu econfig --reset-auth-cnt` -### 4030: MF0_NTAG_GET_PAGE_COUNT -* Command: no data -* Response: 1 byte is the number of pages available in the current card slot -* CLI: unused -### 5000: EM410X_SET_EMU_ID -* Command: 5 bytes. `id[5]`. ID as 5 bytes. -* Response: no data -* CLI: cf `lf em 410x econfig` -### 5001: EM410X_GET_EMU_ID -* Command: no data -* Response: 5 bytes. `id[5]`. ID as 5 bytes. -* CLI: cf `lf em 410x econfig` -### 5002: HIDPROX_SET_EMU_ID -* Command: 13 bytes: `format[1]|facility_code[4]|card_number[5]|issue_level[1]|oem[2]`. -* Response: no data -* CLI: cf `lf hid prox econfig` -### 5003: HIDPROX_GET_EMU_ID -* Command: no data -* Response: 13 bytes: `format[1]|facility_code[4]|card_number[5]|issue_level[1]|oem[2]`. -* CLI: cf `lf hid prox econfig -s 1 --fc 107 --cn 10044 --format H10301` - - -## 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_SUCCESS` for general commands, `STATUS_HF_TAG_OK` for HF commands and `STATUS_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. - -## Room for improvement - -* some `num_to_bytes` `bytes_to_num` could use `hton*`, `ntoh*` instead, to make endianess explicit -* some commands are using bitfields (e.g. mf1_get_detection_log (sending directly the flash stored format) and hf14a_raw) while some commands are spreading bits into 0x00/0x01 bytes (e.g. mf1_get_emulator_config) -* describe flash storage formats diff --git a/protocol/1000.md b/protocol/1000.md new file mode 100644 index 0000000..e69bdb7 --- /dev/null +++ b/protocol/1000.md @@ -0,0 +1,62 @@ +# 1000: GET_APP_VERSION **(DEPRECATED)** + +> [!WARNING] +> This command is deprecated. For firmware version >= `v2.x`, please use [1017: GET_GIT_VERSION](./1017.md) instead. + +Get firmware version. + +Global firmware+CLI versions are following the [semantic versioning](https://semver.org/) logic mostly regarding the protocol version, so third party clients (GUIs, mobile apps, SDKs) can rely on firmware version to know their level of compatibility. + +Given a version number MAJOR.MINOR.PATCH, we will increment the: + +* MAJOR version when we are breaking the existing protocol format +* MINOR version when we are extending the protocol format in a backward compatible manner (new commands,...) +* PATCH version when we are releasing bugfixes not affecting the protocol description + +Besides compatibility with a given firmware version, third party clients may choose to offer to the users the possibility to follow a stable release channel (installing only tagged releases) or the development channel (installing latest commits). + +For the stable channel, a client compatible with versions X.y.z can accept any version > X.y'.z' but should refuse to work with a version X'>X. + +For the development channel, a client compatible with versions X.y.z can accept any latest commit unless a tag X'.0.0 with X'>X is present in the repo, indicating that the corresponding commit and all the commits above are incompatible with the client version. There is still a non negligible risk that breaking changes are pushed while forgetting about putting a new tag, or artefacts being built before the tag being pushed. Here be dragons... It's always a good practice for the client to validate whatever data is transmitted by the firmware, and fail gracefully in case of hiccups. + +cli example: `hw version` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1000)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Request Packet: None + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1000)" ++16: "STATUS" ++16: "LEN (=2)" ++8: "LRC2" ++8: "major version" ++8: "minor version" ++8: "LRC3" +``` + +* DATA in Response Packet + * major version: `1 byte`, major version number + * minor version: `1 byte`, minor version number \ No newline at end of file diff --git a/protocol/1001.md b/protocol/1001.md new file mode 100644 index 0000000..dd40021 --- /dev/null +++ b/protocol/1001.md @@ -0,0 +1,43 @@ +# 1001: CHANGE_DEVICE_MODE + +Change device mode between reader/writer and emulator. + +* CLI: cf `hw mode` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1001)" ++16: "STATUS" ++16: "LEN (=1)" ++8: "LRC2" ++8: "new device mode" ++8: "LRC3" +``` + +* DATA in Request Packet + * device mode: `1 byte`, `0x00`=emulator mode, `0x01`=reader/writer mode + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1001)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Response Packet: None \ No newline at end of file diff --git a/protocol/1002.md b/protocol/1002.md new file mode 100644 index 0000000..42f6594 --- /dev/null +++ b/protocol/1002.md @@ -0,0 +1,43 @@ +# 1002: GET_DEVICE_MODE + +Get current device mode. + +* CLI: cf `hw mode` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1002)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Request Packet: None + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1002)" ++16: "STATUS" ++16: "LEN (=1)" ++8: "LRC2" ++8: "current device mode" ++8: "LRC3" +``` + +* DATA in Response Packet + * device mode: `1 byte`, `0x00`=emulator mode, `0x01`=reader/writer mode \ No newline at end of file diff --git a/protocol/1003.md b/protocol/1003.md new file mode 100644 index 0000000..7d023fc --- /dev/null +++ b/protocol/1003.md @@ -0,0 +1,43 @@ +# 1003: SET_ACTIVE_SLOT + +Set active slot number. + +* CLI: cf `hw slot change` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1003)" ++16: "STATUS" ++16: "LEN (=1)" ++8: "LRC2" ++8: "slot number" ++8: "LRC3" +``` + +* DATA in Request Packet + * slot number: `1 byte`, between `0` and `7`. + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1003)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Response Packet: None \ No newline at end of file diff --git a/protocol/1004.md b/protocol/1004.md new file mode 100644 index 0000000..e30a023 --- /dev/null +++ b/protocol/1004.md @@ -0,0 +1,45 @@ +# 1004: SET_SLOT_TAG_TYPE + +Set tag type of specific slot. + +* CLI: cf `hw slot type` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1004)" ++16: "STATUS" ++16: "LEN (=3)" ++8: "LRC2" ++8: "slot number" ++16: "tag type" ++8: "LRC3" +``` + +* DATA in Request Packet + * slot number: `1 byte`, between `0` and `7`. + * tag type: `2 bytes`, U16 in network byte order, according to `tag_specific_type_t` enum. + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1004)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Response Packet: None \ No newline at end of file diff --git a/protocol/1005.md b/protocol/1005.md new file mode 100644 index 0000000..a75cfa8 --- /dev/null +++ b/protocol/1005.md @@ -0,0 +1,45 @@ +# 1005: SET_SLOT_DATA_DEFAULT + +Reset to tag type's default data of specific slot. + +* CLI: cf `hw slot init` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1005)" ++16: "STATUS" ++16: "LEN (=3)" ++8: "LRC2" ++8: "slot number" ++16: "tag type" ++8: "LRC3" +``` + +* DATA in Request Packet + * slot number: `1 byte`, between `0` and `7`. + * tag type: `2 bytes`, U16 in network byte order, according to `tag_specific_type_t` enum. + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1005)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Response Packet: None \ No newline at end of file diff --git a/protocol/1006.md b/protocol/1006.md new file mode 100644 index 0000000..c265859 --- /dev/null +++ b/protocol/1006.md @@ -0,0 +1,47 @@ +# 1006: SET_SLOT_ENABLE + +Enable/disable specific slot HF/LF. + +* CLI: cf `hw slot enable` / `hw slot disable` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1006)" ++16: "STATUS" ++16: "LEN (=3)" ++8: "LRC2" ++8: "slot number" ++8: "sense type" ++8: "enable / disable" ++8: "LRC3" +``` + +* DATA in Request Packet + * slot number: `1 byte`, between `0` and `7`. + * sense type: `1 byte`, according to `tag_sense_type_t` enum. + * enable / disable: `1 byte`, `0x01`=enable, `0x00`=disable. + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1006)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Response Packet: None \ No newline at end of file diff --git a/protocol/1007.md b/protocol/1007.md new file mode 100644 index 0000000..4404719 --- /dev/null +++ b/protocol/1007.md @@ -0,0 +1,47 @@ +# 1007: SET_SLOT_TAG_NICK + +Set nickname of specific slot HF/LF. + +* CLI: cf `hw slot nick` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1007)" ++16: "STATUS" ++16: "LEN (=N+2)" ++8: "LRC2" ++8: "slot number" ++8: "sense type" ++64: "name, N bytes, 1 <= N <= 32" ++8: "LRC3" +``` + +* DATA in Request Packet + * slot number: `1 byte`, between `0` and `7`. + * sense type: `1 byte`, according to `tag_sense_type_t` enum. + * name: `N bytes`, `1 <= N <= 32`, UTF-8 encoded string, no null terminator. + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1007)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Response Packet: None \ No newline at end of file diff --git a/protocol/1008.md b/protocol/1008.md new file mode 100644 index 0000000..44bebf9 --- /dev/null +++ b/protocol/1008.md @@ -0,0 +1,48 @@ +# 1008: GET_SLOT_TAG_NICK + +Get nickname of specific slot HF/LF. + +* CLI: cf `hw slot nick` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1008)" ++16: "STATUS" ++16: "LEN (=2)" ++8: "LRC2" ++8: "slot number" ++8: "sense type" ++8: "LRC3" +``` + +* DATA in Request Packet + * slot number: `1 byte`, between `0` and `7`. + * sense type: `1 byte`, according to `tag_sense_type_t` enum. + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1008)" ++16: "STATUS" ++16: "LEN (=N)" ++8: "LRC2" ++48: "name, N bytes, 1 <= N <= 32" ++8: "LRC3" +``` + +* DATA in Response Packet + * name: `N bytes`, `1 <= N <= 32`, UTF-8 encoded string, no null terminator. +* If no nick name has been recorded in Flash, response status is `STATUS_FLASH_READ_FAIL`. \ No newline at end of file diff --git a/protocol/1009.md b/protocol/1009.md new file mode 100644 index 0000000..072c304 --- /dev/null +++ b/protocol/1009.md @@ -0,0 +1,41 @@ +# 1009: SLOT_DATA_CONFIG_SAVE + +Save slot data configuration. + +* CLI: cf `hw slot store` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1009)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Request Packet: None + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1009)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Response Packet: None \ No newline at end of file diff --git a/protocol/1010.md b/protocol/1010.md new file mode 100644 index 0000000..0569df4 --- /dev/null +++ b/protocol/1010.md @@ -0,0 +1,27 @@ +# 1010: ENTER_BOOTLOADER + +Enter bootloader mode. + +* CLI: cf `hw dfu` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1010)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Request Packet: None + +## Response Packet + +* No response packet for this special command. The device will disconnect immediately and reboot into bootloader mode for DFU (Device Firmware Update). \ No newline at end of file diff --git a/protocol/1011.md b/protocol/1011.md new file mode 100644 index 0000000..2e473c1 --- /dev/null +++ b/protocol/1011.md @@ -0,0 +1,43 @@ +# 1011: GET_DEVICE_CHIP_ID + +Get device chip ID. + +* CLI: cf `hw chipid` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1011)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Request Packet: None + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1011)" ++16: "STATUS" ++16: "LEN (=8)" ++8: "LRC2" ++64: "device chip id" ++8: "LRC3" +``` + +* DATA in Response Packet + * device chip id: `8 bytes`, U64 in network byte order. \ No newline at end of file diff --git a/protocol/1012.md b/protocol/1012.md new file mode 100644 index 0000000..16c5ce0 --- /dev/null +++ b/protocol/1012.md @@ -0,0 +1,43 @@ +# 1012: GET_DEVICE_ADDRESS + +Get device BLE address. + +* CLI: cf `hw address` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1012)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Request Packet: None + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1012)" ++16: "STATUS" ++16: "LEN (=6)" ++8: "LRC2" ++48: "bluetooth address" ++8: "LRC3" +``` + +* DATA in Response Packet + * bluetooth address: `6 bytes`, U48 in network byte order. \ No newline at end of file diff --git a/protocol/1013.md b/protocol/1013.md new file mode 100644 index 0000000..fa39271 --- /dev/null +++ b/protocol/1013.md @@ -0,0 +1,41 @@ +# 1013: SAVE_SETTINGS + +Save device settings. + +* CLI: cf `hw settings store` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1013)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Request Packet: None + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1013)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Response Packet: None \ No newline at end of file diff --git a/protocol/1014.md b/protocol/1014.md new file mode 100644 index 0000000..e8e8497 --- /dev/null +++ b/protocol/1014.md @@ -0,0 +1,41 @@ +# 1014: RESET_SETTINGS + +Reset device settings. + +* CLI: cf `hw settings reset` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1014)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Request Packet: None + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1014)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Response Packet: None \ No newline at end of file diff --git a/protocol/1015.md b/protocol/1015.md new file mode 100644 index 0000000..5006ccd --- /dev/null +++ b/protocol/1015.md @@ -0,0 +1,43 @@ +# 1015: SET_ANIMATION_MODE + +Set device power on animation. + +* CLI: cf `hw settings animation` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1015)" ++16: "STATUS" ++16: "LEN (=1)" ++8: "LRC2" ++8: "new animation mode" ++8: "LRC3" +``` + +* DATA in Request Packet + * animation mode: `1 byte`, according to `settings_animation_mode_t` enum. + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1015)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Response Packet: None \ No newline at end of file diff --git a/protocol/1016.md b/protocol/1016.md new file mode 100644 index 0000000..55e0282 --- /dev/null +++ b/protocol/1016.md @@ -0,0 +1,43 @@ +# 1016: GET_ANIMATION_MODE + +Get device power on animation. + +* CLI: cf `hw settings animation` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1016)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Request Packet: None + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1016)" ++16: "STATUS" ++16: "LEN (=1)" ++8: "LRC2" ++8: "current animation mode" ++8: "LRC3" +``` + +* DATA in Response Packet + * animation mode: `1 byte`, according to `settings_animation_mode_t` enum. \ No newline at end of file diff --git a/protocol/1017.md b/protocol/1017.md new file mode 100644 index 0000000..eb7bdc0 --- /dev/null +++ b/protocol/1017.md @@ -0,0 +1,50 @@ +# 1017: GET_GIT_VERSION + +Get `git describe` version string of source code. + +> [!NOTE] +> The git describe version is generated by running `git describe --abbrev=7 --dirty --always --tags --match "v*.*"`. The output depends on the repository’s current status and can be: +> +> * A short tag like `v2.0.0` if the firmware is built from a tagged commit. +> * A longer tag indicating how many commits it is from the latest tag and the 7 prefix nibbles of commit hash, prepended with `g`. For example, if there are 5 commits after v2.0.0: `v2.0.0-5-g617d6d0` +> * The same format as above but appended with `-dirty` if you have local changes that haven’t been committed yet, for example: `v2.0.0-5-g617d6d0-dirty` + +* CLI: cf `hw version` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1017)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Request Packet: None + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1017)" ++16: "STATUS" ++16: "LEN (=N)" ++8: "LRC2" ++48: "git describe version, N bytes, 1 <= N <= 4096" ++8: "LRC3" +``` + +* DATA in Response Packet + * git describe version: `N bytes`, a UTF-8 encoded string, no null terminator. \ No newline at end of file diff --git a/protocol/1018.md b/protocol/1018.md new file mode 100644 index 0000000..bcd5865 --- /dev/null +++ b/protocol/1018.md @@ -0,0 +1,43 @@ +# 1018: GET_ACTIVE_SLOT + +Get active slot number. + +* CLI: cf `hw slot list` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1018)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Request Packet: None + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1018)" ++16: "STATUS" ++16: "LEN (=1)" ++8: "LRC2" ++8: "current active slot" ++8: "LRC3" +``` + +* DATA in Response Packet + * current active slot: `1 byte`, between `0` and `7`. \ No newline at end of file diff --git a/protocol/1019.md b/protocol/1019.md new file mode 100644 index 0000000..2450ad7 --- /dev/null +++ b/protocol/1019.md @@ -0,0 +1,58 @@ +# 1019: GET_SLOT_INFO + +Get information about specific slot. + +* CLI: cf `hw slot list` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1019)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Request Packet: None + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1019)" ++16: "STATUS" ++16: "LEN (=32)" ++8: "LRC2" ++16: "tag type of Slot 1 HF" ++16: "tag type of Slot 1 LF" ++16: "tag type of Slot 2 HF" ++16: "tag type of Slot 2 LF" ++16: "tag type of Slot 3 HF" ++16: "tag type of Slot 3 LF" ++16: "tag type of Slot 4 HF" ++16: "tag type of Slot 4 LF" ++16: "tag type of Slot 5 HF" ++16: "tag type of Slot 5 LF" ++16: "tag type of Slot 6 HF" ++16: "tag type of Slot 6 LF" ++16: "tag type of Slot 7 HF" ++16: "tag type of Slot 7 LF" ++16: "tag type of Slot 8 HF" ++16: "tag type of Slot 8 LF" ++8: "LRC3" +``` + +* DATA in Response Packet + * tag type: `2 bytes`, U16 in network byte order, according to `tag_specific_type_t` enum. \ No newline at end of file diff --git a/protocol/1020.md b/protocol/1020.md new file mode 100644 index 0000000..9fa0aed --- /dev/null +++ b/protocol/1020.md @@ -0,0 +1,46 @@ +# 1020: WIPE_FDS + +Device factory reset. + +The device will reboot shortly after this command. + +* CLI: cf `hw factory_reset` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1020)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Request Packet: None + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1020)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* STATUS in Response Packet + * `STATUS_SUCCESS`: Success + * `STATUS_FLASH_WRITE_FAIL`: Fail +* DATA in Response Packet: None \ No newline at end of file diff --git a/protocol/1021.md b/protocol/1021.md new file mode 100644 index 0000000..32bdb61 --- /dev/null +++ b/protocol/1021.md @@ -0,0 +1,45 @@ +# 1021: DELETE_SLOT_TAG_NICK + +Delete nickname of specific slot HF/LF. + +* CLI: cf `hw slot nick` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1021)" ++16: "STATUS" ++16: "LEN (=2)" ++8: "LRC2" ++8: "slot number" ++8: "sense type" ++8: "LRC3" +``` + +* DATA in Request Packet + * slot number: `1 byte`, between `0` and `7`. + * sense type: `1 byte`, according to `tag_sense_type_t` enum. + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1021)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Response Packet: None \ No newline at end of file diff --git a/protocol/1023.md b/protocol/1023.md new file mode 100644 index 0000000..777a970 --- /dev/null +++ b/protocol/1023.md @@ -0,0 +1,59 @@ +# 1023: GET_ENABLED_SLOTS + +Get enabled/disabled of all slots HF/LF. + +* CLI: cf `hw slot list` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1023)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Request Packet: None + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1023)" ++16: "STATUS" ++16: "LEN (=16)" ++8: "LRC2" ++8: "slot 1 HF isEnabled" ++8: "slot 1 LF isEnabled" ++8: "slot 2 HF isEnabled" ++8: "slot 2 LF isEnabled" ++8: "slot 3 HF isEnabled" ++8: "slot 3 LF isEnabled" ++8: "slot 4 HF isEnabled" ++8: "slot 4 LF isEnabled" ++8: "slot 5 HF isEnabled" ++8: "slot 5 LF isEnabled" ++8: "slot 6 HF isEnabled" ++8: "slot 6 LF isEnabled" ++8: "slot 7 HF isEnabled" ++8: "slot 7 LF isEnabled" ++8: "slot 8 HF isEnabled" ++8: "slot 8 LF isEnabled" ++8: "LRC3" +``` + +* DATA in Response Packet + * slot ? HF isEnabled: `1 byte`, `0`=disabled, `1`=enabled + * slot ? LF isEnabled: `1 byte`, `0`=disabled, `1`=enabled \ No newline at end of file diff --git a/protocol/1024.md b/protocol/1024.md new file mode 100644 index 0000000..99147fe --- /dev/null +++ b/protocol/1024.md @@ -0,0 +1,45 @@ +# 1024: DELETE_SLOT_SENSE_TYPE + +Delete data of specific slot HF/LF. + +* CLI: cf `hw slot delete` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1024)" ++16: "STATUS" ++16: "LEN (=2)" ++8: "LRC2" ++8: "slot number" ++8: "sense type" ++8: "LRC3" +``` + +* DATA in Request Packet + * slot number: `1 byte`, between `0` and `7`. + * sense type: `1 byte`, according to `tag_sense_type_t` enum. + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1024)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Response Packet: None \ No newline at end of file diff --git a/protocol/1025.md b/protocol/1025.md new file mode 100644 index 0000000..bacde60 --- /dev/null +++ b/protocol/1025.md @@ -0,0 +1,48 @@ +# 1025: GET_BATTERY_INFO + +Get battery voltage and level. + +> [!NOTE] +> Please wait about 5 seconds after the device wakes up before executing this command; otherwise, the command may not correctly measure the device's battery and will return `0`. + +* CLI: cf `hw battery` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1025)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Request Packet: None + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1025)" ++16: "STATUS" ++16: "LEN (=3)" ++8: "LRC2" ++16: "battery voltage (mV)" ++8: "battery level" ++8: "LRC3" +``` + +* DATA in Response Packet + * battery voltage: `2 bytes`, U16 in network byte order. Unit: `mV`. + * battery level: `1 byte`, between `0` and `100`. \ No newline at end of file diff --git a/protocol/1026.md b/protocol/1026.md new file mode 100644 index 0000000..649fd0b --- /dev/null +++ b/protocol/1026.md @@ -0,0 +1,45 @@ +# 1026: GET_BUTTON_PRESS_CONFIG + +Get button press function of specific button. + +* CLI: cf `hw settings btnpress` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1026)" ++16: "STATUS" ++16: "LEN (=1)" ++8: "LRC2" ++8: "button" ++8: "LRC3" +``` + +* DATA in Request Packet + * button: `1 byte`, Char `'A'`/`'a'`: Button A, Char `'B'`/`'b'`: Button B. + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1026)" ++16: "STATUS" ++16: "LEN (=1)" ++8: "LRC2" ++8: "button function" ++8: "LRC3" +``` + +* DATA in Response Packet + * button function: `1 byte`, according to `settings_button_function_t` enum. \ No newline at end of file diff --git a/protocol/1027.md b/protocol/1027.md new file mode 100644 index 0000000..3c2669f --- /dev/null +++ b/protocol/1027.md @@ -0,0 +1,45 @@ +# 1027: SET_BUTTON_PRESS_CONFIG + +Set button press function of specific button. + +* CLI: cf `hw settings btnpress` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1027)" ++16: "STATUS" ++16: "LEN (=2)" ++8: "LRC2" ++8: "button" ++8: "button function" ++8: "LRC3" +``` + +* DATA in Request Packet + * button: `1 byte`, Char `'A'`/`'a'`: Button A, Char `'B'`/`'b'`: Button B. + * button function: `1 byte`, according to `settings_button_function_t` enum. + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1027)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Response Packet: None \ No newline at end of file diff --git a/protocol/1028.md b/protocol/1028.md new file mode 100644 index 0000000..5d73baa --- /dev/null +++ b/protocol/1028.md @@ -0,0 +1,45 @@ +# 1028: GET_LONG_BUTTON_PRESS_CONFIG + +Get button long press function of specific button. + +* CLI: cf `hw settings btnpress` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1028)" ++16: "STATUS" ++16: "LEN (=1)" ++8: "LRC2" ++8: "button" ++8: "LRC3" +``` + +* DATA in Request Packet + * button: `1 byte`, Char `'A'`/`'a'`: Button A, Char `'B'`/`'b'`: Button B. + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1028)" ++16: "STATUS" ++16: "LEN (=1)" ++8: "LRC2" ++8: "button function" ++8: "LRC3" +``` + +* DATA in Response Packet + * button function: `1 byte`, according to `settings_button_function_t` enum. \ No newline at end of file diff --git a/protocol/1029.md b/protocol/1029.md new file mode 100644 index 0000000..6d23e68 --- /dev/null +++ b/protocol/1029.md @@ -0,0 +1,45 @@ +# 1029: SET_LONG_BUTTON_PRESS_CONFIG + +Set button long press function of specific button. + +* CLI: cf `hw settings btnpress` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1029)" ++16: "STATUS" ++16: "LEN (=2)" ++8: "LRC2" ++8: "button" ++8: "button function" ++8: "LRC3" +``` + +* DATA in Request Packet + * button: `1 byte`, Char `'A'`/`'a'`: Button A, Char `'B'`/`'b'`: Button B. + * button function: `1 byte`, according to `settings_button_function_t` enum. + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1029)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Response Packet: None \ No newline at end of file diff --git a/protocol/1030.md b/protocol/1030.md new file mode 100644 index 0000000..203feea --- /dev/null +++ b/protocol/1030.md @@ -0,0 +1,43 @@ +# 1030: SET_BLE_PAIRING_KEY + +Set BLE pairing key. + +* CLI: cf `hw settings blekey` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1030)" ++16: "STATUS" ++16: "LEN (=6)" ++8: "LRC2" ++48: "BLE pairing key" ++8: "LRC3" +``` + +* DATA in Request Packet + * BLE pairing key: `6 bytes`, ASCII-encoded digits. + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1030)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Response Packet: None \ No newline at end of file diff --git a/protocol/1031.md b/protocol/1031.md new file mode 100644 index 0000000..e4bd046 --- /dev/null +++ b/protocol/1031.md @@ -0,0 +1,43 @@ +# 1031: GET_BLE_PAIRING_KEY + +Get BLE pairing key. + +* CLI: cf `hw settings blekey` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1031)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Request Packet: None + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1031)" ++16: "STATUS" ++16: "LEN (=6)" ++8: "LRC2" ++48: "BLE pairing key" ++8: "LRC3" +``` + +* DATA in Request Packet + * BLE pairing key: `6 bytes`, ASCII-encoded digits. \ No newline at end of file diff --git a/protocol/1032.md b/protocol/1032.md new file mode 100644 index 0000000..a754f38 --- /dev/null +++ b/protocol/1032.md @@ -0,0 +1,41 @@ +# 1032: DELETE_ALL_BLE_BONDS + +Delete all BLE bonded devices. + +* CLI: cf `hw settings bleclearbonds` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1032)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Request Packet: None + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1032)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Response Packet: None \ No newline at end of file diff --git a/protocol/1033.md b/protocol/1033.md new file mode 100644 index 0000000..edd91d8 --- /dev/null +++ b/protocol/1033.md @@ -0,0 +1,43 @@ +# 1033: GET_DEVICE_MODEL + +Get device type (Ultra/Lite). + +* CLI: cf `hw version` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1033)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Request Packet: None + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1033)" ++16: "STATUS" ++16: "LEN (=1)" ++8: "LRC2" ++8: "device type" ++8: "LRC3" +``` + +* DATA in Response Packet + * device type: `1 byte`, according to `chameleon_device_type_t` enum (`0`=Ultra, `1`=Lite) \ No newline at end of file diff --git a/protocol/1034.md b/protocol/1034.md new file mode 100644 index 0000000..e293007 --- /dev/null +++ b/protocol/1034.md @@ -0,0 +1,55 @@ +# 1034: GET_DEVICE_SETTINGS + +Get device settings. + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1034)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Request Packet: None + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1034)" ++16: "STATUS" ++16: "LEN (=13)" ++8: "LRC2" ++8: "setting version" ++8: "animation mode" ++8: "button A function" ++8: "button B function" ++8: "button A long press function" ++8: "button B long press function" ++8: "ble pairing isEnabled" ++48: "ble pairing key" ++8: "LRC3" +``` + +* DATA in Response Packet + * setting version: latest version is `5` + * animation mode: `1 byte`, according to `animation_mode_t` enum + * button A function: `1 byte`, according to `button_function_t` enum + * button B function: `1 byte`, according to `button_function_t` enum + * button A long press function: `1 byte`, according to `button_function_t` enum + * button B long press function: `1 byte`, according to `button_function_t` enum + * ble pairing isEnabled: `1 byte`, `0`=disabled, `1`=enabled + * ble pairing key: `6 bytes`, ASCII-encoded digits. \ No newline at end of file diff --git a/protocol/1035.md b/protocol/1035.md new file mode 100644 index 0000000..763608c --- /dev/null +++ b/protocol/1035.md @@ -0,0 +1,41 @@ +# 1035: GET_DEVICE_CAPABILITIES + +Get supported command IDs. + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1035)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Request Packet: None + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1035)" ++16: "STATUS" ++16: "LEN (=N*2)" ++8: "LRC2" ++16: "supported commands (variable length)" ++8: "LRC3" +``` + +* DATA in Response Packet + * supported commands: `N*2 bytes` in network byte order, a list of supported commands IDs. \ No newline at end of file diff --git a/protocol/1036.md b/protocol/1036.md new file mode 100644 index 0000000..4cbc7f0 --- /dev/null +++ b/protocol/1036.md @@ -0,0 +1,43 @@ +# 1036: GET_BLE_PAIRING_ENABLE + +Get BLE pairing is enabled or not. + +* CLI: cf `hw settings blepair` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1036)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Request Packet: None + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1036)" ++16: "STATUS" ++16: "LEN (=1)" ++8: "LRC2" ++8: "ble pairing isEnabled" ++8: "LRC3" +``` + +* DATA in Response Packet + * ble pairing isEnabled: `1 byte`, `0`=disabled, `1`=enabled \ No newline at end of file diff --git a/protocol/1037.md b/protocol/1037.md new file mode 100644 index 0000000..a2099d0 --- /dev/null +++ b/protocol/1037.md @@ -0,0 +1,43 @@ +# 1037: SET_BLE_PAIRING_ENABLE + +Enable/disable BLE pairing. + +* CLI: cf `hw settings blepair` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1037)" ++16: "STATUS" ++16: "LEN (=1)" ++8: "LRC2" ++8: "ble pairing isEnabled" ++8: "LRC3" +``` + +* DATA in Request Packet + * ble pairing isEnabled: `1 byte`, `0`=disabled, `1`=enabled + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1037)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Response Packet: None \ No newline at end of file diff --git a/protocol/1038.md b/protocol/1038.md new file mode 100644 index 0000000..2f00304 --- /dev/null +++ b/protocol/1038.md @@ -0,0 +1,76 @@ +# 1038: GET_ALL_SLOT_NICKS + +Get nickname of all slots HF/LF. + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1038)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Request Packet: None + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=1038)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "len_hf_0" ++24: "name_hf_0 (len_hf_0 bytes)" ++8: "len_lf_0" ++24: "name_lf_0 (len_lf_0 bytes)" ++8: "len_hf_1" ++24: "name_hf_1 (len_hf_1 bytes)" ++8: "len_lf_1" ++24: "name_lf_1 (len_lf_1 bytes)" ++8: "len_hf_2" ++24: "name_hf_2 (len_hf_2 bytes)" ++8: "len_lf_2" ++24: "name_lf_2 (len_lf_2 bytes)" ++8: "len_hf_3" ++24: "name_hf_3 (len_hf_3 bytes)" ++8: "len_lf_3" ++24: "name_lf_3 (len_lf_3 bytes)" ++8: "len_hf_4" ++24: "name_hf_4 (len_hf_4 bytes)" ++8: "len_lf_4" ++24: "name_lf_4 (len_lf_4 bytes)" ++8: "len_hf_5" ++24: "name_hf_5 (len_hf_5 bytes)" ++8: "len_lf_5" ++24: "name_lf_5 (len_lf_5 bytes)" ++8: "len_hf_6" ++24: "name_hf_6 (len_hf_6 bytes)" ++8: "len_lf_6" ++24: "name_lf_6 (len_lf_6 bytes)" ++8: "len_hf_7" ++24: "name_hf_7 (len_hf_7 bytes)" ++8: "len_lf_7" ++24: "name_lf_7 (len_lf_7 bytes)" ++8: "LRC3" +``` + +* DATA in Response Packet + * For each slot (0-7): + * len_hf_X: `1 byte`, length of HF nickname of slot X + * name_hf_X: `len_hf_X bytes`, HF nickname of slot X (UTF-8) + * len_lf_X: `1 byte`, length of LF nickname of slot X + * name_lf_X: `len_lf_X bytes`, LF nickname of slot X (UTF-8) \ No newline at end of file diff --git a/protocol/2000.md b/protocol/2000.md new file mode 100644 index 0000000..a65d342 --- /dev/null +++ b/protocol/2000.md @@ -0,0 +1,59 @@ +# 2000: HF14A_SCAN + +Scan UID, ATQA, SAK, ATS of 14443-3 (Type A) tags. + +> [!NOTE] +> * remind that if no tag is present, status will be `STATUS_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. + +* CLI: cf `hf 14a scan` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=2000)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Request Packet: None + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=2000)" ++16: "STATUS" ++16: "LEN" ++8: "LRC2" ++8: "TAG1: LEN of UID" ++32: "TAG1: UID (variable length)" ++16: "TAG1: ATQA" ++8: "TAG1: SAK" ++8: "TAG1: LEN of ATS" ++16: "TAG1: ATS (variable length)" ++88: "TAGS... (same format as TAG1)" ++8: "LRC3" +``` + +* DATA in Response Packet + * LEN of UID: `1 byte`, length of tag UID + * UID: `N bytes`, tag UID + * ATQA: `2 bytes`, tag ATQA + * SAK: `1 byte`, tag SAK + * LEN of ATS: `1 byte`, length of tag ATS + * ATS: `N bytes`, tag ATS \ No newline at end of file diff --git a/protocol/2001.md b/protocol/2001.md new file mode 100644 index 0000000..b726c24 --- /dev/null +++ b/protocol/2001.md @@ -0,0 +1,43 @@ +# 2001: MF1_DETECT_SUPPORT + +Detect if tag support Mifare Classic AUTH command or not. + +* CLI: cf `hf 14a info` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=2001)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Request Packet: None + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=2001)" ++16: "STATUS" ++16: "LEN (=1)" ++8: "LRC2" ++8: "MF1 AUTH isSupported" ++8: "LRC3" +``` + +* DATA in Response Packet + * MF1 AUTH isSupported: `1 byte`, `0`=not supported, `1`=supported \ No newline at end of file diff --git a/protocol/2002.md b/protocol/2002.md new file mode 100644 index 0000000..4825b9e --- /dev/null +++ b/protocol/2002.md @@ -0,0 +1,43 @@ +# 2002: MF1_DETECT_PRNG + +Detect PRNG type of Mifare Classic tag. + +* CLI: cf `hf 14a info` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=2002)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Request Packet: None + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=2002)" ++16: "STATUS" ++16: "LEN (=1)" ++8: "LRC2" ++8: "prng type" ++8: "LRC3" +``` + +* DATA in Response Packet + * prng type: `1 byte`, according to `mf1_prng_type_t` enum \ No newline at end of file diff --git a/protocol/2003.md b/protocol/2003.md new file mode 100644 index 0000000..96ef7a4 --- /dev/null +++ b/protocol/2003.md @@ -0,0 +1,59 @@ +# 2003: MF1_STATIC_NESTED_ACQUIRE + +Acquire necessary data from Mifare Classic tag for static nested attack. + +* CLI: cf `hf mf nested` on static nonce tag + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=2003)" ++16: "STATUS" ++16: "LEN (=10)" ++8: "LRC2" ++8: "known key type" ++8: "known key block" ++48: "known key" ++8: "target key type" ++8: "target key block" ++8: "LRC3" +``` + +* DATA in Request Packet + * known key type: `1 byte`, `0x60`=key A, `0x61`=key B. + * known key block: `1 byte`. + * known key: `6 bytes`, the known key. + * target key type: `1 byte`, `0x60`=key A, `0x61`=key B. + * target key block: `1 byte`. + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=2003)" ++16: "STATUS" ++16: "LEN (=20)" ++8: "LRC2" ++32: "UID" ++32: "nt of 1st attempt" ++32: "ntEnc of 1st attempt" ++32: "nt of 2nd attempt" ++32: "ntEnc of 2nd attempt" ++8: "LRC3" +``` + +* DATA in Response Packet + * UID: `4 bytes`, U32 in network byte order, the tag UID. + * nt: `4 bytes`, U32 in network byte order, the tag nonce in first AUTH. + * ntEnc: `4 bytes`, U32 in network byte order, the encrypted tag nonce in nested AUTH. \ No newline at end of file diff --git a/protocol/2004.md b/protocol/2004.md new file mode 100644 index 0000000..4717cd5 --- /dev/null +++ b/protocol/2004.md @@ -0,0 +1,78 @@ +# 2004: MF1_DARKSIDE_ACQUIRE + +Acquire necessary data from Mifare Classic tag for Darkside attack. + +* CLI: cf `hf mf darkside` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=2004)" ++16: "STATUS" ++16: "LEN (=4)" ++8: "LRC2" ++8: "target key type" ++8: "target key block" ++8: "is first attempt" ++8: "sync max" ++8: "LRC3" +``` + +* DATA in Request Packet + * target key type: `1 byte`, `0x60`=key A, `0x61`=key B. + * target key block: `1 byte`. + * is first attempt: `1 byte`, `0`=no, `1`=yes. + * sync max: `1 byte`, the maximum number of synchronization attempts. + +## Response Packet + +```mermaid +--- +title: "Response Packet (Success)" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=2004)" ++16: "STATUS" ++16: "LEN (=33)" ++8: "LRC2" ++8: "darkside status" ++32: "UID" ++32: "nt" ++64: "parity" ++64: "ks1" ++32: "nr" ++32: "ar" ++8: "LRC3" +``` + +```mermaid +--- +title: "Response Packet (Failed)" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=2004)" ++16: "STATUS" ++16: "LEN (=1)" ++8: "LRC2" ++8: "darkside status" ++8: "LRC3" +``` + +* DATA in Response Packet + * darkside status: `1 byte`, according to `mf1_darkside_status_t` enum. + * UID: `4 bytes`, U32 in network byte order, the tag UID. + * nt: `4 bytes`, U32 in network byte order, the tag nonce in AUTH. + * parity: `8 bytes`, U64 in network byte order, the parity bits in AUTH. + * ks1: `8 bytes`, U64 in network byte order, the keystream1 in AUTH. + * nr: `4 bytes`, U32 in network byte order, the reader encrypted nonce in AUTH. + * ar: `4 bytes`, U32 in network byte order, the reader encrypted answer in AUTH. \ No newline at end of file diff --git a/protocol/2005.md b/protocol/2005.md new file mode 100644 index 0000000..b57e33b --- /dev/null +++ b/protocol/2005.md @@ -0,0 +1,51 @@ +# 2005: MF1_DETECT_NT_DIST + +Detect tag nonce distance of Mifare Classic tag. + +* CLI: cf `hf mf nested` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=2005)" ++16: "STATUS" ++16: "LEN (=8)" ++8: "LRC2" ++8: "known key type" ++8: "known key block" ++48: "known key" ++8: "LRC3" +``` + +* DATA in Request Packet + * known key type: `1 byte`, `0x60`=key A, `0x61`=key B. + * known key block: `1 byte`. + * known key: `6 bytes`, the known key. + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=2005)" ++16: "STATUS" ++16: "LEN (=8)" ++8: "LRC2" ++32: "UID" ++32: "prng distance" ++8: "LRC3" +``` + +* DATA in Response Packet + * UID: `4 bytes`, U32 in network byte order, the tag UID. + * prng distance: `4 bytes`, U32 in network byte order, the PRNG distance. \ No newline at end of file diff --git a/protocol/2006.md b/protocol/2006.md new file mode 100644 index 0000000..edc04ee --- /dev/null +++ b/protocol/2006.md @@ -0,0 +1,60 @@ +# 2006: MF1_NESTED_ACQUIRE + +Acquire necessary data from Mifare Classic tag for nested attack. + +* CLI: cf `hf mf nested` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=2006)" ++16: "STATUS" ++16: "LEN (=10)" ++8: "LRC2" ++8: "known key type" ++8: "known key block" ++48: "known key" ++8: "target key type" ++8: "target key block" ++8: "LRC3" +``` + +* DATA in Request Packet + * known key type: `1 byte`, `0x60`=key A, `0x61`=key B. + * known key block: `1 byte`. + * known key: `6 bytes`, the known key. + * target key type: `1 byte`, `0x60`=key A, `0x61`=key B. + * target key block: `1 byte`. + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=2006)" ++16: "STATUS" ++16: "LEN (=18)" ++8: "LRC2" ++32: "nt of 1st attempt" ++32: "ntEnc of 1st attempt" ++8: "parity of 1st attempt" ++32: "nt of 2nd attempt" ++32: "ntEnc of 2nd attempt" ++8: "parity of 2nd attempt" ++8: "LRC3" +``` + +* DATA in Response Packet + * nt: `4 bytes`, U32 in network byte order, the tag nonce in first AUTH. + * ntEnc: `4 bytes`, U32 in network byte order, the encrypted tag nonce in nested AUTH. + * parity: `1 byte`, the parity bits in nested AUTH. \ No newline at end of file diff --git a/protocol/2007.md b/protocol/2007.md new file mode 100644 index 0000000..6b9f600 --- /dev/null +++ b/protocol/2007.md @@ -0,0 +1,50 @@ +# 2007: MF1_AUTH_ONE_KEY_BLOCK + +AUTH specific block and key type of Mifare Classic tag. + +* CLI: cf `hf mf nested` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=2007)" ++16: "STATUS" ++16: "LEN (=8)" ++8: "LRC2" ++8: "known key type" ++8: "known key block" ++48: "known key" ++8: "LRC3" +``` + +* DATA in Request Packet + * known key type: `1 byte`, `0x60`=key A, `0x61`=key B. + * known key block: `1 byte`. + * known key: `6 bytes`, the known key. + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=2007)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* STATUS in Response Packet + * `STATUS_HF_TAG_OK`: auth succeeded + * otherwise: according to `app_status.h` +* DATA in Response Packet: None \ No newline at end of file diff --git a/protocol/2008.md b/protocol/2008.md new file mode 100644 index 0000000..b65228c --- /dev/null +++ b/protocol/2008.md @@ -0,0 +1,49 @@ +# 2008: MF1_READ_ONE_BLOCK + +Read specific block of Mifare Classic tag. + +* CLI: cf `hf mf rdbl` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=2008)" ++16: "STATUS" ++16: "LEN (=8)" ++8: "LRC2" ++8: "known key type" ++8: "known key block" ++48: "known key" ++8: "LRC3" +``` + +* DATA in Request Packet + * known key type: `1 byte`, `0x60`=key A, `0x61`=key B. + * known key block: `1 byte`. + * known key: `6 bytes`, the known key. + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=2008)" ++16: "STATUS" ++16: "LEN (=16)" ++8: "LRC2" ++128: "block data" ++8: "LRC3" +``` + +* DATA in Response Packet + * block data: `16 bytes`, the block data read from the tag. \ No newline at end of file diff --git a/protocol/2009.md b/protocol/2009.md new file mode 100644 index 0000000..0b16a66 --- /dev/null +++ b/protocol/2009.md @@ -0,0 +1,49 @@ +# 2009: MF1_WRITE_ONE_BLOCK + +Write specific block of Mifare Classic tag. + +* CLI: cf `hf mf wrbl` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=2009)" ++16: "STATUS" ++16: "LEN (=24)" ++8: "LRC2" ++8: "known key type" ++8: "known key block" ++48: "known key" ++128: "block data" ++8: "LRC3" +``` + +* DATA in Request Packet + * known key type: `1 byte`, `0x60`=key A, `0x61`=key B. + * known key block: `1 byte`. + * known key: `6 bytes`, the known key. + * block data: `16 bytes`, the block data to be written to the tag. + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=2009)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Response Packet: None \ No newline at end of file diff --git a/protocol/2010.md b/protocol/2010.md new file mode 100644 index 0000000..6eafa2b --- /dev/null +++ b/protocol/2010.md @@ -0,0 +1,62 @@ +# 2010: HF14A_RAW + +Send raw 14443-3 (Type A) commands with options. + +* CLI: cf `hf 14a raw` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=2010)" ++16: "STATUS" ++16: "LEN (=5+N)" ++8: "LRC2" ++1: "activate_rf_field" ++1: "wait_response" ++1: "append_crc" ++1: "auto_select" ++1: "keep_rf_field" ++1: "check_response_crc" ++2: "RFU" ++16: "resp_timeout_ms" ++16: "bitlen" ++16: "raw data (N bytes, 1 <= N)" ++8: "LRC3" +``` + +* DATA in Request Packet + * activate_rf_field: `1 bit`, whether to activate the RF field before sending the raw data. + * wait_response: `1 bit`, whether to wait for a response from the tag after sending the raw data. + * append_crc: `1 bit`, whether to append a CRC to the raw data before sending it. + * auto_select: `1 bit`, whether to automatically select tag before sending the raw data. + * keep_rf_field: `1 bit`, whether to keep the RF field active after sending the raw data. + * check_response_crc: `1 bit`, whether to check the CRC of the response from the tag. + * resp_timeout_ms: `2 bytes`, U16 in network byte order, the timeout in milliseconds to wait for a response from the tag. + * bitlen: `2 bytes`, U16 in network byte order, the length of the raw data to send in bits. + * raw data: `N bytes, 1 <= N`, the raw data to send to the tag. If `bitlen` is not a multiple of 8, the last byte should be padded with zeros in the least significant bits. + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=2010)" ++16: "STATUS" ++16: "LEN (=N)" ++8: "LRC2" ++16: "raw data (N bytes, 0 <= N)" ++8: "LRC3" +``` + +* DATA in Response Packet: data sent by the card + * raw data: `N bytes, 0 <= N`, the raw data received from the tag. If no response is received, N will be 0. If bit length of raw data is not a multiple of 8, the last byte will be padded with zeros in the least significant bits. \ No newline at end of file diff --git a/protocol/2011.md b/protocol/2011.md new file mode 100644 index 0000000..20f9010 --- /dev/null +++ b/protocol/2011.md @@ -0,0 +1,57 @@ +# 2011: MF1_MANIPULATE_VALUE_BLOCK + +Manipulate value block of Mifare Classic tag. + +* CLI: cf `hf mf value` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=2011)" ++16: "STATUS" ++16: "LEN (=21)" ++8: "LRC2" ++8: "src_type" ++8: "src_block" ++48: "src_key" ++8: "operator" ++32: "operand" ++8: "dst_type" ++8: "dst_block" ++48: "dst_key" ++8: "LRC3" +``` + +* DATA in Request Packet + * src_type: `1 byte`, key type of source block. `0x60` for key A, `0x61` for key B. + * src_block: `1 byte`, block number of source block. + * src_key: `6 bytes`, key for source. + * operator: `1 byte`, operation to perform. `0xC0` for decrement, `0xC1` for increment, `0xC2` for restore. + * operand: `4 bytes`, I32 in network byte order. Value to increment/decrement by. Ignored for restore. + * dst_type: `1 byte`, key type of destination block. `0x60` for key A, `0x61` for key B. + * dst_block: `1 byte`, block number of destination block. + * dst_key: `6 bytes`, key for destination. + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=2011)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Response Packet: None \ No newline at end of file diff --git a/protocol/2012.md b/protocol/2012.md new file mode 100644 index 0000000..e8c6bb1 --- /dev/null +++ b/protocol/2012.md @@ -0,0 +1,211 @@ +# 2012: MF1_CHECK_KEYS_OF_SECTORS + +Check keys on sectors of Mifare Classic tag in batch. + +* CLI: cf `hf mf fchk` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=2012)" ++16: "STATUS" ++16: "LEN (=10+N*6)" ++8: "LRC2" ++1: "mask 0A" ++1: "mask 0B" ++1: "mask 1A" ++1: "mask 1B" ++1: "mask 2A" ++1: "mask 2B" ++1: "mask 3A" ++1: "mask 3B" ++1: "mask 4A" ++1: "mask 4B" ++1: "mask 5A" ++1: "mask 5B" ++1: "mask 6A" ++1: "mask 6B" ++1: "mask 7A" ++1: "mask 7B" ++1: "mask 8A" ++1: "mask 8B" ++1: "mask 9A" ++1: "mask 9B" ++1: "mask 10A" ++1: "mask 10B" ++1: "mask 11A" ++1: "mask 11B" ++1: "mask 12A" ++1: "mask 12B" ++1: "mask 13A" ++1: "mask 13B" ++1: "mask 14A" ++1: "mask 14B" ++1: "mask 15A" ++1: "mask 15B" ++1: "mask 16A" ++1: "mask 16B" ++1: "mask 17A" ++1: "mask 17B" ++1: "mask 18A" ++1: "mask 18B" ++1: "mask 19A" ++1: "mask 19B" ++1: "mask 20A" ++1: "mask 20B" ++1: "mask 21A" ++1: "mask 21B" ++1: "mask 22A" ++1: "mask 22B" ++1: "mask 23A" ++1: "mask 23B" ++1: "mask 24A" ++1: "mask 24B" ++1: "mask 25A" ++1: "mask 25B" ++1: "mask 26A" ++1: "mask 26B" ++1: "mask 27A" ++1: "mask 27B" ++1: "mask 28A" ++1: "mask 28B" ++1: "mask 29A" ++1: "mask 29B" ++1: "mask 30A" ++1: "mask 30B" ++1: "mask 31A" ++1: "mask 31B" ++1: "mask 32A" ++1: "mask 32B" ++1: "mask 33A" ++1: "mask 33B" ++1: "mask 34A" ++1: "mask 34B" ++1: "mask 35A" ++1: "mask 35B" ++1: "mask 36A" ++1: "mask 36B" ++1: "mask 37A" ++1: "mask 37B" ++1: "mask 38A" ++1: "mask 38B" ++1: "mask 39A" ++1: "mask 39B" ++48: "key 1...N (N*6 bytes, 1<=N<=83)" ++8: "LRC3" +``` + +* DATA in Request Packet + * mask ?A/?B: `1 bit`, `0b1` represent to skip checking specific block and specific key type. + * key 1...N: `6 bytes/key`, keys to be check. + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=2012)" ++16: "STATUS" ++16: "LEN (=490)" ++8: "LRC2" ++1: "found 0A" ++1: "found 0B" ++1: "found 1A" ++1: "found 1B" ++1: "found 2A" ++1: "found 2B" ++1: "found 3A" ++1: "found 3B" ++1: "found 4A" ++1: "found 4B" ++1: "found 5A" ++1: "found 5B" ++1: "found 6A" ++1: "found 6B" ++1: "found 7A" ++1: "found 7B" ++1: "found 8A" ++1: "found 8B" ++1: "found 9A" ++1: "found 9B" ++1: "found 10A" ++1: "found 10B" ++1: "found 11A" ++1: "found 11B" ++1: "found 12A" ++1: "found 12B" ++1: "found 13A" ++1: "found 13B" ++1: "found 14A" ++1: "found 14B" ++1: "found 15A" ++1: "found 15B" ++1: "found 16A" ++1: "found 16B" ++1: "found 17A" ++1: "found 17B" ++1: "found 18A" ++1: "found 18B" ++1: "found 19A" ++1: "found 19B" ++1: "found 20A" ++1: "found 20B" ++1: "found 21A" ++1: "found 21B" ++1: "found 22A" ++1: "found 22B" ++1: "found 23A" ++1: "found 23B" ++1: "found 24A" ++1: "found 24B" ++1: "found 25A" ++1: "found 25B" ++1: "found 26A" ++1: "found 26B" ++1: "found 27A" ++1: "found 27B" ++1: "found 28A" ++1: "found 28B" ++1: "found 29A" ++1: "found 29B" ++1: "found 30A" ++1: "found 30B" ++1: "found 31A" ++1: "found 31B" ++1: "found 32A" ++1: "found 32B" ++1: "found 33A" ++1: "found 33B" ++1: "found 34A" ++1: "found 34B" ++1: "found 35A" ++1: "found 35B" ++1: "found 36A" ++1: "found 36B" ++1: "found 37A" ++1: "found 37B" ++1: "found 38A" ++1: "found 38B" ++1: "found 39A" ++1: "found 39B" ++48: "key 0A" ++48: "key 0B" ++96: "..." ++48: "key 39A" ++48: "key 39B" ++8: "LRC3" +``` + +* DATA in Response Packet + * found ?A/?B: `1 bit`, `0b1` represent the key is found for specific block and specific key type. + * key ?A/?B: `6 bytes`, key for the specific block and specific key type. If the key is not found, the key will be fill with `0x000000000000`. \ No newline at end of file diff --git a/protocol/2013.md b/protocol/2013.md new file mode 100644 index 0000000..c9fc510 --- /dev/null +++ b/protocol/2013.md @@ -0,0 +1,66 @@ +# 2013: MF1_HARDNESTED_ACQUIRE + +Acquire necessary data from Mifare Classic tag for hardnested attack. + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=2013)" ++16: "STATUS" ++16: "LEN (=24)" ++8: "LRC2" ++8: "slow" ++8: "known_key_type" ++8: "known_key_block" ++48: "known_key" ++8: "target_key_type" ++8: "target_key_block" ++8: "LRC3" +``` + +* DATA in Request Packet + * slow: `1 byte`, `0x00`=normal speed, `0x01`=slow speed (for hardnested acquisition). + * known_key_type: `1 byte`, `0x60`=key A, `0x61`=key B. + * known_key_block: `1 byte`. + * known_key: `6 bytes`, the known key. + * target_key_type: `1 byte`, `0x60`=key A, `0x61`=key B. + * target_key_block: `1 byte`. + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=2013)" ++16: "STATUS" ++16: "LEN (=N*9)" ++8: "LRC2" ++32: "nt" ++32: "ntEnc" ++4: "RFU" ++1: "parity_0" ++1: "parity_1" ++1: "parity_2" ++1: "parity_3" ++72: "repeat N-1 times" ++8: "LRC3" +``` + +* DATA in Response Packet + * repeat N times: + * nt: `4 bytes`, tag nonce of nested authentication. + * ntEnc: `4 bytes`, encrypted tag nonce of nested authentication. + * parity_0: `1 bit`, parity bit of first byte of ntEnc. + * parity_1: `1 bit`, parity bit of second byte of ntEnc. + * parity_2: `1 bit`, parity bit of third byte of ntEnc. + * parity_3: `1 bit`, parity bit of fourth byte of ntEnc. \ No newline at end of file diff --git a/protocol/2014.md b/protocol/2014.md new file mode 100644 index 0000000..384c417 --- /dev/null +++ b/protocol/2014.md @@ -0,0 +1,75 @@ +# 2014: MF1_ENC_NESTED_ACQUIRE + +Acquire necessary data from Mifare Classic tag for encrypted nested attack. + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=2014)" ++16: "STATUS" ++16: "LEN (=8)" ++8: "LRC2" ++48: "known_key" ++8: "max_sector" ++8: "start_sector" ++8: "LRC3" +``` + +* DATA in Request Packet + * known_key: `6 bytes`, the known key. + * max_sector: `1 byte`, the maximum sector number to acquire. + * start_sector: `1 byte`, the start sector number to acquire. + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=2014)" ++16: "STATUS" ++16: "LEN (=4+N*18)" ++8: "LRC2" ++32: "UID" ++32: "a_nt" ++32: "a_ntEnc" ++4: "RFU" ++1: "a_parity_0" ++1: "a_parity_1" ++1: "a_parity_2" ++1: "a_parity_3" ++32: "b_nt" ++32: "b_ntEnc" ++4: "RFU" ++1: "b_parity_0" ++1: "b_parity_1" ++1: "b_parity_2" ++1: "b_parity_3" ++144: "repeat N-1 times" ++8: "LRC3" +``` + +* DATA in Response Packet + * UID: `4 bytes`, the UID of the tag. + * repeat N times: + * a_nt: `4 bytes`, tag nonce of nested authentication. + * a_ntEnc: `4 bytes`, encrypted tag nonce of nested authentication. + * a_parity_0: `1 bit`, parity bit of first byte of ntEnc. + * a_parity_1: `1 bit`, parity bit of second byte of ntEnc. + * a_parity_2: `1 bit`, parity bit of third byte of ntEnc. + * a_parity_3: `1 bit`, parity bit of fourth byte of ntEnc. + * b_nt: `4 bytes`, tag nonce of nested authentication. + * b_ntEnc: `4 bytes`, encrypted tag nonce of nested authentication. + * b_parity_0: `1 bit`, parity bit of first byte of ntEnc. + * b_parity_1: `1 bit`, parity bit of second byte of ntEnc. + * b_parity_2: `1 bit`, parity bit of third byte of ntEnc. + * b_parity_3: `1 bit`, parity bit of fourth byte of ntEnc. \ No newline at end of file diff --git a/protocol/2015.md b/protocol/2015.md new file mode 100644 index 0000000..e90993d --- /dev/null +++ b/protocol/2015.md @@ -0,0 +1,51 @@ +# 2015: MF1_CHECK_KEYS_ON_BLOCK + +Check keys on block of Mifare Classic tag in batch. + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=2015)" ++16: "STATUS" ++16: "LEN (=3+N*6)" ++8: "LRC2" ++8: "block" ++8: "key_type" ++8: "keys_count" ++48: "keys (N*6 bytes)" ++8: "LRC3" +``` + +* DATA in Request Packet + * block: `1 byte`, the block number to check. + * key_type: `1 byte`, the key type to check. `0x60`=key A, `0x61`=key B. + * keys_count: `1 byte`, the number of keys to check (N). + * keys: `N*6 bytes`, the keys to check. + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=2015)" ++16: "STATUS" ++16: "LEN (=7)" ++8: "LRC2" ++8: "found" ++48: "found_key" ++8: "LRC3" +``` + +* DATA in Response Packet + * found: `1 byte`, whether a key is found. `0x00`=not found, `0x01`=found. + * found_key: `6 bytes`, the found key. Valid only if `found`=`0x01`. \ No newline at end of file diff --git a/protocol/3000.md b/protocol/3000.md new file mode 100644 index 0000000..77cf232 --- /dev/null +++ b/protocol/3000.md @@ -0,0 +1,45 @@ +# 3000: EM410X_SCAN + +Scan ID of EM410x tags. + +* CLI: cf `lf em 410x read` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=3000)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Request Packet: None + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=3000)" ++16: "STATUS" ++16: "LEN (=7)" ++8: "LRC2" ++16: "tag_type" ++40: "scanned_id" ++8: "LRC3" +``` + +* DATA in Response Packet + * tag_type: 2 bytes. The type of the scanned tag. Please refer to `TagSpecificType` enum. + * scanned_id: 5 bytes. The EM410x tag ID be scanned. \ No newline at end of file diff --git a/protocol/3001.md b/protocol/3001.md new file mode 100644 index 0000000..2b0d083 --- /dev/null +++ b/protocol/3001.md @@ -0,0 +1,47 @@ +# 3001: EM410X_WRITE_TO_T55XX + +Write EM410x ID to T55xx tag. + +* CLI: cf `lf em 410x write` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=3001)" ++16: "STATUS" ++16: "LEN (=9+N*4)" ++8: "LRC2" ++40: "em410x_id" ++32: "new_key" ++32: "old_keys (N*4 bytes, N>=1)" ++8: "LRC3" +``` + +* DATA in Request Packet + * em410x_id: `5 bytes`, The EM410x tag ID to write to the T55xx tag. + * new_key: `4 bytes`, The new key to be written to the T55xx tag. The key will also be add to old keys list. + * old_keys: `N*4 bytes, N>=1`, The old keys to be used for authentication. + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=3001)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Response Packet: None \ No newline at end of file diff --git a/protocol/3002.md b/protocol/3002.md new file mode 100644 index 0000000..a885476 --- /dev/null +++ b/protocol/3002.md @@ -0,0 +1,51 @@ +# 3002: HIDPROX_SCAN + +Scan ID of HIDProx tags. + +* CLI: cf `lf hid prox read` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=3002)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Request Packet: None + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=3002)" ++16: "STATUS" ++16: "LEN (=13)" ++8: "LRC2" ++8: "format" ++32: "facility_code" ++40: "card_number" ++8: "issue_level" ++16: "oem" ++8: "LRC3" +``` + +* DATA in Response Packet + * format: `1 byte`, The format of the HID Prox card. + * facility_code: `4 bytes`, U32 in network byte order, The facility code of the HID Prox card. + * card_number: `5 bytes`, U40 in network byte order, The card number of the HID Prox card. + * issue_level: `1 byte`, The issue level of the HID Prox card. + * oem: `2 bytes`, The OEM code of the HID Prox card. \ No newline at end of file diff --git a/protocol/3003.md b/protocol/3003.md new file mode 100644 index 0000000..d80a2de --- /dev/null +++ b/protocol/3003.md @@ -0,0 +1,55 @@ +# 3003: HIDPROX_WRITE_TO_T55XX + +Write HIDProx ID to T55xx tag. + +* CLI: cf `lf hid prox write` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=3003)" ++16: "STATUS" ++16: "LEN (=17+N*4)" ++8: "LRC2" ++8: "format" ++32: "facility_code" ++40: "card_number" ++8: "issue_level" ++16: "oem" ++32: "new_key" ++32: "old_keys (N*4 bytes, N>=1)" ++8: "LRC3" +``` + +* DATA in Request Packet + * format: `1 byte`, The format of the HID Prox card. + * facility_code: `4 bytes`, U32 in network byte order, The facility code of the HID Prox card. + * card_number: `5 bytes`, U40 in network byte order, The card number of the HID Prox card. + * issue_level: `1 byte`, The issue level of the HID Prox card. + * oem: `2 bytes`, The OEM code of the HID Prox card. + * new_key: `4 bytes`, The new key to be written to the T55xx tag. The key will also be add to old keys list. + * old_keys: `N*4 bytes, N>=1`, The old keys to be used for authentication. + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=3003)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Response Packet: None \ No newline at end of file diff --git a/protocol/3004.md b/protocol/3004.md new file mode 100644 index 0000000..1c6e03c --- /dev/null +++ b/protocol/3004.md @@ -0,0 +1,41 @@ +# 3004: VIKING_SCAN + +Scan ID of Viking tags. + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=3004)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Request Packet: None + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=3004)" ++16: "STATUS" ++16: "LEN (=4)" ++8: "LRC2" ++32: "scanned_id" ++8: "LRC3" +``` + +* DATA in Response Packet + * scanned_id: 4 bytes. The Viking tag ID be scanned. \ No newline at end of file diff --git a/protocol/3005.md b/protocol/3005.md new file mode 100644 index 0000000..6f19e07 --- /dev/null +++ b/protocol/3005.md @@ -0,0 +1,45 @@ +# 3005: VIKING_WRITE_TO_T55XX + +Write Viking ID to T55xx tag. + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=3005)" ++16: "STATUS" ++16: "LEN (=8+N*4)" ++8: "LRC2" ++32: "viking_id" ++32: "new_key" ++32: "old_keys (N*4 bytes, N>=1)" ++8: "LRC3" +``` + +* DATA in Request Packet + * viking_id: `4 bytes`, The Viking tag ID to write to the T55xx tag. + * new_key: `4 bytes`, The new key to be written to the T55xx tag. The key will also be add to old keys list. + * old_keys: `N*4 bytes, N>=1`, The old keys to be used for authentication. + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=3005)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Response Packet: None \ No newline at end of file diff --git a/protocol/4000.md b/protocol/4000.md new file mode 100644 index 0000000..cfe0bfd --- /dev/null +++ b/protocol/4000.md @@ -0,0 +1,45 @@ +# 4000: MF1_WRITE_EMU_BLOCK_DATA + +Write block data to Mifare Classic emulator. + +* CLI: cf `hf mf eload` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4000)" ++16: "STATUS" ++16: "LEN (=1+N*16)" ++8: "LRC2" ++8: "block_start" ++128: "block_data (N*16 bytes, 1<=N<=31)" ++8: "LRC3" +``` + +* DATA in Request Packet + * block_start: 1 byte. The start block number to write data. + * block_data: N*16 bytes. The data to write into the emulator. + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4000)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Response Packet: None \ No newline at end of file diff --git a/protocol/4001.md b/protocol/4001.md new file mode 100644 index 0000000..d1b5f46 --- /dev/null +++ b/protocol/4001.md @@ -0,0 +1,55 @@ +# 4001: HF14A_SET_ANTI_COLL_DATA + +Set anti-collision data to emulator. + +* CLI: cf `hf mf econfig`/`hf mfu econfig` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4001)" ++16: "STATUS" ++16: "LEN (=5+L1+L2)" ++8: "LRC2" ++8: "uidlen (=L1)" ++32: "uid (L1 bytes, L1=4, 7 or 10)" ++16: "atqa" ++8: "sak" ++8: "atslen (=L2)" ++32: "ats (L2 bytes, 0<=L2<=255)" ++8: "LRC3" +``` + +* DATA in Request Packet + * uidlen: `1 byte`, length of UID (L1, L1 is 4, 7 or 10). + * uid: `L1 bytes, L1=4, 7 or 10`, UID of the 14443-3 (Type A) tag. + * atqa: `2 bytes`, ATQA of the 14443-3 (Type A) tag. + * sak: `1 byte`, SAK of the 14443-3 (Type A) tag. + * atslen: `1 byte`, length of ATS (L2, 0<=L2<=255). + * ats: `L2 bytes, 0<=L2<=255`, ATS of the 14443-3 (Type A) tag. + +* Command: N bytes: `uidlen|uid[uidlen]|atqa[2]|sak|atslen|ats[atslen]`. UID, ATQA, SAK and ATS as bytes. + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4001)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Response Packet: None \ No newline at end of file diff --git a/protocol/4004.md b/protocol/4004.md new file mode 100644 index 0000000..6a2bcbc --- /dev/null +++ b/protocol/4004.md @@ -0,0 +1,43 @@ +# 4004: MF1_SET_DETECTION_ENABLE + +Enable/disable AUTH error logger of Mifare Classic emulator for MFKey32 attack. + +* CLI: cf `hf mf econfig` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4004)" ++16: "STATUS" ++16: "LEN (=1)" ++8: "LRC2" ++8: "detection_toggle" ++8: "LRC3" +``` + +* DATA in Request Packet + * detection_toggle: `1 byte`. Enable or disable the MIFARE detection logger. + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4004)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Response Packet: None \ No newline at end of file diff --git a/protocol/4005.md b/protocol/4005.md new file mode 100644 index 0000000..1425c21 --- /dev/null +++ b/protocol/4005.md @@ -0,0 +1,43 @@ +# 4005: MF1_GET_DETECTION_COUNT + +Get count of AUTH error log of Mifare Classic emulator for MFKey32 attack. + +* CLI: cf `hf mf elog` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4005)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Request Packet: None + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4005)" ++16: "STATUS" ++16: "LEN (=4)" ++8: "LRC2" ++32: "log_count" ++8: "LRC3" +``` + +* DATA in Response Packet + * log_count: `4 bytes`. The count of AUTH error log of Mifare Classic emulator for MFKey32 attack. \ No newline at end of file diff --git a/protocol/4006.md b/protocol/4006.md new file mode 100644 index 0000000..539950f --- /dev/null +++ b/protocol/4006.md @@ -0,0 +1,59 @@ +# 4006: MF1_GET_DETECTION_LOG + +Get AUTH error log of Mifare Classic emulator for MFKey32 attack. + +* CLI: cf `hf mf elog` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4006)" ++16: "STATUS" ++16: "LEN (=4)" ++8: "LRC2" ++32: "log_start" ++8: "LRC3" +``` + +* DATA in Request Packet + * log_start: `4 bytes`, U32 in network byte order. The start index of detection log to read. + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4006)" ++16: "STATUS" ++16: "LEN (=N*18, 0<=N<=28)" ++8: "LRC2" ++8: "block_number" ++6: "RFU" ++1: "is_nested" ++1: "is_key_b" ++32: "uid" ++32: "nt" ++32: "nr" ++32: "ar" ++144: "repeat N-1 times" ++8: "LRC3" +``` + +* DATA in Response Packet + * block_number: `1 byte`. The block number of this AUTH error log. + * is_nested: `1 bit`. `0b1` if this AUTH error log is nested AUTH. + * is_key_b: `1 bit`. `0b1` if this AUTH error log is using Key B to AUTH. + * uid: `4 bytes`, U32 in network byte order. The UID of the MIFARE Classic tag. + * nt: `4 bytes`, U32 in network byte order. The tag nonce (NT) of this AUTH error log. + * nr: `4 bytes`, U32 in network byte order. The encrypted reader nonce (NR) of this AUTH error log. + * ar: `4 bytes`, U32 in network byte order. The encrypted reader answer (AR) of this AUTH error log. \ No newline at end of file diff --git a/protocol/4007.md b/protocol/4007.md new file mode 100644 index 0000000..c6ac207 --- /dev/null +++ b/protocol/4007.md @@ -0,0 +1,43 @@ +# 4007: MF1_GET_DETECTION_ENABLE + +Get AUTH error logger is enabled or not of Mifare Classic emulator for MFKey32 attack. + +* CLI: cf `hw slot list` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4007)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Request Packet: None + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4007)" ++16: "STATUS" ++16: "LEN (=1)" ++8: "LRC2" ++8: "detection_toggle" ++8: "LRC3" +``` + +* DATA in Response Packet + * detection_toggle: `1 byte`. The MIFARE detection logger is enabled or disabled. \ No newline at end of file diff --git a/protocol/4008.md b/protocol/4008.md new file mode 100644 index 0000000..cc69192 --- /dev/null +++ b/protocol/4008.md @@ -0,0 +1,47 @@ +# 4008: MF1_READ_EMU_BLOCK_DATA + +Read block data from Mifare Classic emulator. + +* CLI: cf `hf mf eread` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4008)" ++16: "STATUS" ++16: "LEN (=2)" ++8: "LRC2" ++8: "block_start" ++8: "block_count, (1<=N<=32)" ++8: "LRC3" +``` + +* DATA in Request Packet + * block_start: `1 byte`. Start block number. + * block_count: `1 byte, (1<=N<=32)`. Number of blocks to read. + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4008)" ++16: "STATUS" ++16: "LEN (=N*16)" ++8: "LRC2" ++128: "block_data (N*16 bytes, 1<=N<=32)" ++8: "LRC3" +``` + +* DATA in Response Packet + * block_data: `N*16 bytes`. The block data read from the emulator. \ No newline at end of file diff --git a/protocol/4009.md b/protocol/4009.md new file mode 100644 index 0000000..803983f --- /dev/null +++ b/protocol/4009.md @@ -0,0 +1,51 @@ +# 4009: MF1_GET_EMULATOR_CONFIG + +Get configuration of Mifare Classic emulator. + +* CLI: cf `hf mf econfig` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4009)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Request Packet: None + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4009)" ++16: "STATUS" ++16: "LEN (=5)" ++8: "LRC2" ++8: "detection_toggle" ++8: "gen1a_mode" ++8: "gen2_mode" ++8: "block_anti_coll_mode" ++8: "write_mode" ++8: "LRC3" +``` + +* DATA in Response Packet + * detection_toggle: 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) \ No newline at end of file diff --git a/protocol/4010.md b/protocol/4010.md new file mode 100644 index 0000000..38778b2 --- /dev/null +++ b/protocol/4010.md @@ -0,0 +1,41 @@ +# 4010: MF1_GET_GEN1A_MODE + +Get the Mifare Classic emulator is emulating gen1a magic tag or not. + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4010)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Request Packet: None + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4010)" ++16: "STATUS" ++16: "LEN (=1)" ++8: "LRC2" ++8: "gen1a_mode" ++8: "LRC3" +``` + +* DATA in Response Packet + * gen1a_mode: `1 byte`. Whether to emulate the Gen1A magic tag or not for the actived slot. \ No newline at end of file diff --git a/protocol/4011.md b/protocol/4011.md new file mode 100644 index 0000000..08e03f0 --- /dev/null +++ b/protocol/4011.md @@ -0,0 +1,43 @@ +# 4011: MF1_SET_GEN1A_MODE + +Set the Mifare Classic emulator to emulate gen1a magic tag or not. + +* CLI: cf `hf mf econfig` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4011)" ++16: "STATUS" ++16: "LEN (=1)" ++8: "LRC2" ++8: "gen1a_mode" ++8: "LRC3" +``` + +* DATA in Request Packet + * gen1a_mode: `1 byte`. Whether to emulate the Gen1A magic tag or not for the actived slot. + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4011)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Response Packet: None \ No newline at end of file diff --git a/protocol/4012.md b/protocol/4012.md new file mode 100644 index 0000000..7adc347 --- /dev/null +++ b/protocol/4012.md @@ -0,0 +1,41 @@ +# 4012: MF1_GET_GEN2_MODE + +Get the Mifare Classic emulator is emulating gen2 magic tag or not. + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4012)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Request Packet: None + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4012)" ++16: "STATUS" ++16: "LEN (=1)" ++8: "LRC2" ++8: "gen2_mode" ++8: "LRC3" +``` + +* DATA in Response Packet + * gen2_mode: `1 byte`. Whether to emulate the Gen2 magic tag or not for the actived slot. \ No newline at end of file diff --git a/protocol/4013.md b/protocol/4013.md new file mode 100644 index 0000000..df0d05c --- /dev/null +++ b/protocol/4013.md @@ -0,0 +1,43 @@ +# 4013: MF1_SET_GEN2_MODE + +Set the Mifare Classic emulator to emulate gen2 magic tag or not. + +* CLI: cf `hf mf econfig` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4013)" ++16: "STATUS" ++16: "LEN (=1)" ++8: "LRC2" ++8: "gen2_mode" ++8: "LRC3" +``` + +* DATA in Request Packet + * gen2_mode: `1 byte`. Whether to emulate the Gen2 magic tag or not for the actived slot. + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4013)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Response Packet: None \ No newline at end of file diff --git a/protocol/4014.md b/protocol/4014.md new file mode 100644 index 0000000..302e7bd --- /dev/null +++ b/protocol/4014.md @@ -0,0 +1,41 @@ +# 4014: MF1_GET_BLOCK_ANTI_COLL_MODE + +Get the toggle whether to use anti-collision data from emulator block 0 or not. + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4014)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Request Packet: None + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4014)" ++16: "STATUS" ++16: "LEN (=1)" ++8: "LRC2" ++8: "block_anti_coll_mode" ++8: "LRC3" +``` + +* DATA in Response Packet + * block_anti_coll_mode: `1 byte`. Whether to use anti-collision data from emulator block 0 or not for the actived slot. \ No newline at end of file diff --git a/protocol/4015.md b/protocol/4015.md new file mode 100644 index 0000000..46d5ad0 --- /dev/null +++ b/protocol/4015.md @@ -0,0 +1,43 @@ +# 4015: MF1_SET_BLOCK_ANTI_COLL_MODE + +Set the toggle whether to use anti-collision data from emulator block 0 or not. + +* CLI: cf `hf mf econfig` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4015)" ++16: "STATUS" ++16: "LEN (=1)" ++8: "LRC2" ++8: "block_anti_coll_mode" ++8: "LRC3" +``` + +* DATA in Request Packet + * block_anti_coll_mode: `1 byte`. Whether to use anti-collision data from emulator block 0 or not for the actived slot. + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4015)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Response Packet: None \ No newline at end of file diff --git a/protocol/4016.md b/protocol/4016.md new file mode 100644 index 0000000..de18e54 --- /dev/null +++ b/protocol/4016.md @@ -0,0 +1,41 @@ +# 4016: MF1_GET_WRITE_MODE + +Get the write protect mode of Mifare Classic emulator. + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4016)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Request Packet: None + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4016)" ++16: "STATUS" ++16: "LEN (=1)" ++8: "LRC2" ++8: "write_mode" ++8: "LRC3" +``` + +* DATA in Response Packet + * write_mode: `1 byte`. The write protect mode of Mifare Classic emulator for the actived slot. Please refer to `nfc_tag_mf1_write_mode_t` aka `MifareClassicWriteMode` enum. \ No newline at end of file diff --git a/protocol/4017.md b/protocol/4017.md new file mode 100644 index 0000000..fd2ebd3 --- /dev/null +++ b/protocol/4017.md @@ -0,0 +1,43 @@ +# 4017: MF1_SET_WRITE_MODE + +Set the write protect mode of Mifare Classic emulator. + +* CLI: cf `hf mf econfig` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4017)" ++16: "STATUS" ++16: "LEN (=1)" ++8: "LRC2" ++8: "write_mode" ++8: "LRC3" +``` + +* DATA in Request Packet + * write_mode: `1 byte`. The write protect mode of Mifare Classic emulator for the actived slot. Please refer to `nfc_tag_mf1_write_mode_t` aka `MifareClassicWriteMode` enum. + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4017)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Response Packet: None \ No newline at end of file diff --git a/protocol/4018.md b/protocol/4018.md new file mode 100644 index 0000000..13e2294 --- /dev/null +++ b/protocol/4018.md @@ -0,0 +1,53 @@ +# 4018: HF14A_GET_ANTI_COLL_DATA + +Get anti-collision data from emulator. + +* CLI: cf `hw slot list`/`hf mf econfig`/`hf mfu econfig` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4018)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Request Packet: None + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4018)" ++16: "STATUS" ++16: "LEN (=5+L1+L2)" ++8: "LRC2" ++8: "uidlen (=L1)" ++32: "uid (L1 bytes, L1=4, 7 or 10)" ++16: "atqa" ++8: "sak" ++8: "atslen (=L2)" ++32: "ats (L2 bytes, 0<=L2<=255)" ++8: "LRC3" +``` + +* DATA in Response Packet + * uidlen: `1 byte`, length of UID (L1, L1 is 4, 7 or 10). + * uid: `L1 bytes, L1=4, 7 or 10`, UID of the 14443-3 (Type A) tag. + * atqa: `2 bytes`, ATQA of the 14443-3 (Type A) tag. + * sak: `1 byte`, SAK of the 14443-3 (Type A) tag. + * atslen: `1 byte`, length of ATS (L2, 0<=L2<=255). + * ats: `L2 bytes, 0<=L2<=255`, ATS of the 14443-3 (Type A) tag. \ No newline at end of file diff --git a/protocol/4019.md b/protocol/4019.md new file mode 100644 index 0000000..e2ba04e --- /dev/null +++ b/protocol/4019.md @@ -0,0 +1,43 @@ +# 4019: MF0_NTAG_GET_UID_MAGIC_MODE + +Get the NTAG emulator is emulating UID magic tag or not. + +* CLI: cf `hf mfu econfig` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4019)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Request Packet: None + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4019)" ++16: "STATUS" ++16: "LEN (=1)" ++8: "LRC2" ++8: "uid_magic_mode" ++8: "LRC3" +``` + +* DATA in Response Packet + * uid_magic_mode: `1 byte`. Whether to emulate the UID magic tag or not for the actived slot. \ No newline at end of file diff --git a/protocol/4020.md b/protocol/4020.md new file mode 100644 index 0000000..b557ca0 --- /dev/null +++ b/protocol/4020.md @@ -0,0 +1,43 @@ +# 4020: MF0_NTAG_SET_UID_MAGIC_MODE + +Set the NTAG emulator to emulate UID magic tag or not. + +* CLI: cf `hf mfu econfig --enable-uid-magic`/`hf mfu econfig --disable-uid-magic` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4020)" ++16: "STATUS" ++16: "LEN (=1)" ++8: "LRC2" ++8: "uid_magic_mode" ++8: "LRC3" +``` + +* DATA in Request Packet + * uid_magic_mode: `1 byte`. Whether to emulate the UID magic tag or not for the actived slot. + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4020)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Response Packet: None \ No newline at end of file diff --git a/protocol/4021.md b/protocol/4021.md new file mode 100644 index 0000000..6bb399f --- /dev/null +++ b/protocol/4021.md @@ -0,0 +1,47 @@ +# 4021: MF0_NTAG_READ_EMU_PAGE_DATA + +Read page data from NTAG emulator. + +* CLI: cf `hf mfu eview` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4021)" ++16: "STATUS" ++16: "LEN (=2)" ++8: "LRC2" ++8: "page_start" ++8: "page_count" ++8: "LRC3" +``` + +* DATA in Request Packet + * page_start: `1 byte`. The first page index to read from the emulator. + * page_count: `1 byte`. The number of pages to read from the emulator. + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4021)" ++16: "STATUS" ++16: "LEN (=N*4)" ++8: "LRC2" ++32: "page_data (N*4 bytes)" ++8: "LRC3" +``` + +* DATA in Response Packet + * page_data: `N*4 bytes`. The page data read from the emulator. \ No newline at end of file diff --git a/protocol/4022.md b/protocol/4022.md new file mode 100644 index 0000000..1a21368 --- /dev/null +++ b/protocol/4022.md @@ -0,0 +1,45 @@ +# 4022: MF0_NTAG_WRITE_EMU_PAGE_DATA + +Write page data to NTAG emulator. + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4022)" ++16: "STATUS" ++16: "LEN (=2+N*4)" ++8: "LRC2" ++8: "page_start" ++8: "page_count" ++32: "page_data (N*4 bytes)" ++8: "LRC3" +``` + +* DATA in Request Packet + * page_start: `1 byte`. The first page index to write to the emulator. + * page_count: `1 byte`. The number of pages to write to the emulator. + * page_data: `N*4 bytes`. The page data to be written to the emulator. + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4022)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Response Packet: None \ No newline at end of file diff --git a/protocol/4023.md b/protocol/4023.md new file mode 100644 index 0000000..a3ac475 --- /dev/null +++ b/protocol/4023.md @@ -0,0 +1,70 @@ +# 4023: MF0_NTAG_GET_VERSION_DATA + +Get NTAG version from NTAG emulator. + +* CLI: cf `hf mfu econfig` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4023)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Request Packet: None + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4023)" ++16: "STATUS" ++16: "LEN (=8)" ++8: "LRC2" ++8: "fixed_header" ++8: "vendor_id" ++8: "product_type" ++8: "product_subtype" ++8: "major_product_version" ++8: "minor_product_version" ++8: "storage_size" ++8: "protocol" ++8: "LRC3" +``` + +* DATA in Response Packet + * fixed_header: `1 byte`. Fixed header byte of NTAG version data. + * vendor_id: `1 byte`. Vendor ID of NTAG. + * product_type: `1 byte`. Product type of NTAG. + * product_subtype: `1 byte`. Product subtype of NTAG. + * major_product_version: `1 byte`. Major product version of NTAG. + * minor_product_version: `1 byte`. Minor product version of NTAG. + * storage_size: `1 byte`. Storage size of NTAG. + * protocol: `1 byte`. Protocol of NTAG. + +### NTAG version for NTAG213, NTAG215 and NTAG216 + +| Byte no. | Description | NTAG213 | NTAG215 | NTAG216 | Interpretation | +| --- | --- | --- | --- | --- | --- | +| 0 | fixed Header | 0x00 | 0x00 | 0x00 | | +| 1 | vendor ID | 0x04 | 0x04 | 0x04 | NXP Semiconductors | +| 2 | product type | 0x04 | 0x04 | 0x04 | NTAG | +| 3 | product subtype | 0x02 | 0x02 | 0x02 | 50 pF | +| 4 | major product version | 0x01 | 0x01 | 0x01 | 1 | +| 5 | minor product version | 0x00 | 0x00 | 0x00 | V0 | +| 6 | storage size | 0x0F | 0x11 | 0x13 | [reference](https://www.nxp.com/docs/en/data-sheet/NTAG213_215_216.f#page=36) | +| 7 | protocol | 0x03 | 0x03 | 0x03 | ISO/IEC 14443-3 compliant | \ No newline at end of file diff --git a/protocol/4024.md b/protocol/4024.md new file mode 100644 index 0000000..41e1f17 --- /dev/null +++ b/protocol/4024.md @@ -0,0 +1,70 @@ +# 4024: MF0_NTAG_SET_VERSION_DATA + +Set NTAG version to NTAG emulator. + +* CLI: cf `hf mfu econfig --set-version ` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4024)" ++16: "STATUS" ++16: "LEN (=8)" ++8: "LRC2" ++8: "fixed_header" ++8: "vendor_id" ++8: "product_type" ++8: "product_subtype" ++8: "major_product_version" ++8: "minor_product_version" ++8: "storage_size" ++8: "protocol" ++8: "LRC3" +``` + +* DATA in Request Packet + * fixed_header: `1 byte`. Fixed header byte of NTAG version data. + * vendor_id: `1 byte`. Vendor ID of NTAG. + * product_type: `1 byte`. Product type of NTAG. + * product_subtype: `1 byte`. Product subtype of NTAG. + * major_product_version: `1 byte`. Major product version of NTAG. + * minor_product_version: `1 byte`. Minor product version of NTAG. + * storage_size: `1 byte`. Storage size of NTAG. + * protocol: `1 byte`. Protocol of NTAG. + +### NTAG version for NTAG213, NTAG215 and NTAG216 + +| Byte no. | Description | NTAG213 | NTAG215 | NTAG216 | Interpretation | +| --- | --- | --- | --- | --- | --- | +| 0 | fixed Header | 0x00 | 0x00 | 0x00 | | +| 1 | vendor ID | 0x04 | 0x04 | 0x04 | NXP Semiconductors | +| 2 | product type | 0x04 | 0x04 | 0x04 | NTAG | +| 3 | product subtype | 0x02 | 0x02 | 0x02 | 50 pF | +| 4 | major product version | 0x01 | 0x01 | 0x01 | 1 | +| 5 | minor product version | 0x00 | 0x00 | 0x00 | V0 | +| 6 | storage size | 0x0F | 0x11 | 0x13 | [reference](https://www.nxp.com/docs/en/data-sheet/NTAG213_215_216.f#page=36) | +| 7 | protocol | 0x03 | 0x03 | 0x03 | ISO/IEC 14443-3 compliant | + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4024)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Response Packet: None \ No newline at end of file diff --git a/protocol/4025.md b/protocol/4025.md new file mode 100644 index 0000000..74825a2 --- /dev/null +++ b/protocol/4025.md @@ -0,0 +1,43 @@ +# 4025: MF0_NTAG_GET_SIGNATURE_DATA + +Get signature from NTAG emulator. + +* CLI: cf `hf mfu econfig` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4025)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Request Packet: None + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4025)" ++16: "STATUS" ++16: "LEN (=32)" ++8: "LRC2" ++256: "signature_data (32 bytes)" ++8: "LRC3" +``` + +* DATA in Response Packet + * signature_data: `32 bytes`. Signature data bytes. \ No newline at end of file diff --git a/protocol/4026.md b/protocol/4026.md new file mode 100644 index 0000000..2b3546f --- /dev/null +++ b/protocol/4026.md @@ -0,0 +1,43 @@ +# 4026: MF0_NTAG_SET_SIGNATURE_DATA + +Set signature to NTAG emulator. + +* CLI: cf `hf mfu econfig --set-signature ` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4026)" ++16: "STATUS" ++16: "LEN (=32)" ++8: "LRC2" ++256: "signature_data (32 bytes)" ++8: "LRC3" +``` + +* DATA in Request Packet + * signature_data: `32 bytes`. Signature data bytes. + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4026)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Response Packet: None \ No newline at end of file diff --git a/protocol/4027.md b/protocol/4027.md new file mode 100644 index 0000000..0b09fbc --- /dev/null +++ b/protocol/4027.md @@ -0,0 +1,47 @@ +# 4027: MF0_NTAG_GET_COUNTER_DATA + +Get counter from NTAG emulator. + +* CLI: cf `hf mfu ercnt` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4027)" ++16: "STATUS" ++16: "LEN (=1)" ++8: "LRC2" ++8: "counter_index" ++8: "LRC3" +``` + +* DATA in Request Packet + * counter_index: `1 byte`. Index of the counter to read. Available value: `0`, `1`, `2`. + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4027)" ++16: "STATUS" ++16: "LEN (=4)" ++8: "LRC2" ++24: "counter" ++8: "tearing_flag" ++8: "LRC3" +``` + +* DATA in Response Packet + * counter: `3 bytes`, U24 in network byte order. The counter value in emulator. + * tearing_flag: `1 byte`. `0xBD` means tearing flag is not set. \ No newline at end of file diff --git a/protocol/4028.md b/protocol/4028.md new file mode 100644 index 0000000..4662afe --- /dev/null +++ b/protocol/4028.md @@ -0,0 +1,47 @@ +# 4028: MF0_NTAG_SET_COUNTER_DATA + +Set counter to NTAG emulator. + +* CLI: cf `hf mfu ewcnt` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4028)" ++16: "STATUS" ++16: "LEN (=4)" ++8: "LRC2" ++1: "reset_tearing" ++7: "counter_index" ++24: "counter" ++8: "LRC3" +``` + +* DATA in Request Packet + * reset_tearing: `1 byte`. `0b1` indicates to reset the tearing event flag. + * counter_index: `7 bits`. Index of the counter to set. Available value: `0`, `1`, `2`. + * counter: `3 bytes`, U24 in network byte order. The counter value to set. + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4028)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Response Packet: None \ No newline at end of file diff --git a/protocol/4029.md b/protocol/4029.md new file mode 100644 index 0000000..51e6194 --- /dev/null +++ b/protocol/4029.md @@ -0,0 +1,43 @@ +# 4029: MF0_NTAG_RESET_AUTH_CNT + +Reset AUTH counter of NTAG emulator. + +* CLI: cf `hf mfu econfig --reset-auth-cnt` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4029)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Request Packet: None + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4029)" ++16: "STATUS" ++16: "LEN (=1)" ++8: "LRC2" ++8: "old_auth_counter" ++8: "LRC3" +``` + +* DATA in Response Packet + - old_auth_counter: `1 byte`. The old value of the unsuccessful auth counter. \ No newline at end of file diff --git a/protocol/4030.md b/protocol/4030.md new file mode 100644 index 0000000..172c95e --- /dev/null +++ b/protocol/4030.md @@ -0,0 +1,41 @@ +# 4030: MF0_NTAG_GET_PAGE_COUNT + +Get page count of NTAG emulator. + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4030)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Request Packet: None + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4030)" ++16: "STATUS" ++16: "LEN (=1)" ++8: "LRC2" ++8: "max_page_count" ++8: "LRC3" +``` + +* DATA in Response Packet + * max_page_count: `1 byte`. The maximum page count of the current tag type in actived slot. \ No newline at end of file diff --git a/protocol/4031.md b/protocol/4031.md new file mode 100644 index 0000000..555c1b8 --- /dev/null +++ b/protocol/4031.md @@ -0,0 +1,41 @@ +# 4031: MF0_NTAG_GET_WRITE_MODE + +Get the protected mode of writing to NTAG emulator. + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4031)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Request Packet: None + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4031)" ++16: "STATUS" ++16: "LEN (=1)" ++8: "LRC2" ++8: "write_mode" ++8: "LRC3" +``` + +* DATA in Response Packet + * write_mode: `1 byte`. The write protect mode of Mifare Ultralight emulator for the actived slot. Please refer to `nfc_tag_mf0_ntag_write_mode_t` aka `MifareUltralightWriteMode` enum. \ No newline at end of file diff --git a/protocol/4032.md b/protocol/4032.md new file mode 100644 index 0000000..8589955 --- /dev/null +++ b/protocol/4032.md @@ -0,0 +1,41 @@ +# 4032: MF0_NTAG_SET_WRITE_MODE + +Set the protected mode of writing to NTAG emulator. + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4032)" ++16: "STATUS" ++16: "LEN (=1)" ++8: "LRC2" ++8: "write_mode" ++8: "LRC3" +``` + +* DATA in Request Packet + * write_mode: `1 byte`. The write protect mode of Mifare Ultralight emulator for the actived slot. Please refer to `nfc_tag_mf0_ntag_write_mode_t` aka `MifareUltralightWriteMode` enum. + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4032)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Response Packet: None \ No newline at end of file diff --git a/protocol/4033.md b/protocol/4033.md new file mode 100644 index 0000000..3d43f25 --- /dev/null +++ b/protocol/4033.md @@ -0,0 +1,41 @@ +# 4033: MF0_NTAG_SET_DETECTION_ENABLE + +Enable/disable the AUTH logger of NTAG emulator. + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4033)" ++16: "STATUS" ++16: "LEN (=1)" ++8: "LRC2" ++8: "detection_toggle" ++8: "LRC3" +``` + +* DATA in Request Packet + * detection_toggle: `1 byte`. Enable or disable the AUTH logger of NTAG emulator. + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4033)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Response Packet: None \ No newline at end of file diff --git a/protocol/4034.md b/protocol/4034.md new file mode 100644 index 0000000..852aaa8 --- /dev/null +++ b/protocol/4034.md @@ -0,0 +1,41 @@ +# 4034: MF0_NTAG_GET_DETECTION_COUNT + +Get the AUTH log count of NTAG emulator. + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4034)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Request Packet: None + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4034)" ++16: "STATUS" ++16: "LEN (=4)" ++8: "LRC2" ++32: "log_count" ++8: "LRC3" +``` + +* DATA in Response Packet + * log_count: `4 bytes`. The AUTH log count of NTAG emulator. \ No newline at end of file diff --git a/protocol/4035.md b/protocol/4035.md new file mode 100644 index 0000000..d746a44 --- /dev/null +++ b/protocol/4035.md @@ -0,0 +1,43 @@ +# 4035: MF0_NTAG_GET_DETECTION_LOG + +Get the AUTH log of NTAG emulator. + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4035)" ++16: "STATUS" ++16: "LEN (=4)" ++8: "LRC2" ++32: "log_start" ++8: "LRC3" +``` + +* DATA in Request Packet + * log_start: `4 bytes`, U32 in network byte order. The start index of logged AUTH keys to read. + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4035)" ++16: "STATUS" ++16: "LEN (=N*4)" ++8: "LRC2" ++32: "keys (N*4 bytes)" ++8: "LRC3" +``` + +* DATA in Response Packet + * keys: `4 bytes/key`, U32 in network byte order. The logged AUTH keys. \ No newline at end of file diff --git a/protocol/4036.md b/protocol/4036.md new file mode 100644 index 0000000..0fe5146 --- /dev/null +++ b/protocol/4036.md @@ -0,0 +1,41 @@ +# 4036: MF0_NTAG_GET_DETECTION_ENABLE + +Get the AUTH logger of NTAG emulator is enabled or not. + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4036)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Request Packet: None + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4036)" ++16: "STATUS" ++16: "LEN (=1)" ++8: "LRC2" ++8: "detection_toggle" ++8: "LRC3" +``` + +* DATA in Response Packet + * detection_toggle: `1 byte`. The AUTH logger of NTAG emulator is enabled or not. \ No newline at end of file diff --git a/protocol/4037.md b/protocol/4037.md new file mode 100644 index 0000000..dd93c4d --- /dev/null +++ b/protocol/4037.md @@ -0,0 +1,45 @@ +# 4037: MF0_NTAG_GET_EMULATOR_CONFIG + +Get configuration of NTAG emulator. + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4037)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Request Packet: None + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=4037)" ++16: "STATUS" ++16: "LEN (=3)" ++8: "LRC2" ++8: "detection_toggle" ++8: "uid_magic_mode" ++8: "write_mode" ++8: "LRC3" +``` + +* DATA in Response Packet + * detection_toggle: `1 byte`. The AUTH logger of NTAG emulator is enabled or not. + * uid_magic_mode: `1 byte`. Whether to emulate the UID magic tag or not for the actived slot. + * write_mode: `1 byte`. The write protect mode of Mifare Ultralight emulator for the actived slot. Please refer to `nfc_tag_mf0_ntag_write_mode_t` aka `MifareUltralightWriteMode` enum. \ No newline at end of file diff --git a/protocol/5000.md b/protocol/5000.md new file mode 100644 index 0000000..fd6ae19 --- /dev/null +++ b/protocol/5000.md @@ -0,0 +1,43 @@ +# 5000: EM410X_SET_EMU_ID + +Set EM410x ID to emulator. + +* CLI: cf `lf em 410x econfig` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=5000)" ++16: "STATUS" ++16: "LEN (=5)" ++8: "LRC2" ++40: "em410x_id" ++8: "LRC3" +``` + +* DATA in Request Packet + * em410x_id: `5 bytes`. The EM410x ID to be emulated. + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=5000)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Response Packet: None \ No newline at end of file diff --git a/protocol/5001.md b/protocol/5001.md new file mode 100644 index 0000000..bea7774 --- /dev/null +++ b/protocol/5001.md @@ -0,0 +1,43 @@ +# 5001: EM410X_GET_EMU_ID + +Get EM410x ID from emulator. + +* CLI: cf `lf em 410x econfig` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=5001)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Request Packet: None + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=5001)" ++16: "STATUS" ++16: "LEN (=5)" ++8: "LRC2" ++40: "em410x_id" ++8: "LRC3" +``` + +* DATA in Response Packet + * em410x_id: `5 bytes`. The EM410x ID in the emulator. \ No newline at end of file diff --git a/protocol/5002.md b/protocol/5002.md new file mode 100644 index 0000000..75d91ad --- /dev/null +++ b/protocol/5002.md @@ -0,0 +1,51 @@ +# 5002: HIDPROX_SET_EMU_ID + +Set HIDProx ID to emulator. + +* CLI: cf `lf hid prox econfig` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=5002)" ++16: "STATUS" ++16: "LEN (=13)" ++8: "LRC2" ++8: "format" ++32: "facility_code" ++40: "card_number" ++8: "issue_level" ++16: "oem" ++8: "LRC3" +``` + +* DATA in Request Packet + * format: `1 byte`, The format of the HID Prox card. + * facility_code: `4 bytes`, U32 in network byte order, The facility code of the HID Prox card. + * card_number: `5 bytes`, U40 in network byte order, The card number of the HID Prox card. + * issue_level: `1 byte`, The issue level of the HID Prox card. + * oem: `2 bytes`, The OEM code of the HID Prox card. + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=5002)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Response Packet: None \ No newline at end of file diff --git a/protocol/5003.md b/protocol/5003.md new file mode 100644 index 0000000..33396a8 --- /dev/null +++ b/protocol/5003.md @@ -0,0 +1,51 @@ +# 5003: HIDPROX_GET_EMU_ID + +Get HIDProx ID from emulator. + +* CLI: cf `lf hid prox econfig -s 1 --fc 107 --cn 10044 --format H10301` + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=5003)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Request Packet: None + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=5003)" ++16: "STATUS" ++16: "LEN (=13)" ++8: "LRC2" ++8: "format" ++32: "facility_code" ++40: "card_number" ++8: "issue_level" ++16: "oem" ++8: "LRC3" +``` + +* DATA in Response Packet + * format: `1 byte`, The format of the HID Prox card. + * facility_code: `4 bytes`, U32 in network byte order, The facility code of the HID Prox card. + * card_number: `5 bytes`, U40 in network byte order, The card number of the HID Prox card. + * issue_level: `1 byte`, The issue level of the HID Prox card. + * oem: `2 bytes`, The OEM code of the HID Prox card. \ No newline at end of file diff --git a/protocol/5004.md b/protocol/5004.md new file mode 100644 index 0000000..f19a49c --- /dev/null +++ b/protocol/5004.md @@ -0,0 +1,41 @@ +# 5004: VIKING_SET_EMU_ID + +Set Viking ID to emulator. + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=5004)" ++16: "STATUS" ++16: "LEN (=4)" ++8: "LRC2" ++32: "viking_id" ++8: "LRC3" +``` + +* DATA in Request Packet + * viking_id: `4 bytes`. The Viking ID to be emulated. + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=5004)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Response Packet: None \ No newline at end of file diff --git a/protocol/5005.md b/protocol/5005.md new file mode 100644 index 0000000..deda08a --- /dev/null +++ b/protocol/5005.md @@ -0,0 +1,41 @@ +# 5005: VIKING_GET_EMU_ID + +Get Viking ID from emulator. + +## Request Packet + +```mermaid +--- +title: "Request Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=5005)" ++16: "STATUS" ++16: "LEN (=0)" ++8: "LRC2" ++8: "LRC3" +``` + +* DATA in Request Packet: None + +## Response Packet + +```mermaid +--- +title: "Response Packet" +--- +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD (=5005)" ++16: "STATUS" ++16: "LEN (=4)" ++8: "LRC2" ++32: "viking_id" ++8: "LRC3" +``` + +* DATA in Response Packet + * viking_id: `4 bytes`. The Viking ID in the emulator. \ No newline at end of file diff --git a/protocol/README.md b/protocol/README.md new file mode 100644 index 0000000..4a45573 --- /dev/null +++ b/protocol/README.md @@ -0,0 +1,219 @@ +# Protocol description + +## Changelog + +- 2025/08/12: DATA maxlength changed from 512 to 4096 bytes. ref: [RfidResearchGroup/ChameleonUltra#273](https://github.com/RfidResearchGroup/ChameleonUltra/pull/273) + +## Frame format + +The communication between the firmware and the client is made of frames structured as follows: + +![](images/protocol-packet.png) + +```mermaid +packet ++8: "SOF" ++8: "LRC1" ++16: "CMD" ++16: "STATUS" ++16: "LEN" ++8: "LRC2" ++48: "DATA (variable length)" ++8: "LRC3" +``` + +- **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 `4096`. +- **LRC2**: `1 byte`, LRC over `CMD|STATUS|LEN` bytes. +- **DATA**: `LEN bytes`, data to be sent or received, maximum is `4096 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. + +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 `4106` 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) + +## Command & Data payloads + +For the request and response data payload of individual commands, please refer to the following documentation of that specific command. + +See [Guidelines](#new-data-payloads-guidelines-for-developers) for adding new commands and their data payloads. + +Beware, slots in protocol count from 0 to 7 (and from 1 to 8 in the CLI...). + +### Device & Slot Related + +- [1000: GET_APP_VERSION](./1000.md): **DEPRECATED** Get firmware version. +- [1001: CHANGE_DEVICE_MODE](./1001.md): Change device mode between reader/writer and emulator. +- [1002: GET_DEVICE_MODE](./1002.md): Get current device mode. +- [1003: SET_ACTIVE_SLOT](./1003.md): Set active slot number. +- [1004: SET_SLOT_TAG_TYPE](./1004.md): Set tag type of specific slot. +- [1005: SET_SLOT_DATA_DEFAULT](./1005.md): Reset to tag type's default data of specific slot. +- [1006: SET_SLOT_ENABLE](./1006.md): Enable/disable specific slot HF/LF. +- [1007: SET_SLOT_TAG_NICK](./1007.md): Set nickname of specific slot HF/LF. +- [1008: GET_SLOT_TAG_NICK](./1008.md): Get nickname of specific slot HF/LF. +- [1009: SLOT_DATA_CONFIG_SAVE](./1009.md): Save slot data configuration. +- [1010: ENTER_BOOTLOADER](./1010.md): Enter bootloader mode. +- [1011: GET_DEVICE_CHIP_ID](./1011.md): Get device chip ID. +- [1012: GET_DEVICE_ADDRESS](./1012.md): Get device BLE address. +- [1013: SAVE_SETTINGS](./1013.md): Save device settings. +- [1014: RESET_SETTINGS](./1014.md): Reset device settings. +- [1015: SET_ANIMATION_MODE](./1015.md): Set device power on animation. +- [1016: GET_ANIMATION_MODE](./1016.md): Get device power on animation. +- [1017: GET_GIT_VERSION](./1017.md): Get `git describe` version string of source code. +- [1018: GET_ACTIVE_SLOT](./1018.md): Get active slot number. +- [1019: GET_SLOT_INFO](./1019.md): Get information about specific slot. +- [1020: WIPE_FDS](./1020.md): Device factory reset. +- [1021: DELETE_SLOT_TAG_NICK](./1021.md): Delete nickname of specific slot HF/LF. +- [1023: GET_ENABLED_SLOTS](./1023.md): Get enabled/disabled of all slots HF/LF. +- [1024: DELETE_SLOT_SENSE_TYPE](./1024.md): Delete data of specific slot HF/LF. +- [1025: GET_BATTERY_INFO](./1025.md): Get battery voltage and level. +- [1026: GET_BUTTON_PRESS_CONFIG](./1026.md): Get button press function of specific button. +- [1027: SET_BUTTON_PRESS_CONFIG](./1027.md): Set button press function of specific button. +- [1028: GET_LONG_BUTTON_PRESS_CONFIG](./1028.md): Get button long press function of specific button. +- [1029: SET_LONG_BUTTON_PRESS_CONFIG](./1029.md): Set button long press function of specific button. +- [1030: SET_BLE_PAIRING_KEY](./1030.md): Set BLE pairing key. +- [1031: GET_BLE_PAIRING_KEY](./1031.md): Get BLE pairing key. +- [1032: DELETE_ALL_BLE_BONDS](./1032.md): Delete all BLE bonded devices. +- [1033: GET_DEVICE_MODEL](./1033.md): Get device type (Ultra/Lite). +- [1034: GET_DEVICE_SETTINGS](./1034.md): Get device settings. +- [1035: GET_DEVICE_CAPABILITIES](./1035.md): Get supported command IDs. +- [1036: GET_BLE_PAIRING_ENABLE](./1036.md): Get BLE pairing is enabled or not. +- [1037: SET_BLE_PAIRING_ENABLE](./1037.md): Enable/disable BLE pairing. +- [1038: GET_ALL_SLOT_NICKS](./1038.md): Get nickname of all slots HF/LF. + +### High Frequency (HF) Reader/Writer Related + +- [2000: HF14A_SCAN](./2000.md): Scan UID, ATQA, SAK, ATS of 14443-3 (Type A) tags. +- [2001: MF1_DETECT_SUPPORT](./2001.md): Detect if tag support Mifare Classic AUTH command or not. +- [2002: MF1_DETECT_PRNG](./2002.md): Detect PRNG type of Mifare Classic tag. +- [2003: MF1_STATIC_NESTED_ACQUIRE](./2003.md): Acquire necessary data from Mifare Classic tag for static nested attack. +- [2004: MF1_DARKSIDE_ACQUIRE](./2004.md): Acquire necessary data from Mifare Classic tag for Darkside attack. +- [2005: MF1_DETECT_NT_DIST](./2005.md): Detect tag nonce distance of Mifare Classic tag. +- [2006: MF1_NESTED_ACQUIRE](./2006.md): Acquire necessary data from Mifare Classic tag for nested attack. +- [2007: MF1_AUTH_ONE_KEY_BLOCK](./2007.md): AUTH specific block and key type of Mifare Classic tag. +- [2008: MF1_READ_ONE_BLOCK](./2008.md): Read specific block of Mifare Classic tag. +- [2009: MF1_WRITE_ONE_BLOCK](./2009.md): Write specific block of Mifare Classic tag. +- [2010: HF14A_RAW](./2010.md): Send raw 14443-3 (Type A) commands with options. +- [2011: MF1_MANIPULATE_VALUE_BLOCK](./2011.md): Manipulate value block of Mifare Classic tag. +- [2012: MF1_CHECK_KEYS_OF_SECTORS](./2012.md): Check keys on sectors of Mifare Classic tag in batch. +- [2013: MF1_HARDNESTED_ACQUIRE](./2013.md): Acquire necessary data from Mifare Classic tag for hardnested attack. +- [2014: MF1_ENC_NESTED_ACQUIRE](./2014.md): Acquire necessary data from Mifare Classic tag for encrypted nested attack. +- [2015: MF1_CHECK_KEYS_ON_BLOCK](./2015.md): Check keys on block of Mifare Classic tag in batch. + +### Low Frequency (LF) Reader/Writer Related + +- [3000: EM410X_SCAN](./3000.md): Scan ID of EM410x tags. +- [3001: EM410X_WRITE_TO_T55XX](./3001.md): Write EM410x ID to T55xx tag. +- [3002: HIDPROX_SCAN](./3002.md): Scan ID of HIDProx tags. +- [3003: HIDPROX_WRITE_TO_T55XX](./3003.md): Write HIDProx ID to T55xx tag. +- [3004: VIKING_SCAN](./3004.md): Scan ID of Viking tags. +- [3005: VIKING_WRITE_TO_T55XX](./3005.md): Write Viking ID to T55xx tag. + +### High Frequency (HF) Emulator Related + +- [4000: MF1_WRITE_EMU_BLOCK_DATA](./4000.md): Write block data to Mifare Classic emulator. +- [4001: HF14A_SET_ANTI_COLL_DATA](./4001.md): Set anti-collision data to emulator. +- [4004: MF1_SET_DETECTION_ENABLE](./4004.md): Enable/disable the AUTH error logger of Mifare Classic emulator for MFKey32 attack. +- [4005: MF1_GET_DETECTION_COUNT](./4005.md): Get count of AUTH error log of Mifare Classic emulator for MFKey32 attack. +- [4006: MF1_GET_DETECTION_LOG](./4006.md): Get AUTH error log of Mifare Classic emulator for MFKey32 attack. +- [4007: MF1_GET_DETECTION_ENABLE](./4007.md): Get the AUTH error logger is enabled or not of Mifare Classic emulator for MFKey32 attack. +- [4008: MF1_READ_EMU_BLOCK_DATA](./4008.md): Read block data from Mifare Classic emulator. +- [4009: MF1_GET_EMULATOR_CONFIG](./4009.md): Get configuration of Mifare Classic emulator. +- [4010: MF1_GET_GEN1A_MODE](./4010.md): Get the Mifare Classic emulator is emulating gen1a magic tag or not. +- [4011: MF1_SET_GEN1A_MODE](./4011.md): Set the Mifare Classic emulator to emulate gen1a magic tag or not. +- [4012: MF1_GET_GEN2_MODE](./4012.md): Get the Mifare Classic emulator is emulating gen2 magic tag or not. +- [4013: MF1_SET_GEN2_MODE](./4013.md): Set the Mifare Classic emulator to emulate gen2 magic tag or not. +- [4014: MF1_GET_BLOCK_ANTI_COLL_MODE](./4014.md): Get the toggle whether to use anti-collision data from emulator block 0 or not. +- [4015: MF1_SET_BLOCK_ANTI_COLL_MODE](./4015.md): Set the toggle whether to use anti-collision data from emulator block 0 or not. +- [4016: MF1_GET_WRITE_MODE](./4016.md): Get the write protect mode of Mifare Classic emulator. +- [4017: MF1_SET_WRITE_MODE](./4017.md): Set the write protect mode of Mifare Classic emulator. +- [4018: HF14A_GET_ANTI_COLL_DATA](./4018.md): Get anti-collision data from emulator. +- [4019: MF0_NTAG_GET_UID_MAGIC_MODE](./4019.md): Get the NTAG emulator is emulating UID magic tag or not. +- [4020: MF0_NTAG_SET_UID_MAGIC_MODE](./4020.md): Set the NTAG emulator to emulate UID magic tag or not. +- [4021: MF0_NTAG_READ_EMU_PAGE_DATA](./4021.md): Read page data from NTAG emulator. +- [4022: MF0_NTAG_WRITE_EMU_PAGE_DATA](./4022.md): Write page data to NTAG emulator. +- [4023: MF0_NTAG_GET_VERSION_DATA](./4023.md): Get NTAG version from NTAG emulator. +- [4024: MF0_NTAG_SET_VERSION_DATA](./4024.md): Set NTAG version to NTAG emulator. +- [4025: MF0_NTAG_GET_SIGNATURE_DATA](./4025.md): Get signature from NTAG emulator. +- [4026: MF0_NTAG_SET_SIGNATURE_DATA](./4026.md): Set signature to NTAG emulator. +- [4027: MF0_NTAG_GET_COUNTER_DATA](./4027.md): Get counter from NTAG emulator. +- [4028: MF0_NTAG_SET_COUNTER_DATA](./4028.md): Set counter to NTAG emulator. +- [4029: MF0_NTAG_RESET_AUTH_CNT](./4029.md): Reset AUTH counter of NTAG emulator. +- [4030: MF0_NTAG_GET_PAGE_COUNT](./4030.md): Get page count of NTAG emulator. +- [4031: MF0_NTAG_GET_WRITE_MODE](./4031.md): Get the protected mode of writing to NTAG emulator. +- [4032: MF0_NTAG_SET_WRITE_MODE](./4032.md): Set the protected mode of writing to NTAG emulator. +- [4033: MF0_NTAG_SET_DETECTION_ENABLE](./4033.md): Enable/disable the AUTH logger of NTAG emulator. +- [4034: MF0_NTAG_GET_DETECTION_COUNT](./4034.md): Get the AUTH log count of NTAG emulator. +- [4035: MF0_NTAG_GET_DETECTION_LOG](./4035.md): Get the AUTH log of NTAG emulator. +- [4036: MF0_NTAG_GET_DETECTION_ENABLE](./4036.md): Get the AUTH logger of NTAG emulator is enabled or not. +- [4037: MF0_NTAG_GET_EMULATOR_CONFIG](./4037.md): Get configuration of NTAG emulator. + +### Low Frequency (LF) Emulator Related + +- [5000: EM410X_SET_EMU_ID](./5000.md): Set EM410x ID to emulator. +- [5001: EM410X_GET_EMU_ID](./5001.md): Get EM410x ID from emulator. +- [5002: HIDPROX_SET_EMU_ID](./5002.md): Set HIDProx ID to emulator. +- [5003: HIDPROX_GET_EMU_ID](./5003.md): Get HIDProx ID from emulator. +- [5004: VIKING_SET_EMU_ID](./5004.md): Set Viking ID to emulator. +- [5005: VIKING_GET_EMU_ID](./5005.md): Get Viking ID from emulator. + +## Status + +Standard response status is `STATUS_SUCCESS` for general commands, `STATUS_HF_TAG_OK` for HF commands and `STATUS_LF_TAG_OK` for LF commands. + +## 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_SUCCESS` for general commands, `STATUS_HF_TAG_OK` for HF commands and `STATUS_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. + +## Room for improvement + +* some `num_to_bytes` `bytes_to_num` could use `hton*`, `ntoh*` instead, to make endianess explicit +* some commands are using bitfields (e.g. mf1_get_detection_log (sending directly the flash stored format) and hf14a_raw) while some commands are spreading bits into 0x00/0x01 bytes (e.g. mf1_get_emulator_config) +* describe flash storage formats \ No newline at end of file