- visually closer to pm3 (differenciate groups and commands)
- "dumphelp" allows to quickly dump all cmds and their options
- now all commands support '-h', so e.g. `hw settings store -h` will print help instead of storing
- no more command description in decorator, it is now taken from argparse description
* wip_protocol_refresh: (38 commits)
CI for releases
changelog
build_firmware.yml: fetch depth=0 to be able to build proper version strings
Deduce APP_FW_VER from git tag
bump app version
style
colors
Increase initial button wakeup from 4 to 8 seconds
Adding MIFARE Ultralight reading, wip
hf14a_raw: use @expect_response and fix tests
Fix shadow mode not being preserved. Breaking change: nfc_tag_mf1_write_mode_t has one new mode SHADOW_REQ. Client can set SHADOW or SHADOW_REQ, internally it will be transformed to SHADOW_REQ. When it's time to save data, if SHADOW_REQ, the fw will change it to SHADOW and still allow to save the data before acting as shadow. Breaking: when client reads back MF1 write mode just after settings SHADOW and before saving config, it will receive SHADOW_REQ and must be ready to handle this new enum value.
MF1_DETECT_SUPPORT: remove redundant data
Breaking change: DATA_CMD_GET_DEVICE_MODEL to match chameleon_device_type_t
hw 14a raw: closer to pm3 syntax, removed bit_frame,...
use field LED also in reader mode
fix changelog
new tag_specific_type_t enum, new slotConfig struct. FW will take care of existing slots. Disruptive changes: see below
Implemented hf 14a raw
Fixed initialization bugs and added raw command implementation functions.
Update the table of MFC attack support levels.
...
Initial button press wakeup of 4 seconds is sometimes inadequate to establish BT connection.
This change will expand the Initial button wakeup from 4 seconds to 8 seconds.
Device sleep behavior after will be as follows:
(Changed)
Initial Button Wakeup to Sleep : 8s
(No Change)
Subsequent Button Action to Sleep : 4s
Leaving RF Field wake to sleep : 3s
BLE Disconnect to sleep : 4s
USB Power Disconnect to sleep : 3s
Example behavior :
User wakes device with Button B (8 Sec to sleep)
User pushes button B again (Now 4 Sec to sleep)
User Places device in RF field (Maintain wake)
User removes device from RF field (3 sec to sleep)
If user discontinues the user journey at any point, the identified condition will invoke sleep at defined times.
nfc_tag_mf1_write_mode_t has one new mode SHADOW_REQ.
Client can set SHADOW or SHADOW_REQ, internally it will be transformed to SHADOW_REQ.
When it's time to save data, if SHADOW_REQ, the fw will change it to SHADOW and still allow to save the data before acting as shadow.
Breaking: when client reads back MF1 write mode just after settings SHADOW and before saving config, it will receive SHADOW_REQ and must be ready to handle this new enum value.
Now data length is always in bits
Option -o => -a and only needed to turn field on without select or data
Reorganize pcd_14a_reader_raw_cmd
Some more checks
Disruptive changes:
- tag types are 2-byte long with new values
- GET_SLOT_INFO returns 32 bytes as tag types are now 2-byte long
- "enable" is not common to one slot anymore but bound to the HF or LF part
- GET_ENABLED_SLOTS returns 16 bytes as we get "enabled_hf" and "enabled_lf" for each slot
- SET_SLOT_ENABLE needs 3 bytes slot_number|sense_type|enable as we need to specify to enable HF or LF
- slotConfig changed a lot but this is internal to the fw and its flash and a function does the format conversion on first boot after flash
so slot data is preserved on fw upgrade, but if one downgrades to a previous version, data will be erased.
MF1_DETECT_DARKSIDE was actually runnign the full attack, as there is no quick way to detect Darkside
So if you want to check for Darkside, just run directly MF1_DARKSIDE_ACQUIRE.
This huge commit tries to enhance several things related to the fw/cli protocol.
Generally, the idea is to be verbose, explicit and reuse conventions, in order to enhance code maintainability and understandability for the other contributors.
docs/protocol.md got heavily updated
Many commands have been renamed for consistency. you are invited to adapt your client for easier maintenance
Guidelines, also written in docs/protocol.md "New data payloads: guidelines for developers":
- Now protocol data exchanged over USB or BLE are defined in netdata.h as packed structs and values are stored in Network byte order (=Big Endian)
- Command-specific payloads are defined in their respective cmd_processor handler in app_cmd.c and chameleon_cmd.py
- 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.
- If single byte of data to return, still use a 1-byte `data`, not `status`.
- 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`
- Concentrate payload parsing in the handlers, avoid further parsing in their callers. 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
- Avoid hardcoding offsets, use `sizeof()`, `offsetof(struct, field)` in C and `struct.calcsize()` in Python
- 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
- Validate data before using it, both when receiving command data in the firmware and when receiving response data in the client.
- Validate response status in client.
Disruptive changes:
- GET_DEVICE_CAPABILITIES: list of cmds in data are now really Big Endian
Note: the initial attempt to use macros PP_HTONS were actually considering wrongly that the platform was Big Endian (BYTE_ORDER was actually undefined) while it is actually Little Endian.
- GET_APP_VERSION: response is now a tuple of bytes: major|minor (previously it was in reversed order as a single uint16_t in Little Endian)
- SET_SLOT_TAG_TYPE: tag_type now on 2 bytes, to prepare remapping of its enum
- SET_SLOT_DATA_DEFAULT: tag_type now on 2 bytes, to prepare remapping of its enum
- GET_SLOT_INFO: tag_type now on 2 bytes, to prepare remapping of its enum
- GET_DEVICE_CHIP_ID: now returns its 64b ID following Network byte order (previously, bytes were in the reverse order)
- GET_DEVICE_ADDRESS: now returns its 56b address following Network byte order (previously, bytes were in the reverse order). CLI does not reverse the response anymore so it displays the same value as before.
- MF1_GET_DETECTION_COUNT: now returns its 32b value following Network byte order (previously Little Endian)
- GET_GIT_VERSION response status is now STATUS_DEVICE_SUCCESS
- GET_DEVICE_MODEL response status is now STATUS_DEVICE_SUCCESS
- MF1_READ_EMU_BLOCK_DATA response status is now STATUS_DEVICE_SUCCESS
- GET_DEVICE_CAPABILITIES response status is now STATUS_DEVICE_SUCCESS
- HF14A_SCAN: entirely new response format, room for ATS and multiple tags
- MF1_DETECT_SUPPORT response status is now HF_TAG_OK and support is indicated as bool in 1 byte of data
- MF1_DETECT_PRNG response status is now HF_TAG_OK and prng_type is returned in 1 byte of data with a new enum mf1_prng_type_t == MifareClassicPrngType
- MF1_DETECT_DARKSIDE response status is now HF_TAG_OK and darkside_status is returned in 1 byte of data with a new enum mf1_darkside_status_t == MifareClassicDarksideStatus
- MF1_DARKSIDE_ACQUIRE response status is now HF_TAG_OK and darkside_status is returned in 1 byte of data. If OK, followed by 24 bytes as previously
- MF1_GET_ANTI_COLL_DATA: in case slot does not contain anticoll data, instead of STATUS_PAR_ERR, now it returns STATUS_DEVICE_SUCCESS with empty data
- MF1_SET_ANTI_COLL_DATA and MF1_GET_ANTI_COLL_DATA now use the same data format as HF14A_SCAN
For clients to detect Ultra/Lite with older firmwares, one can issue the GET_APP_VERSION and urge the user to flash his device if needed.
On older firmwares, it will return a status=b'\x00' and data=b'\x00\x01' while up-to-date firmwares will return status=STATUS_DEVICE_SUCCESS and data greater or equal to b'\x01\x00' (v1.0).
Other changes: cf CHANGELOG, and probably a few small changes I forgot about..
TODO:
- remap `tag_specific_type_t` enum to allow future tags (e.g. LF tags) without reshuffling enum and affecting users stored cards
- TEST!
Simulation and emulation used within same document while having no distinctive technical differentiating usage, propose changing all instances to Emulate/Emulation
Avoid
```
Chameleon Connect fail: [Errno 2] could not open port /dev/ttyS15
/dev/ttyS39: [Errno 2] No such file or directory: '/dev/ttyS15\r\n/dev/ttyS39'
```
By only returning the first COM port with `VID_6868&PID_8686`
Please avoid creating variable in middle of functions, and in this particular case double `uint8_t status;`.
Can be valid for some compiler, but does not help to read the code.
Because otherwise one must wait for sleep animation to finish, then press button then wait for boot animation to finish...
Also, fix saved config CRC after config has been saved
Bug when NRF_LOG_DEFERRED=0
due to a userland NRF_LOG_INFO after FDS record update was initiated, interrupted by FDS record IRQ handler and its own NRF_LOG_INFO
resulting in
<error> app: Fatal error
<warning> app: System reset
Added a few more NRF_LOG in FDS module as well.
Added NRF_LOG_FLUSH in system_off_enter to not miss last messages.
Changes made:
- CI properly supports being ran on PRs and shouldn't fail anymore on
the RRG repo;
- The nonsense of unzipping archives during release creation isn't
needed anymore because now there's an artifact that holds all the
files (both zip and others) that should be included in a release;
- Softdevice and Application verification were re-enabled (as per
@doegox suggestion);
- Softdevice is now bundled in `-firmware` artifact;
- `dev` release tag is now updated ad every push to main;
- On PRs a comment linking to artifact is now added by CI after
success, artifact links are done with nightly.link so that they also
fork for unauthenticated users;
There are some quirks:
- on_pr runs on pull_request_target because it needs write access to
packages, but pull_request_target implies that GITHUB_SHA is set to
the base repo HEAD commit, so the whole `checkout-sha` thing is
needed. This also implies that if one of the workflow files are
changed in a PR the changed versions won't be ran against that same
PR.
- Client building per OS isn't yet implemented but all the necessary
scaffolding is there. At the moment the per-OS clients are just a zip
file containing all the client source.
Examples:
- PR comment: https://github.com/augustozanellato/ChameleonUltra/pull/14#issuecomment-1688737709
- `dev` release: https://github.com/augustozanellato/ChameleonUltra/releases/tag/dev
Once an external HF field is detected, when a first byte is received, then NFC IRQ is called non-stop.
But none of the conditions in nrfx_nfct_irq_handler() is met so the handler does nothing and there is no chance to get called from a registered callback.
Side effect is that main loop cannot run, button IRQs are called but button processing in main loop is not called, etc.
So one of the side effects is that bsp_wdt_feed() is not called.
Current workaround is to call bsp_wdt_feed() at the end of nRF SDK nrfx_nfct.c nrfx_nfct_irq_handler()
I suspect the hack of the NFC state machine done in nfc_14a.c nfc_tag_14a_event_callback() case NRFX_NFCT_EVT_FIELD_DETECTED
to get access to the anticollision phase is breaking sth in the SDK state machine, NFC IRQ should be called only on real change (field drop, cmd received,...)
Slot
Won't work like this
More randomness on nested auth (for hardnested recovery) and change default GCC location
Nobody will have GCC in this default location, /usr/bin/ will target way more users
Get enabled slots command
hw slot list show disabled slots
Improve python code quality
Show Mifare Classic emulator settings in hw slot list
Implement hf mf settings to change Mifare Classic emulator settings
Update
* SlotNumber values range from 1 to 8 rather than from 0 to 7
this allows more straightforward usage as ppl can use equivalently SLOT_1 or 1.
* SlotNumber.fix -> .to_fw, and add .from_fw
* removed unnecessary SLOT_NO
* More straightforward use of enums, no need for .value, .__members__, name.replace() etc
* Unify usage between TagSenseType and TagSpecificType
* Add str representations for TagSenseType
* Fixed TagSpecificType related help (e.g. in hw slot type -h)
* Removed some redundant error raise
* Note: iterations can be done with `for slot in chameleon_cmd.SlotNumber:`
* for issues specific to another client than the Python CLI, use the corresponding issue tracker. E.g. [here](https://github.com/GameTec-live/ChameleonUltraGUI/issues) for the ChameleonUltraGUI
***Compilation problems***
Try compiling with verbose. Use `make VERBOSE=1` for the firmware and the software/src tools.
Include the verbose compilation logs.
***flashing problems***
Have you followed the instructions properly?
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior.
Explain it as you would do to someone not familiar with the problematic feature.
What is the abnormal behavior you observed?
E.g.
1. Connect '....'
2. Execute '....'
3. Press button '....'
4. See error '....'
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem. For console text and logs, better to dump them as text than image. Attach files if too long.
**Host (please complete the following information):**
- OS and version
- for compilation issues, the toolchain version
- inside CLI run `hw version` and paste the output here
Please keep in mind we are still at the infancy of the project and a lot has still to be done.
Have first a look at the [Whitepaper](https://github.com/RfidResearchGroup/ChameleonUltra/blob/main/docs/technical_whitepaper.md), the Wiki [Roadmap](https://github.com/RfidResearchGroup/ChameleonUltra/wiki/Public-Roadmap) and [Wishlist](https://github.com/RfidResearchGroup/ChameleonUltra/wiki/Wishlist).
No need for creating issues for well known missing supports, we are already aware :)
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.
Copyright of each contribution is tracked by the Git history.
See the output of `git shortlog -nse` for a full list or `git log --pretty=short --follow <path/to/sourcefile> |git shortlog -ne` to track a specific file.
See also [the Contributors page on Github](https://github.com/RfidResearchGroup/ChameleonUltra/graphs/contributors).
All notable changes to this project will be documented in this file.
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
In this file you can look up how to [edit](#Editing-the-code), [compile](#Compiling-the-code) and [debug](#Debugging-the-code) the code!
## Editing the code
We are using [Visual Studio Code](https://code.visualstudio.com/download) to edit this project! Simply download and install it!
- Install the [ARM-GCC](https://mynewt.apache.org/latest/get_started/native_install/cross_tools.html) version [9.3.1 Compiler](https://developer.arm.com/downloads/-/gnu-rm) and remember the path where you installed it.
- Install the [C++ Extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools) in VS-Code.
- Create a new IntelliSense Configuration:
- press F1 in VS-Code and enter `C/C++: Edit Configurations (UI)`
- Add a new Configuration and name it
- Specify your Compiler path (path of previously installed Compiler `bin` folder)
- Change IntelliSense mode to `gcc-arm (legacy)`
- Add include path `${workspaceFolder}/**`
## Compiling the code
- Install the compiler (for instructions have a look at [Editing the code](#Editing-the-code))
- Edit Makefile.defs:
- Change `GNU_INSTALL_ROOT`(path of previously installed Compiler `bin` folder)
- Change `GNU_VERSION` (Version of the installed Compiler)
- Don't forget to remove the `#` in front of the changed lines
- Install make
- **Ubuntu:**
- Open a terminal.
- Run the following command to install Make: `sudo apt-get install build-essential`
- **Windows using Chocolatey:**
- Install Chocolatey:
- Open a PowerShell terminal with administrator privileges.
- Run the following command to install Chocolatey:
- In the same PowerShell terminal, run the following command to install Make using Chocolatey: `choco install make`
- **macOS:**
- Open a terminal.
- Install Homebrew package manager by running the following command: `/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"`
- Once Homebrew is installed, run the following command to install Make: `brew install make`
This guide goal is to guide you through setting up and using your Chameleon Ultra and Lite.
This Guide is split up into multiple "subguides":
### About the device
- [Whitepaper](./technical_whitepaper.md): Discover what the Chameleon Ultra is capable of.
- [Hardware](./hardware.md): Learn to know the hardware of your Chameleon.
- [Firmware](./firmware.md): Your Chameleon runs a firmware, learn what it can do and how to use it.
### Interacting with the device
- [Quickstart](./quickstart.md): For the impatient people to just get you up and running with anything.
- [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.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.md): For when things go wrong, here are some common tips to maybe fix whatever issue you might have.
### For developers
- [Development](./development.md): For all developers. This covers how to build firmware from source and set up a development environment.
- [SDKs](./sdk.md): SDKs for Chameleon, useful if you want to develop your own application to control Chameleon.
- [Protocol](./protocol.md): The gory details of the communication protocol, useful if you want to develop your own client.
### Miscellaneous
- [Modding](./modding.md): Third party moddings worth mentioning.
- [FAQ](./faq.md): **F**requently **A**sked **Q**uestions, if you have a question, it might already be answered here.
- the *Device Name*: `Chameleon Ultra` or `Chameleon Lite` depending on the device connected ;
- the *Disconnect* button: pressing this icon cleanly disconnects the Chameleon. It is recommended to use this button whenever possible ;
- the *Connected Port*: it tells you where and how the chameleon is connected, followed by how it is connected (*Connection Method*), which displays a USB or Bluetooth icon. Last in that row is the *Battery Charge* display ;
- the *Used Slots*: it displays how many out of the 8 slots are used ;
- the *Slot Changer*: the currently selected slot is highlighted with a red circle, while enabled slots are filled in. Everything else is a hollow circle. The arrows left and right allow you to change the currently selected slot ;
- the *Firmware version*: the version is pulled from the device displayed, as well as git commit information ;
- the *Check for updates* button: it compares the firmware with the one available on GitHub and then updates if a newer version is available ;
- the *Switch mode* button: use it to switch between reader and emulator modes. The icon will update accordingly ;
- the *Device Setting* button: it allows you to change settings concerning the device, like changing the animation mode.
- *Enter DFU mode*: to enter the device DFU mode. Allows the user to take over ;
- *Flash latest FW via DFU*: download the newest firmware from GitHub, disregarding if the device is already up to date, and flash it ;
- *Flash .zip FW via DFU*: it allows the user to select a zip they would like to flash to the device ;
- *Animations*: choose if the device should play the boot-up animation when woken up by an external RFID field ;
- *Button config*: it allows you to define both short-press and long-press actions
- *BLE pairing* toggle: you can decide whether pairing with a BLE PIN is required or not. Enabling PIN increases security at the loss of convenience. You can define a *BLE PIN* once pairing is enabled and you can force forgetting about existing pairings with the *Clear bounded devices* option.
- *Reset settings*: it resets all device settings but does not wipe user data.
- *Factory reset*: **IT WIPES ALL USER DATA** and resets the device to factory settings.
### Slot Manager

The *Slot Manager* consists of 8 cards representing the 8 slots on the device.
The *RFID icon* in the top left corner can either be green or red, meaning the slot is enabled and disabled respectively.
The *Credit Card icon* displays the name and card type of the HF card in the slot.
The *Wi-Fi icon*, on the other hand, displays the name and card type of the LF card in the slot.
The *Gear icon* opens the slot settings. These settings can be changed per slot.
The entire card is also one big button, pressing anywhere on the card opens the select dialog for loading a card.
The two rows at the top, labeled HF and LF respectively, display the names of the currently loaded cards. Next to them, the *X* clears them out of the slot. If both are empty, the slot will automatically be disabled.
Under *Slot Status* you can set if the slot is enabled or disabled.
The *Mifare Classic emulator settings* section allows you to toggle various behaviors:
- *Gen1A Magic Mode*: behaves like a gen1a magic card and allows writing to it using magic commands like the Proxmark3 `cload` ;
- *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.md).
### Search dialog

When using the GUI you may encounter a *Search* dialog. The dialog is structured as follows:
Top left you find the *Back* button, this will abort the selection and bring you back.
Near the end of the row, if it is a card search dialog, a filter option will show. This allows you to filter between *HF*, *LF* and *All* cards.
At the end you find a *X*, this X will clear the query.
You enter the query into the *textbox* on the top with the placeholder text "Search"
The search results get listed below. The Card or Wi-Fi symbol indicates if it is LF/HF. The color of the Icon is the user-defined color.
Listed also are the name and type.
Selecting the entry automatically closes the search.
### Saved Cards

The *Saved Cards* page allows you to manage your cards and dictionaries.
You import a card or dictionary by clicking the *+* button in their respective half. This opens a select dialog. You may then either select a CUGUI Json file or a Bin file. A Json file gets imported immediately while a Bin file asks if the supplied data is correct before saving.
Once again, we got a card per card or dictionary. At the left you find the Icon for HF/LF with the user-defined color. To the left of that the card name, type and quick actions for edit, export and delete.
The Card is again one Big button, pressing it brings up the Slot info. It displays info about the selected item and also has the quick actions present at the bottom.

### Card Edit Menu


Depending on the selected card type the menu only displays options applicable to it.
At the top of the menu is the name and icon. Pressing on the icon allows you to change the color.
Right below is the drop-down for the type. You may switch between any type at will.
A bit lower again you find the UID, SAK, ATQA, ATS and all other options for the selected type. This form auto-validates, so you should not be able to save a invalid config.
And finally at the bottom are the save and cancel options, to save the changes and exits, or to cancel the operation with no changes.
### Settings

The App settings have their own page and consist of a few simple settings:
- *Sidebar Expansion*: Whether or not the sidebar shall be expanded or if the windows size should decide that
- *Theme*: Light/Dark or get it from the System
- *Color Scheme*: Allows you to choose a color you like for the app
- *Language*: Choose any of the languages available. Translating is done via our Crowding project.
- *About*: Displays simple info about the app, such as build number, contributors and people who have donated on Opencollective
- *Activate debug mode*: Don't, just Don't
## How to use MFKEY32
- set slot to MIFARE Classic (by uploading an empty dump)
- enable mfkey32 for that slot (toggle in slot settings)
- select slot and present ultra repeatedly to the reader in order to collect nonces
- after collecting some nonces, go back into slot settings and click recover keys
## Troubleshooting
### Font scaling issues on HiDPI screens
If you have font scaling issues (tiny fonts) with the Linux desktop app and a HiDPI screen, you can solve it by running the app as
### Key recovery from this card is not yet supported
This error may occur when the card you are trying to recovery keys from is requiring a not yet supported recovery technology. You cannot tell the required recovery method from the outside.
You may be able to solve this issue by dumping the card with a Proxmark3 or Mifare Classic Tool (Mobile App) and then importing a bin file.
The CLI (**C**ommand **L**ine **I**nterface) is the official way to control your Chameleon.
It requires at least **Python 3.9** version.
## Installing
There are multiple ways to install the CLI, depending on your OS.
### Windows
Windows users have the choice of 4 options:
#### ProxSpace
Using ProxSpace to build the CLI is the easiest and most comfortable way to get started.
1. Download ProxSpace from the [official GitHub](https://github.com/Gator96100/ProxSpace/releases/latest)
2. [Download 7zip](https://www.7-zip.org/) to extract the archive
3. Install 7zip by double clicking the Installer and clicking `Install`
4. Right-click on the downloaded archive and select `7zip -> Unpack to "ProxSpace"`
5. Open a terminal in the proxspace folder. If you are on a new Windows install, you should be able to just right-click and select `Open in Terminal`. If that option is not visible and the ProxSpace folder is still in your downloads folder, press `win+r` and type `powershell` followed by enter. In Powershell now type `cd ~/Downloads/ProxSpace`
6. Run the command `.\runme64.bat`. After successful completion, you should be dropped to the `pm3 ~ $` shell.
7. Clone the Repository by typing `git clone https://github.com/RfidResearchGroup/ChameleonUltra.git`
8. Now go into the newly created folder with `cd ChameleonUltra/software/src`
9. Prepare for package installation with `pacman-key --init; pacman-key --populate; pacman -S msys2-keyring --noconfirm; pacman-key --refresh`
10. Proceed by installing Ninja with `pacman -S ninja --noconfirm`
11. Build the required config by running `cmake .`
12. And the binaries with `cmake --build .`
13. Copy the binaries by running `cp -r ~/ChameleonUltra/software/bin/* ~/ChameleonUltra/software/script/`
14. Go into the script folder with `cd ~/ChameleonUltra/software/script/`
15. Install python requirements with `pip install -r requirements.txt`
16. Finally run the CLI with `python chameleon_cli_main.py`
To use after installing, just do the following:
1. Run `runme64.bat`
2. Go into the script folder with `cd ~/ChameleonUltra/software/script/`
3. Run the CLI with `python chameleon_cli_main.py`
#### WSL2
Coming Soon
#### WSL1
Coming Soon
#### Build Natively
Building natively is a bit more advanced and not recommended for beginners
1. Download and install [Visual Studio Community](https://visualstudio.microsoft.com/de/downloads/)
2. On the workload selection screen, choose the `Desktop development with C++` workload. Click `Download and Install`
3. Download and install [git](https://git-scm.com/download). When asked, add to your path
4. Download and install [cmake](https://cmake.org/download/). Again, when asked, add to your path
5. Download and install [python](https://www.python.org/downloads/). When asked, add to your path (small checkbox in the bottom left)
6. Choose a suitable location and open a terminal. Clone the repository with `git clone https://github.com/RfidResearchGroup/ChameleonUltra.git`
7. Change into the binaries folder with `cd ChameleonUltra/software/src`
8. Build the required config by running `cmake .`
9. And the binaries with `cmake --build .`
10. Copy the binaries by running `cp -r ../bin/Debug/* ../script/`
11. Go into the script folder with `cd ../script/`
12. Create a python virtual environment with `python -m venv venv`
13. Activate it by running `.\venv\Scripts\Activate.ps1`
14. Install python requirements with `pip install -r requirements.txt`
15. Finally run the CLI with `python chameleon_cli_main.py`
To run again after installing, just do the following:
1. Activate venv by running `.\venv\Scripts\Activate.ps1`
2. Run the CLI with `python chameleon_cli_main.py`
### Linux
*Coming Soon*
### MacOS
*Coming Soon*
## Usage
When in the CLI, plug in your Chameleon and connect with `hw connect`. If autodetection fails, get the Serial Port used by your Chameleon and run `hw connect -p COM11` (Replace `COM11` with your serial port, on Linux it may be `/dev/ttyACM0`)
### Common activities
- Connect to the CLI: `hw connect`
- Change slot: `hw slot change -s [1-8]`
*More examples coming soon*
### MFKEY32v2 walk-through
Make sure to be in the `software/` directory and run the Python CLI from there.
- Connect to the CLI: `hw connect`
- Check which slot can be used: `hw slot list`
- Change the slot type, here using slot 8 for a MFC 1k emulation: `hw slot type -s8 -t3`
- Init the slot content: `hw slot init -s8 -t3`
- or load an existing dump and set UID and anticollision data, cf `hf mf eload -h` and `hf mf sim -h`
- Enable the slot: `hw slot enable -s8 -e1`
- Change to the new slot: `hw slot change -s8`
- Activate the detection: `hf detection enable -e1`
Now disconnect, go to a reader and swipe it a few times
- Come back and connect to the CLI: `hw connect`
- See if nonces were collected: `hf detection count`
- We need 2 nonces per key to recover
- Recover the key(s) based on the collected nonces: `hf detection decrypt`. Output example:
```
- MF1 detection log count = 6, start download.
- Download done (144bytes), start parse and decrypt
- Detection log for uid [DEADBEEF]
> Block 0 detect log decrypting...
> Block 1 detect log decrypting...
> Result ---------------------------
> Block 0, A key result: ['a0a1a2a3a4a5', 'aabbccddeeff']
> Block 1, A key result: ['010203040506']
```
- To clean the logged detection nonces: `hf detection enable -e0` then `hf detection enable -e1`
In this file you can look up how to [install requirements](#Prerequisites-for-compiling), [edit](#Editing-the-code), [compile](#Compiling-the-code) and [debug](#Debugging-the-code) the firmware!
## Prerequisites for compiling
### install a cross-compiler
So far, the following compilers have been reported to work fine.
- [arm-gnu-toolchain-12.2.rel1-XXX-arm-none-eabi](https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads), e.g. [arm-gnu-toolchain-12.2.rel1-x86_64-arm-none-eabi.tar.xz](https://developer.arm.com/-/media/Files/downloads/gnu/12.2.rel1/binrel/arm-gnu-toolchain-12.2.rel1-x86_64-arm-none-eabi.tar.xz) for a x86_64 Linux host
Always use the official versions from ARM, *DO NOT* install `gcc-arm-none-eabi` from Debian/Ubuntu.
For some unknown reasons, same gcc version from Debian creates a bootloader too large to fit in the allocated flash space.
Moreover it does not contain the `gdb` debugger.
### install make
* **Debian/Ubuntu alike**
* Open a terminal.
* Run the following command to install Make: `sudo apt-get install build-essential`
* **Windows using Chocolatey:**
* Open a PowerShell terminal with administrator privileges.
* If not yet installed, run the following command to install Chocolatey:
* In the same PowerShell terminal, run the following command to install Make using Chocolatey: `choco install make`
* **macOS:**
* Open a terminal.
* If not yet installed, install Homebrew package manager by running the following command: `/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"`
* Once Homebrew is installed, run the following command to install Make: `brew install make`
- Install [nRF Command Line Tools](https://www.nordicsemi.com/Products/Development-tools/nrf-command-line-tools/download) to get `nrfjprog`, `mergehex` etc.
### install programmer tools
Depending on the hardware programmer you want to use, additional tools are needed.
- If under Windows, install [ST-Link drivers](https://www.st.com/en/development-tools/stsw-link009.html), extract the zip and run `dpinst_amd64.exe`
### configure the project
- Edit `Makefile.defs`:
- Change `GNU_INSTALL_ROOT` (path of previously installed Compiler `bin` folder)
- Change `GNU_VERSION` (Version of the installed Compiler) (FIXME: is it really used?)
- Change the other paths to match your system if needed
- Don't forget to remove the `#` in front of the changed lines
- Alternatively, if you are committing often code, it may be easier to leave `Makefile.defs` intact and to invoke `make` with the desired variables from a script, e.g. `make GNU_INSTALL_ROOT=../../../arm-gnu-toolchain-12.2.rel1-x86_64-arm-none-eabi/bin/`
## Editing the code
You can use [Visual Studio Code](https://code.visualstudio.com/download) to edit this project! Simply download and
install it!
- Install the [C++ Extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools) in VS-Code.
- Install
the [C++ Extension Pack](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools-extension-pack) in
VS-Code.
- Create a new IntelliSense Configuration:
- press F1 in VS-Code and enter `C/C++: Edit Configurations (UI)`
- Add a new Configuration and name it
- Specify your Compiler path (path of previously installed Compiler `bin` folder)
- Change IntelliSense mode to `gcc-arm (legacy)`
- Add include path `${workspaceFolder}/**`
## Compiling the code
- Install prerequisites (for instructions have a look at [Prerequisites for compiling](#Prerequisites-for-compiling))
- Run `build.sh` or try to execute its steps manually if your platform is not yet properly supported. Feedback is always welcome.
The script produces several images in `objects`.
*`fullimage.hex` to be used with a programmer over the SWD pins
*`dfu-app.zip` and `dfu-full.zip` to be used with DFU mode
## Uploading the code in DFU mode
If the bootloader and the SoftDevice are already properly installed on the Chameleon, you can reflash it directly over DFU.
To set the device in DFU mode:
* you can use the Python client and issue the command `hw dfu`
* you can use the script `resource/tools/enter_dfu.py` that does exactly the same but may be easier to call from your scripts
* you can unplug the device, wait for it to sleep, then press the button B and plug it. If the application is bogus, this is the only way.
The LEDs 4 & 5 should blink green when in DFU mode.
To flash only the application (safer):
`nrfutil device program --firmware objects/dfu-app.zip --traits nordicDfu`
To flash everything (be sure to also have a JLink or ST-Link V2 programmer if something goes wrong):
`nrfutil device program --firmware objects/dfu-full.zip --traits nordicDfu`
Under Linux you can use the scripts `flash-dfu-app.sh` and `flash-dfu-full.sh`, they will put the device in DFU mode and flash it.
## Uploading the code with a programmer
Connect pins GND, SWC (swclk) and SWD (swdio) to your programmer.
If you are adventurous it is possible to flash the device over BLE (DFU mode).
To put the device in DFU mode
* you can use the Python client and issue the command `hw dfu`**TODO:** this will be possible only when the client will be able to work over BLE...
* you can use the script `resource/tools/enter_dfu_over_ble.py`
Once in DFU mode, the device will announce itself over BLE as `CU-xxxx` where xxxx are the last 2 bytes of the Device Serial Number.
Then use the official [nRF Device Firmware Update](https://www.nordicsemi.com/Products/Development-tools/nRF-Device-Firmware-Update) mobile application to flash one of the DFU images.
Get [BMP full sources](https://github.com/blackmagic-debug/blackmagic/releases)
Comment out all probes except Nordic nrf51 in `src/target/cortexm.c` big switch for probes. It should remain
```c
switch(t->designer_code){
caseJEP106_MANUFACTURER_NORDIC:
PROBE(nrf51_probe);
break;
}
```
```
make -j PROBE_HOST=stlink ST_BOOTLOADER=1 ENABLE_RTT=1
```
Then flash the ST_Link V2
```
stlink-tool src/blackmagic.bin
```
See [src/platforms/stlink/README.md](https://github.com/blackmagic-debug/blackmagic/blob/main/src/platforms/stlink/README.md) for more details.
Unplug/plug.
Every time you plug the ST-Link, you have to run `stlink-tool` to enable BMP.
Under linux, it is convenient to install [udev rules](https://github.com/blackmagic-debug/blackmagic/blob/main/driver/README.md#99-blackmagic-plugdevrules) to get aliases `/dev/ttyBmpGdb` and `/dev/ttyBmpTarg`.
Note that using a native ST-Link V2 with BlackMagicProbe "hosted" will not allow to see NRF_LOG messages.
## Debugging the code with gdb and BMP with RTT to monitor NRF_LOG
Assuming you have a BlackMagicProbe with RTT support made out of a ST-Link V2.
RTT usage: https://black-magic.org/usage/rtt.html
```
stlink-tool
sleep 1
screen /dev/ttyBmpTarg
```
In another terminal
```
$ arm-none-eabi-gdb
(gdb) target extended-remote /dev/ttyBmpGdb
(gdb) monitor swdp_scan
1 Nordic nRF52 M4
2 Nordic nRF52 Access Port.
(gdb) attach 1
(gdb) monitor rtt
```
We are now able to use gdb and see the NRF_LOG messages on the other terminal.
One can set `NRF_LOG_UART_ON_SWO_ENABLED := 1` in `Makefile.defs` to activate this functionality.
When activated, NRF_LOG will be available if one connects a UART bridge to the SWO pin which will work as a UART TX pin.
UART works at 115200 bauds. E.g. one can use a FTDI dongle and `screen /dev/ttyUSB0 115200`.
Contrary to RTT that needs to be activated by a JTAG probe, UART logs are immediately available.
Limitations:
* SWO pin is shared with... SWO so when e.g. reflashing the device, garbage may appear on the monitoring terminal.
* SWO pin is also shared with the blue channel of the RGB slot LEDs, so faint blue may appear briefly when logs are sent and LED might not work properly when supposed to be blue.
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.md)
## The Bootloader
The bootloader is the lowest-level program running on your Chameleon. It is read-only and provides the DFU (**D**evice **F**irmware **U**pgrade) mode. The bootloader being read-only, it makes it really hard to brick your Chameleon. The flash also contains a special section to store bootloader settings required by the nRF to deal with upgrades. This is only a concern for developers.
You enter DFU mode by of the following methods:
1. Physical button
- Disconnect the Chameleon and wait for it to enter sleep mode
- Hold down the π button. If you are using Windows you have to wait about ~5s before next step.
- Plug USB into a PC while still holding the button. If you are using Windows you have to wait about ~10s before next step.
- Then release the π button
2. From CLI
- Execute the command `hw dfu`
3. From GUI
- Click on `Enter DFU mode`
4. From Shell
- Execute the script `resource/tools/enter_dfu.py`
The device stays in DFU mode for ~30s.
While in DFU mode waiting for the update, the LEDs 4 and 5 blink alternatively green π’π’.
You can then perform firmware upgrades either via a GUI or the command line:
1. Download nRF Util from the [nRF website](https://www.nordicsemi.com/Products/Development-tools/nrf-util)
2. Open a Command Line / Terminal on your PC
3. Install the "device" toolkit by running `nrfutil install device`
4. Download the Chameleon firmware from [GitHub](https://github.com/RfidResearchGroup/ChameleonUltra/releases). At the moment it is better to take the *Development release* but beware bugs can occur. Choose `ultra-dfu-app.zip` for the Ultra or the Devkit, and `lite-dfu-app.zip` for the Lite.
5. Put your Chameleon into DFU mode and install the firmware with the following command: `nrfutil device program --firmware ultra-dfu-app.zip --traits nordicDfu` (keep in mind to change the filename if you are using a Lite).
Step 5: Alternatively you can connect the Chameleon over USB and use the script `firmware/flash-dfu-app.sh` which will take care of flipping it into DFU mode and flashing it with the adequate firmware.
While flashing firmware is in progress, the LEDs 4 and 5 should blink fast blue π΅π΅ and the firmware update should be finished in a matter of seconds. Using DFU and performing a firmware update also helps recovering from most device-related issues.
If LEDs 4 and 5 are flashing slow red π΄π΄, it indicates an issue with DFU. Try to unplug and plug again or unplug and wait for it to timeout and try again the whole procedure.
## The Application
The application is the piece of software being loaded by the bootloader. It communicates with the client, emulates, reads and writes cards, drives the LEDs, handles buttons and much more. The application is also writable, it is the piece of software being updated via DFU.
The communication with the application is either done via the CLI or a GUI. Communication can be done over USB or BLE (**B**luetooth **L**ow **E**nergy), although, at time of writing, only GUIs support BLE.
On boot, the application starts in emulation mode, so it can emulate up to 8 HF tags and up to 8 LF tags (one slot can handle both a HF and a LF).
The Chameleon can be awaken:
- by pressing a button
- when it comes close to a HF or LF field, *only if* a card corresponding to that field (HF/LF) is loaded into the active slot.
The white LED labeled RF lights up when it detects a field, again only if the active slot supports it.
In some situations, it can be cumbersome to wait for the boot-up animation. This is configurable, cf e.g. the CLI command `hw settings animation set -h`.
On a new Chameleon (or after a factory reset), 3 slots are defined, slot 1 holding both a HF and a LF:
- slot 1 LF: a EM4100 with UID `DEADBEEF88`
- slot 1 HF: a MIFARE Classic 1k with UID `DEADBEEF`
- slot 2 HF: a MIFARE Classic 1k with UID `DEADBEEF`
- slot 3 LF: a EM4100 with UID `DEADBEEF88`
When a slot is selected, the LED shows what type of card is loaded with the following color code:
- π’ HF card loaded
- π΅ LF card loaded
- π΄ Both HF and LF loaded
When a dual HF/LF slot is activated by an external field, it will turn green or blue according to the frequency.
The application controls the buttons. The behavior of the buttons is customizable via the CLI or a GUI. The default behavior is the following:
- π short press: Select previous slot
- π short press: Select next slot
- π long press: Copy LF or HF tag UID (only Ultra, not Lite)
- π long press: Copy LF or HF tag UID (only Ultra, not Lite)
*About UID copy*: the action depends on the current slot support. So to be able to copy an EM4100 LF tag, the slot must be configured firstly to emulate an EM4100 tag. And to be able to copy a HF 14a tag, the slot must be configured for the right type of HF tag. Only the UID will be copied, not the data.
The Chameleon also shows the following LED effects:
- Charging: 4 pulsing green lights
- CLI / GUI connected over USB: Chasing LEDs in the color of the selected slot (left to right for slots 1-4 and right to left for slots 5-8).
The device enters sleep mode after about 5s unless it is plugged in USB or if a client is connected over BLE. You can use the buttons to wake it up again. You can also press quickly a button during the sleep animation to keep the device awake.
## Write Modes
- **Normal**: Behaves like any normal card
- **Denied**: Read-only card, send NACK to write attempts
- **Deceive**: Accepts write commands but don't change any data (reader thinks write was successful but when reading back, nothing changed)
- **Shadow**: Accepts writes but reverts changes when device goes to sleep (reader can read and write like a normal card but changes are kept in RAM and are lost when the chameleon goes to sleep)
## The SoftDevice
A [SoftDevice](https://infocenter.nordicsemi.com/index.jsp?topic=%2Fstruct_nrf52%2Fstruct%2Fnrf52_softdevices.html) is a precompiled and linked binary software implementing a wireless protocol developed by Nordic Semiconductor.
We are using the [SoftDevice S140](https://infocenter.nordicsemi.com/index.jsp?topic=%2Fstruct_nrf52%2Fstruct%2Fnrf52_softdevices.html) which implements a BLE Central and Peripheral protocol stack solution.
## The User Data
The Chameleon has a reserved space of memory and flash where it stores application settings, active slot and slots configurations and data. This will not be overwritten by DFU updates and the data will only be reset by either issuing `hw factory_reset --i-know-what-im-doing` in the CLI or clicking `Factory reset` in a GUI.
*Warning:* Settings and/or data might be reset to defaults if you downgrade the firmware version up to a version not supporting the newer format.
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.