Skip to content

DESFire support for more readers and ISO7816 wrapped commands #314

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 18 commits into from
Jan 28, 2022
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
a038fd0
Proposed initial fix to issue #302 where some application functions r…
maxieds Jan 1, 2022
086d391
Partial progress: The Omnikey reader now offers a 9370 response that …
maxieds Jan 1, 2022
c363091
Stashing incremental changes (NO LOGGING)
maxieds Jan 2, 2022
f3f1a97
Incremental backup (still stuck in a loop after responding to the Omn…
maxieds Jan 2, 2022
adacb77
Cleaning up development code
maxieds Jan 2, 2022
6d603e4
A few changes to logging timing for testing
maxieds Jan 2, 2022
5501a4a
Stashing code that correctly goes through the nfc-anticol utility ; S…
maxieds Jan 16, 2022
2ba6718
Fixing a few details noted in #302
maxieds Jan 16, 2022
4478c6d
Stashing code that correctly makes it through to the RATS, then dies
maxieds Jan 16, 2022
344238b
Stashing code that correctly makes it through to complete RATS ; Now …
maxieds Jan 16, 2022
f6b7037
Fix the issue with the UID0 byte of a random UID needing to be 0x08 n…
maxieds Jan 16, 2022
67e8668
First order approximation to solving issue #313 ; Needs testing
maxieds Jan 16, 2022
e300df7
Progress towards #313 ... Needs further testing
maxieds Jan 18, 2022
1069f07
Fixing issue with trailing CRCA missing from #313
maxieds Jan 20, 2022
8aeb101
Fixing ISO-7816 wrapped commands -- CRC needs to be computed over ent…
maxieds Jan 21, 2022
8ad2971
Removing extraneous code / cleaning up the source modifications
maxieds Jan 23, 2022
69945c6
Adding chamtool DESFire logging codes and a few status code (SW1/SW2)…
maxieds Jan 27, 2022
e6cbc99
Fixing commented multi-line macro in violation of the `make style` gu…
maxieds Jan 27, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
220 changes: 118 additions & 102 deletions Firmware/Chameleon-Mini/Application/DESFire/DESFireISO14443Support.c

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ 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) //(4 * 8) /* Bit */
#define ISO14443A_CRC_BYTES_FRAME_SIZE (ISO14443A_CRCA_SIZE * BITS_PER_BYTE)
#define ISO14443A_CMD_RNAK 0xB2
#define ISO14443A_CRC_FRAME_SIZE (ISO14443A_CRCA_SIZE * BITS_PER_BYTE)

#define ISO14443_PCB_BLOCK_TYPE_MASK 0xC0
#define ISO14443_PCB_I_BLOCK 0x00
Expand All @@ -64,7 +65,9 @@ This notice must be retained at the top of all source files where indicated.
#define ISO14443_R_BLOCK_SIZE 1 /* Bytes */

#define ISO14443_PCB_S_DESELECT (ISO14443_PCB_S_BLOCK_STATIC)
#define ISO14443_PCB_S_DESELECT_V2 0xCA
#define ISO14443_PCB_S_WTX (ISO14443_PCB_S_BLOCK_STATIC | 0x30)
#define ISO14443A_CMD_PPS 0xD0

#define IS_ISO14443A_4_COMPLIANT(buf) (buf[0] & 0x20)
#define MAKE_ISO14443A_4_COMPLIANT(buf) (buf[0] |= 0x20)
Expand All @@ -87,9 +90,10 @@ typedef enum DESFIRE_FIRMWARE_ENUM_PACKING {
extern Iso144434StateType Iso144434State;
extern uint8_t Iso144434BlockNumber;
extern uint8_t Iso144434CardID;
extern uint8_t LastReaderSentCmd;

/* Setup some fuzzy response handling for problematic readers like the ACR122U */
#define MAX_STATE_RETRY_COUNT (2)
#define MAX_STATE_RETRY_COUNT (4)
extern uint8_t StateRetryCount;
bool CheckStateRetryCount(bool resetByDefault);
bool CheckStateRetryCount2(bool resetByDefault, bool performLogging);
Expand All @@ -101,14 +105,27 @@ void ISO144434SwitchState(Iso144434StateType NewState);
void ISO144434SwitchState2(Iso144434StateType NewState, bool performLogging);

void ISO144434Reset(void);
uint16_t ISO144434ProcessBlock(uint8_t* Buffer, uint16_t ByteCount, uint16_t BitCount);
static uint16_t ISO144434ProcessBlock(uint8_t* Buffer, uint16_t ByteCount, uint16_t BitCount);

/*
* ISO/IEC 14443-3A implementation
*/

#define ISO14443A_CRCA_INIT ((uint16_t) 0x6363)

#define GetAndSetBufferCRCA(Buffer, ByteCount) ({ \
uint16_t fullReturnBits = 0; \
ISO14443AAppendCRCA(Buffer, ByteCount); \
fullReturnBits = ByteCount * BITS_PER_BYTE + ISO14443A_CRC_FRAME_SIZE; \
fullReturnBits; \
})
/* TODO: Should we return CRC bytes when giving a NO_RESPONSE ??? ... Apparently "No". */
#define GetAndSetNoResponseCRCA(Buffer) ({ \
uint16_t fullReturnBits = 0; \
ISO14443AAppendCRCA(Buffer, 0); \
fullReturnBits = ISO14443A_CRC_FRAME_SIZE; \
fullReturnBits; \
})

uint16_t ISO14443AUpdateCRCA(const uint8_t *Buffer, uint16_t ByteCount, uint16_t InitCRCA);

typedef enum DESFIRE_FIRMWARE_ENUM_PACKING {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,27 @@ This notice must be retained at the top of all source files where indicated.
#include "DESFirePICCHeaderLayout.h"
#include "DESFireISO7816Support.h"
#include "DESFireInstructions.h"
#include "../ISO14443-3A.h"

Iso7816WrappedParams_t Iso7816P1Data = ISO7816_NO_DATA;
Iso7816WrappedParams_t Iso7816P2Data = ISO7816_NO_DATA;
bool Iso7816FileSelected = false;
uint8_t Iso7816FileOffset = 0;
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 false;
}
else if(!ISO14443ACheckCRCA(Buffer, ByteCount - 2)) {
return false;
}
else if(!Iso7816CLA(Buffer[2])) {
return false;
}
return true;
}

uint16_t SetIso7816WrappedParametersType(uint8_t *Buffer, uint16_t ByteCount) {
if(ByteCount < 8 || !Iso7816CLA(Buffer[0])) {
Iso7816P1Data = ISO7816_UNSUPPORTED_MODE;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ This notice must be retained at the top of all source files where indicated.
#define Iso7816CLA(cmdCode) \
(cmdCode == DESFIRE_ISO7816_CLA)

#define ISO7816_PROLOGUE_SIZE (2)
#define ISO7816_STATUS_RESPONSE_SIZE (0x02)
#define ISO7816_EF_NOT_SPECIFIED (0xff)
#define ISO7816_EFID_NUMBER_MAX (0x0f)
Expand Down Expand Up @@ -79,6 +80,7 @@ extern bool Iso7816FileSelected;
extern uint8_t Iso7816FileOffset;
extern uint8_t Iso7816EfIdNumber;

bool IsWrappedISO7816CommandType(uint8_t *Buffer, uint16_t ByteCount);
uint16_t SetIso7816WrappedParametersType(uint8_t *Buffer, uint16_t ByteCount);

#endif
168 changes: 85 additions & 83 deletions Firmware/Chameleon-Mini/Application/DESFire/DESFireLogging.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ This notice must be retained at the top of all source files where indicated.

INLINE void DesfireLogEntry(LogEntryEnum LogCode, void *LogDataBuffer, uint16_t BufSize) {
if(DESFIRE_MIN_OUTGOING_LOGSIZE <= BufSize) {
LogEntry(LogCode, LogDataBuffer, BufSize);
LogEntry(LogCode, (void *) LogDataBuffer, BufSize);
}
}

Expand Down Expand Up @@ -77,28 +77,27 @@ void DESFireLogPICCHardReset(BYTE *strBuf, SIZET strLength);
void DESFireLogPICCSoftReset(BYTE *strBuf, SIZET strLength);

void DebugPrintP(const char *fmt, ...);
#define DEBUG_PRINT(fmt, ...) \
DebugPrintP(PSTR(fmt), ##__VA_ARGS__)

#define DEBUG_PRINT_P(fmtStr, ...) ({ \
uint8_t logLength = 0; \
do { \
snprintf_P(__InternalStringBuffer, STRING_BUFFER_SIZE, \
fmtStr, ##__VA_ARGS__); \
logLength = StringLength(__InternalStringBuffer, \
STRING_BUFFER_SIZE); \
DesfireLogEntry(LOG_ERR_DESFIRE_GENERIC_ERROR, \
__InternalStringBuffer, logLength); \
} while(0); \
#define DEBUG_PRINT(fmt, ...) DebugPrintP(PSTR(fmt), ##__VA_ARGS__)

#define DEBUG_PRINT_P(fmtStr, ...) ({ \
uint8_t logLength = 0; \
do { \
snprintf_P((char *) __InternalStringBuffer, STRING_BUFFER_SIZE, \
fmtStr, ##__VA_ARGS__); \
logLength = StringLength((char *) __InternalStringBuffer, \
STRING_BUFFER_SIZE); \
DesfireLogEntry(LOG_ERR_DESFIRE_GENERIC_ERROR, \
(char *) __InternalStringBuffer, logLength); \
} while(0); \
})

#define GetSourceFileLoggingData() ({ \
char *strBuffer; \
do { \
snprintf_P(__InternalStringBuffer, STRING_BUFFER_SIZE, \
snprintf_P(__InternalStringBuffer, STRING_BUFFER_SIZE, \
PSTR("@@ LINE #%d in *%s @@"), \
__LINE__, __FILE__); \
__InternalStringBuffer[STRING_BUFFER_SIZE - 1] = '\0'; \
__LINE__, __FILE__); \
__InternalStringBuffer[STRING_BUFFER_SIZE - 1] = '\0'; \
} while(0); \
strBuffer = __InternalStringBuffer; \
strBuffer; \
Expand Down Expand Up @@ -126,78 +125,81 @@ void DebugPrintP(const char *fmt, ...);
strBuffer; \
})

#define LogDebuggingMsg(msg) ({ \
char *strBuffer; \
do { \
strncpy_P(__InternalStringBuffer, msg, STRING_BUFFER_SIZE); \
uint8_t sbufLength = StringLength(__InternalStringBuffer, STRING_BUFFER_SIZE); \
LogEntry(LOG_INFO_DESFIRE_OUTGOING_DATA, (void *) __InternalStringBuffer, \
sbufLength); \
} while(0); \
strBuffer = __InternalStringBuffer; \
strBuffer; \
#if defined(DESFIRE_DEFAULT_LOGGING_MODE) && DESFIRE_DEFAULT_LOGGING_MODE != 0
#define LogDebuggingMsg(msg) ({ \
do { \
strncpy_P((char *) __InternalStringBuffer, msg, STRING_BUFFER_SIZE); \
uint8_t sbufLength = StringLength((char *) __InternalStringBuffer, STRING_BUFFER_SIZE); \
LogEntry(LOG_INFO_DESFIRE_OUTGOING_DATA, (void *) __InternalStringBuffer, \
sbufLength); \
} while(0); \
})
#else
#define LogDebuggingMsg(msg) ({})
#endif

//#define DesfireLogIncoming(incBuf, bitCount) ({ \
uint8_t logLength = 0; \
do { \
logLength = BufferToHexString(__InternalStringBuffer, STRING_BUFFER_SIZE, \
incBuf, (bitCount + 7) / 8); \
snprintf_P(__InternalStringBuffer + logLength, PSTR(" [#=%d] <-- IN"), \
bitCount); \
logLength = StringLength(__InternalStringBuffer, STRING_BUFFER_SIZE); \
DesfireLogEntry(LOG_INFO_DESFIRE_INCOMING_DATA, __InternalStringBuffer, logLength); \
} while(0); \
/*#define DesfireLogIncoming(incBuf, bitCount) ({ \
uint8_t logLength = 0; \
do { \
logLength = BufferToHexString(__InternalStringBuffer, STRING_BUFFER_SIZE, \
incBuf, (bitCount + 7) / 8); \
snprintf_P(__InternalStringBuffer + logLength, PSTR(" [#=%d] <-- IN"), \
bitCount); \
logLength = StringLength(__InternalStringBuffer, STRING_BUFFER_SIZE); \
DesfireLogEntry(LOG_INFO_DESFIRE_INCOMING_DATA, __InternalStringBuffer, logLength); \
} while(0); \
})

//#define DesfireLogOutgoing(incBuf, bitCount) ({ \
uint8_t logLength = 0; \
do { \
logLength = BufferToHexString(__InternalStringBuffer, STRING_BUFFER_SIZE, \
incBuf, (bitCount + 7) / 8); \
snprintf_P(__InternalStringBuffer + logLength, PSTR(" [#=%d] --> OUT"), \
bitCount); \
logLength = StringLength(__InternalStringBuffer, STRING_BUFFER_SIZE); \
DesfireLogEntry(LOG_INFO_DESFIRE_OUTGOING_DATA, __InternalStringBuffer, logLength); \
} while(0); \
#define DesfireLogOutgoing(incBuf, bitCount) ({ \
uint8_t logLength = 0; \
do { \
logLength = BufferToHexString(__InternalStringBuffer, STRING_BUFFER_SIZE, \
incBuf, (bitCount + 7) / 8); \
snprintf_P(__InternalStringBuffer + logLength, PSTR(" [#=%d] --> OUT"), \
bitCount); \
logLength = StringLength(__InternalStringBuffer, STRING_BUFFER_SIZE); \
DesfireLogEntry(LOG_INFO_DESFIRE_OUTGOING_DATA, __InternalStringBuffer, logLength); \
} while(0); \
})
*/

#define DesfireLogISOStateChange(state, logCode)
//#define DesfireLogISOStateChange(state, logCode) ({ \
const char *stateSymbName = NULL; \
uint8_t logLength = 0x00; \
do { \
switch(state) { \
case ISO14443_3A_STATE_IDLE: \
stateSymbName = PSTR("ISO14443_3A_STATE_IDLE"); \
break; \
case ISO14443_3A_STATE_READY1: \
stateSymbName = PSTR("ISO14443_3A_STATE_READY1"); \
break; \
case ISO14443_3A_STATE_READY2: \
stateSymbName = PSTR("ISO14443_3A_STATE_READY2"); \
break; \
case ISO14443_3A_STATE_ACTIVE: \
stateSymbName = PSTR("ISO14443_3A_STATE_ACTIVE"); \
break; \
case ISO14443_3A_STATE_HALT: \
stateSymbName = PSTR("ISO14443_3A_STATE_HALT"); \
break; \
case ISO14443_4_STATE_EXPECT_RATS: \
stateSymbName = PSTR("ISO14443_4_STATE_EXPECT_RATS"); \
break; \
case ISO14443_4_STATE_ACTIVE: \
stateSymbName = PSTR("ISO14443_4_STATE_ACTIVE"); \
break; \
default: \
stateSymbName = PSTR("UNKNOWN_STATE"); \
break; \
} \
snprintf_P(__InternalStringBuffer, STRING_BUFFER_SIZE, PSTR(" => ")); \
strcat_P(__InternalStringBuffer, stateSymbName); \
logLength = StringLength(__InternalStringBuffer, STRING_BUFFER_SIZE); \
DesfireLogEntry(logCode, __InternalStringBuffer, logLength); \
} while(0); \
#define DesfireLogISOStateChange(state, logCode) ({})
/*#define DesfireLogISOStateChange(state, logCode) ({ \
const char *stateSymbName = NULL; \
uint8_t logLength = 0x00; \
do { \
switch(state) { \
case ISO14443_3A_STATE_IDLE: \
stateSymbName = PSTR("ISO14443_3A_STATE_IDLE"); \
break; \
case ISO14443_3A_STATE_READY1: \
stateSymbName = PSTR("ISO14443_3A_STATE_READY1"); \
break; \
case ISO14443_3A_STATE_READY2: \
stateSymbName = PSTR("ISO14443_3A_STATE_READY2"); \
break; \
case ISO14443_3A_STATE_ACTIVE: \
stateSymbName = PSTR("ISO14443_3A_STATE_ACTIVE"); \
break; \
case ISO14443_3A_STATE_HALT: \
stateSymbName = PSTR("ISO14443_3A_STATE_HALT"); \
break; \
case ISO14443_4_STATE_EXPECT_RATS: \
stateSymbName = PSTR("ISO14443_4_STATE_EXPECT_RATS"); \
break; \
case ISO14443_4_STATE_ACTIVE: \
stateSymbName = PSTR("ISO14443_4_STATE_ACTIVE"); \
break; \
default: \
stateSymbName = PSTR("UNKNOWN_STATE"); \
break; \
} \
snprintf_P(__InternalStringBuffer, STRING_BUFFER_SIZE, PSTR(" => ")); \
strcat_P(__InternalStringBuffer, stateSymbName); \
logLength = StringLength(__InternalStringBuffer, STRING_BUFFER_SIZE); \
DesfireLogEntry(logCode, __InternalStringBuffer, logLength); \
} while(0); \
})
*/

#endif
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,10 @@ void FactoryFormatPiccEV0(void) {
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.HwVersionMajor = DESFIRE_HW_MAJOR_EV0;
Expand Down
Loading