diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireISO14443Support.c b/Firmware/Chameleon-Mini/Application/DESFire/DESFireISO14443Support.c index 1587d79c..31977431 100644 --- a/Firmware/Chameleon-Mini/Application/DESFire/DESFireISO14443Support.c +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireISO14443Support.c @@ -347,7 +347,7 @@ uint16_t ISO144433APiccProcess(uint8_t* Buffer, uint16_t BitCount) { Uid[1] = Uid[0]; Uid[0] = ISO14443A_UID0_CT; } - if (ISO14443ASelect(Buffer, &BitCount, Uid, SAK_CL1_VALUE)) { + if (ISO14443ASelectDesfire(Buffer, &BitCount, Uid, SAK_CL1_VALUE)) { /* CL1 stage has ended successfully */ const char *debugPrintStr = PSTR("ISO14443-4: Select OK"); LogDebuggingMsg(debugPrintStr); @@ -372,7 +372,7 @@ uint16_t ISO144433APiccProcess(uint8_t* Buffer, uint16_t BitCount) { /* Load UID CL2 and perform anticollision */ ConfigurationUidType Uid; ApplicationGetUid(Uid); - if (ISO14443ASelect(Buffer, &BitCount, &Uid[3], SAK_CL2_VALUE)) { + if (ISO14443ASelectDesfire(Buffer, &BitCount, &Uid[3], SAK_CL2_VALUE)) { /* CL2 stage has ended successfully. This means * our complete UID has been sent to the reader. */ ISO144433ASwitchState(ISO14443_3A_STATE_ACTIVE); diff --git a/Firmware/Chameleon-Mini/Application/ISO14443-3A.c b/Firmware/Chameleon-Mini/Application/ISO14443-3A.c index c86d3810..7bd739ae 100644 --- a/Firmware/Chameleon-Mini/Application/ISO14443-3A.c +++ b/Firmware/Chameleon-Mini/Application/ISO14443-3A.c @@ -10,6 +10,10 @@ #define CRC_INIT 0x6363 #define CRC_INIT_R 0xC6C6 /* Bit reversed */ +#ifdef CONFIG_MF_DESFIRE_SUPPORT +uint8_t FirstUidCL[4] = { 0 }; +#endif + #define USE_HW_CRC #ifdef USE_HW_CRC diff --git a/Firmware/Chameleon-Mini/Application/ISO14443-3A.h b/Firmware/Chameleon-Mini/Application/ISO14443-3A.h index b41950ee..79d65857 100644 --- a/Firmware/Chameleon-Mini/Application/ISO14443-3A.h +++ b/Firmware/Chameleon-Mini/Application/ISO14443-3A.h @@ -121,6 +121,80 @@ bool ISO14443ASelect(void *Buffer, uint16_t *BitCount, uint8_t *UidCL, uint8_t S } } +#ifdef CONFIG_MF_DESFIRE_SUPPORT +extern uint8_t FirstUidCL[4]; + +INLINE +bool ISO14443ASelectDesfire(void* Buffer, uint16_t* BitCount, uint8_t* UidCL, uint8_t SAKValue) +{ + uint8_t* DataPtr = (uint8_t*) Buffer; + uint8_t NVB = DataPtr[1]; + + switch (NVB) { + case ISO14443A_NVB_AC_START: + /* Start of anticollision procedure. + * Send whole UID CLn + BCC */ + DataPtr[0] = UidCL[0]; + DataPtr[1] = UidCL[1]; + DataPtr[2] = UidCL[2]; + DataPtr[3] = UidCL[3]; + DataPtr[ISO14443A_CL_BCC_OFFSET] = ISO14443A_CALC_BCC(DataPtr); + memcpy(FirstUidCL, UidCL, ISO14443A_CL_UID_SIZE); + *BitCount = ISO14443A_CL_FRAME_SIZE; + return false; + + case ISO14443A_NVB_AC_END: + /* End of anticollision procedure. + * Send SAK CLn if we are selected. */ + if ( (DataPtr[2] == UidCL[0]) && + (DataPtr[3] == UidCL[1]) && + (DataPtr[4] == UidCL[2]) && + (DataPtr[5] == UidCL[3]) ) { + DataPtr[0] = SAKValue; + *BitCount = BITS_PER_BYTE; + return true; + } + else { + /* We have not been selected. Don't send anything. */ + *BitCount = 0; + return false; + } + default: + { + uint8_t CollisionByteCount = ((NVB >> 4) & 0x0f) - 2; + uint8_t CollisionBitCount = (NVB >> 0) & 0x0f; + uint8_t mask = 0xFF >> (8 - CollisionBitCount); + // Since the UidCL does not contain the BCC, we have to distinguish here + if ( + ((CollisionByteCount == 5 || (CollisionByteCount == 4 && CollisionBitCount > 0)) && + memcmp(UidCL, &DataPtr[2], 4) == 0 && (ISO14443A_CALC_BCC(UidCL) & mask) == (DataPtr[6] & mask)) + || + (CollisionByteCount == 4 && CollisionBitCount == 0 && memcmp(UidCL, &DataPtr[2], 4) == 0) + || + (CollisionByteCount < 4 && memcmp(UidCL, &DataPtr[2], CollisionByteCount) == 0 && + (UidCL[CollisionByteCount] & mask) == (DataPtr[CollisionByteCount + 2] & mask)) + ) + { + DataPtr[0] = UidCL[0]; + DataPtr[1] = UidCL[1]; + DataPtr[2] = UidCL[2]; + DataPtr[3] = UidCL[3]; + DataPtr[4] = ISO14443A_CALC_BCC(DataPtr); + + *BitCount = ISO14443A_CL_FRAME_SIZE; + } else { + *BitCount = 0; + } + return false; + } + /* No anticollision supported */ + *BitCount = 0; + return false; + } +} + +#endif + INLINE bool ISO14443AWakeUp(void *Buffer, uint16_t *BitCount, uint16_t ATQAValue, bool FromHalt) { uint8_t *DataPtr = (uint8_t *) Buffer; diff --git a/Software/DESFireLibNFCTesting/LocalInclude/Iso7816Utils.h b/Software/DESFireLibNFCTesting/LocalInclude/Iso7816Utils.h deleted file mode 100644 index 26f4dd50..00000000 --- a/Software/DESFireLibNFCTesting/LocalInclude/Iso7816Utils.h +++ /dev/null @@ -1,75 +0,0 @@ -/* Iso7816Utils.h */ - -#ifndef __ISO7816_UTILS_H__ -#define __ISO7816_UTILS_H__ - -#include -#include -#include -#include - -#include - -#include "ErrorHandling.h" -#include "Config.h" -#include "CryptoUtils.h" -#include "LibNFCUtils.h" -#include "GeneralUtils.h" - -static inline int Iso7816SelectCommand(nfc_device *nfcConnDev) { - if(nfcConnDev == NULL) { - return INVALID_PARAMS_ERROR; - } - return EXIT_SUCCESS; -} - -static inline int Iso7816GetChallengeCommand(nfc_device *nfcConnDev) { - if(nfcConnDev == NULL) { - return INVALID_PARAMS_ERROR; - } - return EXIT_SUCCESS; -} - -static inline int Iso7816ExternalAuthenticateCommand(nfc_device *nfcConnDev) { - if(nfcConnDev == NULL) { - return INVALID_PARAMS_ERROR; - } - return EXIT_SUCCESS; -} - -static inline int Iso7816InternalAuthenticateCommand(nfc_device *nfcConnDev) { - if(nfcConnDev == NULL) { - return INVALID_PARAMS_ERROR; - } - return EXIT_SUCCESS; -} - -static inline int Iso7816ReadBinaryCommand(nfc_device *nfcConnDev) { - if(nfcConnDev == NULL) { - return INVALID_PARAMS_ERROR; - } - return EXIT_SUCCESS; -} - -static inline int Iso7816UpdateBinaryCommand(nfc_device *nfcConnDev) { - if(nfcConnDev == NULL) { - return INVALID_PARAMS_ERROR; - } - return EXIT_SUCCESS; -} - -static inline int Iso7816ReadRecordsCommand(nfc_device *nfcConnDev) { - if(nfcConnDev == NULL) { - return INVALID_PARAMS_ERROR; - } - return EXIT_SUCCESS; -} - -static inline int Iso7816AppendRecordCommand(nfc_device *nfcConnDev) { - if(nfcConnDev == NULL) { - return INVALID_PARAMS_ERROR; - } - return EXIT_SUCCESS; -} - -#endif