From 45d4aea8df646a71452f5486a3995231995d73a8 Mon Sep 17 00:00:00 2001 From: Tomaspre Date: Fri, 14 Oct 2022 14:01:16 +0100 Subject: [PATCH 01/22] Fix CRC32 calculation for Desfire --- .../Chameleon-Mini/Application/CryptoAES128.c | 50 +++++++++++++------ 1 file changed, 35 insertions(+), 15 deletions(-) diff --git a/Firmware/Chameleon-Mini/Application/CryptoAES128.c b/Firmware/Chameleon-Mini/Application/CryptoAES128.c index a6c8a626..ef5abcc9 100644 --- a/Firmware/Chameleon-Mini/Application/CryptoAES128.c +++ b/Firmware/Chameleon-Mini/Application/CryptoAES128.c @@ -36,6 +36,9 @@ #include "CryptoAES128.h" +#include "MifareDESFire.h" +#include "DESFire/DESFireLogging.h" + #define NOP() __asm__ __volatile__("nop") /* AES interrupt callback function pointer. */ @@ -454,22 +457,39 @@ void CryptoAESEncrypt_CBCReceive(uint16_t Count, uint8_t *PlainText, uint8_t *Ci CryptoAES_CBCRecv(Count, PlainText, CipherText, IV, Key, CryptoSpec); } -uint16_t appendBufferCRC32C(uint8_t *bufferData, uint16_t bufferSize) { - uint32_t workingCRC = INIT_CRC32C_VALUE; - for (int i = 0; i < bufferSize; i++) { - workingCRC = workingCRC ^ *(bufferData++); - for (int j = 0; j < 8; j++) { - if (workingCRC & 1) { - workingCRC = (workingCRC >> 1) ^ LE_CRC32C_POLYNOMIAL; - } else { - workingCRC = workingCRC >> 1; - } - } +//Taken from the Proxmark DESFire lib +static void desfire_crc32_byte(uint32_t *crc, const uint8_t value) { + /* x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x + 1 */ + const uint32_t poly = 0xEDB88320; + + *crc ^= value; + for (int current_bit = 7; current_bit >= 0; current_bit--) { + int bit_out = (*crc) & 0x00000001; + *crc >>= 1; + if (bit_out) + *crc ^= poly; + } +} + +//Taken from the Proxmark DESFire lib +void desfire_crc32(const uint8_t *data, const uint16_t len, uint8_t *crc) { + uint32_t desfire_crc = 0xFFFFFFFF; + for (uint16_t i = 0; i < len; i++) { + desfire_crc32_byte(&desfire_crc, data[i]); } + + *((uint32_t *)(crc)) = (desfire_crc); +} + +uint16_t appendBufferCRC32C(uint8_t *bufferData, uint16_t bufferSize) { + uint8_t crc[4]; + desfire_crc32(bufferData, bufferSize, crc); + // Append the CRC32C bytes in little endian byte order to the end of the buffer: - bufferData[bufferSize] = (uint8_t)(workingCRC & 0x000000FF); - bufferData[bufferSize + 1] = (uint8_t)((workingCRC & 0x0000FF00) >> 8); - bufferData[bufferSize + 2] = (uint8_t)((workingCRC & 0x00FF0000) >> 16); - bufferData[bufferSize + 4] = (uint8_t)((workingCRC & 0xFF000000) >> 24); + bufferData[bufferSize] = crc[0]; + bufferData[bufferSize + 1] = crc[1]; + bufferData[bufferSize + 2] = crc[2]; + bufferData[bufferSize + 3] = crc[3]; + return bufferSize + 4; } From 90edf43f1288d93f506f7c15272a59d8fd0248bb Mon Sep 17 00:00:00 2001 From: Tomaspre Date: Fri, 14 Oct 2022 14:02:00 +0100 Subject: [PATCH 02/22] Fix CMAC support for DESFire --- .../Chameleon-Mini/Application/CryptoCMAC.c | 130 +++++++++++++++++- .../Chameleon-Mini/Application/CryptoCMAC.h | 2 + 2 files changed, 131 insertions(+), 1 deletion(-) diff --git a/Firmware/Chameleon-Mini/Application/CryptoCMAC.c b/Firmware/Chameleon-Mini/Application/CryptoCMAC.c index dbdaff9f..bb35b7ab 100644 --- a/Firmware/Chameleon-Mini/Application/CryptoCMAC.c +++ b/Firmware/Chameleon-Mini/Application/CryptoCMAC.c @@ -88,7 +88,8 @@ static bool appendBufferCMACSubroutine(uint8_t cryptoType, const uint8_t *keyDat Encrypt3DESBuffer(newBlockSize, bufferOut, &bufferOut[bufferSize], keyData, bufferIV); break; case CRYPTO_TYPE_AES128: - CryptoAESEncryptBuffer(newBlockSize, bufferOut, &bufferOut[bufferSize], keyData, bufferIV); + //CryptoAESEncryptBuffer(newBlockSize, bufferOut, &bufferOut[bufferSize], keyData, bufferIV); + CryptoAESEncryptBuffer(newBlockSize, bufferOut, &bufferOut[bufferSize], bufferIV, keyData); break; default: return false; @@ -99,6 +100,7 @@ static bool appendBufferCMACSubroutine(uint8_t cryptoType, const uint8_t *keyDat return true; } +//TODO: This did not pass my tests -tomaspre bool appendBufferCMAC(uint8_t cryptoType, const uint8_t *keyData, uint8_t *bufferData, uint16_t bufferSize, uint8_t *IV) { uint8_t blockSize, rb; uint8_t *nistL = _cmac_K2; @@ -129,6 +131,132 @@ bool appendBufferCMAC(uint8_t cryptoType, const uint8_t *keyData, uint8_t *buffe } } +void bin_xor(uint8_t *d1, const uint8_t *d2, size_t len) { + for (size_t i = 0; i < len; i++) + d1[i] = d1[i] ^ d2[i]; +} + +void lsl(uint8_t *data, size_t len) { + for (size_t n = 0; n < len - 1; n++) { + data[n] = (data[n] << 1) | (data[n + 1] >> 7); + } + data[len - 1] <<= 1; +} + +//Taken from https://github.com/RfidResearchGroup/proxmark3/blob/master/client/src/mifare/desfirecrypto.c +bool DesfireCMACGenerateSubkeys(uint8_t cryptoType, const uint8_t *keyData, uint8_t *sk1, uint8_t *sk2) { + int kbs; + uint8_t l[2*CRYPTO_MAX_BLOCK_SIZE]; + uint8_t ivect[CRYPTO_MAX_BLOCK_SIZE]; + + switch (cryptoType) { + case CRYPTO_TYPE_3K3DES: + kbs = CRYPTO_3KTDEA_BLOCK_SIZE; + break; + case CRYPTO_TYPE_AES128: + kbs = CRYPTO_AES_BLOCK_SIZE; + break; + default: + return false; + } + + const uint8_t R = (kbs == 8) ? 0x1B : 0x87; + + memset(l, 0, kbs); + memset(ivect, 0, kbs); + + switch (cryptoType) { + case CRYPTO_TYPE_3K3DES: + Encrypt3DESBuffer(kbs, l, l+kbs, ivect, keyData); + break; + case CRYPTO_TYPE_AES128: + CryptoAESEncryptBuffer(kbs, l, l+kbs, ivect, keyData); + break; + default: + return false; + } + + memcpy(l, l+kbs, kbs); + + bool txor = false; + + // Used to compute CMAC on complete blocks + memcpy(sk1, l, kbs); + txor = l[0] & 0x80; + lsl(sk1, kbs); + if (txor) { + sk1[kbs - 1] ^= R; + } + + // Used to compute CMAC on the last block if non-complete + memcpy(sk2, sk1, kbs); + txor = sk1[0] & 0x80; + lsl(sk2, kbs); + if (txor) { + sk2[kbs - 1] ^= R; + } + + return true; +} + +//Taken from https://github.com/RfidResearchGroup/proxmark3/blob/master/client/src/mifare/desfirecrypto.c +bool DesfireCryptoCMAC(uint8_t cryptoType, const uint8_t *keyData, uint8_t *bufferDataIn, uint16_t bufferSize, uint8_t *IV, uint8_t *cmac) { + uint8_t kbs; + uint8_t len = bufferSize; + uint8_t * bufferData = bufferDataIn + bufferSize; + memcpy(bufferData, bufferDataIn, bufferSize); + + switch (cryptoType) { + case CRYPTO_TYPE_3K3DES: + kbs = CRYPTO_3KTDEA_BLOCK_SIZE; + break; + case CRYPTO_TYPE_AES128: + kbs = CRYPTO_AES_BLOCK_SIZE; + break; + default: + return false; + } + + + uint8_t sk1[24] = {0}; + uint8_t sk2[24] = {0}; + + DesfireCMACGenerateSubkeys(cryptoType, keyData, sk1, sk2); + + if ((!len) || (len % kbs)) { + bufferData[len++] = 0x80; + while (len % kbs) { + bufferData[len++] = 0x00; + } + bin_xor(bufferData + len - kbs, sk2, kbs); + } else { + bin_xor(bufferData + len - kbs, sk1, kbs); + } + + bool retval = false; + + switch (cryptoType) { + case CRYPTO_TYPE_3K3DES: + retval = Encrypt3DESBuffer(len, bufferData, bufferData+len, IV, keyData); + break; + case CRYPTO_TYPE_AES128: + retval = CryptoAESEncryptBuffer(len, bufferData, bufferData+len, IV, keyData); + break; + default: + return false; + } + + if (cmac != NULL) { + memcpy(cmac, IV, kbs); + return retval; + } + + return false; + +} + + + bool checkBufferCMAC(uint8_t *bufferData, uint16_t bufferSize, uint16_t checksumSize) { if (checksumSize > bufferSize) { return false; diff --git a/Firmware/Chameleon-Mini/Application/CryptoCMAC.h b/Firmware/Chameleon-Mini/Application/CryptoCMAC.h index 06fae00a..8ee397cd 100644 --- a/Firmware/Chameleon-Mini/Application/CryptoCMAC.h +++ b/Firmware/Chameleon-Mini/Application/CryptoCMAC.h @@ -42,4 +42,6 @@ bool checkBufferMAC(uint8_t *bufferData, uint16_t bufferSize, uint16_t checksumS uint16_t appendBufferMAC(const uint8_t *keyData, uint8_t *bufferData, uint16_t bufferSize); bool checkBufferCMAC(uint8_t *bufferData, uint16_t bufferSize, uint16_t checksumSize); +bool DesfireCryptoCMAC(uint8_t cryptoType, const uint8_t *keyData, uint8_t *bufferDataIn, uint16_t bufferSize, uint8_t *IV, uint8_t *cmac); + #endif From 51f6d4da9475bd630abb4e035b017da1dd26221c Mon Sep 17 00:00:00 2001 From: Tomaspre Date: Fri, 14 Oct 2022 14:13:50 +0100 Subject: [PATCH 03/22] Do not reset DESFire state every tick --- Firmware/Chameleon-Mini/Application/MifareDESFire.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Firmware/Chameleon-Mini/Application/MifareDESFire.c b/Firmware/Chameleon-Mini/Application/MifareDESFire.c index 576b186a..30c98f9c 100644 --- a/Firmware/Chameleon-Mini/Application/MifareDESFire.c +++ b/Firmware/Chameleon-Mini/Application/MifareDESFire.c @@ -121,8 +121,8 @@ void MifareDesfireAppReset(void) { void MifareDesfireAppTick(void) { if (!CheckStateRetryCount(false)) { - ResetISOState(); - MifareDesfireReset(); + //ResetISOState(); + //MifareDesfireReset(); } } From 40c20571a865440e62dcf9f98668003667627bbf Mon Sep 17 00:00:00 2001 From: Tomaspre Date: Fri, 14 Oct 2022 14:15:49 +0100 Subject: [PATCH 04/22] Decrypt encrypted payload for some DESFire EV1+ cases --- .../Application/MifareDESFire.c | 82 +++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/Firmware/Chameleon-Mini/Application/MifareDESFire.c b/Firmware/Chameleon-Mini/Application/MifareDESFire.c index 30c98f9c..7e65bc68 100644 --- a/Firmware/Chameleon-Mini/Application/MifareDESFire.c +++ b/Firmware/Chameleon-Mini/Application/MifareDESFire.c @@ -130,6 +130,85 @@ void MifareDesfireAppTask(void) { /* EMPTY -- Do nothing. */ } +//Checks if this is an EV1 frame which's content needs decryption. +//TODO: Other modes than AES +uint16_t CheckNeedForDecryptionAndDecrypt(uint8_t *Buffer, uint16_t ByteCount) { + if (ByteCount == 0) { + return 0; + } + + if (Buffer[0] == CMD_CHANGE_KEY_SETTINGS) { + //TODO + return ByteCount; + } + + if (Buffer[0] == CMD_CHANGE_KEY) { + if (((ByteCount - 2) % 16) != 0 ) { + return ByteCount; + } + + //TODO: 0x0A and 0x1A autrhenticate commands + + uint8_t tmpIV[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + CryptoAESDecryptBuffer(ByteCount - 2, Buffer + ByteCount, Buffer + 2, tmpIV, SessionKey); + memmove(Buffer + 2, Buffer + ByteCount, ByteCount - 2); + + //TODO: + //check decryption success + + //UnXOR + //TODO: Check that the application id matches too? EV1 datasheet, page 43, unclear + if ((AuthenticatedWithKey != Buffer[1]) && (ReadKeySettings(SelectedApp.Slot, Buffer[1]) == 0x0E)) { + //Strip padding + // cmd + keyNo + data + vers + crc + crc + ByteCount = 1 + 1 + 16 + 1 + 4 + 4; + + uint8_t tmpKeyBuff[16]; + ReadAppKey(SelectedApp.Slot, Buffer[1], tmpKeyBuff, 16); + for (int i = 2; i < 18; ++i) { + Buffer[i] = Buffer[i] ^ tmpKeyBuff[i]; + } + //TODO: + //Check first checksum + //Check second checksum + //Strip checksums + return 18; + } else { + //Strip padding + //cmd + keyNo + data + vers + crc + ByteCount = 1 + 1 + 16 + 1 + 4; + + //Check checksum + uint8_t recvCRC[4]; + recvCRC[0] = Buffer[19]; + recvCRC[1] = Buffer[20]; + recvCRC[2] = Buffer[21]; + recvCRC[3] = Buffer[22]; + appendBufferCRC32C(Buffer, 19); + if (recvCRC[0] != Buffer[19] || recvCRC[1] != Buffer[20] || recvCRC[2] != Buffer[21] || recvCRC[3] != Buffer[22]) { + DEBUG_PRINT_P(PSTR("CRC does not match")); + return 0; + } else { + return 18; //Caution! Stripping KeyVers! + } + } + } + + if (Buffer[0] == CMD_SET_CONFIGURATION) { + //TODO + return ByteCount; + } + + if (Buffer[0] == CMD_CHANGE_FILE_SETTINGS) { + //TODO + return ByteCount; + } + + return ByteCount; +} + + + uint16_t MifareDesfireProcessCommand(uint8_t *Buffer, uint16_t ByteCount) { if (ByteCount == 0) { @@ -137,6 +216,9 @@ uint16_t MifareDesfireProcessCommand(uint8_t *Buffer, uint16_t ByteCount) { } else if (Buffer[0] != STATUS_ADDITIONAL_FRAME) { DesfireState = DESFIRE_IDLE; } + + ByteCount = CheckNeedForDecryptionAndDecrypt(Buffer, ByteCount); + DesfireLogEntry(LOG_INFO_DESFIRE_INCOMING_DATA, (void *) Buffer, ByteCount); uint16_t ReturnBytes = 0; From 1b3d5fd507ecfd223622e3cd4cd6620c4aef043b Mon Sep 17 00:00:00 2001 From: Tomaspre Date: Fri, 14 Oct 2022 14:16:40 +0100 Subject: [PATCH 05/22] Fix frame processing for DESFire EV1 in edge cases --- .../Application/MifareDESFire.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/Firmware/Chameleon-Mini/Application/MifareDESFire.c b/Firmware/Chameleon-Mini/Application/MifareDESFire.c index 7e65bc68..63d52891 100644 --- a/Firmware/Chameleon-Mini/Application/MifareDESFire.c +++ b/Firmware/Chameleon-Mini/Application/MifareDESFire.c @@ -338,9 +338,16 @@ uint16_t MifareDesfireAppProcess(uint8_t *Buffer, uint16_t BitCount) { } else { ISO14443ALastIncomingDataFrameBits = ISO14443AStoreLastDataFrameAndReturn(Buffer, BitCount); } + if (ByteCount >= 8 && DesfireCLA(Buffer[1]) && Buffer[2] == STATUS_ADDITIONAL_FRAME && - Buffer[3] == 0x00 && Buffer[4] == 0x00 && Buffer[5] == ByteCount - 8 && + Buffer[3] == 0x00 && Buffer[4] == 0x00 && (Buffer[5] == ByteCount - 8 || Buffer[5] == ByteCount - 9) && DesfireStateExpectingAdditionalFrame(DesfireState)) { + + bool nine = false; + if (Buffer[5] == ByteCount - 9) { + nine = true; + } + /* [PM3-V1] : Handle the native-wrapped version of the additional frame data: */ uint16_t checkSumPostVerifyBytes = DesfirePreprocessAPDUAndTruncate(ActiveCommMode, Buffer, ByteCount); if (checkSumPostVerifyBytes == 0) { @@ -356,8 +363,16 @@ uint16_t MifareDesfireAppProcess(uint8_t *Buffer, uint16_t BitCount) { if (ProcessedByteCount == 0) { return ISO14443A_APP_NO_RESPONSE; } - /* Re-wrap into padded APDU form */ + + uint8_t StatusByte = Buffer[0]; Buffer[0] = PrologueCounterByte; + if (nine) { + Buffer[ProcessedByteCount] = 0x91; + Buffer[ProcessedByteCount + 1] = StatusByte; + ++ProcessedByteCount; + } + + /* Re-wrap into padded APDU form */ uint16_t ProcessedByteCountWithCRCA = DesfirePostprocessAPDU(ActiveCommMode, Buffer, ProcessedByteCount + 1); return ISO14443AStoreLastDataFrameAndReturn(Buffer, ASBITS(ProcessedByteCountWithCRCA)); } else if (ByteCount >= 3 && Buffer[2] == STATUS_ADDITIONAL_FRAME && DesfireStateExpectingAdditionalFrame(DesfireState)) { From 0527c61a6bf5f168693969dc11a04d64fa1d87b0 Mon Sep 17 00:00:00 2001 From: Tomaspre Date: Fri, 14 Oct 2022 14:23:02 +0100 Subject: [PATCH 06/22] DESFire: Reset IV only when needed --- .../DESFire/DESFireApplicationDirectory.c | 4 ++-- .../Application/DESFire/DESFireCrypto.c | 7 +++++-- .../Application/DESFire/DESFireFile.c | 8 +++++++- .../Application/DESFire/DESFirePICCControl.c | 14 +++++++------- 4 files changed, 21 insertions(+), 12 deletions(-) diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireApplicationDirectory.c b/Firmware/Chameleon-Mini/Application/DESFire/DESFireApplicationDirectory.c index df51cce0..12c1982e 100644 --- a/Firmware/Chameleon-Mini/Application/DESFire/DESFireApplicationDirectory.c +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireApplicationDirectory.c @@ -208,8 +208,8 @@ void SetAppProperty(DesfireCardLayout propId, BYTE AppSlot, SIZET Value) { bool KeyIdValid(uint8_t AppSlot, uint8_t KeyId) { if (KeyId >= DESFIRE_MAX_KEYS || KeyId >= ReadMaxKeyCount(AppSlot)) { - const char *debugMsg = PSTR("INVKEY-KeyId(%02x)-RdMax(%02x)"); - DEBUG_PRINT_P(debugMsg, KeyId, ReadMaxKeyCount(AppSlot)); + const char *debugMsg = PSTR("INVKEY-KeyId(%02x)-RdMax(%02x),App(%02x)"); + DEBUG_PRINT_P(debugMsg, KeyId, ReadMaxKeyCount(AppSlot), AppSlot); return false; } return true; diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireCrypto.c b/Firmware/Chameleon-Mini/Application/DESFire/DESFireCrypto.c index 5eed543f..ba9ce6f8 100644 --- a/Firmware/Chameleon-Mini/Application/DESFire/DESFireCrypto.c +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireCrypto.c @@ -37,6 +37,7 @@ This notice must be retained at the top of all source files where indicated. #include "DESFireISO14443Support.h" #include "DESFireStatusCodes.h" #include "DESFireLogging.h" +#include "System.h" CryptoKeyBufferType SessionKey = { 0 }; CryptoIVBufferType SessionIV = { 0 }; @@ -56,9 +57,11 @@ void InvalidateAuthState(BYTE keepPICCAuthData) { if (!keepPICCAuthData) { AuthenticatedWithPICCMasterKey = false; memset(&SessionKey[0], 0x00, CRYPTO_MAX_BLOCK_SIZE); - memset(&SessionIV[0], 0x00, CRYPTO_MAX_BLOCK_SIZE); - SessionIVByteSize = 0; } + + memset(&SessionIV[0], 0x00, CRYPTO_MAX_BLOCK_SIZE); + SessionIVByteSize = 0; + Authenticated = false; AuthenticatedWithKey = DESFIRE_NOT_AUTHENTICATED; Iso7816FileSelected = false; diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireFile.c b/Firmware/Chameleon-Mini/Application/DESFire/DESFireFile.c index 3a4d37e6..caef81cd 100644 --- a/Firmware/Chameleon-Mini/Application/DESFire/DESFireFile.c +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireFile.c @@ -337,7 +337,7 @@ uint8_t CreateFileCommonValidation(uint8_t FileNum) { return STATUS_AUTHENTICATION_ERROR; } uint8_t selectedKeyPerms = ReadKeySettings(SelectedApp.Slot, AuthenticatedWithKey); - if ((selectedKeyPerms & DESFIRE_FREE_CREATE_DELETE) == 0x00) { + if ((selectedKeyPerms & DESFIRE_FREE_CREATE_DELETE) == 0x00 && !AuthenticatedWithPICCMasterKey) { return STATUS_PERMISSION_DENIED; } return STATUS_OPERATION_OK; @@ -350,6 +350,12 @@ uint8_t ValidateAuthentication(uint16_t AccessRights, uint16_t CheckMask) { GetReadWritePermissions(CheckMask & AccessRights), GetChangePermissions(CheckMask & AccessRights) }; + + if (DesfireDebuggingOn) { + const char *debugMsg = PSTR("Perm-R(%02x),W(%02x),RW(%02x),CHG(%02x)"); + DEBUG_PRINT_P(debugMsg, SplitPerms[0], SplitPerms[1], SplitPerms[2], SplitPerms[3]); + } + bool PermsRelevant[] = { CheckMask & VALIDATE_ACCESS_READ, CheckMask & VALIDATE_ACCESS_WRITE, diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFirePICCControl.c b/Firmware/Chameleon-Mini/Application/DESFire/DESFirePICCControl.c index 1082c229..c5f73612 100644 --- a/Firmware/Chameleon-Mini/Application/DESFire/DESFirePICCControl.c +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFirePICCControl.c @@ -115,15 +115,15 @@ uint8_t ReadDataFilterSetup(uint8_t CommSettings) { case DESFIRE_COMMS_PLAINTEXT: break; case DESFIRE_COMMS_PLAINTEXT_MAC: - memset(SessionIV, PICC_EMPTY_BYTE, sizeof(SessionIV)); + //memset(SessionIV, PICC_EMPTY_BYTE, sizeof(SessionIV)); SessionIVByteSize = CRYPTO_2KTDEA_KEY_SIZE; break; case DESFIRE_COMMS_CIPHERTEXT_DES: - memset(SessionIV, PICC_EMPTY_BYTE, sizeof(SessionIV)); + //memset(SessionIV, PICC_EMPTY_BYTE, sizeof(SessionIV)); SessionIVByteSize = CRYPTO_3KTDEA_KEY_SIZE; break; case DESFIRE_COMMS_CIPHERTEXT_AES128: - memset(SessionIV, 0, sizeof(SessionIVByteSize)); + //memset(SessionIV, 0, sizeof(SessionIVByteSize)); SessionIVByteSize = CRYPTO_AES_KEY_SIZE; default: return STATUS_PARAMETER_ERROR; @@ -134,19 +134,19 @@ uint8_t ReadDataFilterSetup(uint8_t CommSettings) { uint8_t WriteDataFilterSetup(uint8_t CommSettings) { switch (CommSettings) { case DESFIRE_COMMS_PLAINTEXT: - memset(SessionIV, 0, sizeof(SessionIVByteSize)); + //memset(SessionIV, 0, sizeof(SessionIVByteSize)); SessionIVByteSize = 0; break; case DESFIRE_COMMS_PLAINTEXT_MAC: - memset(SessionIV, 0, sizeof(SessionIVByteSize)); + //memset(SessionIV, 0, sizeof(SessionIVByteSize)); SessionIVByteSize = CRYPTO_2KTDEA_KEY_SIZE; break; case DESFIRE_COMMS_CIPHERTEXT_DES: - memset(SessionIV, 0, sizeof(SessionIVByteSize)); + //memset(SessionIV, 0, sizeof(SessionIVByteSize)); SessionIVByteSize = CRYPTO_AES_KEY_SIZE; break; case DESFIRE_COMMS_CIPHERTEXT_AES128: - memset(SessionIV, 0, sizeof(SessionIVByteSize)); + //memset(SessionIV, 0, sizeof(SessionIVByteSize)); SessionIVByteSize = CRYPTO_AES_KEY_SIZE; break; default: From 39a8483c78578e1682713d9892d20e790397867b Mon Sep 17 00:00:00 2001 From: Tomaspre Date: Fri, 14 Oct 2022 14:23:46 +0100 Subject: [PATCH 07/22] DESFire: Reclaim allocated space on PICC format --- Firmware/Chameleon-Mini/Application/DESFire/DESFirePICCControl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFirePICCControl.c b/Firmware/Chameleon-Mini/Application/DESFire/DESFirePICCControl.c index c5f73612..3d249f92 100644 --- a/Firmware/Chameleon-Mini/Application/DESFire/DESFirePICCControl.c +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFirePICCControl.c @@ -338,6 +338,7 @@ void FactoryFormatPiccEV1(uint8_t StorageSize) { Picc.SwVersionMajor = DESFIRE_SW_MAJOR_EV1; Picc.SwVersionMinor = DESFIRE_SW_MINOR_EV1; /* Reset the free block pointer */ + InitBlockSizes(); Picc.FirstFreeBlock = DESFIRE_FIRST_FREE_BLOCK_ID; /* Continue with user data initialization */ SynchronizePICCInfo(); From e974b224825c053a38c059e5c3af1337286b457a Mon Sep 17 00:00:00 2001 From: Tomaspre Date: Fri, 14 Oct 2022 14:35:05 +0100 Subject: [PATCH 08/22] Reset selected AID to 000000 after WUPA --- .../Application/DESFire/DESFireISO14443Support.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireISO14443Support.c b/Firmware/Chameleon-Mini/Application/DESFire/DESFireISO14443Support.c index 1bbc701d..02e89568 100644 --- a/Firmware/Chameleon-Mini/Application/DESFire/DESFireISO14443Support.c +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireISO14443Support.c @@ -354,6 +354,9 @@ uint16_t ISO144433APiccProcess(uint8_t *Buffer, uint16_t BitCount) { StateRetryCount = 0; } else if (ISO14443ACmdIsWUPA(Cmd)) { DesfireLogEntry(LOG_INFO_APP_CMD_WUPA, NULL, 0); + //Resetting the selected app seems to be required but not docummented + const DESFireAidType Aid = {0,0,0}; + SelectApp(Aid); ISO144433ASwitchState(ISO14443_3A_STATE_IDLE); StateRetryCount = 0; } else if (ISO144433AIsHalt(Buffer, BitCount)) { From f3fae16cd35f0bda41b8720c85e3bf597856825c Mon Sep 17 00:00:00 2001 From: Tomaspre Date: Fri, 14 Oct 2022 14:38:19 +0100 Subject: [PATCH 09/22] Various debug messages + various fixes --- .../Application/DESFire/DESFireFile.c | 2 + .../Application/DESFire/DESFireInstructions.c | 52 +++++++++++++------ .../DESFire/DESFireMemoryOperations.c | 2 + .../Application/DESFire/DESFireUtils.c | 3 ++ .../Application/DESFire/DESFireUtils.h | 2 +- 5 files changed, 43 insertions(+), 18 deletions(-) diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireFile.c b/Firmware/Chameleon-Mini/Application/DESFire/DESFireFile.c index caef81cd..1cc8b595 100644 --- a/Firmware/Chameleon-Mini/Application/DESFire/DESFireFile.c +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireFile.c @@ -308,6 +308,8 @@ uint16_t ReadDataFileIterator(uint8_t *Buffer) { uint8_t WriteDataFileInternal(uint8_t *Buffer, uint16_t ByteCount) { uint8_t Status; + + //decipher? Status = WriteDataFileTransfer(Buffer, ByteCount); switch (Status) { case STATUS_OPERATION_OK: diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireInstructions.c b/Firmware/Chameleon-Mini/Application/DESFire/DESFireInstructions.c index cb964a32..7ccb0fc9 100644 --- a/Firmware/Chameleon-Mini/Application/DESFire/DESFireInstructions.c +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireInstructions.c @@ -628,31 +628,33 @@ uint16_t EV0CmdChangeKey(uint8_t *Buffer, uint16_t ByteCount) { break; default: /* Authentication with a specific key is required */ - if (!IsAuthenticated() || (KeyId != ChangeKeyId)) { + if (!IsAuthenticated() || (AuthenticatedWithKey != ChangeKeyId)) { Buffer[0] = STATUS_PERMISSION_DENIED; return DESFIRE_STATUS_RESPONSE_SIZE; } break; } - /* Figure out the key size, and the crypto type from it: */ - uint8_t keySize = ByteCount - 2; - uint8_t cryptoType; - if ((keySize != CRYPTO_3KTDEA_KEY_SIZE) && (keySize != CRYPTO_AES_KEY_SIZE)) { - Buffer[0] = STATUS_NO_SUCH_KEY; - return DESFIRE_STATUS_RESPONSE_SIZE; - } else if (keySize == CRYPTO_3KTDEA_KEY_SIZE) { - cryptoType = CRYPTO_TYPE_3K3DES; - } else { - cryptoType = CRYPTO_TYPE_AES128; + /* Figure out the key size, and the crypto type from it:*/ + if (cryptoType == 0xFF) { + uint8_t keySize = ByteCount - 2; + if ((keySize != CRYPTO_3KTDEA_KEY_SIZE) && (keySize != CRYPTO_AES_KEY_SIZE)) { + Buffer[0] = STATUS_NO_SUCH_KEY; + return DESFIRE_STATUS_RESPONSE_SIZE; + } else if (keySize == CRYPTO_3KTDEA_KEY_SIZE) { + cryptoType = CRYPTO_TYPE_3K3DES; + } else { + cryptoType = CRYPTO_TYPE_AES128; + } } uint8_t nextKeyVersion = ReadKeyVersion(SelectedApp.Slot, KeyId) + 1; - /* TODO: The PCD generates data differently based on whether AuthKeyId == ChangeKeyId */ - /* TODO: [NEED DOCS] NewKey^OldKey | CRC(NewKey^OldKey) | CRC(NewKey) | Padding */ - /* TODO: [NEED DOCS] NewKey | CRC(NewKey) | Padding */ /* TODO: NOTE: Padding checks are skipped, because meh. */ + const char *debugMsg = PSTR("KeyWrt,id(%02x),v(%02x),CT(%02x),size(%02x),ASlot(%02x)"); + DEBUG_PRINT_P(debugMsg, KeyId, nextKeyVersion, cryptoType,keySize, SelectedApp.Slot); + DesfireLogEntry(LOG_APP_AUTH_KEY, (void *) &Buffer[2], keySize); + /* Write the key, next version, and scrub */ WriteAppKey(SelectedApp.Slot, KeyId, &Buffer[2], keySize); WriteKeyVersion(SelectedApp.Slot, KeyId, nextKeyVersion); @@ -899,7 +901,9 @@ uint16_t EV0CmdCreateStandardDataFile(uint8_t *Buffer, uint16_t ByteCount) { if (Status != STATUS_OPERATION_OK) { return ExitWithStatus(Buffer, Status, DESFIRE_STATUS_RESPONSE_SIZE); } - FileSize = GET_LE24(&Buffer[5]); + //Warning, stripping the MSB of the size! + FileSize = Buffer[5] + (Buffer[6] * 256); + DesfireLogEntry(LOG_INFO_DESFIRE_PROTECTED_DATA_SET, (void *) &FileSize, 2); Status = CreateStandardFile(FileNum, CommSettings, AccessRights, (uint16_t)FileSize); return ExitWithStatus(Buffer, Status, DESFIRE_STATUS_RESPONSE_SIZE); } @@ -1170,6 +1174,7 @@ uint16_t EV0CmdReadData(uint8_t *Buffer, uint16_t ByteCount) { uint8_t fileIndex = LookupFileNumberIndex(SelectedApp.Slot, FileNum); if (fileIndex >= DESFIRE_MAX_FILES) { Status = STATUS_PARAMETER_ERROR; + DEBUG_PRINT_P(PSTR("FileIndexError")); return ExitWithStatus(Buffer, Status, DESFIRE_STATUS_RESPONSE_SIZE); } AccessRights = ReadFileAccessRights(SelectedApp.Slot, fileIndex); @@ -1186,13 +1191,16 @@ uint16_t EV0CmdReadData(uint8_t *Buffer, uint16_t ByteCount) { /* Carry on */ break; } + /* Validate the file type */ uint8_t fileType = ReadFileType(SelectedApp.Slot, fileIndex); if (fileType != DESFIRE_FILE_STANDARD_DATA && fileType != DESFIRE_FILE_BACKUP_DATA) { Status = STATUS_PARAMETER_ERROR; + DEBUG_PRINT_P(PSTR("FileTypeError")); return ExitWithStatus(Buffer, Status, DESFIRE_STATUS_RESPONSE_SIZE); } + /* Validate offset and length (preliminary) */ Offset = GET_LE24(&Buffer[2]); Length = GET_LE24(&Buffer[5]); @@ -1230,6 +1238,7 @@ uint16_t EV0CmdWriteData(uint8_t *Buffer, uint16_t ByteCount) { } AccessRights = ReadFileAccessRights(SelectedApp.Slot, fileIndex); CommSettings = ReadFileCommSettings(SelectedApp.Slot, fileIndex); + /* Verify authentication: read or read&write required */ switch (ValidateAuthentication(AccessRights, VALIDATE_ACCESS_READWRITE | VALIDATE_ACCESS_WRITE)) { case VALIDATED_ACCESS_DENIED: @@ -1240,6 +1249,7 @@ uint16_t EV0CmdWriteData(uint8_t *Buffer, uint16_t ByteCount) { case VALIDATED_ACCESS_GRANTED: break; } + /* Validate the file type */ uint8_t fileType = ReadFileType(SelectedApp.Slot, fileIndex); if (fileType != DESFIRE_FILE_STANDARD_DATA && @@ -1267,6 +1277,7 @@ uint16_t EV0CmdWriteData(uint8_t *Buffer, uint16_t ByteCount) { * blocks to FRAM memory: */ uint16_t dataWriteSize = ByteCount - 8; + uint8_t *dataWriteBuffer = &Buffer[8]; if (Offset > 0) { uint8_t precursorFileData[Offset]; @@ -1901,6 +1912,10 @@ uint16_t DesfireCmdAuthenticateAES1(uint8_t *Buffer, uint16_t ByteCount) { return DESFIRE_STATUS_RESPONSE_SIZE; } + const char *debugMsg = PSTR("KeyId(%02x)-RdMax(%02x),App(%02x)"); + DEBUG_PRINT_P(debugMsg, KeyId, ReadMaxKeyCount(SelectedApp.Slot), SelectedApp.Slot); + + /* Make sure that this key is AES, and figure out its byte size */ BYTE cryptoKeyType = ReadKeyCryptoType(SelectedApp.Slot, KeyId); if (!CryptoTypeAES(cryptoKeyType)) { @@ -2020,8 +2035,11 @@ uint16_t DesfireCmdAuthenticateAES2(uint8_t *Buffer, uint16_t ByteCount) { */ Authenticated = true; AuthenticatedWithKey = KeyId; - AuthenticatedWithPICCMasterKey = (SelectedApp.Slot == DESFIRE_PICC_APP_SLOT) && - (KeyId == DESFIRE_MASTER_KEY_ID); + if ((SelectedApp.Slot == DESFIRE_PICC_APP_SLOT) && (KeyId == DESFIRE_MASTER_KEY_ID)){ + AuthenticatedWithPICCMasterKey = true; + } + + memset(&SessionIV[0], 0x00, CRYPTO_MAX_BLOCK_SIZE); /* Return the status on success */ Buffer[0] = STATUS_OPERATION_OK; diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireMemoryOperations.c b/Firmware/Chameleon-Mini/Application/DESFire/DESFireMemoryOperations.c index 44af3e51..fd8b7789 100644 --- a/Firmware/Chameleon-Mini/Application/DESFire/DESFireMemoryOperations.c +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireMemoryOperations.c @@ -64,9 +64,11 @@ uint16_t AllocateBlocksMain(uint16_t BlockCount) { if (Block + BlockCount < Block || Block + BlockCount >= StorageSizeToBytes(Picc.StorageSize) || Block + BlockCount >= MEMORY_SIZE_PER_SETTING / BLOCKWISE_IO_MULTIPLIER) { return 0; } + Picc.FirstFreeBlock = Block + BlockCount; DESFIRE_FIRST_FREE_BLOCK_ID = Picc.FirstFreeBlock; SynchronizePICCInfo(); + return Block; } diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireUtils.c b/Firmware/Chameleon-Mini/Application/DESFire/DESFireUtils.c index 172870db..3d19f6b3 100644 --- a/Firmware/Chameleon-Mini/Application/DESFire/DESFireUtils.c +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireUtils.c @@ -148,6 +148,9 @@ bool DesfireCheckParityBits(uint8_t *Buffer, uint16_t BitCount) { uint16_t DesfirePreprocessAPDUWrapper(uint8_t CommMode, uint8_t *Buffer, uint16_t BufferSize, bool TruncateChecksumBytes) { uint16_t ChecksumBytes = 0; + const char *debugMsg = PSTR("Commode(%02x)"); + DEBUG_PRINT_P(debugMsg, CommMode); + switch (CommMode) { case DESFIRE_COMMS_PLAINTEXT_MAC: { if (DesfireCommandState.CryptoMethodType == CRYPTO_TYPE_DES || DesfireCommandState.CryptoMethodType == CRYPTO_TYPE_2KTDEA) { diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireUtils.h b/Firmware/Chameleon-Mini/Application/DESFire/DESFireUtils.h index d4dd0e86..2717647d 100644 --- a/Firmware/Chameleon-Mini/Application/DESFire/DESFireUtils.h +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireUtils.h @@ -35,7 +35,7 @@ This notice must be retained at the top of all source files where indicated. #define ASBITS(bc) ((bc) * BITS_PER_BYTE) #define GET_LE16(p) (*((uint16_t*)&(p)[0])) -#define GET_LE24(p) (*((__uint24*)&(p)[0])) +#define GET_LE24(p) (*((__uint24*)&(p)[0])) // Careful! Don't use this if the first byte is LSB!! #define GET_LE32(p) (*((uint32_t*)&(p)[0])) #define UnsignedTypeToUINT(typeValue) \ From 3b8c3e6a66fa6051ddb9472d6fcbc22109dc042a Mon Sep 17 00:00:00 2001 From: Tomaspre Date: Fri, 14 Oct 2022 15:04:44 +0100 Subject: [PATCH 10/22] Convert AES 3DES key numbers --- .../Application/DESFire/DESFireInstructions.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireInstructions.c b/Firmware/Chameleon-Mini/Application/DESFire/DESFireInstructions.c index 7ccb0fc9..f797a738 100644 --- a/Firmware/Chameleon-Mini/Application/DESFire/DESFireInstructions.c +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireInstructions.c @@ -311,6 +311,18 @@ static const DESFireCommand DESFireCommandSet[] = { }, }; +//Sets the key number to a real key number after deriving the crypto type from it +uint8_t ProcessKeyNumber(uint8_t * KeyNumber) { + if (*KeyNumber & APPLICATION_CRYPTO_AES) { + *KeyNumber = (*KeyNumber) & APPLICATION_CRYPTO_AES; + return CRYPTO_TYPE_AES128; + } else if (*KeyNumber & APPLICATION_CRYPTO_3K3DES) { + *KeyNumber = (*KeyNumber) & APPLICATION_CRYPTO_3K3DES; + return CRYPTO_TYPE_3K3DES; + } + return 0xFF; +} + uint16_t CallInstructionHandler(uint8_t *Buffer, uint16_t ByteCount) { if (ByteCount == 0) { Buffer[0] = STATUS_PARAMETER_ERROR; @@ -1901,6 +1913,8 @@ uint16_t DesfireCmdAuthenticateAES1(uint8_t *Buffer, uint16_t ByteCount) { /* Check if we are authenticating with the PICC/Master key setup correctly */ KeyId = Buffer[1]; + uint8_t cryptoType = ProcessKeyNumber(&KeyId); + if (SelectedApp.Slot == DESFIRE_PICC_APP_SLOT && KeyId != DESFIRE_MASTER_KEY_ID) { Buffer[0] = STATUS_PERMISSION_DENIED; return DESFIRE_STATUS_RESPONSE_SIZE; From 9651d3c6c7a969f1139996cbf291c2033483587d Mon Sep 17 00:00:00 2001 From: Tomaspre Date: Fri, 14 Oct 2022 15:05:41 +0100 Subject: [PATCH 11/22] Update CMAC at **some** of the needed stages --- .../Application/DESFire/DESFireInstructions.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireInstructions.c b/Firmware/Chameleon-Mini/Application/DESFire/DESFireInstructions.c index f797a738..54c5ddd7 100644 --- a/Firmware/Chameleon-Mini/Application/DESFire/DESFireInstructions.c +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireInstructions.c @@ -323,6 +323,17 @@ uint8_t ProcessKeyNumber(uint8_t * KeyNumber) { return 0xFF; } +//This should be only called when the command itself does not require encryption! +//But it should be called every time we're authenticated, using EV1 mode and are not ecrypting! TODO!! +//Currently used only in commands needed for Gallagher +//Conforms with EV1 datsheet, chap 7.3.4 (CMAC) +void UpdateIVIfNeeded(uint8_t *Buffer, uint16_t ByteCount) { + if (ActiveCommMode == DESFIRE_COMMS_PLAINTEXT && Authenticated && ReadKeyCryptoType(SelectedApp.Slot, AuthenticatedWithKey)== CRYPTO_TYPE_AES128) { + uint8_t cmac[32]; + DesfireCryptoCMAC(CRYPTO_TYPE_AES128, SessionKey, Buffer, ByteCount, SessionIV, cmac); + } +} + uint16_t CallInstructionHandler(uint8_t *Buffer, uint16_t ByteCount) { if (ByteCount == 0) { Buffer[0] = STATUS_PARAMETER_ERROR; @@ -905,6 +916,9 @@ uint16_t EV0CmdCreateStandardDataFile(uint8_t *Buffer, uint16_t ByteCount) { Status = STATUS_LENGTH_ERROR; return ExitWithStatus(Buffer, Status, DESFIRE_STATUS_RESPONSE_SIZE); } + + UpdateIVIfNeeded(Buffer, ByteCount); + /* Common args validation */ FileNum = Buffer[1]; CommSettings = Buffer[2]; @@ -1181,6 +1195,9 @@ uint16_t EV0CmdReadData(uint8_t *Buffer, uint16_t ByteCount) { Status = STATUS_LENGTH_ERROR; return ExitWithStatus(Buffer, Status, DESFIRE_STATUS_RESPONSE_SIZE); } + + UpdateIVIfNeeded(Buffer, ByteCount); + /* Validate file number */ FileNum = Buffer[1]; uint8_t fileIndex = LookupFileNumberIndex(SelectedApp.Slot, FileNum); From 75e49c3332b8e8b0d7756a58992591a0b7058974 Mon Sep 17 00:00:00 2001 From: Tomaspre Date: Fri, 14 Oct 2022 15:06:01 +0100 Subject: [PATCH 12/22] Fix command binary search --- .../Chameleon-Mini/Application/DESFire/DESFireInstructions.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireInstructions.c b/Firmware/Chameleon-Mini/Application/DESFire/DESFireInstructions.c index 54c5ddd7..e8d350b9 100644 --- a/Firmware/Chameleon-Mini/Application/DESFire/DESFireInstructions.c +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireInstructions.c @@ -344,7 +344,7 @@ uint16_t CallInstructionHandler(uint8_t *Buffer, uint16_t ByteCount) { uint16_t curInsIndex; DESFireCommand dfCmd; while (curInsUpper >= curInsLower) { - curInsIndex = curInsLower + (curInsUpper + 1 - curInsLower) / 2; + curInsIndex = (curInsLower + curInsUpper) / 2; dfCmd = DESFireCommandSet[curInsIndex]; if (dfCmd.insCode == insCode) { if (dfCmd.insFunc == NULL) { From 836c4f42ea17e7060f28f5b75b61d555ba1e663a Mon Sep 17 00:00:00 2001 From: Tomaspre Date: Fri, 14 Oct 2022 15:07:04 +0100 Subject: [PATCH 13/22] DESFire: More fixes on key numbers --- .../Application/DESFire/DESFireInstructions.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireInstructions.c b/Firmware/Chameleon-Mini/Application/DESFire/DESFireInstructions.c index e8d350b9..d19a017f 100644 --- a/Firmware/Chameleon-Mini/Application/DESFire/DESFireInstructions.c +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireInstructions.c @@ -621,8 +621,23 @@ uint16_t EV0CmdChangeKey(uint8_t *Buffer, uint16_t ByteCount) { Buffer[0] = STATUS_LENGTH_ERROR; return DESFIRE_STATUS_RESPONSE_SIZE; } + + KeyId = Buffer[1]; + + /* Are we changing the card master key? + * Which crypto type are we using? + * TODO: Is this really ok for non master keys that are AES/3k3DES? */ + uint8_t keySize = ByteCount - 2; + uint8_t cryptoType = 0xFF; + + if (keySize == CRYPTO_AES_KEY_SIZE || keySize == CRYPTO_2KTDEA_KEY_SIZE || keySize == CRYPTO_3KTDEA_KEY_SIZE) { + cryptoType = ProcessKeyNumber(&KeyId); + } else { + Buffer[0] = STATUS_NO_SUCH_KEY; + return DESFIRE_STATUS_RESPONSE_SIZE; + } + /* Validate number of keys, and make sure the KeyId is valid given the AID selected */ - KeyId = Buffer[1]; if (!KeyIdValid(SelectedApp.Slot, KeyId)) { Buffer[0] = STATUS_PARAMETER_ERROR; return DESFIRE_STATUS_RESPONSE_SIZE; From 0e3e1080f92958235a1a3f489a7dcc96f728ac83 Mon Sep 17 00:00:00 2001 From: Tomaspre Date: Fri, 14 Oct 2022 15:08:33 +0100 Subject: [PATCH 14/22] DESFire: Various fixes --- .../Application/DESFire/DESFireInstructions.c | 39 +++++++++++++------ 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireInstructions.c b/Firmware/Chameleon-Mini/Application/DESFire/DESFireInstructions.c index d19a017f..4bb84f92 100644 --- a/Firmware/Chameleon-Mini/Application/DESFire/DESFireInstructions.c +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireInstructions.c @@ -817,29 +817,40 @@ uint16_t EV0CmdCreateApplication(uint8_t *Buffer, uint16_t ByteCount) { uint8_t Status; uint8_t KeyCount; uint8_t KeySettings; + uint8_t KeySettings2; + /* Validate command length */ + //TODO: Can contain optional fields if (ByteCount != 1 + 3 + 1 + 1) { Status = STATUS_LENGTH_ERROR; return ExitWithStatus(Buffer, Status, DESFIRE_STATUS_RESPONSE_SIZE); } + + UpdateIVIfNeeded(Buffer, ByteCount); + /* Require the PICC app to be selected */ if (!AuthenticatedWithPICCMasterKey) { Status = STATUS_PERMISSION_DENIED; return ExitWithStatus(Buffer, Status, DESFIRE_STATUS_RESPONSE_SIZE); } + const DESFireAidType Aid = { Buffer[1], Buffer[2], Buffer[3] }; KeySettings = Buffer[4]; - KeyCount = Buffer[5]; + KeyCount = Buffer[5] & 0x0f; //Only the lower four bits contain key count + KeySettings2 = Buffer[5] & 0xf0; + /* Validate number of keys: less than max (one for the Master Key) */ if (KeyCount > DESFIRE_MAX_KEYS || KeyCount == 0) { Status = STATUS_PARAMETER_ERROR; return ExitWithStatus(Buffer, Status, DESFIRE_STATUS_RESPONSE_SIZE); } + if (PMKRequiredForAppCreateDelete() != 0x00 && (Authenticated == 0x00 || AuthenticatedWithKey != 0x00)) { /* PICC master key authentication is required */ Status = STATUS_AUTHENTICATION_ERROR; return ExitWithStatus(Buffer, Status, DESFIRE_STATUS_RESPONSE_SIZE); } + /* Done */ Status = CreateApp(Aid, KeyCount, KeySettings); return ExitWithStatus(Buffer, Status, DESFIRE_STATUS_RESPONSE_SIZE); @@ -1223,17 +1234,21 @@ uint16_t EV0CmdReadData(uint8_t *Buffer, uint16_t ByteCount) { } AccessRights = ReadFileAccessRights(SelectedApp.Slot, fileIndex); CommSettings = ReadFileCommSettings(SelectedApp.Slot, fileIndex); - /* Verify authentication: read or read&write required */ - switch (ValidateAuthentication(AccessRights, VALIDATE_ACCESS_READWRITE | VALIDATE_ACCESS_READ)) { - case VALIDATED_ACCESS_DENIED: - Status = STATUS_AUTHENTICATION_ERROR; - return ExitWithStatus(Buffer, Status, DESFIRE_STATUS_RESPONSE_SIZE); - case VALIDATED_ACCESS_GRANTED_PLAINTEXT: - CommSettings = DESFIRE_COMMS_PLAINTEXT; - /* Fall through */ - case VALIDATED_ACCESS_GRANTED: - /* Carry on */ - break; + + /* Verify authentication: read or read&write required + * Except for cases when AppDirectory can be read freely*/ + if (!AMKFreeDirectoryListing()) { + switch (ValidateAuthentication(AccessRights, VALIDATE_ACCESS_READWRITE | VALIDATE_ACCESS_READ)) { + case VALIDATED_ACCESS_DENIED: + Status = STATUS_AUTHENTICATION_ERROR; + return ExitWithStatus(Buffer, Status, DESFIRE_STATUS_RESPONSE_SIZE); + case VALIDATED_ACCESS_GRANTED_PLAINTEXT: + CommSettings = DESFIRE_COMMS_PLAINTEXT; + /* Fall through */ + case VALIDATED_ACCESS_GRANTED: + /* Carry on */ + break; + } } /* Validate the file type */ From 4859d84aa11cbbadd0e2c4ea23502e75b1092078 Mon Sep 17 00:00:00 2001 From: Tomaspre Date: Fri, 14 Oct 2022 15:09:09 +0100 Subject: [PATCH 15/22] DESFire: Add support for one block EV1 encrypted file read and write --- .../Application/DESFire/DESFireInstructions.c | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireInstructions.c b/Firmware/Chameleon-Mini/Application/DESFire/DESFireInstructions.c index 4bb84f92..3f4b0849 100644 --- a/Firmware/Chameleon-Mini/Application/DESFire/DESFireInstructions.c +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireInstructions.c @@ -1268,11 +1268,42 @@ uint16_t EV0CmdReadData(uint8_t *Buffer, uint16_t ByteCount) { Status = STATUS_BOUNDARY_ERROR; return ExitWithStatus(Buffer, Status, DESFIRE_STATUS_RESPONSE_SIZE); } + /* Setup and start the transfer */ Status = ReadDataFileSetup(fileIndex, CommSettings, (uint16_t) Offset, (uint16_t) Length); if (Status != STATUS_OPERATION_OK) { return ExitWithStatus(Buffer, Status, DESFIRE_STATUS_RESPONSE_SIZE); } + + //TODO: This WILL break for files that use full encryption and are more than 16 bytes long! + //TODO: See commands for file writing for instructions on how to fix this + //Non-encrypted files are fine + if (CommSettings == 0x03) { + Length = (Length > 32) ? 32 : Length; + uint16_t size = ReadDataFileIterator(Buffer); + + Buffer[size] = Buffer[0]; + appendBufferCRC32C(Buffer+1, size); + memmove(Buffer+size, Buffer+size+1, 4); + + size += 4; + + uint8_t rem = (size-1) % CRYPTO_AES_BLOCK_SIZE; + if (rem) { + for (uint8_t i = 0; i < CRYPTO_AES_BLOCK_SIZE - rem; ++i) { + Buffer[size] = 0; + size++; + } + } + + uint8_t ciphertext[64]; + CryptoAESEncryptBuffer(size-1, Buffer+1, ciphertext, SessionIV, SessionKey); + memmove(Buffer+1, ciphertext, size-1); + + return size; + } + + return ReadDataFileIterator(Buffer); } @@ -1347,11 +1378,42 @@ uint16_t EV0CmdWriteData(uint8_t *Buffer, uint16_t ByteCount) { dataWriteSize += Offset; dataWriteBuffer = &Buffer[1]; } + /* Setup and start the transfer */ Status = WriteDataFileSetup(fileIndex, fileType, CommSettings, (uint16_t) Offset, (uint16_t) Length); if (Status != STATUS_OPERATION_OK) { return ExitWithStatus(Buffer, Status, DESFIRE_STATUS_RESPONSE_SIZE); } + + //TODO: This will(!) break if we would need to split the **encrypted** write into multiple segments! + //TODO: But at least there is *some* support for ecrypted write + //TODO: It'll be best to decipher in the actual writing function as we can then use + //TODO: the existing code for encrypted comms + //TODO: This also breaks if there's any write offset + //Non-encrypted write is ok + //Decrypt the incoming buffer if needed: + if (CommSettings == 0x03) { + //TODO: Check if the cipher is actually AES + DesfireLogEntry(LOG_APP_SESSION_IV, (void *) SessionIV, 16); + CryptoAESDecryptBuffer(dataWriteSize, dataWriteBuffer + dataWriteSize, dataWriteBuffer, SessionIV, SessionKey); + memmove(dataWriteBuffer, dataWriteBuffer + dataWriteSize, dataWriteSize); + + dataWriteSize = (Length > 32) ? 32 : Length; //To make sure we only process data in one command + + //Check checksum + uint8_t recvCRC[4]; + recvCRC[0] = dataWriteBuffer[dataWriteSize]; + recvCRC[1] = dataWriteBuffer[dataWriteSize+1]; + recvCRC[2] = dataWriteBuffer[dataWriteSize+2]; + recvCRC[3] = dataWriteBuffer[dataWriteSize+3]; + appendBufferCRC32C(Buffer, dataWriteSize+8); + if (recvCRC[0] != dataWriteBuffer[dataWriteSize] || recvCRC[1] != dataWriteBuffer[dataWriteSize+1] || + recvCRC[2] != dataWriteBuffer[dataWriteSize+2] || recvCRC[3] != dataWriteBuffer[dataWriteSize+3]) { + Status = STATUS_PARAMETER_ERROR; + return ExitWithStatus(Buffer, Status, DESFIRE_STATUS_RESPONSE_SIZE); + } + } + Status = WriteDataFileIterator(dataWriteBuffer, dataWriteSize); return ExitWithStatus(Buffer, Status, DESFIRE_STATUS_RESPONSE_SIZE); } From 7312a6f8c9c207e057c122692be0ce8aaf9cc541 Mon Sep 17 00:00:00 2001 From: Tomaspre Date: Sat, 15 Oct 2022 16:15:27 +0100 Subject: [PATCH 16/22] Fix response to 0x6A --- .../Application/DESFire/DESFireInstructions.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireInstructions.c b/Firmware/Chameleon-Mini/Application/DESFire/DESFireInstructions.c index 3f4b0849..ed793f76 100644 --- a/Firmware/Chameleon-Mini/Application/DESFire/DESFireInstructions.c +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireInstructions.c @@ -796,13 +796,14 @@ uint16_t EV0CmdGetApplicationIds1(uint8_t *Buffer, uint16_t ByteCount) { return DESFIRE_STATUS_RESPONSE_SIZE; } /* Require the PICC app to be selected */ - if (!AuthenticatedWithPICCMasterKey) { + if (SelectedApp.Slot != DESFIRE_PICC_APP_SLOT) { Buffer[0] = STATUS_PERMISSION_DENIED; return DESFIRE_STATUS_RESPONSE_SIZE; } + + //(ReadKeySettings(SelectedApp.Slot, AuthenticatedWithKey) & DESFIRE_FREE_DIRECTORY_LIST) /* Verify authentication settings */ - if ((ReadKeySettings(SelectedApp.Slot, AuthenticatedWithKey) & DESFIRE_FREE_DIRECTORY_LIST) && - (AuthenticatedWithKey != DESFIRE_MASTER_KEY_ID)) { + if (!AMKFreeDirectoryListing() && (AuthenticatedWithKey != DESFIRE_MASTER_KEY_ID)) { /* PICC master key authentication is required */ Buffer[0] = STATUS_AUTHENTICATION_ERROR; return DESFIRE_STATUS_RESPONSE_SIZE; From bddd1e619cb947136abfbb71ac312192c71385c0 Mon Sep 17 00:00:00 2001 From: Tomaspre Date: Sun, 16 Oct 2022 14:00:04 +0100 Subject: [PATCH 17/22] Fix processing of native wrapped commands that have zeros as arguments --- Firmware/Chameleon-Mini/Application/MifareDESFire.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/Chameleon-Mini/Application/MifareDESFire.c b/Firmware/Chameleon-Mini/Application/MifareDESFire.c index 63d52891..ac9f5ade 100644 --- a/Firmware/Chameleon-Mini/Application/MifareDESFire.c +++ b/Firmware/Chameleon-Mini/Application/MifareDESFire.c @@ -428,7 +428,7 @@ uint16_t MifareDesfireAppProcess(uint8_t *Buffer, uint16_t BitCount) { } ProcessedByteCount = DesfirePostprocessAPDU(ActiveCommMode, Buffer, ProcessedByteCount); return ISO14443AStoreLastDataFrameAndReturn(Buffer, ASBITS(ProcessedByteCount)); - } else if ((ByteCount >= 8 && DesfireCLA(Buffer[1]) && + } else if ((ByteCount >= 8 && Buffer[1] == DESFIRE_NATIVE_CLA && Buffer[3] == 0x00 && Buffer[4] == 0x00 && Buffer[5] == ByteCount - 8) || (ByteCount >= 9 && DesfireCLA(Buffer[1]) && Buffer[3] == 0x00 && Buffer[4] == 0x00 && Buffer[5] == ByteCount - 9)) { From 45e50af94e4d6b9dfcd0c0faaec57fd243382a9e Mon Sep 17 00:00:00 2001 From: Tomaspre Date: Tue, 18 Oct 2022 12:54:44 +0100 Subject: [PATCH 18/22] Fix key read and write for keys with different numbers than zero --- .../DESFire/DESFireApplicationDirectory.c | 27 ++++++++++++------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireApplicationDirectory.c b/Firmware/Chameleon-Mini/Application/DESFire/DESFireApplicationDirectory.c index 12c1982e..1f884fe1 100644 --- a/Firmware/Chameleon-Mini/Application/DESFire/DESFireApplicationDirectory.c +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireApplicationDirectory.c @@ -304,10 +304,12 @@ void ReadAppKey(uint8_t AppSlot, uint8_t KeyId, uint8_t *Key, SIZET KeySize) { } else if (KeySize > CRYPTO_MAX_KEY_SIZE) { return; } + SIZET keyStorageArrayBlockId = ReadKeyStorageAddress(AppSlot); - SIZET keyStorageArray[DESFIRE_MAX_KEYS]; - ReadBlockBytes(keyStorageArray, keyStorageArrayBlockId, 2 * DESFIRE_MAX_KEYS); - ReadBlockBytes(Key, keyStorageArray[KeyId], KeySize); + + SIZET keyBlockID; + ReadBlockBytes(&keyBlockID, keyStorageArrayBlockId + (sizeof(SIZET) * KeyId), sizeof(SIZET)); + ReadBlockBytes(Key, keyBlockID, KeySize); } void WriteAppKey(uint8_t AppSlot, uint8_t KeyId, const uint8_t *Key, SIZET KeySize) { @@ -316,10 +318,12 @@ void WriteAppKey(uint8_t AppSlot, uint8_t KeyId, const uint8_t *Key, SIZET KeySi } else if (KeySize > CRYPTO_MAX_KEY_SIZE) { return; } + SIZET keyStorageArrayBlockId = ReadKeyStorageAddress(AppSlot); - SIZET keyStorageArray[DESFIRE_MAX_KEYS]; - ReadBlockBytes(keyStorageArray, keyStorageArrayBlockId, 2 * DESFIRE_MAX_KEYS); - WriteBlockBytes(Key, keyStorageArray[KeyId], KeySize); + + SIZET keyBlockID; + ReadBlockBytes(&keyBlockID, keyStorageArrayBlockId + (sizeof(SIZET) * KeyId), sizeof(SIZET)); + WriteBlockBytes(Key, keyBlockID, KeySize); } /* @@ -662,11 +666,14 @@ uint16_t CreateApp(const DESFireAidType Aid, uint8_t KeyCount, uint8_t KeySettin } else { SIZET keyAddresses[DESFIRE_MAX_KEYS]; memset(keyAddresses, 0x00, sizeof(SIZET) * DESFIRE_MAX_KEYS); - // Allocate the application Master Key: - keyAddresses[0] = AllocateBlocks(APP_CACHE_MAX_KEY_BLOCK_SIZE); - if (keyAddresses[0] == 0) { - return STATUS_OUT_OF_EEPROM_ERROR; + // Allocate space for all keys: + for (uint8_t i = 0; i < KeyCount; ++i) { + keyAddresses[i] = AllocateBlocks(APP_CACHE_MAX_KEY_BLOCK_SIZE); + if (keyAddresses[i] == 0) { + return STATUS_OUT_OF_EEPROM_ERROR; + } } + BYTE cryptoBlankKeyData[CRYPTO_MAX_KEY_SIZE]; memset(cryptoBlankKeyData, 0x00, CRYPTO_MAX_KEY_SIZE); WriteBlockBytes(cryptoBlankKeyData, keyAddresses[0], CRYPTO_MAX_KEY_SIZE); From 0fe06759fd1435be49cb42ef1efdca58b4540711 Mon Sep 17 00:00:00 2001 From: Tomaspre Date: Tue, 18 Oct 2022 14:03:57 +0100 Subject: [PATCH 19/22] Return correct error code when file index is out of range --- .../Chameleon-Mini/Application/DESFire/DESFireInstructions.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireInstructions.c b/Firmware/Chameleon-Mini/Application/DESFire/DESFireInstructions.c index ed793f76..880a64ac 100644 --- a/Firmware/Chameleon-Mini/Application/DESFire/DESFireInstructions.c +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireInstructions.c @@ -801,7 +801,6 @@ uint16_t EV0CmdGetApplicationIds1(uint8_t *Buffer, uint16_t ByteCount) { return DESFIRE_STATUS_RESPONSE_SIZE; } - //(ReadKeySettings(SelectedApp.Slot, AuthenticatedWithKey) & DESFIRE_FREE_DIRECTORY_LIST) /* Verify authentication settings */ if (!AMKFreeDirectoryListing() && (AuthenticatedWithKey != DESFIRE_MASTER_KEY_ID)) { /* PICC master key authentication is required */ @@ -1229,7 +1228,7 @@ uint16_t EV0CmdReadData(uint8_t *Buffer, uint16_t ByteCount) { FileNum = Buffer[1]; uint8_t fileIndex = LookupFileNumberIndex(SelectedApp.Slot, FileNum); if (fileIndex >= DESFIRE_MAX_FILES) { - Status = STATUS_PARAMETER_ERROR; + Status = STATUS_FILE_NOT_FOUND; DEBUG_PRINT_P(PSTR("FileIndexError")); return ExitWithStatus(Buffer, Status, DESFIRE_STATUS_RESPONSE_SIZE); } From ea636a4f90c3db8bc23404fea190d5378ce3532a Mon Sep 17 00:00:00 2001 From: Tomaspre Date: Tue, 18 Oct 2022 15:01:42 +0100 Subject: [PATCH 20/22] Add custom build setting for Gallagher emulation (increase max number of keys to 3) --- .../BuildScripts/custom_build_targets.mk | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Firmware/Chameleon-Mini/BuildScripts/custom_build_targets.mk b/Firmware/Chameleon-Mini/BuildScripts/custom_build_targets.mk index 754799d4..df5d9b5e 100644 --- a/Firmware/Chameleon-Mini/BuildScripts/custom_build_targets.mk +++ b/Firmware/Chameleon-Mini/BuildScripts/custom_build_targets.mk @@ -61,6 +61,20 @@ desfire: TARGET_CUSTOM_BUILD_NAME:=DESFire desfire: CONFIG_SETTINGS:=$(SUPPORTED_TAGS_BUILD) -DDEFAULT_CONFIGURATION=CONFIG_NONE $(EXTRA_CONFIG_SETTINGS) desfire: custom-build +desfire-gallagher: FLASH_DATA_SIZE_CONST:=0F000 # Eight settings (save some space): 4 * 0x2000 +desfire-gallagher: FLASH_DATA_SIZE:=0x$(FLASH_DATA_SIZE_CONST) +desfire-gallagher: FLASH_DATA_SIZE_UPPER_CONST:=20000 +desfire-gallagher: FLASH_DATA_ADDR:=0x$(shell echo $$(( 0x$(FLASH_DATA_SIZE_UPPER_CONST) - 0x$(FLASH_DATA_SIZE_CONST) )) | xargs -0 printf %X) +desfire-gallagher: SUPPORTED_TAGS_BUILD:=-DCONFIG_MF_DESFIRE_SUPPORT +desfire-gallagher: EXTRA_CONFIG_SETTINGS:=-DDESFIRE_CUSTOM_MAX_APPS=3 + -DDESFIRE_CUSTOM_MAX_FILES=4 \ + -DDESFIRE_CUSTOM_MAX_KEYS=3 \ + -DDESFIRE_CRYPTO1_SAVE_SPACE \ + -finline-small-functions +desfire-gallagher: TARGET_CUSTOM_BUILD_NAME:=DESFire +desfire-gallagher: CONFIG_SETTINGS:=$(SUPPORTED_TAGS_BUILD) -DDEFAULT_CONFIGURATION=CONFIG_NONE $(EXTRA_CONFIG_SETTINGS) +desfire-gallagher: custom-build + desfire-dev: FLASH_DATA_SIZE_CONST:=08000 # Four settings (save some space): 4 * 0x2000 desfire-dev: FLASH_DATA_SIZE:=0x$(FLASH_DATA_SIZE_CONST) desfire-dev: FLASH_DATA_SIZE_UPPER_CONST:=20000 From 1333762bc8c65670dbd961f2e9ba4bfd777ece91 Mon Sep 17 00:00:00 2001 From: Tomaspre Date: Tue, 18 Oct 2022 15:03:26 +0100 Subject: [PATCH 21/22] Set custom build name for Gallagher build --- Firmware/Chameleon-Mini/BuildScripts/custom_build_targets.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/Chameleon-Mini/BuildScripts/custom_build_targets.mk b/Firmware/Chameleon-Mini/BuildScripts/custom_build_targets.mk index df5d9b5e..5632a4a2 100644 --- a/Firmware/Chameleon-Mini/BuildScripts/custom_build_targets.mk +++ b/Firmware/Chameleon-Mini/BuildScripts/custom_build_targets.mk @@ -71,7 +71,7 @@ desfire-gallagher: EXTRA_CONFIG_SETTINGS:=-DDESFIRE_CUSTOM_MAX_APPS=3 -DDESFIRE_CUSTOM_MAX_KEYS=3 \ -DDESFIRE_CRYPTO1_SAVE_SPACE \ -finline-small-functions -desfire-gallagher: TARGET_CUSTOM_BUILD_NAME:=DESFire +desfire-gallagher: TARGET_CUSTOM_BUILD_NAME:=DESFire_Gallagher desfire-gallagher: CONFIG_SETTINGS:=$(SUPPORTED_TAGS_BUILD) -DDEFAULT_CONFIGURATION=CONFIG_NONE $(EXTRA_CONFIG_SETTINGS) desfire-gallagher: custom-build From 108d45cf734f1171bce4a5d962ae536a2f17a4e8 Mon Sep 17 00:00:00 2001 From: Tomaspre Date: Thu, 27 Oct 2022 11:39:50 +0100 Subject: [PATCH 22/22] Support Gallagher when using make desfire --- .../DESFire/DESFireApplicationDirectory.h | 2 +- .../BuildScripts/custom_build_targets.mk | 14 -------------- 2 files changed, 1 insertion(+), 15 deletions(-) diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireApplicationDirectory.h b/Firmware/Chameleon-Mini/Application/DESFire/DESFireApplicationDirectory.h index 3c501617..e9240597 100644 --- a/Firmware/Chameleon-Mini/Application/DESFire/DESFireApplicationDirectory.h +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireApplicationDirectory.h @@ -58,7 +58,7 @@ This notice must be retained at the top of all source files where indicated. #endif #ifdef MEMORY_LIMITED_TESTING -#define DESFIRE_MAX_KEYS (2) +#define DESFIRE_MAX_KEYS (3) #else #ifdef DESFIRE_CUSTOM_MAX_KEYS #define DESFIRE_MAX_KEYS (DESFIRE_CUSTOM_MAX_KEYS) diff --git a/Firmware/Chameleon-Mini/BuildScripts/custom_build_targets.mk b/Firmware/Chameleon-Mini/BuildScripts/custom_build_targets.mk index 5632a4a2..754799d4 100644 --- a/Firmware/Chameleon-Mini/BuildScripts/custom_build_targets.mk +++ b/Firmware/Chameleon-Mini/BuildScripts/custom_build_targets.mk @@ -61,20 +61,6 @@ desfire: TARGET_CUSTOM_BUILD_NAME:=DESFire desfire: CONFIG_SETTINGS:=$(SUPPORTED_TAGS_BUILD) -DDEFAULT_CONFIGURATION=CONFIG_NONE $(EXTRA_CONFIG_SETTINGS) desfire: custom-build -desfire-gallagher: FLASH_DATA_SIZE_CONST:=0F000 # Eight settings (save some space): 4 * 0x2000 -desfire-gallagher: FLASH_DATA_SIZE:=0x$(FLASH_DATA_SIZE_CONST) -desfire-gallagher: FLASH_DATA_SIZE_UPPER_CONST:=20000 -desfire-gallagher: FLASH_DATA_ADDR:=0x$(shell echo $$(( 0x$(FLASH_DATA_SIZE_UPPER_CONST) - 0x$(FLASH_DATA_SIZE_CONST) )) | xargs -0 printf %X) -desfire-gallagher: SUPPORTED_TAGS_BUILD:=-DCONFIG_MF_DESFIRE_SUPPORT -desfire-gallagher: EXTRA_CONFIG_SETTINGS:=-DDESFIRE_CUSTOM_MAX_APPS=3 - -DDESFIRE_CUSTOM_MAX_FILES=4 \ - -DDESFIRE_CUSTOM_MAX_KEYS=3 \ - -DDESFIRE_CRYPTO1_SAVE_SPACE \ - -finline-small-functions -desfire-gallagher: TARGET_CUSTOM_BUILD_NAME:=DESFire_Gallagher -desfire-gallagher: CONFIG_SETTINGS:=$(SUPPORTED_TAGS_BUILD) -DDEFAULT_CONFIGURATION=CONFIG_NONE $(EXTRA_CONFIG_SETTINGS) -desfire-gallagher: custom-build - desfire-dev: FLASH_DATA_SIZE_CONST:=08000 # Four settings (save some space): 4 * 0x2000 desfire-dev: FLASH_DATA_SIZE:=0x$(FLASH_DATA_SIZE_CONST) desfire-dev: FLASH_DATA_SIZE_UPPER_CONST:=20000