Skip to content

Commit

Permalink
New DF_ENCMODE command to set ECB/CBC crypto modes ; Incremental chan…
Browse files Browse the repository at this point in the history
…ges to LibNFC test code ; Incomplete docs to edit elsewhere
  • Loading branch information
maxieds committed Jul 17, 2022
1 parent 3a89c4b commit 306865e
Show file tree
Hide file tree
Showing 11 changed files with 132 additions and 23 deletions.
53 changes: 51 additions & 2 deletions Doc/DESFireSupportReadme.md
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,23 @@ DESFire emulation if things suddenly fail after a call to this terminal command.
Putting the Chameleon through a full power recycle (battery off) should reset the setting
to the defaults.

#### DF_COMM_MODE -- Manually sets the communication mode of the current session

This commanf sets the encryption mode for cryptographic operations.
The two supported modes are ECB and CBC.
The default mode for AES and DES (all types) of encryption is ECB mode.
This is the supported mode for DESFire tags using the latest Proxmark3 software.

The syntax is demonstrated by the following examples:
```bash
DF_ENCMODE=ECB
DF_ENCMODE=DES:ECB
DF_ENCMODE=AES:ECB
DF_ENCMODE=CBC
DF_ENCMODE=DES:CBC
DF_ENCMODE=AES:CBC
```

## Supported functionality

### Tables of tested support for active commands
Expand Down Expand Up @@ -283,6 +300,33 @@ to the defaults.
| CMD_ISO7816_READ_RECORDS | 0xb2 | | :wavy_dash: :question: | Needs testing. |
| CMD_ISO7816_APPEND_RECORD | 0xe2 | | :wavy_dash: :question: | Especially needs testing for corner case checks. |

### Proxmark3 (PM3) compatibility and support

The next PM3 commands are known to work with the Chameleon DESFire tag emulation (using both the RDV4 and Easy device types).
The sample outputs obtained running the ``pm3`` command line utility below may vary by usage and proximity to the PM3 hardware.

#### Getting a summary of tag information

```bash
TODO
```

#### ISODES authentication with the PICC and PICC master key

```bash
TODO
```

### Compatibility with external USB readers and LibNFC

The DESFire configurations are known to work with the anticollision and RATS handshaking utility ``nfc-anticol`` from LibNFC.
The Mifare DESFire commands installed by LibFreeFare have not been tested nor confirmed to work with the Chameleon Mini.
The developers are actively working to ensure compatibility of the Chameleon DESFire emulation with external USB readers used
running ``pcscd`` and ``pcsc_spy``. This support is not yet functional with tests using ACR-122 and HID Omnikey 5022CL readers.
The DESFire support for the Chameleon Mini is tested with the LibNFC-based source code
[developed in this directory]() with
[sample dumps and output here]().

### Links to public datasheets and online specs

The following links are the original online resource links are
Expand Down Expand Up @@ -342,12 +386,17 @@ repositories and code bases:

## New development sources of DESFire support for the Chameleon Mini

David Oswald has added a [DESFire emulation project](https://github.com/orgs/emsec/projects?type=classic) to organize tasks in progress for DESFire emulation support on the Chameleon Mini. The [original development sources](https://github.com/maxieds/ChameleonMiniDESFireStack/releases) are now archived and not kept up to date. Development sources for pull request projects in progress by **@maxieds** are [located here](https://github.com/maxieds/ChameleonMini). For example, a newer branch can be built by running
David Oswald has added a [DESFire emulation project](https://github.com/orgs/emsec/projects?type=classic) to organize tasks in
progress for DESFire emulation support on the Chameleon Mini. The
[original development sources](https://github.com/maxieds/ChameleonMiniDESFireStack/releases) are now archived and
not kept up to date with the latest firmware pull requests and development sources. There are development sources for pull request projects in
progress written by **@maxieds** are [located here](https://github.com/maxieds/ChameleonMini).
For example, a newer branch can be built by running
```bash
$ git clone https://github.com/maxieds/ChameleonMini.git
$ cd ChameleonMini
$ git checkout DESFireNFCExternalUSBReaderPatches-LibNFCTestCode
$ cd Firmware/ChameleonMini
$ make desfire-dev
```
Other GitHub users are developing mods of the emsec firmware sources for projects such as Mifare DESFire Plus support elsewhere.
Other GitHub users are developing modifications of the main firmware sources for projects that include Mifare DESFire Plus support elsewhere.
2 changes: 1 addition & 1 deletion Firmware/Chameleon-Mini/Application/CryptoAES128.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ static aes_callback_t __CryptoAESCallbackFunc = NULL;
static CryptoAESBlock_t __CryptoAES_IVData = { 0 };

/* Set the last operation mode (ECB or CBC) init for the context */
static uint8_t __CryptoAESOpMode = CRYPTO_AES_ECB_MODE;
uint8_t __CryptoAESOpMode = CRYPTO_AES_ECB_MODE;

void aes_start(void) {
AES.CTRL |= AES_START_bm;
Expand Down
10 changes: 6 additions & 4 deletions Firmware/Chameleon-Mini/Application/CryptoAES128.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,14 @@
#define CRYPTO_AES_KEY_SIZE_192 1 // 192-bit
#define CRYPTO_AES_KEY_SIZE_256 2 // 256-bit

/* AES Operation cipher mode */
/* AES Operation cipher modes */
#define CRYPTO_AES_ECB_MODE 0 // Electronic Code Book mode
#define CRYPTO_AES_CBC_MODE 1 // Cipher Block Chaining mode
#define CRYPTO_AES_OFB_MODE 2 // Output FeedBack mode
#define CRYPTO_AES_CFB_MODE 3 // Cipher FeedBack mode
#define CRYPTO_AES_CTR_MODE 4 // Counter mode
#define CRYPTO_AES_OFB_MODE 2 // Output FeedBack mode (NOT SUPPORTED)
#define CRYPTO_AES_CFB_MODE 3 // Cipher FeedBack mode (NOT SUPPORTED)
#define CRYPTO_AES_CTR_MODE 4 // Counter mode (NOT SUPPORTED)

extern uint8_t __CryptoAESOpMode;

/* AES URAD Type */
#define CRYPTO_AES_URAT_INPUTWRITE_DMA 0 // Input Data Register written during the data processing in DMA mode
Expand Down
2 changes: 1 addition & 1 deletion Firmware/Chameleon-Mini/Application/CryptoTDEA.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
#include "CryptoAES128.h"

/* Set the last operation mode (ECB or CBC) init for the context */
static uint8_t __CryptoDESOpMode = CRYPTO_DES_ECB_MODE;
uint8_t __CryptoDESOpMode = CRYPTO_DES_ECB_MODE;

static void CryptoEncryptCBCBuffer(CryptoTDEA_CBCSpec *CryptoSpec, uint16_t Count, const void *Plaintext, void *Ciphertext, const uint8_t *IVIn, const uint8_t *Keys);
static void CryptoEncryptCBCBuffer(CryptoTDEA_CBCSpec *CryptoSpec, uint16_t Count, const void *Plaintext, void *Ciphertext, const uint8_t *IVIn, const uint8_t *Keys) {
Expand Down
4 changes: 3 additions & 1 deletion Firmware/Chameleon-Mini/Application/CryptoTDEA.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,12 @@ PCD's side.
*/

/* DES Operation cipher mode */
/* DES Operation cipher modes */
#define CRYPTO_DES_ECB_MODE 0 // Electronic Code Book mode
#define CRYPTO_DES_CBC_MODE 1 // Cipher Block Chaining mode

extern uint8_t __CryptoDESOpMode;

/* Key sizes, in bytes */
#define CRYPTO_DES_KEY_SIZE 8 /* Bytes */
#define CRYPTO_2KTDEA_KEY_SIZE (CRYPTO_DES_KEY_SIZE * 2)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,4 +145,46 @@ CommandStatusIdType CommandDESFireSetCommMode(char *OutParam, const char *InPara
return COMMAND_ERR_INVALID_USAGE_ID;
}

CommandStatusIdType CommandDESFireSetEncryptionMode(char *OutParam, const char *InParams) {
if (!IsDESFireConfiguration()) {
return COMMAND_ERR_INVALID_USAGE_ID;
}
char valueStr[16];
if (!sscanf_P(InParams, PSTR("%15s"), valueStr)) {
return COMMAND_ERR_INVALID_PARAM_ID;
}
valueStr[15] = '\0';
char *modeStartPos = strchr(valueStr, ':');
bool setAESCryptoMode = true, setDESCryptoMode = true;
bool ecbModeEnabled = true;
if (modeStartPos == NULL) {
modeStartPos = &valueStr;
} else {
uint8_t prefixLength = (uint8_t)(modeStartPos - valueStr);
if (prefixLength == 0) {
return COMMAND_ERR_INVALID_USAGE_ID;
} else if (!strncasecmp_P(valueStr, PSTR("DES"), prefixLength)) {
setAESCryptoMode = false;
} else if (!strncasecmp_P(valueStr, PSTR("AES"), prefixLength)) {
setDESCryptoMode = false;
} else {
return COMMAND_ERR_INVALID_USAGE_ID;
}
}
if (!strcasecmp_P(modeStartPos, PSTR("ECB"))) {
ecbModeEnabled = true;
} else if (!strcasecmp_P(modeStartPos, PSTR("CBC"))) {
ecbModeEnabled = false;
} else {
return COMMAND_ERR_INVALID_USAGE_ID;
}
if (setDESCryptoMode) {
__CryptoDESOpMode = ecbModeEnabled ? CRYPTO_DES_ECB_MODE : CRYPTO_DES_CBC_MODE;
}
if (setAESCryptoMode) {
__CryptoAESOpMode = ecbModeEnabled ? CRYPTO_AES_ECB_MODE : CRYPTO_AES_CBC_MODE;
}
return COMMAND_INFO_OK;
}

#endif /* CONFIG_MF_DESFIRE_SUPPORT */
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ CommandStatusIdType CommandDESFireSetHeaderProperty(char *OutMessage, const char
#define DFCOMMAND_COMM_MODE "DF_COMM_MODE"
CommandStatusIdType CommandDESFireSetCommMode(char *OutMessage, const char *InParams);

#define DFCOMMAND_SET_ENCMODE "DF_ENCMODE"
CommandStatusIdType CommandDESFireSetEncryptionMode(char *OutMessage, const char *InParams);

#endif /* DESFire Support */

#endif /* __DESFIRE_CHAMELEON_TERMINAL_H__ */
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ This notice must be retained at the top of all source files where indicated.
.ExecParamFunc = NO_FUNCTION,
.SetFunc = CommandDESFireSetCommMode,
.GetFunc = NO_FUNCTION
}, {
.Command = DFCOMMAND_SET_ENCMODE,
.ExecFunc = NO_FUNCTION,
.ExecParamFunc = NO_FUNCTION,
.SetFunc = CommandDESFireSetEncryptionMode,
.GetFunc = NO_FUNCTION
},

#endif
Expand Down
10 changes: 6 additions & 4 deletions Firmware/Chameleon-Mini/BuildScripts/custom_build_targets.mk
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ desfire: FLASH_DATA_SIZE:=0x$(FLASH_DATA_SIZE_CONST)
desfire: FLASH_DATA_SIZE_UPPER_CONST:=20000
desfire: FLASH_DATA_ADDR:=0x$(shell echo $$(( 0x$(FLASH_DATA_SIZE_UPPER_CONST) - 0x$(FLASH_DATA_SIZE_CONST) )) | xargs -0 printf %X)
desfire: SUPPORTED_TAGS_BUILD:=-DCONFIG_MF_DESFIRE_SUPPORT
desfire: EXTRA_CONFIG_SETTINGS:=-DDESFIRE_CRYPTO1_SAVE_SPACE \
desfire: EXTRA_CONFIG_SETTINGS:=-DMEMORY_LIMITED_TESTING=1 \
-DDESFIRE_CRYPTO1_SAVE_SPACE \
-finline-small-functions
desfire: TARGET_CUSTOM_BUILD_NAME:=DESFire
desfire: CONFIG_SETTINGS:=$(SUPPORTED_TAGS_BUILD) -DDEFAULT_CONFIGURATION=CONFIG_NONE $(EXTRA_CONFIG_SETTINGS)
Expand All @@ -67,11 +68,12 @@ desfire-dev: FLASH_DATA_SIZE:=0x$(FLASH_DATA_SIZE_CONST)
desfire-dev: FLASH_DATA_SIZE_UPPER_CONST:=20000
desfire-dev: FLASH_DATA_ADDR:=0x$(shell echo $$(( 0x$(FLASH_DATA_SIZE_UPPER_CONST) - 0x$(FLASH_DATA_SIZE_CONST) )) | xargs -0 printf %X)
desfire-dev: SUPPORTED_TAGS_BUILD:=-DCONFIG_MF_DESFIRE_SUPPORT
desfire-dev: EXTRA_CONFIG_SETTINGS:=-DDESFIRE_CRYPTO1_SAVE_SPACE \
-finline-small-functions \
desfire-dev: EXTRA_CONFIG_SETTINGS:=-DMEMORY_LIMITED_TESTING=1 \
-DDESFIRE_CRYPTO1_SAVE_SPACE \
-DDESFIRE_MIN_OUTGOING_LOGSIZE=0 \
-DDESFIRE_MIN_INCOMING_LOGSIZE=0 \
-DDESFIRE_DEBUGGING=1
-DDESFIRE_DEBUGGING=1 \
-finline-small-functions
desfire-dev: TARGET_CUSTOM_BUILD_NAME:=DESFire_DEV
desfire-dev: CONFIG_SETTINGS:=$(SUPPORTED_TAGS_BUILD) -DDEFAULT_CONFIGURATION=CONFIG_NONE $(EXTRA_CONFIG_SETTINGS)
desfire-dev: custom-build
Expand Down
2 changes: 1 addition & 1 deletion Firmware/Chameleon-Mini/Log.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#include "Common.h"

#ifdef MEMORY_LIMITED_TESTING
#define LOG_SIZE 1664 // 1024
#define LOG_SIZE 1536
#else
#define LOG_SIZE 2048
#endif
Expand Down
21 changes: 12 additions & 9 deletions Software/DESFireLibNFCTesting/LocalInclude/DesfireUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -177,25 +177,22 @@ static inline int AuthenticateISO(nfc_device *nfcConnDev, uint8_t keyIndex, cons
uint8_t *IVBuf = ActiveCryptoIVBuffer;
memcpy(encryptedRndB, rxDataStorage->rxDataBuf, CRYPTO_CHALLENGE_RESPONSE_SIZE);
memset(IVBuf, 0x00, CRYPTO_CHALLENGE_RESPONSE_SIZE);
//memcpy(IVBuf, &encryptedRndB[CRYPTO_CHALLENGE_RESPONSE_SIZE - CRYPTO_3KTDEA_BLOCK_SIZE], CRYPTO_3KTDEA_BLOCK_SIZE);
CryptoData_t desCryptoData = { 0 };
desCryptoData.keySize = 3 * 8;
desCryptoData.keyData = keyData;
desCryptoData.ivSize = CRYPTO_CHALLENGE_RESPONSE_SIZE;
Decrypt3DES(encryptedRndB, CRYPTO_CHALLENGE_RESPONSE_SIZE, plainTextRndB, IVBuf, desCryptoData);
if (PRINT_STATUS_EXCHANGE_MESSAGES) {
fprintf(stdout, " -- IV = ");
fprintf(stdout, " -- IV = ");
print_hex(IVBuf, CRYPTO_3KTDEA_BLOCK_SIZE);
}
RotateArrayRight(plainTextRndB, rotatedRndB, CRYPTO_CHALLENGE_RESPONSE_SIZE);
//memset(IVBuf, 0x00, CRYPTO_CHALLENGE_RESPONSE_SIZE);
memcpy(IVBuf, &encryptedRndB[CRYPTO_CHALLENGE_RESPONSE_SIZE - CRYPTO_3KTDEA_BLOCK_SIZE], CRYPTO_3KTDEA_BLOCK_SIZE);
desCryptoData.ivData = IVBuf;
GenerateRandomBytes(rndA, CRYPTO_CHALLENGE_RESPONSE_SIZE);
ConcatByteArrays(rndA, CRYPTO_CHALLENGE_RESPONSE_SIZE, rotatedRndB, CRYPTO_CHALLENGE_RESPONSE_SIZE, challengeResponse);
Encrypt3DES(challengeResponse, 2 * CRYPTO_CHALLENGE_RESPONSE_SIZE, challengeResponseCipherText, IVBuf, desCryptoData);
if (PRINT_STATUS_EXCHANGE_MESSAGES) {
fprintf(stdout, " -- IV = ");
fprintf(stdout, " -- IV = ");
print_hex(IVBuf, CRYPTO_3KTDEA_BLOCK_SIZE);
}

Expand All @@ -208,12 +205,14 @@ static inline int AuthenticateISO(nfc_device *nfcConnDev, uint8_t keyIndex, cons
memcpy(&sendBytesBuf[5], challengeResponseCipherText, 2 * CRYPTO_CHALLENGE_RESPONSE_SIZE);

if (PRINT_STATUS_EXCHANGE_MESSAGES) {
fprintf(stdout, " -- RNDA = ");
fprintf(stdout, " -- RNDA = ");
print_hex(rndA, CRYPTO_CHALLENGE_RESPONSE_SIZE);
fprintf(stdout, " -- RNDB = ");
fprintf(stdout, " -- RNDB = ");
print_hex(plainTextRndB, CRYPTO_CHALLENGE_RESPONSE_SIZE);
fprintf(stdout, " -- CHAL = ");
fprintf(stdout, " -- CHAL = ");
print_hex(challengeResponse, 2 * CRYPTO_CHALLENGE_RESPONSE_SIZE);
fprintf(stdout, " -- ENC-CHAL = ");
print_hex(challengeResponseCipherText, 2 * CRYPTO_CHALLENGE_RESPONSE_SIZE);
fprintf(stdout, " -> ");
print_hex(sendBytesBuf, sizeof(sendBytesBuf));
}
Expand All @@ -236,9 +235,13 @@ static inline int AuthenticateISO(nfc_device *nfcConnDev, uint8_t keyIndex, cons
uint8_t decryptedRndAFromPICCRotated[CRYPTO_CHALLENGE_RESPONSE_SIZE], decryptedRndA[CRYPTO_CHALLENGE_RESPONSE_SIZE];
//memcpy(IVBuf, &rxDataStorage->rxDataBuf[rxDataStorage->recvSzRx - CRYPTO_3KTDEA_BLOCK_SIZE - 1], CRYPTO_3KTDEA_BLOCK_SIZE);
//memset(IVBuf, 0x00, CRYPTO_CHALLENGE_RESPONSE_SIZE);
//memcpy(IVBuf, &rxDataStorage->rxDataBuf[CRYPTO_3KTDEA_BLOCK_SIZE], CRYPTO_3KTDEA_BLOCK_SIZE);
//memcpy(IVBuf, &rxDataStorage->rxDataBuf[CRYPTO_CHALLENGE_RESPONSE_SIZE - CRYPTO_3KTDEA_BLOCK_SIZE], CRYPTO_3KTDEA_BLOCK_SIZE);
//memcpy(IVBuf, &challengeResponseCipherText[2 * CRYPTO_CHALLENGE_RESPONSE_SIZE - CRYPTO_3KTDEA_BLOCK_SIZE], CRYPTO_3KTDEA_BLOCK_SIZE);
memcpy(IVBuf, &encryptedRndB[CRYPTO_3KTDEA_BLOCK_SIZE], CRYPTO_3KTDEA_BLOCK_SIZE);
Decrypt3DES(rxDataStorage->rxDataBuf, CRYPTO_CHALLENGE_RESPONSE_SIZE, decryptedRndAFromPICCRotated, IVBuf, desCryptoData);
if (PRINT_STATUS_EXCHANGE_MESSAGES) {
fprintf(stdout, " -- IV = ");
fprintf(stdout, " -- IV = ");
print_hex(IVBuf, CRYPTO_3KTDEA_BLOCK_SIZE);
}
RotateArrayLeft(decryptedRndAFromPICCRotated, decryptedRndA, CRYPTO_CHALLENGE_RESPONSE_SIZE);
Expand Down

0 comments on commit 306865e

Please sign in to comment.