From e7790dceede8c292e761a813d167540ae2e07542 Mon Sep 17 00:00:00 2001 From: Maxie Dion Schmidt Date: Sun, 17 Jul 2022 06:56:28 -0400 Subject: [PATCH] Updates to LibNFC test code (ISO auth works) ; Untested changes to fw source to support recall of header data from EEPROM on power cycle (need to test) ; Other misc minor modifications to stash as a restore point --- .../Chameleon-Mini/Application/CryptoTDEA.h | 2 +- .../DESFire/DESFireChameleonTerminal.c | 4 +- .../DESFire/DESFireFirmwareSettings.h | 10 ++- .../Application/DESFire/DESFireInstructions.c | 77 ++++++++++++------- .../DESFire/DESFireLoggingCodesInclude.c | 20 +++-- .../DESFire/DESFireMemoryOperations.c | 20 +++++ .../DESFire/DESFireMemoryOperations.h | 9 ++- .../Application/DESFire/DESFirePICCControl.c | 6 +- Firmware/Chameleon-Mini/Log.h | 2 +- Firmware/Chameleon-Mini/Settings.h | 12 +-- Software/ChamTool/Chameleon/Log.py | 21 ++--- .../LocalInclude/CryptoUtils.h | 51 +++++++----- .../LocalInclude/DesfireUtils.h | 61 +++++++-------- .../TestAuthenticateISO.dump | 22 ++++++ .../Source/TestAuthenticateAES128.c | 11 --- .../Source/TestAuthenticateISO.c | 5 -- .../Source/TestAuthenticateLegacy.c | 3 +- .../Source/TestFormatAndBuildCustomTag.c | 0 .../Source/TestISO7816CommandsSupport.c | 3 - .../TestTransactionHandlingCommandsSupport.c | 2 - 20 files changed, 196 insertions(+), 145 deletions(-) create mode 100644 Software/DESFireLibNFCTesting/SampleOutputDumps/TestAuthenticateISO.dump delete mode 100644 Software/DESFireLibNFCTesting/Source/TestFormatAndBuildCustomTag.c delete mode 100644 Software/DESFireLibNFCTesting/Source/TestISO7816CommandsSupport.c delete mode 100644 Software/DESFireLibNFCTesting/Source/TestTransactionHandlingCommandsSupport.c diff --git a/Firmware/Chameleon-Mini/Application/CryptoTDEA.h b/Firmware/Chameleon-Mini/Application/CryptoTDEA.h index 531c44c4..bfc9cfe7 100644 --- a/Firmware/Chameleon-Mini/Application/CryptoTDEA.h +++ b/Firmware/Chameleon-Mini/Application/CryptoTDEA.h @@ -34,7 +34,7 @@ PCD's side. extern uint8_t __CryptoDESOpMode; /* Key sizes, in bytes */ -#define CRYPTO_DES_KEY_SIZE 8 /* Bytes */ +#define CRYPTO_DES_KEY_SIZE (8) /* Bytes */ #define CRYPTO_2KTDEA_KEY_SIZE (CRYPTO_DES_KEY_SIZE * 2) #define CRYPTO_3KTDEA_KEY_SIZE (CRYPTO_DES_KEY_SIZE * 3) diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireChameleonTerminal.c b/Firmware/Chameleon-Mini/Application/DESFire/DESFireChameleonTerminal.c index 3c345b83..537edeeb 100644 --- a/Firmware/Chameleon-Mini/Application/DESFire/DESFireChameleonTerminal.c +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireChameleonTerminal.c @@ -29,10 +29,10 @@ This notice must be retained at the top of all source files where indicated. #include "../../Terminal/Terminal.h" #include "../../Terminal/Commands.h" #include "../../Settings.h" -#include "../../Memory.h" #include "DESFireChameleonTerminal.h" #include "DESFireFirmwareSettings.h" #include "DESFirePICCControl.h" +#include "DESFireMemoryOperations.h" #include "DESFireLogging.h" bool IsDESFireConfiguration(void) { @@ -111,7 +111,7 @@ CommandStatusIdType CommandDESFireSetHeaderProperty(char *OutParam, const char * return COMMAND_ERR_INVALID_USAGE_ID; } SynchronizePICCInfo(); - MemoryStore(); + MemoryStoreDesfireHeaderBytes(); return COMMAND_INFO_OK_ID; } #endif /* DISABLE_PERMISSIVE_DESFIRE_SETTINGS */ diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireFirmwareSettings.h b/Firmware/Chameleon-Mini/Application/DESFire/DESFireFirmwareSettings.h index bf516d5c..180a9acb 100644 --- a/Firmware/Chameleon-Mini/Application/DESFire/DESFireFirmwareSettings.h +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireFirmwareSettings.h @@ -36,8 +36,8 @@ This notice must be retained at the top of all source files where indicated. #define DESFIRE_FIRMWARE_BUILD_TIMESTAMP PSTR(BUILD_DATE) #define DESFIRE_FIRMWARE_GIT_COMMIT_ID PSTR(COMMIT_ID) -#define DESFIRE_FIRMWARE_REVISION PSTR("1.0.0-testing") -#define DESFIRE_FIRMWARE_PICC_LAYOUT_REVISION (0x03) +#define DESFIRE_FIRMWARE_REVISION PSTR("1.0.1-beta") +#define DESFIRE_FIRMWARE_PICC_LAYOUT_REVISION (0x04) #define DESFIRE_LITTLE_ENDIAN (1) @@ -64,7 +64,8 @@ typedef uint32_t UINT; #define IsFalse(rcond) (rcond == FALSE) /* Allow users to modify typically reserved and protected read-only data on the tag - like the manufacturer bytes and the serial number (set in Makefile)? */ + * like the manufacturer bytes and the serial number (set in Makefile): + */ #ifdef ENABLE_PERMISSIVE_DESFIRE_SETTINGS #define DESFIRE_ALLOW_PROTECTED_MODIFY (1) #else @@ -72,7 +73,8 @@ typedef uint32_t UINT; #endif /* Whether to auto select application ID and file before the user (input system) - even invokes an ISO SELECT APPLICATION [0x00 0xa4 0x04] command? */ + * even invokes an ISO SELECT APPLICATION [0x00 0xa4 0x04] command: + */ #define DESFIRE_LEGACY_SUPPORT (0) #endif diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireInstructions.c b/Firmware/Chameleon-Mini/Application/DESFire/DESFireInstructions.c index d32973ef..52121171 100644 --- a/Firmware/Chameleon-Mini/Application/DESFire/DESFireInstructions.c +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireInstructions.c @@ -441,10 +441,13 @@ uint16_t DesfireCmdFreeMemory(uint8_t *Buffer, uint16_t ByteCount) { uint16_t EV0CmdAuthenticateLegacy1(uint8_t *Buffer, uint16_t ByteCount) { BYTE KeyId; BYTE keySize; - BYTE *Key; + BYTE *Key, *IV; + BYTE CryptoChallengeResponseBytesSize; /* Reset authentication state right away */ - InvalidateAuthState(SelectedApp.Slot == DESFIRE_PICC_APP_SLOT); + if (!Authenticated || !AuthenticatedWithPICCMasterKey) { + InvalidateAuthState(SelectedApp.Slot == DESFIRE_PICC_APP_SLOT); + } /* Validate command length */ if (ByteCount != 2) { Buffer[0] = STATUS_LENGTH_ERROR; @@ -466,9 +469,11 @@ uint16_t EV0CmdAuthenticateLegacy1(uint8_t *Buffer, uint16_t ByteCount) { /* Indicate that we are in DES key authentication land */ keySize = GetDefaultCryptoMethodKeySize(CRYPTO_TYPE_2KTDEA); Key = SessionKey; + IV = SessionIV; DesfireCommandState.KeyId = KeyId; - DesfireCommandState.CryptoMethodType = CRYPTO_TYPE_3K3DES; - DesfireCommandState.ActiveCommMode = GetCryptoMethodCommSettings(CRYPTO_TYPE_3K3DES); + DesfireCommandState.CryptoMethodType = CRYPTO_TYPE_DES; + DesfireCommandState.ActiveCommMode = GetCryptoMethodCommSettings(CRYPTO_TYPE_DES); + CryptoChallengeResponseBytesSize = CRYPTO_DES_BLOCK_SIZE; /* Fetch the key */ if (cryptoKeyType == CRYPTO_TYPE_DES) { @@ -480,7 +485,7 @@ uint16_t EV0CmdAuthenticateLegacy1(uint8_t *Buffer, uint16_t ByteCount) { DesfireLogEntry(LOG_APP_AUTH_KEY, (const void *) Key, keySize); /* Generate the nonce B (RndB / Challenge response) */ - if (DesfireDebuggingOn) { + if (!DesfireDebuggingOn) { RandomGetBuffer(DesfireCommandState.RndB, CRYPTO_CHALLENGE_RESPONSE_BYTES); } else { /* Fixed nonce for testing */ @@ -504,8 +509,10 @@ uint16_t EV0CmdAuthenticateLegacy1(uint8_t *Buffer, uint16_t ByteCount) { DesfireLogEntry(LOG_APP_NONCE_B, DesfireCommandState.RndB, CRYPTO_CHALLENGE_RESPONSE_BYTES); /* Encrypt RndB with the selected key and transfer it back to the PCD */ - Encrypt2K3DESBuffer(CRYPTO_CHALLENGE_RESPONSE_BYTES, DesfireCommandState.RndB, - &Buffer[1], NULL, Key); + DesfireLogEntry(LOG_APP_SESSION_IV, (void *) IV, CryptoChallengeResponseBytesSize); + EncryptDESBuffer(CryptoChallengeResponseBytesSize, DesfireCommandState.RndB, + &Buffer[1], IV, Key); + DesfireLogEntry(LOG_APP_SESSION_IV, (void *) IV, CryptoChallengeResponseBytesSize); /* Scrub the key */ memset(Key, 0, keySize); @@ -519,13 +526,14 @@ uint16_t EV0CmdAuthenticateLegacy1(uint8_t *Buffer, uint16_t ByteCount) { uint16_t EV0CmdAuthenticateLegacy2(uint8_t *Buffer, uint16_t ByteCount) { BYTE KeyId; BYTE cryptoKeyType, keySize; - BYTE *Key; + BYTE *Key, *IV; + BYTE CryptoChallengeResponseBytesSize; /* Set status for the next incoming command on error */ DesfireState = DESFIRE_IDLE; /* Validate command length */ - if (ByteCount != 2 * CRYPTO_CHALLENGE_RESPONSE_BYTES + 1) { + if (ByteCount != 2 * CryptoChallengeResponseBytesSize + 1) { Buffer[0] = STATUS_LENGTH_ERROR; return DESFIRE_STATUS_RESPONSE_SIZE; } @@ -535,6 +543,7 @@ uint16_t EV0CmdAuthenticateLegacy2(uint8_t *Buffer, uint16_t ByteCount) { cryptoKeyType = DesfireCommandState.CryptoMethodType; keySize = GetDefaultCryptoMethodKeySize(CRYPTO_TYPE_3K3DES); Key = SessionKey; + IV = SessionIV; 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); @@ -543,28 +552,33 @@ uint16_t EV0CmdAuthenticateLegacy2(uint8_t *Buffer, uint16_t ByteCount) { } /* Decrypt the challenge sent back to get RndA and a shifted RndB */ - BYTE challengeRndAB[2 * CRYPTO_CHALLENGE_RESPONSE_BYTES]; - BYTE challengeRndA[CRYPTO_CHALLENGE_RESPONSE_BYTES]; - BYTE challengeRndB[CRYPTO_CHALLENGE_RESPONSE_BYTES]; - Decrypt2K3DESBuffer(2 * CRYPTO_CHALLENGE_RESPONSE_BYTES, challengeRndAB, - &Buffer[1], NULL, Key); - RotateArrayLeft(challengeRndAB + CRYPTO_CHALLENGE_RESPONSE_BYTES, challengeRndB, - CRYPTO_CHALLENGE_RESPONSE_BYTES); - memcpy(challengeRndA, challengeRndAB, CRYPTO_CHALLENGE_RESPONSE_BYTES); + CryptoChallengeResponseBytesSize = CRYPTO_DES_BLOCK_SIZE; + BYTE challengeRndAB[2 * CryptoChallengeResponseBytesSize]; + BYTE challengeRndA[CryptoChallengeResponseBytesSize]; + BYTE challengeRndB[CryptoChallengeResponseBytesSize]; + DesfireLogEntry(LOG_APP_SESSION_IV, (void *) IV, CryptoChallengeResponseBytesSize); + DecryptDESBuffer(2 * CryptoChallengeResponseBytesSize, challengeRndAB, + &Buffer[1], IV, Key); + DesfireLogEntry(LOG_APP_SESSION_IV, (void *) IV, CryptoChallengeResponseBytesSize); + RotateArrayLeft(challengeRndAB + CryptoChallengeResponseBytesSize, challengeRndB, + CryptoChallengeResponseBytesSize); + memcpy(challengeRndA, challengeRndAB, CryptoChallengeResponseBytesSize); /* Check that the returned RndB matches what we sent in the previous round */ - if (memcmp(DesfireCommandState.RndB, challengeRndB, CRYPTO_CHALLENGE_RESPONSE_BYTES)) { + if (memcmp(DesfireCommandState.RndB, challengeRndB, CryptoChallengeResponseBytesSize)) { Buffer[0] = STATUS_AUTHENTICATION_ERROR; return DESFIRE_STATUS_RESPONSE_SIZE; } /* Encrypt and send back the once rotated RndA buffer to the PCD */ - RotateArrayRight(challengeRndA, challengeRndAB, CRYPTO_CHALLENGE_RESPONSE_BYTES); - Encrypt2K3DESBuffer(CRYPTO_CHALLENGE_RESPONSE_BYTES, challengeRndAB, - &Buffer[1], NULL, Key); + RotateArrayRight(challengeRndA, challengeRndAB, CryptoChallengeResponseBytesSize); + DesfireLogEntry(LOG_APP_SESSION_IV, (void *) IV, CryptoChallengeResponseBytesSize); + EncryptDESBuffer(CryptoChallengeResponseBytesSize, challengeRndAB, + &Buffer[1], IV, Key); + DesfireLogEntry(LOG_APP_SESSION_IV, (void *) IV, CryptoChallengeResponseBytesSize); /* Create the session key based on the previous exchange */ - generateSessionKey(SessionKey, challengeRndA, challengeRndB, CRYPTO_TYPE_2KTDEA); + generateSessionKey(SessionKey, challengeRndA, challengeRndB, CRYPTO_TYPE_DES); /* Now that we have auth'ed with the legacy command, a ChangeKey command will * allow for subsequent authentication with the ISO or AES routines @@ -576,7 +590,7 @@ uint16_t EV0CmdAuthenticateLegacy2(uint8_t *Buffer, uint16_t ByteCount) { /* Return the status on success */ Buffer[0] = STATUS_OPERATION_OK; - return DESFIRE_STATUS_RESPONSE_SIZE + CRYPTO_CHALLENGE_RESPONSE_BYTES; + return DESFIRE_STATUS_RESPONSE_SIZE + CryptoChallengeResponseBytesSize; } uint16_t EV0CmdChangeKey(uint8_t *Buffer, uint16_t ByteCount) { @@ -1785,7 +1799,7 @@ uint16_t DesfireCmdAuthenticate3KTDEA1(uint8_t *Buffer, uint16_t ByteCount) { } else { Encrypt2K3DESBuffer(CryptoChallengeResponseBytesSize, DesfireCommandState.RndB, &Buffer[1], IV, Key); } - DesfireLogEntry(LOG_INFO_DESFIRE_STATUS_INFO, (void *) IV, CryptoChallengeResponseBytesSize); + DesfireLogEntry(LOG_APP_SESSION_IV, (void *) IV, CryptoChallengeResponseBytesSize); /* Scrub the key */ memset(Key, 0, keySize); @@ -1835,6 +1849,7 @@ uint16_t DesfireCmdAuthenticate3KTDEA2(uint8_t *Buffer, uint16_t ByteCount) { BYTE challengeRndAB[2 * CryptoChallengeResponseBytesSize]; BYTE challengeRndA[CryptoChallengeResponseBytesSize]; BYTE challengeRndB[CryptoChallengeResponseBytesSize]; + DesfireLogEntry(LOG_APP_SESSION_IV, (void *) IV, CryptoChallengeResponseBytesSize); if (cryptoKeyType == CRYPTO_TYPE_DES || cryptoKeyType == CRYPTO_TYPE_3K3DES || cryptoKeyType == CRYPTO_TYPE_ANY) { Decrypt3DESBuffer(2 * CryptoChallengeResponseBytesSize, challengeRndAB, @@ -1843,7 +1858,7 @@ uint16_t DesfireCmdAuthenticate3KTDEA2(uint8_t *Buffer, uint16_t ByteCount) { Decrypt2K3DESBuffer(2 * CryptoChallengeResponseBytesSize, challengeRndAB, &Buffer[1], IV, Key); } - DesfireLogEntry(LOG_INFO_DESFIRE_STATUS_INFO, (void *) IV, CryptoChallengeResponseBytesSize); + DesfireLogEntry(LOG_APP_SESSION_IV, (void *) IV, CryptoChallengeResponseBytesSize); RotateArrayLeft(challengeRndAB + CryptoChallengeResponseBytesSize, challengeRndB, CryptoChallengeResponseBytesSize); memcpy(challengeRndA, challengeRndAB, CryptoChallengeResponseBytesSize); @@ -1857,6 +1872,7 @@ uint16_t DesfireCmdAuthenticate3KTDEA2(uint8_t *Buffer, uint16_t ByteCount) { /* Encrypt and send back the once rotated RndA buffer to the PCD */ RotateArrayRight(challengeRndA, challengeRndAB, CryptoChallengeResponseBytesSize); + DesfireLogEntry(LOG_APP_SESSION_IV, (void *) IV, CryptoChallengeResponseBytesSize); if (cryptoKeyType == CRYPTO_TYPE_DES || cryptoKeyType == CRYPTO_TYPE_3K3DES || cryptoKeyType == CRYPTO_TYPE_ANY) { Encrypt3DESBuffer(CryptoChallengeResponseBytesSize, challengeRndAB, @@ -1865,7 +1881,7 @@ uint16_t DesfireCmdAuthenticate3KTDEA2(uint8_t *Buffer, uint16_t ByteCount) { Encrypt2K3DESBuffer(CryptoChallengeResponseBytesSize, challengeRndAB, &Buffer[1], IV, Key); } - DesfireLogEntry(LOG_INFO_DESFIRE_STATUS_INFO, (void *) IV, CryptoChallengeResponseBytesSize); + DesfireLogEntry(LOG_APP_SESSION_IV, (void *) IV, CryptoChallengeResponseBytesSize); /* Create the session key based on the previous exchange */ generateSessionKey(SessionKey, challengeRndA, challengeRndB, cryptoKeyType); @@ -1944,7 +1960,7 @@ uint16_t DesfireCmdAuthenticateAES1(uint8_t *Buffer, uint16_t ByteCount) { CryptoAESInitContext(&AESCryptoContext); /* Generate the nonce B (RndB / Challenge response) */ - if (DesfireDebuggingOn) { + if (!DesfireDebuggingOn) { RandomGetBuffer(&(DesfireCommandState.RndB[0]), CRYPTO_CHALLENGE_RESPONSE_BYTES); } else { /* Fixed nonce for testing */ @@ -1968,8 +1984,11 @@ uint16_t DesfireCmdAuthenticateAES1(uint8_t *Buffer, uint16_t ByteCount) { DesfireLogEntry(LOG_APP_NONCE_B, DesfireCommandState.RndB, CRYPTO_CHALLENGE_RESPONSE_BYTES); /* Encrypt RndB with the selected key and transfer it back to the PCD */ + DesfireLogEntry(LOG_APP_SESSION_IV, (void *) IVBuffer, CRYPTO_CHALLENGE_RESPONSE_BYTES); Status = CryptoAESEncryptBuffer(CRYPTO_CHALLENGE_RESPONSE_BYTES, DesfireCommandState.RndB, &Buffer[1], IVBuffer, Key); + DesfireLogEntry(LOG_APP_SESSION_IV, (void *) IVBuffer, CRYPTO_CHALLENGE_RESPONSE_BYTES); + if (Status != STATUS_OPERATION_OK) { Buffer[0] = Status; return DESFIRE_STATUS_RESPONSE_SIZE; @@ -2010,7 +2029,9 @@ uint16_t DesfireCmdAuthenticateAES2(uint8_t *Buffer, uint16_t ByteCount) { BYTE challengeRndAB[2 * CRYPTO_CHALLENGE_RESPONSE_BYTES]; BYTE challengeRndA[CRYPTO_CHALLENGE_RESPONSE_BYTES]; BYTE challengeRndB[CRYPTO_CHALLENGE_RESPONSE_BYTES]; + DesfireLogEntry(LOG_APP_SESSION_IV, (void *) IVBuffer, CRYPTO_CHALLENGE_RESPONSE_BYTES); CryptoAESDecryptBuffer(2 * CRYPTO_CHALLENGE_RESPONSE_BYTES, challengeRndAB, &Buffer[1], IVBuffer, Key); + DesfireLogEntry(LOG_APP_SESSION_IV, (void *) IVBuffer, CRYPTO_CHALLENGE_RESPONSE_BYTES); RotateArrayLeft(challengeRndAB + CRYPTO_CHALLENGE_RESPONSE_BYTES, challengeRndB, CRYPTO_CHALLENGE_RESPONSE_BYTES); memcpy(challengeRndA, challengeRndAB, CRYPTO_CHALLENGE_RESPONSE_BYTES); @@ -2024,7 +2045,9 @@ uint16_t DesfireCmdAuthenticateAES2(uint8_t *Buffer, uint16_t ByteCount) { /* Encrypt and send back the once rotated RndA buffer to the PCD */ RotateArrayRight(challengeRndA, challengeRndAB, CRYPTO_CHALLENGE_RESPONSE_BYTES); + DesfireLogEntry(LOG_APP_SESSION_IV, (void *) IVBuffer, CRYPTO_CHALLENGE_RESPONSE_BYTES); CryptoAESEncryptBuffer(CRYPTO_CHALLENGE_RESPONSE_BYTES, challengeRndA, &Buffer[1], IVBuffer, Key); + DesfireLogEntry(LOG_APP_SESSION_IV, (void *) IVBuffer, CRYPTO_CHALLENGE_RESPONSE_BYTES); /* Create the session key based on the previous exchange */ generateSessionKey(SessionKey, challengeRndA, challengeRndB, CRYPTO_TYPE_AES128); diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireLoggingCodesInclude.c b/Firmware/Chameleon-Mini/Application/DESFire/DESFireLoggingCodesInclude.c index 440c5e6a..087e00ae 100644 --- a/Firmware/Chameleon-Mini/Application/DESFire/DESFireLoggingCodesInclude.c +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireLoggingCodesInclude.c @@ -28,11 +28,7 @@ This notice must be retained at the top of all source files where indicated. #ifndef __DESFIRE_LOGGING_CODES_INCLUDE_C__ #define __DESFIRE_LOGGING_CODES_INCLUDE_C__ -/* Intended to log all routine, complete transaction records (verbose output), and - to source a list of debugging messages and TODO items in the - developing DESFire emulation support within the firmware sources. - These codes should almost immediately be supported for use of the Chameleon Mini - devices with the Chameleon Mini Live Debugger logger application for Android: */ + LOG_ERR_DESFIRE_GENERIC_ERROR = 0xE0, LOG_INFO_DESFIRE_STATUS_INFO = 0xE1, LOG_INFO_DESFIRE_DEBUGGING_OUTPUT = 0xE2, @@ -49,14 +45,16 @@ LOG_INFO_DESFIRE_PROTECTED_DATA_SET = 0xEC, LOG_INFO_DESFIRE_PROTECTED_DATA_SET_VERBOSE = 0xED, /* DESFire app */ -LOG_APP_AUTH_KEY = 0xD0, ///< The key used for authentication -LOG_APP_NONCE_B = 0xD1, ///< Nonce B's value (generated) -LOG_APP_NONCE_AB = 0xD2, ///< Nonces A and B values (received) +LOG_APP_AUTH_KEY = 0xD0, ///< The key used for authentication +LOG_APP_NONCE_B = 0xD1, ///< Nonce B's value (generated) +LOG_APP_NONCE_AB = 0xD2, ///< Nonces A and B values (received) +LOG_APP_SESSION_IV = 0xD3, ///< Contents of the session IV buffer /* ISO 14443 related entries */ -LOG_ISO14443_3A_STATE = 0x53, -LOG_ISO14443_4_STATE = 0x54, -LOG_ISO14443A_APP_NO_RESPONSE = 0x55, +LOG_ISO14443_3A_STATE = 0x53, +LOG_ISO14443_4_STATE = 0x54, +LOG_ISO14443A_APP_NO_RESPONSE = 0x55, + #endif #endif /* CONFIG_MF_DESFIRE_SUPPORT */ diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireMemoryOperations.c b/Firmware/Chameleon-Mini/Application/DESFire/DESFireMemoryOperations.c index 22d29e61..763d4c94 100644 --- a/Firmware/Chameleon-Mini/Application/DESFire/DESFireMemoryOperations.c +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireMemoryOperations.c @@ -27,6 +27,7 @@ This notice must be retained at the top of all source files where indicated. #ifdef CONFIG_MF_DESFIRE_SUPPORT #include "../../Common.h" +#include "../../Settings.h" #include "../../Memory.h" #include "DESFireMemoryOperations.h" @@ -88,6 +89,25 @@ uint8_t GetCardCapacityBlocks(void) { return MaxFreeBlocks - Picc.FirstFreeBlock; } +/* TODO: Note: If things suddenly start to break, this code is a good first place to look ... */ +void MemoryStoreDesfireHeaderBytes(void) { + void *PiccHeaderDataAddr = (void *) &Picc; + uint16_t PiccHeaderDataSize = sizeof(Picc); + /* Place the header data in EEPROM in the space directly below the settings structures + * (see function SettingsUpdate in "../../Settings.h"): + */ + uintptr_t EEWriteAddr = (uintptr_t)PiccHeaderDataAddr - (uintptr_t)&GlobalSettings - (uintptr_t)((SETTINGS_COUNT - GlobalSettings.ActiveSettingIdx) * PiccHeaderDataSize); + eeprom_update_block((uint8_t *) PiccHeaderDataAddr, (uint8_t *) EEWriteAddr, PiccHeaderDataSize); +} + +/* TODO: Same note to examine code here on unexpected new errors ... */ +void MemoryRestoreDesfireHeaderBytes(void) { + void *PiccHeaderDataAddr = (void *) &Picc; + uint16_t PiccHeaderDataSize = sizeof(Picc); + uintptr_t EEReadAddr = (uintptr_t)PiccHeaderDataAddr - (uintptr_t)&GlobalSettings - (uintptr_t)((SETTINGS_COUNT - GlobalSettings.ActiveSettingIdx) * PiccHeaderDataSize); + eeprom_read_block((uint8_t *) PiccHeaderDataAddr, (uint8_t *) EEReadAddr, PiccHeaderDataSize); +} + void ReadDataEEPROMSource(uint8_t *Buffer, uint8_t Count) { MemoryReadBlock(Buffer, TransferState.ReadData.Source.Pointer, Count); TransferState.ReadData.Source.Pointer += DESFIRE_BYTES_TO_BLOCKS(Count); diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireMemoryOperations.h b/Firmware/Chameleon-Mini/Application/DESFire/DESFireMemoryOperations.h index 714ee150..56d4d4f2 100644 --- a/Firmware/Chameleon-Mini/Application/DESFire/DESFireMemoryOperations.h +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireMemoryOperations.h @@ -42,15 +42,16 @@ extern volatile char __InternalStringBuffer[STRING_BUFFER_SIZE]; void ReadBlockBytes(void *Buffer, SIZET StartBlock, SIZET Count); void WriteBlockBytesMain(const void *Buffer, SIZET StartBlock, SIZET Count); -#define WriteBlockBytes(Buffer, StartBlock, Count) \ - WriteBlockBytesMain(Buffer, StartBlock, Count); +#define WriteBlockBytes(Buffer, StartBlock, Count) WriteBlockBytesMain(Buffer, StartBlock, Count); uint16_t AllocateBlocksMain(uint16_t BlockCount); -#define AllocateBlocks(BlockCount) \ - AllocateBlocksMain(BlockCount); +#define AllocateBlocks(BlockCount) AllocateBlocksMain(BlockCount); BYTE GetCardCapacityBlocks(void); +void MemoryStoreDesfireHeaderBytes(void); +void MemoryRestoreDesfireHeaderBytes(void); + /* File data transfer related routines: */ void ReadDataEEPROMSource(uint8_t *Buffer, uint8_t Count); void WriteDataEEPROMSink(uint8_t *Buffer, uint8_t Count); diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFirePICCControl.c b/Firmware/Chameleon-Mini/Application/DESFire/DESFirePICCControl.c index ab2b896c..5dda280e 100644 --- a/Firmware/Chameleon-Mini/Application/DESFire/DESFirePICCControl.c +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFirePICCControl.c @@ -216,6 +216,7 @@ void InitialisePiccBackendEV0(uint8_t StorageSize, bool formatPICC) { DesfireLogEntry(LOG_INFO_DESFIRE_PICC_RESET, (void *) NULL, 0); FactoryFormatPiccEV0(); } else { + MemoryRestoreDesfireHeaderBytes(); ReadBlockBytes(&AppDir, DESFIRE_APP_DIR_BLOCK_ID, sizeof(DESFireAppDirType)); SelectPiccApp(); } @@ -235,6 +236,7 @@ void InitialisePiccBackendEV1(uint8_t StorageSize, bool formatPICC) { DesfireLogEntry(LOG_INFO_DESFIRE_PICC_RESET, (void *) NULL, 0); FactoryFormatPiccEV1(StorageSize); } else { + MemoryRestoreDesfireHeaderBytes(); ReadBlockBytes(&AppDir, DESFIRE_APP_DIR_BLOCK_ID, sizeof(DESFireAppDirType)); SelectPiccApp(); } @@ -254,6 +256,7 @@ void InitialisePiccBackendEV2(uint8_t StorageSize, bool formatPICC) { DesfireLogEntry(LOG_INFO_DESFIRE_PICC_RESET, (void *) NULL, 0); FactoryFormatPiccEV2(StorageSize); } else { + MemoryRestoreDesfireHeaderBytes(); ReadBlockBytes(&AppDir, DESFIRE_APP_DIR_BLOCK_ID, sizeof(DESFireAppDirType)); SelectPiccApp(); } @@ -332,7 +335,8 @@ void FormatPicc(void) { SynchronizeAppDir(); /* Initialize the root app data */ CreatePiccApp(); - MemoryStore(); + //MemoryStore(); + MemoryStoreDesfireHeaderBytes(); } void CreatePiccApp(void) { diff --git a/Firmware/Chameleon-Mini/Log.h b/Firmware/Chameleon-Mini/Log.h index b503a8d7..6c350e88 100644 --- a/Firmware/Chameleon-Mini/Log.h +++ b/Firmware/Chameleon-Mini/Log.h @@ -4,7 +4,7 @@ #include "Common.h" #ifdef MEMORY_LIMITED_TESTING -#define LOG_SIZE 1536 +#define LOG_SIZE 1284 #else #define LOG_SIZE 2048 #endif diff --git a/Firmware/Chameleon-Mini/Settings.h b/Firmware/Chameleon-Mini/Settings.h index a1eb20e1..d1dbaee2 100644 --- a/Firmware/Chameleon-Mini/Settings.h +++ b/Firmware/Chameleon-Mini/Settings.h @@ -25,12 +25,12 @@ */ typedef struct { ButtonActionEnum ButtonActions[BUTTON_TYPE_COUNT]; /// Button actions for this setting. - LogModeEnum LogMode; /// Log mode for this setting. - ConfigurationEnum Configuration; /// Active configuration for this setting. - LEDHookEnum LEDRedFunction; /// Red LED function for this setting. - LEDHookEnum LEDGreenFunction; /// Green LED function for this setting. - uint16_t PendingTaskTimeout; /// Timeout for timeout commands for this setting, in multiples of 100 ms. - uint16_t ReaderThreshold; /// Reader threshold + LogModeEnum LogMode; /// Log mode for this setting. + ConfigurationEnum Configuration; /// Active configuration for this setting. + LEDHookEnum LEDRedFunction; /// Red LED function for this setting. + LEDHookEnum LEDGreenFunction; /// Green LED function for this setting. + uint16_t PendingTaskTimeout; /// Timeout for timeout commands for this setting, in multiples of 100 ms. + uint16_t ReaderThreshold; /// Reader threshold } SettingsEntryType; typedef struct { diff --git a/Software/ChamTool/Chameleon/Log.py b/Software/ChamTool/Chameleon/Log.py index 82d0ff15..94554421 100644 --- a/Software/ChamTool/Chameleon/Log.py +++ b/Software/ChamTool/Chameleon/Log.py @@ -62,15 +62,15 @@ def binaryParityDecoder(data): 0x13: { 'name': 'UID SET', 'decoder': binaryDecoder }, 0x20: { 'name': 'RESET APP', 'decoder': noDecoder }, - 0x40: { 'name': 'CODEC RX', 'decoder': binaryDecoder }, - 0x41: { 'name': 'CODEC TX', 'decoder': binaryDecoder }, + 0x40: { 'name': 'CODEC RX', 'decoder': binaryDecoder }, + 0x41: { 'name': 'CODEC TX', 'decoder': binaryDecoder }, 0x42: { 'name': 'CODEC RX W/PARITY', 'decoder': binaryDecoder }, 0x43: { 'name': 'CODEC TX W/PARITY', 'decoder': binaryDecoder }, - 0x44: { 'name': 'CODEC RX SNI READER', 'decoder': binaryDecoder }, - 0x45: { 'name': 'CODEC RX SNI READER W/PARITY', 'decoder': binaryParityDecoder }, - 0x46: { 'name': 'CODEC RX SNI CARD', 'decoder': binaryDecoder }, - 0x47: { 'name': 'CODEC RX SNI CARD W/PARITY', 'decoder': binaryParityDecoder }, + 0x44: { 'name': 'CODEC RX SNI READER', 'decoder': binaryDecoder }, + 0x45: { 'name': 'CODEC RX SNI READER W/PARITY', 'decoder': binaryParityDecoder }, + 0x46: { 'name': 'CODEC RX SNI CARD', 'decoder': binaryDecoder }, + 0x47: { 'name': 'CODEC RX SNI CARD W/PARITY', 'decoder': binaryParityDecoder }, 0x48: { 'name': 'CODEC RX SNI READER FIELD DETECTED', 'decoder': noDecoder }, 0x53: { 'name': 'ISO14443A (DESFIRE) STATE', 'decoder': binaryDecoder }, @@ -98,10 +98,11 @@ def binaryParityDecoder(data): 0xC1: { 'name': 'APP CSUM FAILED', 'decoder': binaryDecoder }, 0xC2: { 'name': 'APP NOT AUTHED', 'decoder': binaryDecoder }, - 0xD0: { 'name': 'APP DESFIRE AUTH KEY', 'decoder': binaryDecoder }, - 0xD1: { 'name': 'APP DESFIRE NONCE B', 'decoder': binaryDecoder }, - 0xD2: { 'name': 'APP DESFIRE NONCE AB', 'decoder': binaryDecoder }, - + 0xD0: { 'name': 'APP DESFIRE AUTH KEY', 'decoder': binaryDecoder }, + 0xD1: { 'name': 'APP DESFIRE NONCE B', 'decoder': binaryDecoder }, + 0xD2: { 'name': 'APP DESFIRE NONCE AB', 'decoder': binaryDecoder }, + 0xD3: { 'name': 'APP DESFIRE SESION IV', 'decoder': binaryDecoder }, + 0xE0: { 'name': 'APP DESFIRE GENERIC ERROR', 'decoder': textDecoder }, 0xE1: { 'name': 'APP DESFIRE STATUS INFO', 'decoder': binaryDecoder }, 0xE2: { 'name': 'APP DESFIRE DEBUG OUTPUT', 'decoder': binaryDecoder }, diff --git a/Software/DESFireLibNFCTesting/LocalInclude/CryptoUtils.h b/Software/DESFireLibNFCTesting/LocalInclude/CryptoUtils.h index 96bb00bf..b057f0c7 100644 --- a/Software/DESFireLibNFCTesting/LocalInclude/CryptoUtils.h +++ b/Software/DESFireLibNFCTesting/LocalInclude/CryptoUtils.h @@ -13,34 +13,36 @@ #include "LibNFCUtils.h" -/* DES Operation cipher mode */ -#define CRYPTO_DES_ECB_MODE 0 // Electronic Code Book mode -#define CRYPTO_DES_CBC_MODE 1 // Cipher Block Chaining mode +/* DES Operation cipher modes: */ +#define CRYPTO_DES_ECB_MODE 0 // Electronic Code Book mode +#define CRYPTO_DES_CBC_MODE 1 // Cipher Block Chaining mode -/* AES Operation cipher mode */ -#define CRYPTO_AES_ECB_MODE 0 // Electronic Code Book mode -#define CRYPTO_AES_CBC_MODE 1 // Cipher Block Chaining mode +/* AES Operation cipher modes: */ +#define CRYPTO_AES_ECB_MODE 0 // Electronic Code Book mode +#define CRYPTO_AES_CBC_MODE 1 // Cipher Block Chaining mode -#define DESFIRE_CRYPTO_AUTHTYPE_AES128 (1) -#define DESFIRE_CRYPTO_AUTHTYPE_ISODES (2) -#define DESFIRE_CRYPTO_AUTHTYPE_LEGACY (3) +#define DESFIRE_CRYPTO_AUTHTYPE_AES128 (1) +#define DESFIRE_CRYPTO_AUTHTYPE_ISODES (2) +#define DESFIRE_CRYPTO_AUTHTYPE_LEGACY (3) -#define CRYPTO_DES_KEY_SIZE (8) -#define CRYPTO_3KTDEA_KEY_SIZE (3 * CRYPTO_DES_KEY_SIZE) +#define CRYPTO_DES_BLOCK_SIZE (8) +#define CRYPTO_3KTDEA_BLOCK_SIZE (CRYPTO_DES_BLOCK_SIZE) +#define AES128_BLOCK_SIZE (16) +#define CRYPTO_MAX_BLOCK_SIZE (16) -#define CRYPTO_DES_BLOCK_SIZE (8) -#define CRYPTO_3KTDEA_BLOCK_SIZE (CRYPTO_DES_BLOCK_SIZE) -#define AES128_BLOCK_SIZE (16) -#define CRYPTO_MAX_BLOCK_SIZE (16) +#define CRYPTO_DES_KEY_SIZE (CRYPTO_DES_BLOCK_SIZE) +#define CRYPTO_3KTDEA_KEY_SIZE (3 * CRYPTO_DES_KEY_SIZE) +#define CRYPTO_AES128_KEY_SIZE (AES128_BLOCK_SIZE) typedef uint8_t CryptoAESBlock_t[AES128_BLOCK_SIZE]; static uint8_t SessionIV[CRYPTO_MAX_BLOCK_SIZE]; /* Key sizes, block sizes (in bytes): */ -#define CRYPTO_MAX_KEY_SIZE (24) -#define CRYPTO_MAX_BLOCK_SIZE (16) +#define CRYPTO_MAX_KEY_SIZE (24) +#define CRYPTO_MAX_BLOCK_SIZE (16) -#define CRYPTO_CHALLENGE_RESPONSE_SIZE (16) +#define CRYPTO_CHALLENGE_RESPONSE_SIZE (16) +#define CRYPTO_CHALLENGE_RESPONSE_SIZE_LEGACY (8) static const uint8_t ZERO_KEY[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -234,7 +236,7 @@ static inline size_t Decrypt2K3DES(const uint8_t *encSrcBuf, size_t bufSize, static inline size_t Encrypt3DES(const uint8_t *plainSrcBuf, size_t bufSize, uint8_t *encDestBuf, const uint8_t *IVIn, CryptoData_t cdata) { DES_key_schedule keySched1, keySched2, keySched3; - uint8_t *IV = SessionIV; + uint8_t IV[CRYPTO_DES_BLOCK_SIZE]; uint8_t *kd1 = cdata.keyData, *kd2 = &(cdata.keyData[CRYPTO_DES_BLOCK_SIZE]), *kd3 = &(cdata.keyData[2 * CRYPTO_DES_BLOCK_SIZE]); DES_set_key(kd1, &keySched1); DES_set_key(kd2, &keySched2); @@ -256,13 +258,16 @@ static inline size_t Encrypt3DES(const uint8_t *plainSrcBuf, size_t bufSize, memcpy(IV, &encDestBuf[blk * CRYPTO_DES_BLOCK_SIZE], CRYPTO_DES_BLOCK_SIZE); } } + if (IVIn != NULL) { + memcpy(IVIn, IV, CRYPTO_DES_BLOCK_SIZE); + } return bufSize; } static inline size_t Decrypt3DES(const uint8_t *encSrcBuf, size_t bufSize, uint8_t *plainDestBuf, const uint8_t *IVIn, CryptoData_t cdata) { DES_key_schedule keySched1, keySched2, keySched3; - uint8_t *IV = SessionIV; + uint8_t IV[CRYPTO_DES_BLOCK_SIZE]; uint8_t *kd1 = cdata.keyData, *kd2 = &(cdata.keyData[CRYPTO_DES_BLOCK_SIZE]), *kd3 = &(cdata.keyData[2 * CRYPTO_DES_BLOCK_SIZE]); DES_set_key(kd1, &keySched1); DES_set_key(kd2, &keySched2); @@ -284,6 +289,9 @@ static inline size_t Decrypt3DES(const uint8_t *encSrcBuf, size_t bufSize, memcpy(IV, &encSrcBuf[blk * CRYPTO_DES_BLOCK_SIZE], CRYPTO_DES_BLOCK_SIZE); } } + if (IVIn != NULL) { + memcpy(IVIn, IV, CRYPTO_DES_BLOCK_SIZE); + } return bufSize; } @@ -497,10 +505,11 @@ static inline void RotateArrayRight(uint8_t *srcBuf, uint8_t *destBuf, size_t bu } static inline void RotateArrayLeft(uint8_t *srcBuf, uint8_t *destBuf, size_t bufSize) { + uint8_t lastDataByte = srcBuf[bufSize - 1]; for (int bidx = 1; bidx < bufSize; bidx++) { destBuf[bidx] = srcBuf[bidx - 1]; } - destBuf[0] = srcBuf[bufSize - 1]; + destBuf[0] = lastDataByte; } static inline void ConcatByteArrays(uint8_t *arrA, size_t arrASize, diff --git a/Software/DESFireLibNFCTesting/LocalInclude/DesfireUtils.h b/Software/DESFireLibNFCTesting/LocalInclude/DesfireUtils.h index 7702af74..ae03a94c 100644 --- a/Software/DESFireLibNFCTesting/LocalInclude/DesfireUtils.h +++ b/Software/DESFireLibNFCTesting/LocalInclude/DesfireUtils.h @@ -66,12 +66,11 @@ static inline int AuthenticateAES128(nfc_device *nfcConnDev, uint8_t keyIndex, c uint8_t *IVBuf = ActiveCryptoIVBuffer; memcpy(encryptedRndB, rxDataStorage->rxDataBuf, CRYPTO_CHALLENGE_RESPONSE_SIZE); CryptoData_t aesCryptoData = { 0 }; - aesCryptoData.keySize = 16; + aesCryptoData.keySize = CRYPTO_AES128_KEY_SIZE; aesCryptoData.keyData = keyData; aesCryptoData.ivSize = CRYPTO_CHALLENGE_RESPONSE_SIZE; DecryptAES128(encryptedRndB, CRYPTO_CHALLENGE_RESPONSE_SIZE, plainTextRndB, aesCryptoData); RotateArrayRight(plainTextRndB, rotatedRndB, CRYPTO_CHALLENGE_RESPONSE_SIZE); - memset(IVBuf, 0x00, CRYPTO_CHALLENGE_RESPONSE_SIZE); aesCryptoData.ivData = IVBuf; GenerateRandomBytes(rndA, CRYPTO_CHALLENGE_RESPONSE_SIZE); ConcatByteArrays(rndA, CRYPTO_CHALLENGE_RESPONSE_SIZE, rotatedRndB, CRYPTO_CHALLENGE_RESPONSE_SIZE, challengeResponse); @@ -178,7 +177,7 @@ static inline int AuthenticateISO(nfc_device *nfcConnDev, uint8_t keyIndex, cons memcpy(encryptedRndB, rxDataStorage->rxDataBuf, CRYPTO_CHALLENGE_RESPONSE_SIZE); memset(IVBuf, 0x00, CRYPTO_CHALLENGE_RESPONSE_SIZE); CryptoData_t desCryptoData = { 0 }; - desCryptoData.keySize = 3 * 8; + desCryptoData.keySize = CRYPTO_3KTDEA_KEY_SIZE; desCryptoData.keyData = keyData; desCryptoData.ivSize = CRYPTO_CHALLENGE_RESPONSE_SIZE; Decrypt3DES(encryptedRndB, CRYPTO_CHALLENGE_RESPONSE_SIZE, plainTextRndB, IVBuf, desCryptoData); @@ -233,19 +232,12 @@ static inline int AuthenticateISO(nfc_device *nfcConnDev, uint8_t keyIndex, cons // decrypt rndA sent by PICC, compare it to our original randomized rndA computed above, // and report back whether they match: uint8_t decryptedRndAFromPICCRotated[CRYPTO_CHALLENGE_RESPONSE_SIZE], decryptedRndA[CRYPTO_CHALLENGE_RESPONSE_SIZE]; - //memcpy(IVBuf, &rxDataStorage->rxDataBuf[rxDataStorage->recvSzRx - CRYPTO_3KTDEA_BLOCK_SIZE - 1], CRYPTO_3KTDEA_BLOCK_SIZE); - //memset(IVBuf, 0x00, CRYPTO_CHALLENGE_RESPONSE_SIZE); - //memcpy(IVBuf, &rxDataStorage->rxDataBuf[CRYPTO_3KTDEA_BLOCK_SIZE], CRYPTO_3KTDEA_BLOCK_SIZE); - //memcpy(IVBuf, &rxDataStorage->rxDataBuf[CRYPTO_CHALLENGE_RESPONSE_SIZE - CRYPTO_3KTDEA_BLOCK_SIZE], CRYPTO_3KTDEA_BLOCK_SIZE); - //memcpy(IVBuf, &challengeResponseCipherText[2 * CRYPTO_CHALLENGE_RESPONSE_SIZE - CRYPTO_3KTDEA_BLOCK_SIZE], CRYPTO_3KTDEA_BLOCK_SIZE); - memcpy(IVBuf, &encryptedRndB[CRYPTO_3KTDEA_BLOCK_SIZE], CRYPTO_3KTDEA_BLOCK_SIZE); Decrypt3DES(rxDataStorage->rxDataBuf, CRYPTO_CHALLENGE_RESPONSE_SIZE, decryptedRndAFromPICCRotated, IVBuf, desCryptoData); if (PRINT_STATUS_EXCHANGE_MESSAGES) { fprintf(stdout, " -- IV = "); print_hex(IVBuf, CRYPTO_3KTDEA_BLOCK_SIZE); } RotateArrayLeft(decryptedRndAFromPICCRotated, decryptedRndA, CRYPTO_CHALLENGE_RESPONSE_SIZE); - memcpy(decryptedRndA, decryptedRndAFromPICCRotated, CRYPTO_CHALLENGE_RESPONSE_SIZE); if (!memcmp(rndA, decryptedRndA, CRYPTO_CHALLENGE_RESPONSE_SIZE)) { if (PRINT_STATUS_EXCHANGE_MESSAGES) { fprintf(stdout, " ... AUTH OK! :)\n\n"); @@ -258,7 +250,9 @@ static inline int AuthenticateISO(nfc_device *nfcConnDev, uint8_t keyIndex, cons } else { if (PRINT_STATUS_EXCHANGE_MESSAGES) { fprintf(stdout, " ... AUTH FAILED -- X; :(\n"); - fprintf(stdout, " ... "); + fprintf(stdout, " ... INIT (ROTATED) PICC RNDA CONF:\n "); + print_hex(decryptedRndAFromPICCRotated, CRYPTO_CHALLENGE_RESPONSE_SIZE); + fprintf(stdout, " ... SHIFTED DECRYPTED PICC RNDA:\n "); print_hex(decryptedRndA, CRYPTO_CHALLENGE_RESPONSE_SIZE); } FreeRxDataStruct(rxDataStorage, true); @@ -304,40 +298,39 @@ static inline int AuthenticateLegacy(nfc_device *nfcConnDev, uint8_t keyIndex, c // Now need to decrypt the challenge response sent back as rndB, // rotate it left, generate a random rndA, concat rndA+rotatedRndB, // encrypt this result, and send it forth to the PICC: - uint8_t encryptedRndB[CRYPTO_CHALLENGE_RESPONSE_SIZE], plainTextRndB[CRYPTO_CHALLENGE_RESPONSE_SIZE], rotatedRndB[CRYPTO_CHALLENGE_RESPONSE_SIZE]; - uint8_t rndA[CRYPTO_CHALLENGE_RESPONSE_SIZE], challengeResponse[2 * CRYPTO_CHALLENGE_RESPONSE_SIZE], challengeResponseCipherText[2 * CRYPTO_CHALLENGE_RESPONSE_SIZE]; + uint8_t encryptedRndB[CRYPTO_CHALLENGE_RESPONSE_SIZE_LEGACY], plainTextRndB[CRYPTO_CHALLENGE_RESPONSE_SIZE_LEGACY], rotatedRndB[CRYPTO_CHALLENGE_RESPONSE_SIZE_LEGACY]; + uint8_t rndA[CRYPTO_CHALLENGE_RESPONSE_SIZE_LEGACY], challengeResponse[2 * CRYPTO_CHALLENGE_RESPONSE_SIZE_LEGACY], challengeResponseCipherText[2 * CRYPTO_CHALLENGE_RESPONSE_SIZE_LEGACY]; uint8_t *IVBuf = ActiveCryptoIVBuffer; - memcpy(encryptedRndB, rxDataStorage->rxDataBuf, CRYPTO_CHALLENGE_RESPONSE_SIZE); + memcpy(encryptedRndB, rxDataStorage->rxDataBuf, CRYPTO_CHALLENGE_RESPONSE_SIZE_LEGACY); CryptoData_t desCryptoData = { 0 }; - desCryptoData.keySize = 3 * 8; + desCryptoData.keySize = CRYPTO_DES_KEY_SIZE; desCryptoData.keyData = keyData; - desCryptoData.ivSize = CRYPTO_CHALLENGE_RESPONSE_SIZE; - Decrypt2K3DES(encryptedRndB, CRYPTO_CHALLENGE_RESPONSE_SIZE, plainTextRndB, NULL, desCryptoData); - RotateArrayRight(plainTextRndB, rotatedRndB, CRYPTO_CHALLENGE_RESPONSE_SIZE); - memset(IVBuf, 0x00, CRYPTO_CHALLENGE_RESPONSE_SIZE); + desCryptoData.ivSize = CRYPTO_CHALLENGE_RESPONSE_SIZE_LEGACY; + DecryptDES(encryptedRndB, CRYPTO_CHALLENGE_RESPONSE_SIZE_LEGACY, plainTextRndB, NULL, desCryptoData); + RotateArrayRight(plainTextRndB, rotatedRndB, CRYPTO_CHALLENGE_RESPONSE_SIZE_LEGACY); desCryptoData.ivData = IVBuf; - GenerateRandomBytes(rndA, CRYPTO_CHALLENGE_RESPONSE_SIZE); - ConcatByteArrays(rndA, CRYPTO_CHALLENGE_RESPONSE_SIZE, rotatedRndB, CRYPTO_CHALLENGE_RESPONSE_SIZE, challengeResponse); - Encrypt2K3DES(challengeResponse, 2 * CRYPTO_CHALLENGE_RESPONSE_SIZE, challengeResponseCipherText, NULL, desCryptoData); + GenerateRandomBytes(rndA, CRYPTO_CHALLENGE_RESPONSE_SIZE_LEGACY); + ConcatByteArrays(rndA, CRYPTO_CHALLENGE_RESPONSE_SIZE_LEGACY, rotatedRndB, CRYPTO_CHALLENGE_RESPONSE_SIZE_LEGACY, challengeResponse); + EncryptDES(challengeResponse, 2 * CRYPTO_CHALLENGE_RESPONSE_SIZE_LEGACY, challengeResponseCipherText, NULL, desCryptoData); - uint8_t sendBytesBuf[2 * CRYPTO_CHALLENGE_RESPONSE_SIZE + 6]; - memset(sendBytesBuf, 0x00, 2 * CRYPTO_CHALLENGE_RESPONSE_SIZE + 6); + uint8_t sendBytesBuf[2 * CRYPTO_CHALLENGE_RESPONSE_SIZE_LEGACY + 6]; + memset(sendBytesBuf, 0x00, 2 * CRYPTO_CHALLENGE_RESPONSE_SIZE_LEGACY + 6); sendBytesBuf[0] = 0x90; sendBytesBuf[1] = 0xaf; sendBytesBuf[4] = 0x20; - memcpy(sendBytesBuf + 5, challengeResponseCipherText, 2 * CRYPTO_CHALLENGE_RESPONSE_SIZE); + memcpy(sendBytesBuf + 5, challengeResponseCipherText, 2 * CRYPTO_CHALLENGE_RESPONSE_SIZE_LEGACY); if (PRINT_STATUS_EXCHANGE_MESSAGES) { fprintf(stdout, " -- RNDA = "); - print_hex(rndA, CRYPTO_CHALLENGE_RESPONSE_SIZE); + print_hex(rndA, CRYPTO_CHALLENGE_RESPONSE_SIZE_LEGACY); fprintf(stdout, " -- RNDB = "); - print_hex(plainTextRndB, CRYPTO_CHALLENGE_RESPONSE_SIZE); + print_hex(plainTextRndB, CRYPTO_CHALLENGE_RESPONSE_SIZE_LEGACY); fprintf(stdout, " -- CHAL = "); - print_hex(challengeResponse, 2 * CRYPTO_CHALLENGE_RESPONSE_SIZE); + print_hex(challengeResponse, 2 * CRYPTO_CHALLENGE_RESPONSE_SIZE_LEGACY); fprintf(stdout, " -> "); print_hex(sendBytesBuf, sizeof(sendBytesBuf)); } - rxDataStatus = libnfcTransmitBits(nfcConnDev, sendBytesBuf, 2 * CRYPTO_CHALLENGE_RESPONSE_SIZE + 6, rxDataStorage); + rxDataStatus = libnfcTransmitBits(nfcConnDev, sendBytesBuf, 2 * CRYPTO_CHALLENGE_RESPONSE_SIZE_LEGACY + 6, rxDataStorage); if (rxDataStatus && PRINT_STATUS_EXCHANGE_MESSAGES) { fprintf(stdout, " <- "); print_hex(rxDataStorage->rxDataBuf, rxDataStorage->recvSzRx); @@ -353,10 +346,10 @@ static inline int AuthenticateLegacy(nfc_device *nfcConnDev, uint8_t keyIndex, c // Finally, to finish up the auth process: // decrypt rndA sent by PICC, compare it to our original randomized rndA computed above, // and report back whether they match: - uint8_t decryptedRndAFromPICCRotated[CRYPTO_CHALLENGE_RESPONSE_SIZE], decryptedRndA[CRYPTO_CHALLENGE_RESPONSE_SIZE]; - Decrypt2K3DES(rxDataStorage->rxDataBuf, CRYPTO_CHALLENGE_RESPONSE_SIZE, decryptedRndAFromPICCRotated, NULL, desCryptoData); - RotateArrayLeft(decryptedRndAFromPICCRotated, decryptedRndA, CRYPTO_CHALLENGE_RESPONSE_SIZE); - if (!memcmp(rndA, decryptedRndA, CRYPTO_CHALLENGE_RESPONSE_SIZE)) { + uint8_t decryptedRndAFromPICCRotated[CRYPTO_CHALLENGE_RESPONSE_SIZE_LEGACY], decryptedRndA[CRYPTO_CHALLENGE_RESPONSE_SIZE_LEGACY]; + DecryptDES(rxDataStorage->rxDataBuf, CRYPTO_CHALLENGE_RESPONSE_SIZE_LEGACY, decryptedRndAFromPICCRotated, NULL, desCryptoData); + RotateArrayLeft(decryptedRndAFromPICCRotated, decryptedRndA, CRYPTO_CHALLENGE_RESPONSE_SIZE_LEGACY); + if (!memcmp(rndA, decryptedRndA, CRYPTO_CHALLENGE_RESPONSE_SIZE_LEGACY)) { if (PRINT_STATUS_EXCHANGE_MESSAGES) { fprintf(stdout, " ... AUTH OK! :)\n\n"); } @@ -369,7 +362,7 @@ static inline int AuthenticateLegacy(nfc_device *nfcConnDev, uint8_t keyIndex, c if (PRINT_STATUS_EXCHANGE_MESSAGES) { fprintf(stdout, " ... AUTH FAILED -- X; :(\n"); fprintf(stdout, " ... "); - print_hex(decryptedRndA, CRYPTO_CHALLENGE_RESPONSE_SIZE); + print_hex(decryptedRndA, CRYPTO_CHALLENGE_RESPONSE_SIZE_LEGACY); } FreeRxDataStruct(rxDataStorage, true); InvalidateAuthenticationStatus(); diff --git a/Software/DESFireLibNFCTesting/SampleOutputDumps/TestAuthenticateISO.dump b/Software/DESFireLibNFCTesting/SampleOutputDumps/TestAuthenticateISO.dump new file mode 100644 index 00000000..51249b5b --- /dev/null +++ b/Software/DESFireLibNFCTesting/SampleOutputDumps/TestAuthenticateISO.dump @@ -0,0 +1,22 @@ +>>> Select Application By AID: + -> 90 5a 00 00 03 00 00 00 | 00 + <- 91 00 + +>>> GetApplicationIds command: + -> 90 6a 00 00 00 00 + <- 91 00 + +>>> Start ISO Authenticate: + -> 90 1a 00 00 01 00 00 + <- ee 91 30 1e e8 f5 84 d6 | c7 85 1d 05 65 13 90 a6 | 91 af + -- IV = c7 85 1d 05 65 13 90 a6 + -- IV = c5 25 0d 7e 64 7e 43 d7 + -- RNDA = bc e1 65 56 92 10 6f 94 | f7 e3 9a a6 b0 90 3c 9e + -- RNDB = ca fe ba be 00 11 22 33 | ca fe ba be 00 11 22 33 + -- CHAL = bc e1 65 56 92 10 6f 94 | f7 e3 9a a6 b0 90 3c 9e | fe ba be 00 11 22 33 ca | fe ba be 00 11 22 33 ca + -- ENC-CHAL = 93 ee 86 d9 87 d1 88 9a | 4b 5c 95 04 f1 52 b0 dd | 65 83 d1 db 79 15 10 03 | c5 25 0d 7e 64 7e 43 d7 + -> 90 af 00 00 20 93 ee 86 | d9 87 d1 88 9a 4b 5c 95 | 04 f1 52 b0 dd 65 83 d1 | db 79 15 10 03 c5 25 0d | 7e 64 7e 43 d7 00 + <- c1 db ec f1 8a 53 de 82 | be 7d 33 28 1f a5 2e 91 | 91 00 83 d1 + -- IV = be 7d 33 28 1f a5 2e 91 + ... AUTH OK! :) + diff --git a/Software/DESFireLibNFCTesting/Source/TestAuthenticateAES128.c b/Software/DESFireLibNFCTesting/Source/TestAuthenticateAES128.c index 228ef991..549c7f7e 100644 --- a/Software/DESFireLibNFCTesting/Source/TestAuthenticateAES128.c +++ b/Software/DESFireLibNFCTesting/Source/TestAuthenticateAES128.c @@ -21,12 +21,6 @@ int main(int argc, char **argv) { return EXIT_FAILURE; } - // First, we have to authenticate with the master key (PICC AID: 0) either using - // legacy crypto (plain DES) or with the ISO (3DES), the latter as below: - if (Authenticate(nfcPnd, DESFIRE_CRYPTO_AUTHTYPE_ISODES, MASTER_KEY_INDEX, ZERO_KEY)) { - return EXIT_FAILURE; - } - // Select AID application 0x000000: if (SelectApplication(nfcPnd, MASTER_APPLICATION_AID, APPLICATION_AID_LENGTH)) { return EXIT_FAILURE; @@ -37,11 +31,6 @@ int main(int argc, char **argv) { return EXIT_FAILURE; } - // First, authenticate with the legacy command (PICC master key): - //if (Authenticate(nfcPnd, DESFIRE_CRYPTO_AUTHTYPE_LEGACY, MASTER_KEY_INDEX, ZERO_KEY)) { - // return EXIT_FAILURE; - //} - // Start AES authentication (default key, blank setting of all zeros): if (Authenticate(nfcPnd, DESFIRE_CRYPTO_AUTHTYPE_AES128, MASTER_KEY_INDEX, ZERO_KEY)) { return EXIT_FAILURE; diff --git a/Software/DESFireLibNFCTesting/Source/TestAuthenticateISO.c b/Software/DESFireLibNFCTesting/Source/TestAuthenticateISO.c index 28538e21..6b2071d6 100644 --- a/Software/DESFireLibNFCTesting/Source/TestAuthenticateISO.c +++ b/Software/DESFireLibNFCTesting/Source/TestAuthenticateISO.c @@ -28,11 +28,6 @@ int main(int argc, char **argv) { return EXIT_FAILURE; } - // First, authenticate with the legacy command (PICC master key): - //if (Authenticate(nfcPnd, DESFIRE_CRYPTO_AUTHTYPE_LEGACY, MASTER_KEY_INDEX, ZERO_KEY)) { - // return EXIT_FAILURE; - //} - // Start ISO authentication (default key, blank setting of all zeros): if (Authenticate(nfcPnd, DESFIRE_CRYPTO_AUTHTYPE_ISODES, MASTER_KEY_INDEX, ZERO_KEY)) { diff --git a/Software/DESFireLibNFCTesting/Source/TestAuthenticateLegacy.c b/Software/DESFireLibNFCTesting/Source/TestAuthenticateLegacy.c index 09b70c9c..6c8c55e7 100644 --- a/Software/DESFireLibNFCTesting/Source/TestAuthenticateLegacy.c +++ b/Software/DESFireLibNFCTesting/Source/TestAuthenticateLegacy.c @@ -23,8 +23,7 @@ int main(int argc, char **argv) { return EXIT_FAILURE; } // Start ISO authentication (default key, blank setting of all zeros): - if (Authenticate(nfcPnd, DESFIRE_CRYPTO_AUTHTYPE_LEGACY, - MASTER_KEY_INDEX, ZERO_KEY)) { + if (Authenticate(nfcPnd, DESFIRE_CRYPTO_AUTHTYPE_LEGACY, MASTER_KEY_INDEX, ZERO_KEY)) { return EXIT_FAILURE; } diff --git a/Software/DESFireLibNFCTesting/Source/TestFormatAndBuildCustomTag.c b/Software/DESFireLibNFCTesting/Source/TestFormatAndBuildCustomTag.c deleted file mode 100644 index e69de29b..00000000 diff --git a/Software/DESFireLibNFCTesting/Source/TestISO7816CommandsSupport.c b/Software/DESFireLibNFCTesting/Source/TestISO7816CommandsSupport.c deleted file mode 100644 index 19b4b8bd..00000000 --- a/Software/DESFireLibNFCTesting/Source/TestISO7816CommandsSupport.c +++ /dev/null @@ -1,3 +0,0 @@ -/* TestISO7816CommandsSupport.c */ - - diff --git a/Software/DESFireLibNFCTesting/Source/TestTransactionHandlingCommandsSupport.c b/Software/DESFireLibNFCTesting/Source/TestTransactionHandlingCommandsSupport.c deleted file mode 100644 index af8edf99..00000000 --- a/Software/DESFireLibNFCTesting/Source/TestTransactionHandlingCommandsSupport.c +++ /dev/null @@ -1,2 +0,0 @@ -/* TestTransactionHandlingCommandsSupport.c */ -