Skip to content

Enhanced support for DESFire tag emulation#351

Open
maxieds wants to merge 32 commits intoemsec:masterfrom
maxieds:default-crypto-modes-in-makefile
Open

Enhanced support for DESFire tag emulation#351
maxieds wants to merge 32 commits intoemsec:masterfrom
maxieds:default-crypto-modes-in-makefile

Conversation

@maxieds
Copy link
Contributor

@maxieds maxieds commented Feb 6, 2026

Pull request - Enhanced support for DESFire emulation

New features provided

  • Support for the DF_KEYSCRUB command in the Chameleon terminal. It overwrites the DESFire AES/3DES key and IV buffers with random bytes one time. Successive calls to this command can be used to effectively obliterate the stored key data.
  • Software support for AES-192 and AES-256 encryption modes. Note that there are Atmel-supported AES-enabled boot loaders (see AN2462, page 20, XMEGA A Manual and XMEGA B Manual). It is not apparent to me how to install these boot loader variants on the Chameleon RevG AVR -
    but this boot loader support would allow hardware enabled AES-192 and AES-256 encryption.
  • Support for default PICC configurations in the Makefile. These settings are discussed in the DESFire Support documentation. The relevant Makefile lines for the default configurations are reproduced below:
## Manually set default DESFire PICC / tag spec settings: 
## See also the documentation for: ``make desfire-custom-tag``
SETTINGS += -DDESFIRE_DEFAULT_PICC_UID="(uint8_t *) { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 }"
SETTINGS += -DDESFIRE_DEFAULT_PICC_ATS="(uint8_t *) { 0x06, 0x75, 0x77, 0x81, 0x02, 0x80 }"
SETTINGS += -DDESFIRE_DEFAULT_PICC_ATQA="(uint8_t *) { 0x44, 0x03 }"
SETTINGS += -DDESFIRE_DEFAULT_PICC_MANUID="(uint8_t *) { 0x01 }"
SETTINGS += -DDESFIRE_DEFAULT_PICC_HWTYPE="(uint8_t *) { 0x01 }"
SETTINGS += -DDESFIRE_DEFAULT_PICC_HWSUBTYPE="(uint8_t *) { 0x00 }"
SETTINGS += -DDESFIRE_DEFAULT_PICC_HWPROTOTYPE="(uint8_t *) { 0x00 }"
SETTINGS += -DDESFIRE_DEFAULT_PICC_HWVERS="(uint8_t *) { 0x00, 0x00 }"
SETTINGS += -DDESFIRE_DEFAULT_PICC_SWTYPE="(uint8_t *) { 0x01 }"
SETTINGS += -DDESFIRE_DEFAULT_PICC_SWSUBTYPE="(uint8_t *) { 0x00 }"
SETTINGS += -DDESFIRE_DEFAULT_PICC_SWPROTOTYPE="(uint8_t *) { 0x00 }"
SETTINGS += -DDESFIRE_DEFAULT_PICC_SWVERS="(uint8_t *) { 0x00, 0x00 }"
SETTINGS += -DDESFIRE_DEFAULT_PICC_BATCHNO="(uint8_t *) { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }"
SETTINGS += -DDESFIRE_DEFAULT_PICC_PRODDATE="(uint8_t *) { 0x00, 0x26 }"
  • Support for scriptable (config-file-based in Firmware/Chameleon-Mini/DESFireCustomConfig/*.cfg) default PICC configurations. See the DESFire Support documentation: custom builds using make desire-custom-tag. The configuration file syntax is as in the following skeleton file:
# Configuration settings to emulate a custom tag
UID=xxxxxxxxxxxxxx
ATS=NNxxxx[...]
ATQA=xxxx
ManuID=xx
HwType=xx
HwSubtype=xx
HwProtoType=xx
HwVers=mmMM
SwType=xx
SwSubtype=xx
SwProtoType=xx
SwVers=mmMM
BatchNo=xxxxxxxxxx
ProdDate=WWYY
  • Support for a default DESFire PICC (master) key at build-time. This can be enabled by uncommenting the following line in Firmware/Chameleon-Mini/Makefile:
SETTINGS += -DDESFIRE_DEFAULT_PICC_MASTER_KEY='"My key string..."'

DESFire Gallagher support

Note that DESFire Gallagher support is now optional and enabled in the Firmware/Chameleon-Mini
Makefile by uncommenting:

SETTINGS += -DENABLE_DESFIRE_GALLAGHER -UENABLE_DESFIRE_AES_EXTENDED

TODO / NOTE: The current firmware compiled with make clean && make desfire crashes out with the following error when building with DESFire Gallagher support (enabled as above): "Application Section size 66205 excedes maximum allowed 65536. Please disable some features in Makefile" -- even with extended AES-192/256 support disabled. Can we save some space by omitting the large lut (scramble function) buffer and compute these values on the fly -- possibly with a penalty of slower scramble function performance?

@maxieds
Copy link
Contributor Author

maxieds commented Feb 6, 2026

Please note that this pull request is currently incomplete. I am stashing a working copy of the write-up for the PR here tonight. I am still working on the implementation of the software-based AES-192 and AES-256 encryption modes. This was supposed to be a one-day project, but as in most things software I am going to have to quit, sleep and multiply by 2-3. I will post back when the final branch is ready to be reviewed.

@tomaspre
Copy link
Collaborator

tomaspre commented Feb 6, 2026

When it comes to the AES192/256 bootloaders: As far as I'm aware, the HW crypto engine in the XMEGA supports only 128bit AES. The AN you linked only describes a process for the bootloader to decrypt AES192/256 encrypted FW. So this is relevant iff we'd encrypt our FW builds.

BTW, while it's nice to have the option to set the PICC specific settings (ATQA, manufacturer data, ...) using terminal commands, is it possible that those functions are using up the much needed space? It's perfectly ok to only change the UID (and possibly ATQA) using the terminal commands and rely on the UPLOAD/DOWNLOAD function for the rest. This would mean that those fields can only be changed by uploading a dump (which is definitely fine and easy).

As for the huge LUT for Gallagher: Unfortunately, that has to be there. It's a reverse engineered LUT from a different project.

@maxieds
Copy link
Contributor Author

maxieds commented Feb 6, 2026

The build script code to grep the config file for complete default configuration of a DESFire tag is implemented with a bash script (not built into the firmware) that outputs -D... type defines - which IIRC is just cut and paste at compile time for gcc. When I tested the Gallagher support this morning, I was not using the default configurations - so probably not. There is something weird going on with the Gallagher code though. I have the Makefile setup to exclude the AES-192/256 code when Gallagher support is enabled. The new AES-192/256 code defines two 256-byte arrays as const (and this works / compiles correctly) whereas the Gallagher code only defines one 256-byte array (which doesn't work / compile as expected) - even with those AES buffers excluded. So I'm not sure.

Update (see below): No, it's not the default configuration structures.

@maxieds
Copy link
Contributor Author

maxieds commented Feb 6, 2026

What remains to complete the pull request is to write the LibNFC test code for the new AES-192 and AES-256 encryption routines. I'm going to have to come back to this another day.

Dr. Maxie Dion Schmidt added 3 commits February 6, 2026 15:43
@maxieds
Copy link
Contributor Author

maxieds commented Feb 6, 2026

The issue with Gallagher support compilation is now fixed. Moreover, Gallagher support is now back in the default build of the DESFire firmware. The solution was to restrict the Chameleon terminal commands to only essential functionality.

@tomaspre: Does the new build have all the terminal commands you need to run Gallagher support?

@tomaspre
Copy link
Collaborator

tomaspre commented Feb 9, 2026

I've been thinking about this over the weekend, and I feel like it's a better idea to restrict the number of slots to seven or maybe even six. That should be enough space for all the code. :-)

…- Now works after restricting to two config slots (cannot go higher)
@maxieds
Copy link
Contributor Author

maxieds commented Feb 10, 2026

@tomaspre
DESFire Gallagher support can now be enabled in the Makefile by restricting to two config slots (cannot go higher in testing) and by excluding the new AES-192/256 software support.

@maxieds
Copy link
Contributor Author

maxieds commented Feb 13, 2026

@fptrs @david-oswald
I think the pull request is good to go. I haven't been able to run the LibNFC test code for the AES-128/192/256 routines because of bad driver issues on my old MacBook:

$ LIBNFC_LOG_LEVEL=3 nfc-list -v
info	libnfc.config	Unable to open file: /opt/local/etc/nfc/libnfc.conf
debug	libnfc.config	Unable to open directory: /opt/local/etc/nfc/devices.d
debug	libnfc.general	log_level is set to 3
debug	libnfc.general	allow_autoscan is set to true
debug	libnfc.general	allow_intrusive_scan is set to false
debug	libnfc.general	0 device(s) defined by user
nfc-list uses libnfc 1.7.1
debug	libnfc.driver.acr122_usb	device found: Bus 020 Device 009 Name ACS ACR122
debug	libnfc.general	1 device(s) found using acr122_usb driver
debug	libnfc.general	0 device(s) found using pn53x_usb driver
debug	libnfc.driver.acr122_usb	3 element(s) have been decoded from "acr122_usb:020:009"
error	libnfc.driver.acr122_usb	Unable to set alternate setting on USB interface (Result too large)
debug	libnfc.general	Unable to open "acr122_usb:020:009".
nfc-list: ERROR: Unable to open NFC device: acr122_usb:020:009
$ LIBNFC_LOG_LEVEL=3 nfc-scan-device -v
info	libnfc.config	Unable to open file: /opt/local/etc/nfc/libnfc.conf
debug	libnfc.config	Unable to open directory: /opt/local/etc/nfc/devices.d
debug	libnfc.general	log_level is set to 3
debug	libnfc.general	allow_autoscan is set to true
debug	libnfc.general	allow_intrusive_scan is set to false
debug	libnfc.general	0 device(s) defined by user
nfc-scan-device uses libnfc 1.7.1
debug	libnfc.driver.acr122_usb	device found: Bus 020 Device 010 Name ACS ACR122
debug	libnfc.general	1 device(s) found using acr122_usb driver
debug	libnfc.general	0 device(s) found using pn53x_usb driver
1 NFC device(s) found:
debug	libnfc.driver.acr122_usb	3 element(s) have been decoded from "acr122_usb:020:010"
error	libnfc.driver.acr122_usb	Unable to set alternate setting on USB interface (Result too large)
debug	libnfc.general	Unable to open "acr122_usb:020:010".
nfc_open failed for acr122_usb:020:010

Please merge the commits into the DESFire emulation when you can. Thank you guys at KAOS for the development hardware :)

@maxieds
Copy link
Contributor Author

maxieds commented Feb 22, 2026

@fptrs @david-oswald
Any progress towards merging this pull request?

@tomaspre
Copy link
Collaborator

The KAOS guys have tasked me with some maintenance for this repo. I'll try to go through your code and merge it asap. However, since you were not able to test it, it will probably take some time.

Also, could you please let me know of a practical use case for AES192/256 in DESFire? :-) As far as I know, even DESFire EV3 only supports AES128.

@maxieds
Copy link
Contributor Author

maxieds commented Feb 22, 2026

@tomaspre
Please use the PM3 to test. I do not have a precise test point from the DESFire sheets. I remember a couple of more recent DESFire tags using AES-256. Thank you.

@maxieds
Copy link
Contributor Author

maxieds commented Feb 25, 2026

@tomaspre
If you have access to an ACR122U NFC reader (or possibly another external reader supported by LibNFC), then you can run the tests I couldn't run because of driver issues as follows:

# From within the Github firmware directory:
$ cd Software/DESFireLibNFCTesting
$ make 
$ chmod + x ./Bin/TestAuthenticateAES*.exe
# Touch Chameleon RevG to ACR reader: 
$ ./Bin/TestAuthenticateAES128.exe
$ ./Bin/TestAuthenticateAES192.exe
$ ./Bin/TestAuthenticateAES256.exe

As far as whether Mifare DESFire tags in the wild support better than AES-128 bit encryption, I could not find a good data sheet reference, though Google's AI suggests the following:
Screen Shot 2026-02-25 at 4 33 21 PM
-- MDS

@maxieds
Copy link
Contributor Author

maxieds commented Mar 5, 2026

@tomaspre
Any progress with this pull request?

@Maxhy
Copy link

Maxhy commented Mar 5, 2026

@maxieds DESFire EV1/EV2/EV3 only support AES128. Complementary products around the DESFire family have some support of greater key length (eg. NXP SAM AV3), but the RFID chip itself not at this moment. Still, it could be good to be future proof for the next generation DESFire products I guess.
Thanks anyway for working at it!

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants