Skip to content

Commit

Permalink
Adding more complete support for PM3 ISO auth (stashing incremental c…
Browse files Browse the repository at this point in the history
…hanges as reference point)
  • Loading branch information
maxieds committed Mar 21, 2022
1 parent aafc5ab commit bb7d46f
Show file tree
Hide file tree
Showing 6 changed files with 31 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ uint8_t ISO14443ALastDataFrame[MAX_DATA_FRAME_XFER_SIZE] = { 0x00 };
uint16_t ISO14443ALastDataFrameBits = 0;

bool CheckStateRetryCount2(bool resetByDefault, bool performLogging) {
if (resetByDefault || ++StateRetryCount >= MAX_STATE_RETRY_COUNT) {
if (resetByDefault || ++StateRetryCount > MAX_STATE_RETRY_COUNT) {
ISO144434SwitchState2(Iso144433AIdleState, performLogging);
StateRetryCount = 0x00;
const char *debugStatusMsg = PSTR("RETRY-RESET");
Expand Down Expand Up @@ -311,16 +311,16 @@ uint16_t ISO144433APiccProcess(uint8_t *Buffer, uint16_t BitCount) {

/* Wakeup and Request may occure in all states */
bool checkStateRetryStatus = CheckStateRetryCount(false);
bool decrementRetryCount = true;
bool incrementRetryCount = true;
if ((Cmd == ISO14443A_CMD_REQA) && (LastReaderSentCmd == ISO14443A_CMD_REQA) && !checkStateRetryStatus) {
/* Catch timing issues where the reader sends multiple
REQA bytes, in between which we would have already sent
back a response, so that we should not reset. */
decrementRetryCount = false;
REQA bytes, in between which we would have already sent
back a response, so that we should not reset. */
incrementRetryCount = false;
} else if (Cmd == ISO14443A_CMD_REQA || ISO14443ACmdIsWUPA(Cmd)) {
ISO144434Reset();
ISO144433ASwitchState(ISO14443_3A_STATE_IDLE);
decrementRetryCount = false;
incrementRetryCount = false;
} else if (ISO144433AIsHalt(Buffer, BitCount)) {
LogEntry(LOG_INFO_APP_CMD_HALT, NULL, 0);
ISO144433ASwitchState(ISO14443_3A_STATE_HALT);
Expand All @@ -332,8 +332,8 @@ uint16_t ISO144433APiccProcess(uint8_t *Buffer, uint16_t BitCount) {
return ISO14443A_APP_NO_RESPONSE;
}
LastReaderSentCmd = Cmd;
if (decrementRetryCount && StateRetryCount > 0) {
StateRetryCount -= 1;
if (incrementRetryCount) {
StateRetryCount += 1;
}

/* This implements ISO 14443-3A state machine */
Expand Down Expand Up @@ -406,17 +406,20 @@ uint16_t ISO144433APiccProcess(uint8_t *Buffer, uint16_t BitCount) {
break;

case ISO14443_3A_STATE_ACTIVE:
StateRetryCount = MAX_STATE_RETRY_COUNT;
/* Recognise the HLTA command */
if (ISO144433AIsHalt(Buffer, BitCount)) {
LogEntry(LOG_INFO_APP_CMD_HALT, NULL, 0);
ISO144434SwitchState(ISO14443_3A_STATE_HALT);
const char *logMsg = PSTR("ISO14443-3: Got HALT");
LogDebuggingMsg(logMsg);
return ISO14443A_APP_NO_RESPONSE;
} else if(Cmd == ISO14443A_CMD_RATS) {
} else if (Cmd == ISO14443A_CMD_RATS) {
ISO144433ASwitchState(ISO14443_4_STATE_EXPECT_RATS);
const char *logMsg = PSTR("ISO14443-3/4: EXPECTING RATS");
LogDebuggingMsg(logMsg);
} else if (Cmd == ISO14443A_CMD_SELECT_CL3) {
return ISO14443A_APP_NO_RESPONSE;
}
/* Forward to ISO/IEC 14443-4 processing code */
uint16_t ByteCount = (BitCount + BITS_PER_BYTE - 1) / BITS_PER_BYTE;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ INLINE ISO14443AStoreLastDataFrameAndReturn(const uint8_t *Buffer, uint16_t Buff

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

#define MAX_STATE_RETRY_COUNT (0x8f) /* For all intensive purposes, as many as necessary */
#define MAX_STATE_RETRY_COUNT (0x04) /* For all intensive purposes, as many as necessary */
extern uint8_t StateRetryCount;
bool CheckStateRetryCount(bool resetByDefault);
bool CheckStateRetryCount2(bool resetByDefault, bool performLogging);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ uint8_t Iso7816EfIdNumber = ISO7816_EF_NOT_SPECIFIED;
bool IsWrappedISO7816CommandType(uint8_t *Buffer, uint16_t ByteCount) {
if (ByteCount <= ISO7816_PROLOGUE_SIZE + ISO14443A_CRCA_SIZE + 2) {
return ISO7816_WRAPPED_CMD_TYPE_NONE;
} else if (!ISO14443ACheckCRCA(Buffer, ByteCount - 2)) {
} else if (!ISO14443ACheckCRCA(&Buffer[0], ByteCount - 2)) {
return ISO7816_WRAPPED_CMD_TYPE_NONE;
} else if (ByteCount >= 4 && Buffer[3] == ByteCount - 4) {
} else if (ByteCount >= 6 && Buffer[3] == ByteCount - 6) {
return ISO7816_WRAPPED_CMD_TYPE_PM3RAW;
} else if (!Iso7816CLA(Buffer[2])) {
return ISO7816_WRAPPED_CMD_TYPE_NONE;
Expand Down
4 changes: 2 additions & 2 deletions Firmware/Chameleon-Mini/Application/ISO14443-3A.c
Original file line number Diff line number Diff line change
Expand Up @@ -160,10 +160,10 @@ bool ISO14443ACheckCRCA(const void *Buffer, uint16_t ByteCount) {
bool ISO14443ASelect(void *Buffer, uint16_t *BitCount, uint8_t *UidCL, uint8_t SAKValue) {
uint8_t *DataPtr = (uint8_t *) Buffer;
uint8_t NVB = DataPtr[1];
//uint8_t CollisionByteCount = (NVB >> 4) & 0x0F;
//uint8_t CollisionBitCount = (NVB >> 0) & 0x0F;

switch (NVB) {
case 0x00:
case ISO14443A_CMD_HLTA:
case ISO14443A_NVB_AC_START:
/* Start of anticollision procedure.
* Send whole UID CLn + BCC */
Expand Down
11 changes: 7 additions & 4 deletions Firmware/Chameleon-Mini/Application/MifareDESFire.c
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ void MifareDesfireAppReset(void) {
/* This is called repeatedly, so limit the amount of work done */
ISO144433AReset();
ISO144434Reset();
StateRetryCount = MAX_STATE_RETRY_COUNT;
MifareDesfireReset();
}

Expand Down Expand Up @@ -230,16 +231,18 @@ uint16_t MifareDesfireAppProcess(uint8_t *Buffer, uint16_t BitCount) {
DesfireCmdCLA = (Iso7816CmdType == ISO7816_WRAPPED_CMD_TYPE_STANDARD) ? Buffer[2] : DESFIRE_ISO7816_CLA;
uint8_t ISO7816PrologueBytes[2];
memcpy(&ISO7816PrologueBytes[0], Buffer, 2);
uint16_t IncomingByteCount = DesfirePreprocessAPDU(ActiveCommMode, Buffer, IncomingByteCount);
if (Iso7816CmdType == ISO7816_WRAPPED_CMD_TYPE_STANDARD) {
memmove(&Buffer[0], &Buffer[2], IncomingByteCount - 2);
memmove(&Buffer[0], &Buffer[2], ByteCount - 2);
} else if (Iso7816CmdType == ISO7816_WRAPPED_CMD_TYPE_PM3RAW) {
/* Looks something like: 0a 00 1a 00 CRC1 CRC2 (for PM3 raw ISO auth) */
Buffer[0] = DesfireCmdCLA;
Buffer[1] = Buffer[2];
Buffer[2] = 0x04;
memmove(&Buffer[4], &Buffer[3], IncomingByteCount - 2);
memmove(&Buffer[5], &Buffer[3], ByteCount - 3);
Buffer[2] = 0x00;
Buffer[3] = 0x00;
Buffer[4] = ByteCount - 5;
}
uint16_t IncomingByteCount = DesfirePreprocessAPDU(ActiveCommMode, Buffer, IncomingByteCount);
uint16_t UnwrappedBitCount = (IncomingByteCount - 2) * BITS_PER_BYTE;
uint16_t ProcessedBitCount = MifareDesfireProcess(Buffer, UnwrappedBitCount);
uint16_t ProcessedByteCount = (ProcessedBitCount + BITS_PER_BYTE - 1) / BITS_PER_BYTE;
Expand Down
12 changes: 7 additions & 5 deletions Firmware/Chameleon-Mini/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -124,9 +124,9 @@ SETTINGS += -DDESFIRE_DEFAULT_TESTING_MODE=0

#Set a minimum incoming/outgoing log size so we do not spam the
#Chameleon Mini logs to much by logging everything:
SETTINGS += -DDESFIRE_MIN_INCOMING_LOGSIZE=1
SETTINGS += -DDESFIRE_MIN_OUTGOING_LOGSIZE=1
#SETTINGS += -DDESFIRE_MIN_OUTGOING_LOGSIZE=0
SETTINGS += -DDESFIRE_MIN_INCOMING_LOGSIZE=0
#SETTINGS += -DDESFIRE_MIN_OUTGOING_LOGSIZE=1
SETTINGS += -DDESFIRE_MIN_OUTGOING_LOGSIZE=0

#Enable printing of crypto tests when a new DESFire emulation instance is started:
#SETTINGS += -DDESFIRE_RUN_CRYPTO_TESTING_PROCEDURE
Expand Down Expand Up @@ -303,6 +303,8 @@ local-clean:

git-add-dev:
@git add Makefile ./*.{c,h} ./*/*.{c,h} ./*/*/*.{c,h}
@cd ../../Software/DESFireLibNFCTesting && \
git add Makefile LocalInclude/*.h Source/*.c SampleOutputDumps/*.dump

## Defining custom targets for the DESFire build (normal/user mode) and
## developer mode for use with the Android CMLD application that enables
Expand All @@ -311,10 +313,10 @@ desfire-build: local-clean $(TARGET).elf $(TARGET).hex $(TARGET).eep $(TARGET).b
@cp $(TARGET).hex $(TARGET)-DESFire.hex
@cp $(TARGET).eep $(TARGET)-DESFire.eep
@cp $(TARGET).bin $(TARGET)-DESFire.bin
@echo -e "\n"
@echo ""
@avr-size -A -x $(TARGET).elf
@avr-size -B -x $(TARGET).elf
@echo -e "\n"
@echo ""
@avr-size -C -x $(TARGET).elf
desfire: CONFIG_SETTINGS:=$(DESFIRE_CONFIG_SETTINGS_BASE) -DDEFAULT_CONFIGURATION=CONFIG_NONE -fno-inline-small-functions
desfire: desfire-build

0 comments on commit bb7d46f

Please sign in to comment.