Skip to content

Commit aafc5ab

Browse files
committed
Stashing more incremental updates to the code to get/verify PM3 compatibility
1 parent 64d1fff commit aafc5ab

File tree

6 files changed

+45
-21
lines changed

6 files changed

+45
-21
lines changed

Firmware/Chameleon-Mini/Application/DESFire/DESFireISO14443Support.c

+11-12
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ static uint16_t ISO144434ProcessBlock(uint8_t *Buffer, uint16_t ByteCount, uint1
127127
ISO144434SwitchState(ISO14443_4_STATE_ACTIVE);
128128
const char *debugPrintStr = PSTR("ISO14443-4: SEND RATS");
129129
LogDebuggingMsg(debugPrintStr);
130-
return GetAndSetBufferCRCA(Buffer, ByteCount);
130+
return ByteCount * BITS_PER_BYTE; // PM3 expects no CRCA bytes
131131
}
132132
case ISO14443_4_STATE_ACTIVE: {
133133
/* See: ISO/IEC 14443-4; 7.1 Block format */
@@ -277,6 +277,7 @@ Iso144433AStateType Iso144433AIdleState = ISO14443_3A_STATE_IDLE;
277277

278278
void ISO144433ASwitchState(Iso144433AStateType NewState) {
279279
Iso144433AState = NewState;
280+
StateRetryCount = 0x00;
280281
DesfireLogISOStateChange(Iso144433AState, LOG_ISO14443_3A_STATE);
281282
}
282283

@@ -316,9 +317,9 @@ uint16_t ISO144433APiccProcess(uint8_t *Buffer, uint16_t BitCount) {
316317
REQA bytes, in between which we would have already sent
317318
back a response, so that we should not reset. */
318319
decrementRetryCount = false;
319-
} else if (Cmd == ISO14443A_CMD_REQA || Cmd == ISO14443A_CMD_WUPA) {
320+
} else if (Cmd == ISO14443A_CMD_REQA || ISO14443ACmdIsWUPA(Cmd)) {
320321
ISO144434Reset();
321-
ISO144433ASwitchState(ISO14443_3A_STATE_READY1);
322+
ISO144433ASwitchState(ISO14443_3A_STATE_IDLE);
322323
decrementRetryCount = false;
323324
} else if (ISO144433AIsHalt(Buffer, BitCount)) {
324325
LogEntry(LOG_INFO_APP_CMD_HALT, NULL, 0);
@@ -339,7 +340,7 @@ uint16_t ISO144433APiccProcess(uint8_t *Buffer, uint16_t BitCount) {
339340
/* See: ISO/IEC 14443-3, clause 6.2 */
340341
switch (Iso144433AState) {
341342
case ISO14443_3A_STATE_HALT:
342-
if (Cmd != ISO14443A_CMD_WUPA) {
343+
if (!ISO14443ACmdIsWUPA(Cmd)) {
343344
const char *debugPrintStr = PSTR("ISO14443-4: HALT / NOT WUPA");
344345
LogDebuggingMsg(debugPrintStr);
345346
break;
@@ -349,12 +350,6 @@ uint16_t ISO144433APiccProcess(uint8_t *Buffer, uint16_t BitCount) {
349350
/* Fall-through */
350351

351352
case ISO14443_3A_STATE_IDLE:
352-
if (Cmd != ISO14443A_CMD_REQA &&
353-
Cmd != ISO14443A_CMD_WUPA) {
354-
const char *debugPrintStr = PSTR("ISO14443-4: IDLE / NOT WUPA 0x%02x");
355-
DEBUG_PRINT_P(debugPrintStr);
356-
break;
357-
}
358353
Iso144433AIdleState = Iso144433AState;
359354
ISO144433ASwitchState(ISO14443_3A_STATE_READY1);
360355
Buffer[0] = (ATQA_VALUE) & 0x00FF;
@@ -364,7 +359,7 @@ uint16_t ISO144433APiccProcess(uint8_t *Buffer, uint16_t BitCount) {
364359
return ISO14443A_ATQA_FRAME_SIZE_BYTES * BITS_PER_BYTE;
365360

366361
case ISO14443_3A_STATE_READY1:
367-
if (Cmd == ISO14443A_CMD_SELECT_CL1 || Cmd == ISO14443A_CMD_REQA || Cmd == ISO14443A_CMD_WUPA) {
362+
if (Cmd == ISO14443A_CMD_SELECT_CL1 || Cmd == ISO14443A_CMD_REQA || ISO14443ACmdIsWUPA(Cmd)) {
368363
/* Load UID CL1 and perform anticollision. */
369364
ConfigurationUidType Uid;
370365
ApplicationGetUid(Uid);
@@ -414,10 +409,14 @@ uint16_t ISO144433APiccProcess(uint8_t *Buffer, uint16_t BitCount) {
414409
/* Recognise the HLTA command */
415410
if (ISO144433AIsHalt(Buffer, BitCount)) {
416411
LogEntry(LOG_INFO_APP_CMD_HALT, NULL, 0);
417-
ISO144433ASwitchState(ISO14443_3A_STATE_HALT);
412+
ISO144434SwitchState(ISO14443_3A_STATE_HALT);
418413
const char *logMsg = PSTR("ISO14443-3: Got HALT");
419414
LogDebuggingMsg(logMsg);
420415
return ISO14443A_APP_NO_RESPONSE;
416+
} else if(Cmd == ISO14443A_CMD_RATS) {
417+
ISO144433ASwitchState(ISO14443_4_STATE_EXPECT_RATS);
418+
const char *logMsg = PSTR("ISO14443-3/4: EXPECTING RATS");
419+
LogDebuggingMsg(logMsg);
421420
}
422421
/* Forward to ISO/IEC 14443-4 processing code */
423422
uint16_t ByteCount = (BitCount + BITS_PER_BYTE - 1) / BITS_PER_BYTE;

Firmware/Chameleon-Mini/Application/DESFire/DESFireISO14443Support.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ This notice must be retained at the top of all source files where indicated.
4545
#define ISO14443A_CMD_RNAK 0xB2
4646
#define ISO14443A_CRC_FRAME_SIZE (ISO14443A_CRCA_SIZE * BITS_PER_BYTE)
4747

48+
#define ISO14443ACmdIsPM3WUPA(cmd) ((cmd & 0x54) == 0x54)
49+
#define ISO14443ACmdIsWUPA(cmd) ((cmd == ISO14443A_CMD_WUPA) || ISO14443ACmdIsPM3WUPA(cmd))
50+
4851
#define ISO14443_PCB_BLOCK_TYPE_MASK 0xC0
4952
#define ISO14443_PCB_I_BLOCK 0x00
5053
#define ISO14443_PCB_R_BLOCK 0x80
@@ -109,7 +112,7 @@ INLINE ISO14443AStoreLastDataFrameAndReturn(const uint8_t *Buffer, uint16_t Buff
109112

110113
/* Setup some fuzzy response handling for problematic readers like the ACR122U */
111114

112-
#define MAX_STATE_RETRY_COUNT (4)
115+
#define MAX_STATE_RETRY_COUNT (0x8f) /* For all intensive purposes, as many as necessary */
113116
extern uint8_t StateRetryCount;
114117
bool CheckStateRetryCount(bool resetByDefault);
115118
bool CheckStateRetryCount2(bool resetByDefault, bool performLogging);

Firmware/Chameleon-Mini/Application/DESFire/DESFireISO7816Support.c

+6-4
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,15 @@ uint8_t Iso7816EfIdNumber = ISO7816_EF_NOT_SPECIFIED;
3636

3737
bool IsWrappedISO7816CommandType(uint8_t *Buffer, uint16_t ByteCount) {
3838
if (ByteCount <= ISO7816_PROLOGUE_SIZE + ISO14443A_CRCA_SIZE + 2) {
39-
return false;
39+
return ISO7816_WRAPPED_CMD_TYPE_NONE;
4040
} else if (!ISO14443ACheckCRCA(Buffer, ByteCount - 2)) {
41-
return false;
41+
return ISO7816_WRAPPED_CMD_TYPE_NONE;
42+
} else if (ByteCount >= 4 && Buffer[3] == ByteCount - 4) {
43+
return ISO7816_WRAPPED_CMD_TYPE_PM3RAW;
4244
} else if (!Iso7816CLA(Buffer[2])) {
43-
return false;
45+
return ISO7816_WRAPPED_CMD_TYPE_NONE;
4446
}
45-
return true;
47+
return ISO7816_WRAPPED_CMD_TYPE_STANDARD;
4648
}
4749

4850
uint16_t SetIso7816WrappedParametersType(uint8_t *Buffer, uint16_t ByteCount) {

Firmware/Chameleon-Mini/Application/DESFire/DESFireISO7816Support.h

+7
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,13 @@ extern bool Iso7816FileSelected;
8383
extern uint8_t Iso7816FileOffset;
8484
extern uint8_t Iso7816EfIdNumber;
8585

86+
typedef enum {
87+
ISO7816_WRAPPED_CMD_TYPE_NONE = 0,
88+
ISO7816_WRAPPED_CMD_TYPE_STANDARD,
89+
ISO7816_WRAPPED_CMD_TYPE_PM3RAW,
90+
/* Others ??? */
91+
} Iso7816WrappedCommandType_t;
92+
8693
bool IsWrappedISO7816CommandType(uint8_t *Buffer, uint16_t ByteCount);
8794
uint16_t SetIso7816WrappedParametersType(uint8_t *Buffer, uint16_t ByteCount);
8895

Firmware/Chameleon-Mini/Application/MifareDESFire.c

+16-4
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ DesfireStateType DesfireState = DESFIRE_HALT;
5151
DesfireStateType DesfirePreviousState = DESFIRE_IDLE;
5252
bool DesfireFromHalt = false;
5353
BYTE DesfireCmdCLA = DESFIRE_NATIVE_CLA;
54+
Iso7816WrappedCommandType_t Iso7816CmdType;
5455
static bool AnticolNoResp = false;
5556

5657
/* Dispatching routines */
@@ -223,13 +224,22 @@ uint16_t MifareDesfireAppProcess(uint8_t *Buffer, uint16_t BitCount) {
223224
uint16_t UnwrappedBitCount = DesfirePreprocessAPDU(ActiveCommMode, Buffer, IncomingByteCount) * BITS_PER_BYTE;
224225
uint16_t ProcessedBitCount = MifareDesfireProcess(Buffer, UnwrappedBitCount);
225226
uint16_t ProcessedByteCount = (ProcessedBitCount + BITS_PER_BYTE - 1) / BITS_PER_BYTE;
226-
return ISO14443AStoreLastDataFrameAndReturn(Buffer, DesfirePostprocessAPDU(ActiveCommMode, Buffer, ProcessedByteCount) * BITS_PER_BYTE);
227-
} else if (IsWrappedISO7816CommandType(Buffer, ByteCount)) {
228-
DesfireCmdCLA = Buffer[2];
227+
return ISO14443AStoreLastDataFrameAndReturn(Buffer,
228+
DesfirePostprocessAPDU(ActiveCommMode, Buffer, ProcessedByteCount) * BITS_PER_BYTE);
229+
} else if ((Iso7816CmdType = IsWrappedISO7816CommandType(Buffer, ByteCount)) && Iso7816CmdType != ISO7816_WRAPPED_CMD_TYPE_NONE) {
230+
DesfireCmdCLA = (Iso7816CmdType == ISO7816_WRAPPED_CMD_TYPE_STANDARD) ? Buffer[2] : DESFIRE_ISO7816_CLA;
229231
uint8_t ISO7816PrologueBytes[2];
230232
memcpy(&ISO7816PrologueBytes[0], Buffer, 2);
231233
uint16_t IncomingByteCount = DesfirePreprocessAPDU(ActiveCommMode, Buffer, IncomingByteCount);
232-
memmove(&Buffer[0], &Buffer[2], IncomingByteCount - 2);
234+
if (Iso7816CmdType == ISO7816_WRAPPED_CMD_TYPE_STANDARD) {
235+
memmove(&Buffer[0], &Buffer[2], IncomingByteCount - 2);
236+
} else if (Iso7816CmdType == ISO7816_WRAPPED_CMD_TYPE_PM3RAW) {
237+
Buffer[0] = DesfireCmdCLA;
238+
Buffer[1] = Buffer[2];
239+
Buffer[2] = 0x04;
240+
memmove(&Buffer[4], &Buffer[3], IncomingByteCount - 2);
241+
Buffer[3] = 0x00;
242+
}
233243
uint16_t UnwrappedBitCount = (IncomingByteCount - 2) * BITS_PER_BYTE;
234244
uint16_t ProcessedBitCount = MifareDesfireProcess(Buffer, UnwrappedBitCount);
235245
uint16_t ProcessedByteCount = (ProcessedBitCount + BITS_PER_BYTE - 1) / BITS_PER_BYTE;
@@ -255,6 +265,8 @@ uint16_t MifareDesfireAppProcess(uint8_t *Buffer, uint16_t BitCount) {
255265
// even when the reader has not been put in scan mode --
256266
// and it really screws things up timing-wise!
257267
AnticolNoResp = true;
268+
const char *debugPrintStr = PSTR("DESFire: Anticol NO-RESP set");
269+
LogDebuggingMsg(debugPrintStr);
258270
}
259271
return ISO14443AStoreLastDataFrameAndReturn(Buffer, PiccProcessRespBits);
260272
}

Firmware/Chameleon-Mini/Application/MifareDESFire.h

+1
Original file line numberDiff line numberDiff line change
@@ -89,5 +89,6 @@ extern DesfireStateType DesfireState;
8989
extern DesfireStateType DesfirePreviousState;
9090
extern bool DesfireFromHalt;
9191
extern BYTE DesfireCmdCLA;
92+
extern Iso7816WrappedCommandType_t Iso7816CmdType;
9293

9394
#endif /* MIFAREDESFIRE_H_ */

0 commit comments

Comments
 (0)