Skip to content
This repository has been archived by the owner on Mar 18, 2023. It is now read-only.

Commit

Permalink
Finalizing the fixes to emsec#313 to verify PM3 support
Browse files Browse the repository at this point in the history
  • Loading branch information
maxieds committed Jun 4, 2022
1 parent f9c1dab commit 024c699
Show file tree
Hide file tree
Showing 16 changed files with 525 additions and 486 deletions.
614 changes: 313 additions & 301 deletions Doc/DESFireSupportReadme.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -71,39 +71,45 @@ CommandStatusIdType CommandDESFireSetHeaderProperty(char *OutParam, const char *
dataByteCount = HexStringToBuffer(propSpecBytes, 16, propSpecBytesStr);
if (!strcasecmp_P(hdrPropSpecStr, PSTR("ATS"))) {
if (dataByteCount != 5) {
StatusError = 0x01;
StatusError = 1;
} else {
memcpy(&Picc.ATSBytes[0], propSpecBytes, dataByteCount);
}
} else if (!strcasecmp_P(hdrPropSpecStr, PSTR("ManuID"))) {
if (dataByteCount != 1) {
StatusError = 1;
} else {
Picc.ManufacturerID = propSpecBytes[0];
}
} else if (!strcasecmp_P(hdrPropSpecStr, PSTR("HardwareVersion"))) {
if (dataByteCount != 2) {
StatusError = 0x01;
StatusError = 1;
} else {
Picc.HwVersionMajor = propSpecBytes[0];
Picc.HwVersionMinor = propSpecBytes[1];
}
} else if (!strcasecmp_P(hdrPropSpecStr, PSTR("SoftwareVersion"))) {
if (dataByteCount != 2) {
StatusError = 0x01;
StatusError = 1;
} else {
Picc.SwVersionMajor = propSpecBytes[0];
Picc.SwVersionMinor = propSpecBytes[1];
}
} else if (!strcasecmp_P(hdrPropSpecStr, PSTR("BatchNumber"))) {
if (dataByteCount != 5) {
StatusError = 0x01;
StatusError = 1;
} else {
memcpy(Picc.BatchNumber, propSpecBytes, 5);
}
} else if (!strcasecmp_P(hdrPropSpecStr, PSTR("ProductionDate"))) {
if (dataByteCount != 2) {
StatusError = 0x01;
StatusError = 1;
} else {
Picc.ProductionWeek = propSpecBytes[0];
Picc.ProductionYear = propSpecBytes[1];
}
} else {
StatusError = 0x01;
StatusError = 1;
}
if (StatusError) {
CommandDESFireGetHeaderProperty(OutParam);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ void ISO144434Reset(void) {
Iso144434State = ISO14443_4_STATE_EXPECT_RATS;
Iso144434BlockNumber = 1;
ISO14443ALastDataFrameBits = 0;
LastReaderSentCmd = 0x00;
}

static uint16_t ISO144434ProcessBlock(uint8_t *Buffer, uint16_t ByteCount, uint16_t BitCount) {
Expand All @@ -100,9 +101,9 @@ static uint16_t ISO144434ProcessBlock(uint8_t *Buffer, uint16_t ByteCount, uint1
if (!ISO14443ACheckCRCA(Buffer, ByteCount)) {
LogEntry(LOG_ERR_APP_CHECKSUM_FAIL, Buffer, ByteCount);
/* ISO/IEC 14443-4, clause 7.5.5. The PICC does not attempt any error recovery. */
const char *debugPrintStr = PSTR("ISO14443-4: CRC fail; %04X vs %04X");
const char *debugPrintStr = PSTR("WARN: 14443-4: CRC fail; %04X vs %04X");
DEBUG_PRINT_P(debugPrintStr, *(uint16_t *)&Buffer[ByteCount],
ISO14443AUpdateCRCA(Buffer, ByteCount, 0x00));
ISO14443AAppendCRCA(Buffer, ByteCount));
return ISO14443A_APP_NO_RESPONSE;
}

Expand All @@ -127,7 +128,7 @@ static uint16_t ISO144434ProcessBlock(uint8_t *Buffer, uint16_t ByteCount, uint1
ISO144434SwitchState(ISO14443_4_STATE_ACTIVE);
const char *debugPrintStr = PSTR("ISO14443-4: SEND RATS");
LogDebuggingMsg(debugPrintStr);
return ByteCount * BITS_PER_BYTE; // PM3 expects no CRCA bytes
return ASBITS(ByteCount); // PM3 expects no CRCA bytes
}
case ISO14443_4_STATE_ACTIVE: {
/* See: ISO/IEC 14443-4; 7.1 Block format */
Expand Down Expand Up @@ -210,7 +211,6 @@ static uint16_t ISO144434ProcessBlock(uint8_t *Buffer, uint16_t ByteCount, uint1
/* 7.5.4.3, rule 12 */
/* This is a NAK. Send an ACK back */
Buffer[0] = ISO14443_PCB_R_BLOCK_STATIC | ISO14443_PCB_R_BLOCK_ACK | MyBlockNumber;
//ByteCount = 1;
// Per the NXP data sheet MF1S50YYX_V1 (Table 10: ACK / NAK), we should return 4 bits:
return 4;
} else {
Expand All @@ -220,7 +220,7 @@ static uint16_t ISO144434ProcessBlock(uint8_t *Buffer, uint16_t ByteCount, uint1
DEBUG_PRINT_P(debugPrintStr, __LINE__);
// Resend the data from the last frame:
if (ISO14443ALastDataFrameBits > 0) {
memcpy(&Buffer[0], &ISO14443ALastDataFrame[0], (ISO14443ALastDataFrameBits + BITS_PER_BYTE - 1) / BITS_PER_BYTE);
memcpy(&Buffer[0], &ISO14443ALastDataFrame[0], ASBYTES(ISO14443ALastDataFrameBits));
return ISO14443ALastDataFrameBits;
} else {
return ISO14443A_APP_NO_RESPONSE;
Expand Down Expand Up @@ -249,6 +249,9 @@ static uint16_t ISO144434ProcessBlock(uint8_t *Buffer, uint16_t ByteCount, uint1
return ISO14443A_APP_NO_RESPONSE;
}

default:
break;

}

/* Fall through (default handling when there is no response to register/return to the sender): */
Expand Down Expand Up @@ -296,15 +299,17 @@ void ISO144433AHalt(void) {
}

bool ISO144433AIsHalt(const uint8_t *Buffer, uint16_t BitCount) {
return BitCount == ISO14443A_HLTA_FRAME_SIZE + ISO14443A_CRCA_SIZE * BITS_PER_BYTE
return BitCount == ISO14443A_HLTA_FRAME_SIZE + ASBITS(ISO14443A_CRCA_SIZE)
&& Buffer[0] == ISO14443A_CMD_HLTA
&& Buffer[1] == 0x00
&& ISO14443ACheckCRCA(Buffer, (ISO14443A_HLTA_FRAME_SIZE + BITS_PER_BYTE - 1) / BITS_PER_BYTE);
&& ISO14443ACheckCRCA(Buffer, ASBYTES(ISO14443A_HLTA_FRAME_SIZE));
}

uint16_t ISO144433APiccProcess(uint8_t *Buffer, uint16_t BitCount) {

if (BitCount == 0) {
ISO144434Reset();
ISO144433AHalt();
return ISO14443A_APP_NO_RESPONSE;
}

Expand All @@ -324,12 +329,10 @@ uint16_t ISO144433APiccProcess(uint8_t *Buffer, uint16_t BitCount) {
incrementRetryCount = false;
} else if (ISO144433AIsHalt(Buffer, BitCount)) {
LogEntry(LOG_INFO_APP_CMD_HALT, NULL, 0);
ISO144433ASwitchState(ISO14443_3A_STATE_HALT);
LastReaderSentCmd = Cmd;
CheckStateRetryCount(true);
ISO144434Reset();
const char *logMsg = PSTR("ISO14443-3: HALTING");
LogDebuggingMsg(logMsg);
ISO144434Reset();
ISO144433AHalt();
return ISO14443A_APP_NO_RESPONSE;
}
LastReaderSentCmd = Cmd;
Expand Down Expand Up @@ -357,7 +360,7 @@ uint16_t ISO144433APiccProcess(uint8_t *Buffer, uint16_t BitCount) {
Buffer[1] = (ATQA_VALUE >> 8) & 0x00FF;
const char *debugPrintStr = PSTR("ISO14443-4 (IDLE): ATQA");
LogDebuggingMsg(debugPrintStr);
return ISO14443A_ATQA_FRAME_SIZE_BYTES * BITS_PER_BYTE;
return ASBITS(ISO14443A_ATQA_FRAME_SIZE_BYTES);

case ISO14443_3A_STATE_READY1:
if (Cmd == ISO14443A_CMD_SELECT_CL1) {
Expand Down Expand Up @@ -425,7 +428,7 @@ uint16_t ISO144433APiccProcess(uint8_t *Buffer, uint16_t BitCount) {
return ISO14443A_SAK_FRAME_SIZE;
}
/* Forward to ISO/IEC 14443-4 processing code */
uint16_t ByteCount = (BitCount + BITS_PER_BYTE - 1) / BITS_PER_BYTE;
uint16_t ByteCount = ASBYTES(BitCount);
uint16_t ReturnBits = ISO144434ProcessBlock(Buffer, ByteCount, BitCount);
const char *debugPrintStr2 = PSTR("ISO14443-4: ACTIVE RET");
LogDebuggingMsg(debugPrintStr2);
Expand All @@ -437,7 +440,7 @@ uint16_t ISO144433APiccProcess(uint8_t *Buffer, uint16_t BitCount) {
}

/* Unknown command. Reset back to idle/halt state. */
bool defaultReset = false; //Iso144433AState != ISO14443_3A_STATE_IDLE;
bool defaultReset = false;
if (!CheckStateRetryCount(defaultReset)) {
const char *logMsg = PSTR("ISO14443-3: RESET TO IDLE 0x%02x");
DEBUG_PRINT_P(logMsg, Cmd);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ This notice must be retained at the top of all source files where indicated.
#define __DESFIRE_ISO14443_SUPPORT_H__

#include "DESFireFirmwareSettings.h"
#include "DESFireUtils.h"

#include "../ISO14443-3A.h"
#include "../../Codec/ISO14443-2A.h"
Expand All @@ -41,9 +42,9 @@ This notice must be retained at the top of all source files where indicated.
*/

#define ISO14443A_CMD_RATS 0xE0
#define ISO14443A_RATS_FRAME_SIZE (6 * BITS_PER_BYTE) /* Bit */
#define ISO14443A_RATS_FRAME_SIZE ASBITS(6) /* Bit */
#define ISO14443A_CMD_RNAK 0xB2
#define ISO14443A_CRC_FRAME_SIZE (ISO14443A_CRCA_SIZE * BITS_PER_BYTE)
#define ISO14443A_CRC_FRAME_SIZE ASBITS(ISO14443A_CRCA_SIZE)

#define ISO14443ACmdIsPM3WUPA(cmd) ((cmd & 0x54) == 0x54)
#define ISO14443ACmdIsWUPA(cmd) ((cmd == ISO14443A_CMD_WUPA) || ISO14443ACmdIsPM3WUPA(cmd))
Expand Down Expand Up @@ -132,7 +133,7 @@ static uint16_t ISO144434ProcessBlock(uint8_t *Buffer, uint16_t ByteCount, uint1
#define GetAndSetBufferCRCA(Buffer, ByteCount) ({ \
uint16_t fullReturnBits = 0; \
ISO14443AAppendCRCA(Buffer, ByteCount); \
fullReturnBits = ByteCount * BITS_PER_BYTE + ISO14443A_CRC_FRAME_SIZE; \
fullReturnBits = ASBITS(ByteCount) + ISO14443A_CRC_FRAME_SIZE; \
fullReturnBits; \
})
#define GetAndSetNoResponseCRCA(Buffer) ({ \
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@ uint16_t CmdNotImplemented(uint8_t *Buffer, uint16_t ByteCount) {

uint16_t EV0CmdGetVersion1(uint8_t *Buffer, uint16_t ByteCount) {
Buffer[0] = STATUS_ADDITIONAL_FRAME;
Buffer[1] = DESFIRE_MANUFACTURER_ID;
Buffer[1] = Picc.ManufacturerID;
Buffer[2] = DESFIRE_TYPE;
Buffer[3] = DESFIRE_SUBTYPE;
GetPiccHardwareVersionInfo(&Buffer[4]);
Expand All @@ -367,7 +367,7 @@ uint16_t EV0CmdGetVersion1(uint8_t *Buffer, uint16_t ByteCount) {

uint16_t EV0CmdGetVersion2(uint8_t *Buffer, uint16_t ByteCount) {
Buffer[0] = STATUS_ADDITIONAL_FRAME;
Buffer[1] = DESFIRE_MANUFACTURER_ID;
Buffer[1] = Picc.ManufacturerID;
Buffer[2] = DESFIRE_TYPE;
Buffer[3] = DESFIRE_SUBTYPE;
GetPiccSoftwareVersionInfo(&Buffer[4]);
Expand Down Expand Up @@ -1798,8 +1798,7 @@ uint16_t DesfireCmdAuthenticate3KTDEA1(uint8_t *Buffer, uint16_t ByteCount) {
LogEntry(LOG_APP_NONCE_B, DesfireCommandState.RndB, CryptoChallengeResponseBytesSize);

/* Encrypt RndB with the selected key and transfer it back to the PCD */
if (cryptoKeyType == CRYPTO_TYPE_DES || cryptoKeyType == CRYPTO_TYPE_3K3DES ||
cryptoKeyType == CRYPTO_TYPE_ANY) {
if (cryptoKeyType == CRYPTO_TYPE_DES || cryptoKeyType == CRYPTO_TYPE_3K3DES || cryptoKeyType == CRYPTO_TYPE_ANY) {
Encrypt3DESBuffer(CryptoChallengeResponseBytesSize, DesfireCommandState.RndB,
&Buffer[1], IV, Key);
} else {
Expand Down Expand Up @@ -1836,6 +1835,7 @@ uint16_t DesfireCmdAuthenticate3KTDEA2(uint8_t *Buffer, uint16_t ByteCount) {
DesfireState = DESFIRE_IDLE;
/* Validate command length */
if (ByteCount != 2 * CryptoChallengeResponseBytesSize + 1) {
LogEntry(LOG_INFO_DESFIRE_OUTGOING_DATA, Buffer, ByteCount);
Buffer[0] = STATUS_LENGTH_ERROR;
return DESFIRE_STATUS_RESPONSE_SIZE;
}
Expand Down
35 changes: 18 additions & 17 deletions Firmware/Chameleon-Mini/Application/DESFire/DESFirePICCControl.c
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,23 @@ void FormatPicc(void) {
/* Wipe application directory */
memset(&AppDir, 0x00, sizeof(DESFireAppDirType));
memset(&SelectedApp, 0x00, sizeof(SelectedAppCacheType));
/* Set a random new UID */
BYTE uidData[DESFIRE_UID_SIZE];
RandomGetBuffer(uidData, DESFIRE_UID_SIZE);
memcpy(&Picc.Uid[0], uidData, DESFIRE_UID_SIZE);
/* Conform to NXP Application Note AN10927 about the first
* byte of a randomly generated UID (refer to section 2.1.1).
*/
Picc.Uid[0] = ISO14443A_UID0_RANDOM;
/* Randomize the initial batch number data: */
BYTE batchNumberData[5];
RandomGetBuffer(batchNumberData, 5);
memcpy(&Picc.BatchNumber[0], batchNumberData, 5);
/* Production dates should be obvious until the user changes them: */
Picc.ProductionWeek = 0x44;
Picc.ProductionYear = 0x7c;
/* Assign the default manufacturer ID: */
Picc.ManufacturerID = DESFIRE_MANUFACTURER_ID;
/* Set the ATS bytes to defaults: */
Picc.ATSBytes[0] = DESFIRE_EV0_ATS_TL_BYTE;
Picc.ATSBytes[1] = DESFIRE_EV0_ATS_T0_BYTE;
Expand Down Expand Up @@ -313,16 +330,8 @@ void CreatePiccApp(void) {
void FactoryFormatPiccEV0(void) {
/* Wipe PICC data */
memset(&Picc, PICC_FORMAT_BYTE, sizeof(Picc));
/* Set a random new UID */
BYTE uidData[DESFIRE_UID_SIZE];
RandomGetBuffer(uidData, DESFIRE_UID_SIZE);
memcpy(&Picc.Uid[0], uidData, DESFIRE_UID_SIZE);
/* Conform to NXP Application Note AN10927 about the first
* byte of a randomly generated UID (refer to section 2.1.1).
*/
Picc.Uid[0] = ISO14443A_UID0_RANDOM;
/* Initialize params to look like EV0 */
Picc.StorageSize = DESFIRE_STORAGE_SIZE_4K;
Picc.StorageSize = CardCapacityBlocks;
Picc.HwVersionMajor = DESFIRE_HW_MAJOR_EV0;
Picc.HwVersionMinor = DESFIRE_HW_MINOR_EV0;
Picc.SwVersionMajor = DESFIRE_SW_MAJOR_EV0;
Expand All @@ -337,14 +346,6 @@ void FactoryFormatPiccEV0(void) {
void FactoryFormatPiccEV1(uint8_t StorageSize) {
/* Wipe PICC data */
memset(&Picc, PICC_FORMAT_BYTE, sizeof(Picc));
/* Set a random new UID */
BYTE uidData[DESFIRE_UID_SIZE];
RandomGetBuffer(uidData, DESFIRE_UID_SIZE);
memcpy(&Picc.Uid[0], uidData, DESFIRE_UID_SIZE);
/* Conform to NXP Application Note AN10927 about the first
* byte of a randomly generated UID (refer to section 2.1.1).
*/
Picc.Uid[0] = ISO14443A_UID0_RANDOM;
/* Initialize params to look like EV1 */
Picc.StorageSize = StorageSize;
Picc.HwVersionMajor = DESFIRE_HW_MAJOR_EV1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,44 +100,6 @@ This notice must be retained at the top of all source files where indicated.
#define DESFIRE_SW_MAJOR_EV2 0x12
#define DESFIRE_SW_MINOR_EV2 0x01

/* Other HW product types for DESFire tags: See page 7 of
* https://www.nxp.com/docs/en/application-note/AN12343.pdf
*/
// typedef enum DESFIRE_FIRMWARE_ENUM_PACKING {
// NATIVEIC_PHYS_CARD = 0x01,
// LIGHT_NATIVEIC_PHYS_CARD = 0x08,
// MICROCONTROLLER_PHYS_CARDI = 0x81,
// MICROCONTROLLER_PHYS_CARDII = 0x83,
// JAVACARD_SECURE_ELEMENT_PHYS_CARD = 0x91,
// HCE_MIFARE_2GO = 0xa1,
// } DESFireHWProductCodes;
//
// const BYTE DefaultDESFireATS[] = {
// 0x06, 0x75, 0x77, 0x81, 0x02, 0x80
// };
// const BYTE DefaultJCOPDESFireATS[] = {
// 0x06, 0x75, 0xf7, 0xb1, 0x02, 0x80
// };
//
// const BYTE DEFAULT_SELECT_DESFIRE_AID[] = {
// 0xd2, 0x76, 0x00, 0x00, 0x85, 0x01, 0x00
// };
// const BYTE DEFAULT_SELECT_ISO7816_AID[] = {
// 0xa0, 0x00, 0x00, 0x00, 0x03, 0x96
// };
//
// const BYTE VERSION1[] = {
// 0x04, 0x01, 0x01, 0x01, 0x00, 0x1a, 0x05
// };
// const BYTE VERSION2[] = {
// 0x04, 0x01, 0x01, 0x01, 0x03, 0x1a, 0x05
// };
// const BYTE VERSION3[] = {
// // Expected Response: 00 04 91 3a 29 93 26 80 00 00 00 00 00 39 08 91 00
// 0x04, (BYTE) 0x91, 0x3a, 0x29, (BYTE) 0x93,
// 0x26, (BYTE) 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0x08
// };

#define DESFIRE_STORAGE_SIZE_2K 0x16
#define DESFIRE_STORAGE_SIZE_4K 0x18
#define DESFIRE_STORAGE_SIZE_8K 0x1A
Expand All @@ -158,6 +120,7 @@ typedef struct {
*/
uint8_t Uid[DESFIRE_UID_SIZE] DESFIRE_FIRMWARE_ALIGNAT;
uint8_t StorageSize;
uint8_t ManufacturerID;
uint8_t HwVersionMajor;
uint8_t HwVersionMinor;
uint8_t SwVersionMajor;
Expand All @@ -169,7 +132,6 @@ typedef struct {
/* Dynamic data: changes during the PICC's lifetime */
uint16_t FirstFreeBlock;
uint8_t TransactionStarted;
//uint8_t Spare[9] DESFIRE_FIRMWARE_ALIGNAT; // USED ANYWHERE ???
} DESFirePICCInfoType DESFIRE_FIRMWARE_PACKING;

typedef struct {
Expand Down
Loading

0 comments on commit 024c699

Please sign in to comment.