From 136920bcdd856371e54ad039f52f3a72c25bbb71 Mon Sep 17 00:00:00 2001 From: TNEd Date: Tue, 6 Jun 2017 12:02:17 +0200 Subject: [PATCH 1/4] 4K fixes for authentication --- .../Application/MifareClassic.c | 566 ++++++++++-------- 1 file changed, 304 insertions(+), 262 deletions(-) diff --git a/Firmware/Chameleon-Mini/Application/MifareClassic.c b/Firmware/Chameleon-Mini/Application/MifareClassic.c index e843b30..61867c7 100644 --- a/Firmware/Chameleon-Mini/Application/MifareClassic.c +++ b/Firmware/Chameleon-Mini/Application/MifareClassic.c @@ -33,6 +33,7 @@ #define MEM_KEY_SIZE 6 /* Bytes */ #define MEM_ACC_GPB_SIZE 4 /* Bytes */ #define MEM_SECTOR_ADDR_MASK 0xFC +#define MEM_BIGSECTOR_ADDR_MASK 0xF0 #define MEM_BYTES_PER_BLOCK 16 /* Bytes */ #define MEM_VALUE_SIZE 4 /* Bytes */ @@ -302,12 +303,24 @@ INLINE uint8_t GetAccessCondition(uint8_t Block) /* Check */ if ( ((InvSAcc0 ^ Acc1) & 0xf0) || /* C1x */ ((InvSAcc0 ^ Acc2) & 0x0f) || /* C2x */ - ((InvSAcc1 ^ Acc2) & 0xf0) || /* C1x */ - ((InvSAcc1 ^ Acc0) & 0x0f)) /* C3x */ + ((InvSAcc1 ^ Acc2) & 0xf0)) /* C3x */ { return(NO_ACCESS); } - Block &= 3; + /* Fix for MFClassic 4K cards */ + if(Block<128) + Block &= 3; + else { + Block &= 15; + if (Block& 15) + Block=3; + else if (Block<=4) + Block=0; + else if (Block<=9) + Block=1; + else + Block=2; + } Acc0 = ~Acc0; /* C1x Bits to bit 0..3 */ Acc1 = Acc2; /* C2x Bits to bit 0..3 */ @@ -376,7 +389,24 @@ void MifareClassicAppInit1K(void) FromHalt = false; } +void MifareClassicAppInit1K7B(void) +{ + State = STATE_IDLE; + CardATQAValue = MFCLASSIC_1K_7B_ATQA_VALUE; + CardSAKValue = MFCLASSIC_1K_SAK_VALUE; + FromHalt = false; +} + + void MifareClassicAppInit4K(void) +{ + State = STATE_IDLE; + CardATQAValue = MFCLASSIC_4K_ATQA_VALUE; + CardSAKValue = MFCLASSIC_4K_SAK_VALUE; + FromHalt = false; +} + +void MifareClassicAppInit4K7B(void) { State = STATE_IDLE; CardATQAValue = MFCLASSIC_4K_7B_ATQA_VALUE; @@ -573,77 +603,77 @@ uint16_t MifareClassicAppProcess(uint8_t* Buffer, uint16_t BitCount) return ACK_NAK_FRAME_SIZE; } } else if ( (Buffer[0] == CMD_AUTH_A) || (Buffer[0] == CMD_AUTH_B)) { - if (ISO14443ACheckCRCA(Buffer, CMD_AUTH_FRAME_SIZE)) { + if (ISO14443ACheckCRCA(Buffer, CMD_AUTH_FRAME_SIZE)) { - uint16_t SectorAddress = Buffer[1] & MEM_SECTOR_ADDR_MASK; - uint16_t KeyOffset = (Buffer[0] == CMD_AUTH_A ? MEM_KEY_A_OFFSET : MEM_KEY_B_OFFSET); - uint16_t SectorStartAddress = (uint16_t)SectorAddress * MEM_BYTES_PER_BLOCK; - uint8_t Key[6]; - uint8_t Uid[4]; - uint8_t CardNonce[4]; + //uint16_t SectorAddress = Buffer[1] & MEM_SECTOR_ADDR_MASK; + uint16_t KeyOffset = (Buffer[0] == CMD_AUTH_A ? MEM_KEY_A_OFFSET : MEM_KEY_B_OFFSET); + uint16_t AccessOffset = MEM_KEY_A_OFFSET + MEM_KEY_SIZE; + uint16_t SectorStartAddress; + uint8_t Key[6]; + uint8_t Uid[4]; + uint8_t CardNonce[8]; - /* Fix for MFClassic 4k cards */ - if(Buffer[1] >= 128) - { - SectorStartAddress += MEM_KEY_BIGSECTOR_OFFSET; - } + /* Fix for MFClassic 4k cards */ + if(Buffer[1] >= 128) { + SectorStartAddress = (Buffer[1] & MEM_BIGSECTOR_ADDR_MASK) * MEM_BYTES_PER_BLOCK ; + KeyOffset += MEM_KEY_BIGSECTOR_OFFSET; + AccessOffset += MEM_KEY_BIGSECTOR_OFFSET; + } else { + SectorStartAddress = (Buffer[1] & MEM_SECTOR_ADDR_MASK) * MEM_BYTES_PER_BLOCK ; + } - LogEntry(LOG_INFO_APP_CMD_AUTH, Buffer, 2); + LogEntry(LOG_INFO_APP_CMD_AUTH, Buffer, 2); + /* set KeyInUse for global use to keep info about authentication */ + KeyInUse = Buffer[0] & 1; + CurrentAddress = SectorStartAddress / MEM_BYTES_PER_BLOCK; + //if (!AccessConditions[MEM_ACC_GPB_SIZE-1] ||(CurrentAddress != AccessAddress)) { + /* Get access conditions from the sector trailor */ + MemoryReadBlock(AccessConditions, SectorStartAddress + AccessOffset, MEM_ACC_GPB_SIZE); + AccessAddress = CurrentAddress; + //} - KeyInUse = Buffer[0] & 1; - CurrentAddress = Buffer[1] & MEM_SECTOR_ADDR_MASK; - if (!AccessConditions[MEM_ACC_GPB_SIZE-1] ||(CurrentAddress != AccessAddress)) { - /* Get access conditions from the sector trailor */ - MemoryReadBlock(AccessConditions, SectorStartAddress + MEM_KEY_A_OFFSET + MEM_KEY_SIZE, MEM_ACC_GPB_SIZE); - AccessAddress = CurrentAddress; - } - /* Generate a random nonce and read UID and key from memory */ - RandomGetBuffer(CardNonce, sizeof(CardNonce)); - if (ActiveConfiguration.UidSize == 7) - MemoryReadBlock(Uid, MEM_UID_CL2_ADDRESS, MEM_UID_CL2_SIZE); - else - MemoryReadBlock(Uid, MEM_UID_CL1_ADDRESS, MEM_UID_CL1_SIZE); + /* Generate a random nonce and read UID and key from memory */ + RandomGetBuffer(CardNonce, sizeof(CardNonce)); + if (ActiveConfiguration.UidSize == 7) + MemoryReadBlock(Uid, MEM_UID_CL2_ADDRESS, MEM_UID_CL2_SIZE); + else + MemoryReadBlock(Uid, MEM_UID_CL1_ADDRESS, MEM_UID_CL1_SIZE); + MemoryReadBlock(Key, SectorStartAddress + KeyOffset, MEM_KEY_SIZE); - MemoryReadBlock(Key, SectorStartAddress + KeyOffset, MEM_KEY_SIZE); + /* Precalculate the reader response from card-nonce */ + for (uint8_t i=0; i= 128) - { - SectorStartAddress += MEM_KEY_BIGSECTOR_OFFSET; - } + return ACK_NAK_FRAME_SIZE; + } else if ( (Buffer[0] == CMD_AUTH_A) || (Buffer[0] == CMD_AUTH_B) ) { + if (ISO14443ACheckCRCA(Buffer, CMD_AUTH_FRAME_SIZE)) + { + /* Nested authentication. */ + //uint16_t SectorAddress = Buffer[1] & MEM_SECTOR_ADDR_MASK; + uint16_t KeyOffset = (Buffer[0] == CMD_AUTH_A ? MEM_KEY_A_OFFSET : MEM_KEY_B_OFFSET); + uint16_t AccOffset = MEM_KEY_A_OFFSET + MEM_KEY_SIZE; + uint16_t SectorStartAddress; + uint8_t Key[6]; + uint8_t Uid[4]; + uint8_t CardNonce[8]; - LogEntry(LOG_INFO_APP_CMD_AUTH, Buffer, 2); + /* Fix for MFClassic 4k cards */ + if(Buffer[1] >= 128) { + SectorStartAddress = (Buffer[1] & MEM_BIGSECTOR_ADDR_MASK) * MEM_BYTES_PER_BLOCK ; + KeyOffset += MEM_KEY_BIGSECTOR_OFFSET; + AccOffset += MEM_KEY_BIGSECTOR_OFFSET; + } else { + SectorStartAddress = (Buffer[1] & MEM_SECTOR_ADDR_MASK) * MEM_BYTES_PER_BLOCK ; + } - KeyInUse = Buffer[0] & 1; - CurrentAddress = Buffer[1] & MEM_SECTOR_ADDR_MASK; - if (CurrentAddress != AccessAddress) { - /* Get access conditions from the sector trailor */ - MemoryReadBlock(AccessConditions, SectorStartAddress + MEM_KEY_A_OFFSET + MEM_KEY_SIZE, MEM_ACC_GPB_SIZE); - AccessAddress = CurrentAddress; - } + LogEntry(LOG_INFO_APP_CMD_AUTH, Buffer, 2); + /* set KeyInUse for global use to keep info about authentication */ + KeyInUse = Buffer[0] & 1; + CurrentAddress = SectorStartAddress / MEM_BYTES_PER_BLOCK; + if (CurrentAddress != AccessAddress) { + /* Get access conditions from the sector trailor */ + MemoryReadBlock(AccessConditions, SectorStartAddress + AccOffset, MEM_ACC_GPB_SIZE); + AccessAddress = CurrentAddress; + } - /* Generate a random nonce and read UID and key from memory */ - RandomGetBuffer(CardNonce, sizeof(CardNonce)); - if (ActiveConfiguration.UidSize == 7) - MemoryReadBlock(Uid, MEM_UID_CL2_ADDRESS, MEM_UID_CL2_SIZE); - else - MemoryReadBlock(Uid, MEM_UID_CL1_ADDRESS, MEM_UID_CL1_SIZE); - MemoryReadBlock(Key, SectorStartAddress + KeyOffset, MEM_KEY_SIZE); + /* Generate a random nonce and read UID and key from memory */ + RandomGetBuffer(CardNonce, sizeof(CardNonce)); + if (ActiveConfiguration.UidSize == 7) + MemoryReadBlock(Uid, MEM_UID_CL2_ADDRESS, MEM_UID_CL2_SIZE); + else + MemoryReadBlock(Uid, MEM_UID_CL1_ADDRESS, MEM_UID_CL1_SIZE); + MemoryReadBlock(Key, SectorStartAddress + KeyOffset, MEM_KEY_SIZE); - /* Precalculate the reader response from card-nonce */ - for (uint8_t i=0; i Date: Tue, 6 Jun 2017 12:59:59 +0200 Subject: [PATCH 2/4] remove partial auth --- Firmware/Chameleon-Mini/Application/MifareClassic.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/Firmware/Chameleon-Mini/Application/MifareClassic.c b/Firmware/Chameleon-Mini/Application/MifareClassic.c index 61867c7..548c921 100644 --- a/Firmware/Chameleon-Mini/Application/MifareClassic.c +++ b/Firmware/Chameleon-Mini/Application/MifareClassic.c @@ -714,13 +714,7 @@ uint16_t MifareClassicAppProcess(uint8_t* Buffer, uint16_t BitCount) /* Reader delivers an encrypted nonce. We use it * to setup the crypto1 LFSR in nonlinear feedback mode. * Furthermore it delivers an encrypted answer. Decrypt and check it */ - LogEntry(LOG_INFO_APP_CMD_AUTH,&BitCount,1); - /* Fix for quick nested authing no Reader Nonce */ - uint8_t start = 4; - if (BitCount<64) - start = 0; - else - Crypto1Auth(&Buffer[0]); + Crypto1Auth(&Buffer[0]); Crypto1ByteArray(&Buffer[start], 4); From e579bfb46970f334bed64d61e4d90c3de6f508bf Mon Sep 17 00:00:00 2001 From: TNEd Date: Tue, 6 Jun 2017 13:15:12 +0200 Subject: [PATCH 3/4] remove partial auth all --- Firmware/Chameleon-Mini/Application/MifareClassic.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Firmware/Chameleon-Mini/Application/MifareClassic.c b/Firmware/Chameleon-Mini/Application/MifareClassic.c index 548c921..b0e7df0 100644 --- a/Firmware/Chameleon-Mini/Application/MifareClassic.c +++ b/Firmware/Chameleon-Mini/Application/MifareClassic.c @@ -716,14 +716,14 @@ uint16_t MifareClassicAppProcess(uint8_t* Buffer, uint16_t BitCount) * Furthermore it delivers an encrypted answer. Decrypt and check it */ Crypto1Auth(&Buffer[0]); - Crypto1ByteArray(&Buffer[start], 4); + Crypto1ByteArray(&Buffer[4], 4); LogEntry(LOG_INFO_APP_AUTHING, &Buffer[start], 4); - if ((Buffer[start] == ReaderResponse[0]) && - (Buffer[start+1] == ReaderResponse[1]) && - (Buffer[start+2] == ReaderResponse[2]) && - (Buffer[start+3] == ReaderResponse[3])) { + if ((Buffer[4] == ReaderResponse[0]) && + (Buffer[5] == ReaderResponse[1]) && + (Buffer[6] == ReaderResponse[2]) && + (Buffer[7] == ReaderResponse[3])) { /* Reader is authenticated. Encrypt the precalculated card response * and generate the parity bits. */ From 2b127e4d3255df6f3e6ab7123d94a8e950ea66f9 Mon Sep 17 00:00:00 2001 From: TNEd Date: Tue, 6 Jun 2017 13:18:31 +0200 Subject: [PATCH 4/4] remove partial auth all2 --- Firmware/Chameleon-Mini/Application/MifareClassic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/Chameleon-Mini/Application/MifareClassic.c b/Firmware/Chameleon-Mini/Application/MifareClassic.c index b0e7df0..aa071ac 100644 --- a/Firmware/Chameleon-Mini/Application/MifareClassic.c +++ b/Firmware/Chameleon-Mini/Application/MifareClassic.c @@ -718,7 +718,7 @@ uint16_t MifareClassicAppProcess(uint8_t* Buffer, uint16_t BitCount) Crypto1ByteArray(&Buffer[4], 4); - LogEntry(LOG_INFO_APP_AUTHING, &Buffer[start], 4); + LogEntry(LOG_INFO_APP_AUTHING, &Buffer[4], 4); if ((Buffer[4] == ReaderResponse[0]) && (Buffer[5] == ReaderResponse[1]) &&