From bf1eadc337c39b75793472c2dd24ff7ee81868b1 Mon Sep 17 00:00:00 2001 From: Maxie Dion Schmidt Date: Sun, 13 Feb 2022 00:29:24 -0500 Subject: [PATCH] Making a sane backup point while prfusely debugging --- .../Application/DESFire/DESFireCrypto.c | 1 + .../Application/DESFire/DESFireInstructions.c | 15 ++---- .../Application/DESFire/DESFireUtils.c | 20 ++++---- .../Application/MifareDESFire.c | 48 ++++++++----------- .../Libs/ArduinoCryptoLib/aes/aes128.h | 22 ++++----- 5 files changed, 46 insertions(+), 60 deletions(-) diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireCrypto.c b/Firmware/Chameleon-Mini/Application/DESFire/DESFireCrypto.c index e2654d98..6c671beb 100644 --- a/Firmware/Chameleon-Mini/Application/DESFire/DESFireCrypto.c +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireCrypto.c @@ -62,6 +62,7 @@ void InvalidateAuthState(BYTE keepPICCAuthData) { Iso7816FileSelected = false; CryptoAuthMethod = CRYPTO_TYPE_ANY; ActiveCommMode = DESFIRE_DEFAULT_COMMS_STANDARD; + DesfireCommMode = ActiveCommMode; } bool IsAuthenticated(void) { diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireInstructions.c b/Firmware/Chameleon-Mini/Application/DESFire/DESFireInstructions.c index 89883f4e..c390be55 100644 --- a/Firmware/Chameleon-Mini/Application/DESFire/DESFireInstructions.c +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireInstructions.c @@ -518,8 +518,6 @@ uint16_t EV0CmdAuthenticateLegacy1(uint8_t *Buffer, uint16_t ByteCount) { keySize = GetDefaultCryptoMethodKeySize(CRYPTO_TYPE_2KTDEA); Key = SessionKey; DesfireCommandState.KeyId = KeyId; - DesfireCommandState.CryptoMethodType = CRYPTO_TYPE_3K3DES; - DesfireCommandState.ActiveCommMode = GetCryptoMethodCommSettings(CRYPTO_TYPE_3K3DES); /* Fetch the key */ if (cryptoKeyType == CRYPTO_TYPE_DES) { @@ -583,15 +581,10 @@ uint16_t EV0CmdAuthenticateLegacy2(uint8_t *Buffer, uint16_t ByteCount) { /* Reset parameters for authentication from the first exchange */ KeyId = DesfireCommandState.KeyId; - cryptoKeyType = DesfireCommandState.CryptoMethodType; - keySize = GetDefaultCryptoMethodKeySize(CRYPTO_TYPE_3K3DES); + cryptoKeyType = CRYPTO_TYPE_2KTDEA; + keySize = GetDefaultCryptoMethodKeySize(CRYPTO_TYPE_2KTDEA); Key = SessionKey; - if (cryptoKeyType == CRYPTO_TYPE_DES) { - ReadAppKey(SelectedApp.Slot, KeyId, Key, CRYPTO_DES_KEY_SIZE); - memcpy(Key + CRYPTO_DES_KEY_SIZE, Key, CRYPTO_DES_KEY_SIZE); - } else { - ReadAppKey(SelectedApp.Slot, KeyId, Key, keySize); - } + ReadAppKey(SelectedApp.Slot, KeyId, Key, keySize); /* Decrypt the challenge sent back to get RndA and a shifted RndB */ BYTE challengeRndAB[2 * CRYPTO_CHALLENGE_RESPONSE_BYTES]; @@ -624,6 +617,8 @@ uint16_t EV0CmdAuthenticateLegacy2(uint8_t *Buffer, uint16_t ByteCount) { AuthenticatedWithKey = KeyId; AuthenticatedWithPICCMasterKey = (SelectedApp.Slot == DESFIRE_PICC_APP_SLOT) && (KeyId == DESFIRE_MASTER_KEY_ID); + DesfireCommandState.CryptoMethodType = CRYPTO_TYPE_2KTDEA; + DesfireCommandState.ActiveCommMode = GetCryptoMethodCommSettings(CRYPTO_TYPE_2KTDEA); /* Return the status on success */ Buffer[0] = STATUS_OPERATION_OK; diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireUtils.c b/Firmware/Chameleon-Mini/Application/DESFire/DESFireUtils.c index 8abec899..e9d18d42 100644 --- a/Firmware/Chameleon-Mini/Application/DESFire/DESFireUtils.c +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireUtils.c @@ -30,6 +30,7 @@ This notice must be retained at the top of all source files where indicated. #include "DESFireUtils.h" #include "DESFirePICCControl.h" +#include "DESFireLogging.h" void RotateArrayRight(BYTE *srcBuf, BYTE *destBuf, SIZET bufSize) { destBuf[bufSize - 1] = srcBuf[0]; @@ -147,10 +148,8 @@ bool DesfireCheckParityBits(uint8_t *Buffer, uint16_t BitCount) { } uint16_t DesfirePreprocessAPDU(uint8_t CommMode, uint8_t *Buffer, uint16_t BufferSize) { + DEBUG_PRINT_P(PSTR("PRE -- CommMode -- 0x%02x"), CommMode); switch (CommMode) { - case DESFIRE_COMMS_PLAINTEXT: - // Remove the CRCA bytes at the end of the buffer: - return MAX(0, BufferSize - 2); case DESFIRE_COMMS_PLAINTEXT_MAC: { uint16_t ChecksumBytes = 0; if (DesfireCommandState.CryptoMethodType == CRYPTO_TYPE_DES || DesfireCommandState.CryptoMethodType == CRYPTO_TYPE_2KTDEA) { @@ -189,17 +188,16 @@ uint16_t DesfirePreprocessAPDU(uint8_t CommMode, uint8_t *Buffer, uint16_t Buffe } return MAX(0, BufferSize - ChecksumBytes); } + case DESFIRE_COMMS_PLAINTEXT: default: - break; + // Leave the CRCA bytes intact: + return BufferSize; } - return 0; } uint16_t DesfirePostprocessAPDU(uint8_t CommMode, uint8_t *Buffer, uint16_t BufferSize) { + DEBUG_PRINT_P(PSTR("POST -- CommMode -- 0x%02x"), CommMode); switch (CommMode) { - case DESFIRE_COMMS_PLAINTEXT: - ISO14443AAppendCRCA(Buffer, BufferSize); - return BufferSize + 2; case DESFIRE_COMMS_PLAINTEXT_MAC: { if (DesfireCommandState.CryptoMethodType == CRYPTO_TYPE_DES || DesfireCommandState.CryptoMethodType == CRYPTO_TYPE_2KTDEA) { return appendBufferMAC(SessionKey, Buffer, BufferSize); @@ -238,10 +236,12 @@ uint16_t DesfirePostprocessAPDU(uint8_t CommMode, uint8_t *Buffer, uint16_t Buff memmove(&Buffer[0], &Buffer[XferBytes], XferBytes); return XferBytes; } + case DESFIRE_COMMS_PLAINTEXT: default: - break; + //ISO14443AAppendCRCA(Buffer, BufferSize); + //return BufferSize + 2; + return BufferSize; } - return 0; } #endif /* CONFIG_MF_DESFIRE_SUPPORT */ diff --git a/Firmware/Chameleon-Mini/Application/MifareDESFire.c b/Firmware/Chameleon-Mini/Application/MifareDESFire.c index 1a4ec777..a71a600c 100644 --- a/Firmware/Chameleon-Mini/Application/MifareDESFire.c +++ b/Firmware/Chameleon-Mini/Application/MifareDESFire.c @@ -174,25 +174,22 @@ uint16_t MifareDesfireProcessCommand(uint8_t *Buffer, uint16_t ByteCount) { uint16_t MifareDesfireProcess(uint8_t *Buffer, uint16_t BitCount) { size_t ByteCount = (BitCount + BITS_PER_BYTE - 1) / BITS_PER_BYTE; DesfireCmdCLA = Buffer[0]; + LogEntry(LOG_INFO_DESFIRE_INCOMING_DATA, Buffer, ByteCount); if (BitCount == 0) { return ISO14443A_APP_NO_RESPONSE; - } else if ((ByteCount >= 8 && DesfireCLA(Buffer[0]) && Buffer[2] == 0x00 && + } else if ((ByteCount >= 6 && DesfireCLA(Buffer[0]) && Buffer[2] == 0x00 && Buffer[3] == 0x00 && (Buffer[4] == ByteCount - 6 || Buffer[4] == ByteCount - 8)) || Iso7816CLA(DesfireCmdCLA)) { - // Wrapped native command structure: - /* Unwrap the PDU from ISO 7816-4 */ - // Check CRC bytes appended to the buffer: - // -- Actually, just ignore parity problems if they exist, + /* Wrapped native command structure or ISO7816: */ if (Iso7816CLA(DesfireCmdCLA)) { uint16_t iso7816ParamsStatus = SetIso7816WrappedParametersType(Buffer, ByteCount); if (iso7816ParamsStatus != ISO7816_CMD_NO_ERROR) { Buffer[0] = (uint8_t)((iso7816ParamsStatus >> 8) & 0x00ff); Buffer[1] = (uint8_t)(iso7816ParamsStatus & 0x00ff); - ISO14443AAppendCRCA(Buffer, 2); - ByteCount = 2 + 2; - return ByteCount * BITS_PER_BYTE; + ByteCount = 2; + return ByteCount * BITS_PER_BYTE; } } - ByteCount = Buffer[4]; // also removing the trailing two parity bytes + ByteCount = Buffer[4]; Buffer[0] = Buffer[1]; memmove(&Buffer[1], &Buffer[5], ByteCount); /* Process the command */ @@ -206,7 +203,7 @@ uint16_t MifareDesfireProcess(uint8_t *Buffer, uint16_t BitCount) { } else { /* Re-wrap into ISO 7816-4 */ } - //LogEntry(LOG_INFO_DESFIRE_OUTGOING_DATA, Buffer, ByteCount); + LogEntry(LOG_INFO_DESFIRE_OUTGOING_DATA, Buffer, ByteCount); return ByteCount * BITS_PER_BYTE; } else { /* ISO/IEC 14443-4 PDUs: No extra work */ @@ -218,43 +215,36 @@ uint16_t MifareDesfireProcess(uint8_t *Buffer, uint16_t BitCount) { uint16_t MifareDesfireAppProcess(uint8_t *Buffer, uint16_t BitCount) { uint16_t ByteCount = (BitCount + BITS_PER_BYTE - 1) / BITS_PER_BYTE; uint16_t ReturnedBytes = 0; - /* Is this first case really just a padded ISO7816 APDU with 2-byte prologue ??? */ - //if (ByteCount >= 8 && DesfireCLA(Buffer[0]) && Buffer[2] == 0x00 && - // Buffer[3] == 0x00 && Buffer[4] == ByteCount - 8) { - // return MifareDesfireProcess(Buffer, BitCount); - //} if (ByteCount >= 6 && DesfireCLA(Buffer[0]) && Buffer[2] == 0x00 && - Buffer[3] == 0x00 && Buffer[4] == ByteCount - 6) { + Buffer[3] == 0x00 && (Buffer[4] == ByteCount - 6 || Buffer[4] == ByteCount - 8)) { uint16_t IncomingByteCount = (BitCount + BITS_PER_BYTE - 1) / BITS_PER_BYTE; - uint16_t UnwrappedBitCount = DesfirePreprocessAPDU(DesfireCommMode, Buffer, IncomingByteCount) * BITS_PER_BYTE; + uint16_t UnwrappedBitCount = DesfirePreprocessAPDU(ActiveCommMode, Buffer, IncomingByteCount) * BITS_PER_BYTE; uint16_t ProcessedBitCount = MifareDesfireProcess(Buffer, UnwrappedBitCount); uint16_t ProcessedByteCount = (ProcessedBitCount + BITS_PER_BYTE - 1) / BITS_PER_BYTE; - ProcessedBitCount = DesfirePostprocessAPDU(DesfireCommMode, Buffer, ProcessedByteCount) * BITS_PER_BYTE; + ProcessedBitCount = DesfirePostprocessAPDU(ActiveCommMode, Buffer, ProcessedByteCount) * BITS_PER_BYTE; return ProcessedBitCount; - } else if (ByteCount == 4 && Buffer[2] == 0x37 && Buffer[3] == 0xC8) { + } else if (BitCount == 4 && (Buffer[0] & 0xF0) == 0xA0) { // NXP-based PCD sent a "keep alive" response of ACK, // so we respond with a corresponding NAK (with CRCA bytes appended): - Buffer[2] = 0x7E; - Buffer[3] = 0x44; - ISO14443AAppendCRCA(Buffer, 4); - return 6 * BITS_PER_BYTE; + Buffer[0] = 0x00; + return 4; } else if (IsWrappedISO7816CommandType(Buffer, ByteCount)) { uint8_t ISO7816PrologueBytes[2]; memcpy(&ISO7816PrologueBytes[0], Buffer, 2); - memmove(&Buffer[0], &Buffer[2], ByteCount - 2); - uint16_t IncomingByteCount = (BitCount + BITS_PER_BYTE - 1) / BITS_PER_BYTE; - uint16_t UnwrappedBitCount = DesfirePreprocessAPDU(DesfireCommMode, Buffer, IncomingByteCount) * BITS_PER_BYTE; - uint16_t ProcessedBitCount = MifareDesfireProcess(Buffer, UnwrappedBitCount); + uint16_t IncomingByteCount = DesfirePreprocessAPDU(ActiveCommMode, Buffer, IncomingByteCount); + memmove(&Buffer[0], &Buffer[2], IncomingByteCount - 2); + 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; /* Append the same ISO7816 prologue bytes to the response: */ memmove(&Buffer[2], &Buffer[0], ProcessedByteCount); memcpy(&Buffer[0], &ISO7816PrologueBytes[0], 2); - ProcessedBitCount = DesfirePostprocessAPDU(DesfireCommMode, Buffer, ProcessedByteCount) * BITS_PER_BYTE; + ProcessedBitCount = DesfirePostprocessAPDU(ActiveCommMode, Buffer, ProcessedByteCount + 2) * BITS_PER_BYTE; return ProcessedBitCount; } else if ((ReturnedBytes = CallInstructionHandler(Buffer, ByteCount)) != ISO14443A_APP_NO_RESPONSE) { /* This case should handle non-wrappped native commands. No pre/postprocessing afterwards: */ return ReturnedBytes; - } else if (!AnticolNoResp) { + } else { // if (!AnticolNoResp) { /* This case is to exchange anticollision loop and RATS data. No need to pre/postprocess it depending * on the CommMode, which has not been set yet if we reach this point: */ diff --git a/Software/DESFireLibNFCTesting/Libs/ArduinoCryptoLib/aes/aes128.h b/Software/DESFireLibNFCTesting/Libs/ArduinoCryptoLib/aes/aes128.h index 6d3e528a..a9f69634 100644 --- a/Software/DESFireLibNFCTesting/Libs/ArduinoCryptoLib/aes/aes128.h +++ b/Software/DESFireLibNFCTesting/Libs/ArduinoCryptoLib/aes/aes128.h @@ -1,22 +1,22 @@ /* -The DESFire stack portion of this firmware source -is free software written by Maxie Dion Schmidt (@maxieds): +The DESFire stack portion of this firmware source +is free software written by Maxie Dion Schmidt (@maxieds): You can redistribute it and/or modify it under the terms of this license. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -The complete source distribution of +The complete source distribution of this firmware is available at the following link: https://github.com/maxieds/ChameleonMiniFirmwareDESFireStack. -Based in part on the original DESFire code created by -@dev-zzo (GitHub handle) [Dmitry Janushkevich] available at +Based in part on the original DESFire code created by +@dev-zzo (GitHub handle) [Dmitry Janushkevich] available at https://github.com/dev-zzo/ChameleonMini/tree/desfire. -This notice must be retained at the top of all source files where indicated. +This notice must be retained at the top of all source files where indicated. */ /* @@ -26,7 +26,7 @@ This notice must be retained at the top of all source files where indicated. * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the + * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included @@ -34,15 +34,15 @@ This notice must be retained at the top of all source files where indicated. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -/* aes128.h : Standalone C library adapted from the ArduinoCryptoLib source to - * implement AES128 encryption with a small foorprint. +/* aes128.h : Standalone C library adapted from the ArduinoCryptoLib source to + * implement AES128 encryption with a small foorprint. */ #ifndef __AES128_CRYPTO_H__