From 8a3f64bf41d70973213a2b3c831274aacb93102b Mon Sep 17 00:00:00 2001 From: Tomaspre Date: Fri, 11 Nov 2022 13:06:49 +0000 Subject: [PATCH 01/12] Initial commit for Gallagher terminal support --- .../Application/DESFire/DESFireGallagher.c | 39 +++++++++++++++++++ .../Application/DESFire/DESFireGallagher.h | 11 ++++++ 2 files changed, 50 insertions(+) create mode 100644 Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagher.c create mode 100644 Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagher.h diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagher.c b/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagher.c new file mode 100644 index 00000000..204df64a --- /dev/null +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagher.c @@ -0,0 +1,39 @@ +// +// Created by Tom on 27.10.2022. +// + +#include "DESFireGallagher.h" + + +static const uint32_t CAD_AID = 0x2F81F4; + +//Defaults to the default gallagher site key +uint8_t GallagherSiteKey[] = { + 0x31, 0x12, 0xB7, 0x38, 0xD8, 0x86, 0x2C, 0xCD, + 0x34, 0x30, 0x2E, 0xB2, 0x99, 0xAA, 0xB4, 0x56, +}; + +bool CreateGallagherApp(uint32_t cardId, uint16_t facilityId, uint8_t issueLevel, uint8_t regionCode) { + + //Determine AID + + return CreateGallagherAppWithAID(cardId, facilityId, issueLevel, regionCode, AID); +} + +bool CreateGallagherAppWithAID(uint32_t cardId, uint16_t facilityId, uint8_t issueLevel, uint8_t regionCode, uint8_t* AID) { + +} + +void SetGallagherSiteKey(uint8_t* key) { + for (uint8_t i = 0; i < 16; ++i) { + GallagherSiteKey[i] = key[i]; + } +} + +void ResetGallagherSiteKey() { + key[16] = { + 0x31, 0x12, 0xB7, 0x38, 0xD8, 0x86, 0x2C, 0xCD, + 0x34, 0x30, 0x2E, 0xB2, 0x99, 0xAA, 0xB4, 0x56, + }; + SetGallagherSiteKey(key); +} diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagher.h b/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagher.h new file mode 100644 index 00000000..12253104 --- /dev/null +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagher.h @@ -0,0 +1,11 @@ +// +// Created by Tom on 27.10.2022. +// + +#ifndef CHAMELEON_MINI_DESFIREGALLAGHER_H +#define CHAMELEON_MINI_DESFIREGALLAGHER_H + +bool CreateGallagherApp(uint32_t cardId, uint16_t facilityId, uint8_t issueLevel, uint8_t regionCode); +bool CreateGallagherAppWithAID(uint32_t cardId, uint16_t facilityId, uint8_t issueLevel, uint8_t regionCode, uint8_t* AID); + +#endif //CHAMELEON_MINI_DESFIREGALLAGHER_H From a4c240a4041d2cf76be915f0836037693caec5d5 Mon Sep 17 00:00:00 2001 From: Tomaspre Date: Sun, 13 Nov 2022 11:23:50 +0000 Subject: [PATCH 02/12] Outline for loading Gallagher --- .../Application/DESFire/DESFireGallagher.c | 85 ++++++++++++++++++- .../Application/DESFire/DESFireGallagher.h | 6 ++ 2 files changed, 88 insertions(+), 3 deletions(-) diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagher.c b/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagher.c index 204df64a..2f342a9c 100644 --- a/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagher.c +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagher.c @@ -3,9 +3,13 @@ // #include "DESFireGallagher.h" +//SelectedApp +//Authenticated, wthkey, wthmasterkey +//CRYPTO_AES_KEY_SIZE +#define CAD_BLOCK_LEN 0x24 +#define GALL_BLOCK_LEN 0x10 -static const uint32_t CAD_AID = 0x2F81F4; //Defaults to the default gallagher site key uint8_t GallagherSiteKey[] = { @@ -13,14 +17,89 @@ uint8_t GallagherSiteKey[] = { 0x34, 0x30, 0x2E, 0xB2, 0x99, 0xAA, 0xB4, 0x56, }; +//Warning - running this function resets the AUTH state! bool CreateGallagherApp(uint32_t cardId, uint16_t facilityId, uint8_t issueLevel, uint8_t regionCode) { - //Determine AID + //TODO: Find a suitable AID + DESFireAidType AID = {0x20, 0x81, 0xF4}; return CreateGallagherAppWithAID(cardId, facilityId, issueLevel, regionCode, AID); } -bool CreateGallagherAppWithAID(uint32_t cardId, uint16_t facilityId, uint8_t issueLevel, uint8_t regionCode, uint8_t* AID) { +//Warning - running this function resets the AUTH state! +bool CreateGallagherAppWithAID(uint32_t cardId, uint16_t facilityId, uint8_t issueLevel, uint8_t regionCode, DESFireAidType AID) { + uint8_t Status; + InvalidateAuthState(false); + + //TODO: Is this needed? + Authenticated = true; + AuthenticatedWithKey = 0; + AuthenticatedWithPICCMasterKey = true; + + //Create card app directory app + const DESFireAidType CADAid = {0x2F, 0x81, 0xF4}; //0x2F81F4 + Status = CreateApp(CADAid, 0x0B, 1); + + //TODO: Difersify key for app directory app + uint8_t[CRYPTO_AES_KEY_SIZE] CADKeyZero; + + //Select the app direcory app + SelectApp(CADAid); + + //Channge key + uint8_t nextKeyVersion = ReadKeyVersion(SelectedApp.Slot, KeyId) + 1; + WriteAppKey(SelectedApp.Slot, 0, CADKeyZero, CRYPTO_AES_KEY_SIZE); + WriteKeyVersion(SelectedApp.Slot, 0, nextKeyVersion); + WriteKeyCryptoType(SelectedApp.Slot, 0, CRYPTO_TYPE_AES128); + + //Select the app direcory app + SelectApp(CADAid); + + //Create file in CAD + Status = CreateStandardFile(0x00, 0x00, 0xE000, CAD_BLOCK_LEN); + + //TODO: Get CAD block to write + uint8_t[CAD_BLOCK_LEN] CADBlock; + + //Update file in CAD + uint8_t fileIndex = LookupFileNumberIndex(SelectedApp.Slot, 0); + uint8_t fileType = ReadFileType(SelectedApp.Slot, fileIndex); + Status = WriteDataFileSetup(fileIndex, fileType, 0x00, 0, CAD_BLOCK_LEN); + Status = WriteDataFileIterator(CADBlock, CAD_BLOCK_LEN); + + //Create Gall app + Status = CreateApp(AID, 0x0B, 3); + + //Diversify and change key 2 + uint8_t[CRYPTO_AES_KEY_SIZE] GallAppKeyTwo; + //TODO: Diversify + + nextKeyVersion = ReadKeyVersion(SelectedApp.Slot, KeyId) + 1; + WriteAppKey(SelectedApp.Slot, 2, GallAppKeyTwo, CRYPTO_AES_KEY_SIZE); + WriteKeyVersion(SelectedApp.Slot, 0, nextKeyVersion); + WriteKeyCryptoType(SelectedApp.Slot, 0, CRYPTO_TYPE_AES128); + + //Diversify and change key 0 + uint8_t[CRYPTO_AES_KEY_SIZE] GallAppKeyZero; + //TODO: Diversify + + nextKeyVersion = ReadKeyVersion(SelectedApp.Slot, KeyId) + 1; + WriteAppKey(SelectedApp.Slot, 0, GallAppKeyZero, CRYPTO_AES_KEY_SIZE); + WriteKeyVersion(SelectedApp.Slot, 0, nextKeyVersion); + WriteKeyCryptoType(SelectedApp.Slot, 0, CRYPTO_TYPE_AES128); + + //Create file + Status = CreateStandardFile(0x00, 0x03, 0x2000, GALL_BLOCK_LEN); + + //TODO: Get CAD block to write + uint8_t[GALL_BLOCK_LEN] GallBlock; + + //Update file with Gall access data + fileIndex = LookupFileNumberIndex(SelectedApp.Slot, 0); + fileType = ReadFileType(SelectedApp.Slot, fileIndex); + Status = WriteDataFileSetup(fileIndex, fileType, 0x03, 0, GALL_BLOCK_LEN); + Status = WriteDataFileIterator(GallBlock, GALL_BLOCK_LEN); + } diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagher.h b/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagher.h index 12253104..68cce58a 100644 --- a/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagher.h +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagher.h @@ -5,7 +5,13 @@ #ifndef CHAMELEON_MINI_DESFIREGALLAGHER_H #define CHAMELEON_MINI_DESFIREGALLAGHER_H +//Warning - running this function resets the AUTH state! bool CreateGallagherApp(uint32_t cardId, uint16_t facilityId, uint8_t issueLevel, uint8_t regionCode); + +//Warning - running this function resets the AUTH state! bool CreateGallagherAppWithAID(uint32_t cardId, uint16_t facilityId, uint8_t issueLevel, uint8_t regionCode, uint8_t* AID); +void SetGallagherSiteKey(uint8_t* key); +void ResetGallagherSiteKey(); + #endif //CHAMELEON_MINI_DESFIREGALLAGHER_H From 17ba662a3d76f482710b3d9bed67002f2faa34ae Mon Sep 17 00:00:00 2001 From: Tomaspre Date: Mon, 14 Nov 2022 14:32:31 +0000 Subject: [PATCH 03/12] Skeleton for minimal self programming Gallagher support --- .../Application/DESFire/DESFireGallagher.c | 77 ++++++-- .../Application/DESFire/DESFireGallagher.h | 2 + .../DESFire/DESFireGallagherTools.c | 185 ++++++++++++++++++ .../DESFire/DESFireGallagherTools.h | 21 ++ 4 files changed, 270 insertions(+), 15 deletions(-) create mode 100644 Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagherTools.c create mode 100644 Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagherTools.h diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagher.c b/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagher.c index 2f342a9c..c439da0f 100644 --- a/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagher.c +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagher.c @@ -2,7 +2,9 @@ // Created by Tom on 27.10.2022. // +#include #include "DESFireGallagher.h" +#include "DESFireGallagherTools.h" //SelectedApp //Authenticated, wthkey, wthmasterkey //CRYPTO_AES_KEY_SIZE @@ -28,7 +30,9 @@ bool CreateGallagherApp(uint32_t cardId, uint16_t facilityId, uint8_t issueLevel //Warning - running this function resets the AUTH state! bool CreateGallagherAppWithAID(uint32_t cardId, uint16_t facilityId, uint8_t issueLevel, uint8_t regionCode, DESFireAidType AID) { - uint8_t Status; + uint8_t Status = 0; + ConfigurationUidType UID_GALL; + GetPiccUid(UID_GALL); InvalidateAuthState(false); //TODO: Is this needed? @@ -40,14 +44,19 @@ bool CreateGallagherAppWithAID(uint32_t cardId, uint16_t facilityId, uint8_t iss const DESFireAidType CADAid = {0x2F, 0x81, 0xF4}; //0x2F81F4 Status = CreateApp(CADAid, 0x0B, 1); - //TODO: Difersify key for app directory app - uint8_t[CRYPTO_AES_KEY_SIZE] CADKeyZero; + if (Status != STATUS_OPERATION_OK) { + return false; + } + + //Difersify key for app directory app + uint8_t CADKeyZero[CRYPTO_AES_KEY_SIZE]; + hfgal_diversify_key(GallagherSiteKey, UID_GALL, 7, 0, CADAid[0]*256*256 + CADAid[1]*256 + CADAid[2], CADKeyZero); //Select the app direcory app SelectApp(CADAid); //Channge key - uint8_t nextKeyVersion = ReadKeyVersion(SelectedApp.Slot, KeyId) + 1; + uint8_t nextKeyVersion = ReadKeyVersion(SelectedApp.Slot, 0) + 1; WriteAppKey(SelectedApp.Slot, 0, CADKeyZero, CRYPTO_AES_KEY_SIZE); WriteKeyVersion(SelectedApp.Slot, 0, nextKeyVersion); WriteKeyCryptoType(SelectedApp.Slot, 0, CRYPTO_TYPE_AES128); @@ -58,32 +67,53 @@ bool CreateGallagherAppWithAID(uint32_t cardId, uint16_t facilityId, uint8_t iss //Create file in CAD Status = CreateStandardFile(0x00, 0x00, 0xE000, CAD_BLOCK_LEN); - //TODO: Get CAD block to write - uint8_t[CAD_BLOCK_LEN] CADBlock; + if (Status != STATUS_OPERATION_OK) { + return false; + } + + //TODO: This needs to be rewritten to support more than one Gallagher app on the card + //Get CAD block to write + uint8_t CADBlock[CAD_BLOCK_LEN]; + CADBlock[0] = regionCode; + CADBlock[1] = (facilityId >> 8) & 0xFF; + CADBlock[2] = facilityId & 0xFF; + CADBlock[3] = CADAid[0]; + CADBlock[4] = CADAid[1]; + CADBlock[5] = CADAid[2]; + memset(CADBlock+6, 0, CAD_BLOCK_LEN-6); //Update file in CAD uint8_t fileIndex = LookupFileNumberIndex(SelectedApp.Slot, 0); uint8_t fileType = ReadFileType(SelectedApp.Slot, fileIndex); Status = WriteDataFileSetup(fileIndex, fileType, 0x00, 0, CAD_BLOCK_LEN); + + if (Status != STATUS_OPERATION_OK) { + return false; + } + Status = WriteDataFileIterator(CADBlock, CAD_BLOCK_LEN); + if (Status != STATUS_OPERATION_OK) { + return false; + } + //Create Gall app Status = CreateApp(AID, 0x0B, 3); //Diversify and change key 2 - uint8_t[CRYPTO_AES_KEY_SIZE] GallAppKeyTwo; - //TODO: Diversify + uint8_t GallAppKeyTwo[CRYPTO_AES_KEY_SIZE]; + hfgal_diversify_key(GallagherSiteKey, UID_GALL, 7, 2, AID[0]*256*256 + AID[1]*256 + AID[2], GallAppKeyTwo); - nextKeyVersion = ReadKeyVersion(SelectedApp.Slot, KeyId) + 1; + nextKeyVersion = ReadKeyVersion(SelectedApp.Slot, 2) + 1; WriteAppKey(SelectedApp.Slot, 2, GallAppKeyTwo, CRYPTO_AES_KEY_SIZE); WriteKeyVersion(SelectedApp.Slot, 0, nextKeyVersion); WriteKeyCryptoType(SelectedApp.Slot, 0, CRYPTO_TYPE_AES128); //Diversify and change key 0 - uint8_t[CRYPTO_AES_KEY_SIZE] GallAppKeyZero; - //TODO: Diversify + uint8_t GallAppKeyZero[CRYPTO_AES_KEY_SIZE]; + hfgal_diversify_key(GallagherSiteKey, UID_GALL, 7, 0, AID[0]*256*256 + AID[1]*256 + AID[2], GallAppKeyZero); - nextKeyVersion = ReadKeyVersion(SelectedApp.Slot, KeyId) + 1; + nextKeyVersion = ReadKeyVersion(SelectedApp.Slot, 0) + 1; WriteAppKey(SelectedApp.Slot, 0, GallAppKeyZero, CRYPTO_AES_KEY_SIZE); WriteKeyVersion(SelectedApp.Slot, 0, nextKeyVersion); WriteKeyCryptoType(SelectedApp.Slot, 0, CRYPTO_TYPE_AES128); @@ -91,16 +121,33 @@ bool CreateGallagherAppWithAID(uint32_t cardId, uint16_t facilityId, uint8_t iss //Create file Status = CreateStandardFile(0x00, 0x03, 0x2000, GALL_BLOCK_LEN); - //TODO: Get CAD block to write - uint8_t[GALL_BLOCK_LEN] GallBlock; + if (Status != STATUS_OPERATION_OK) { + return false; + } + + //Get Gallagher block to write + uint8_t GallBlock[GALL_BLOCK_LEN]; + gallagher_encode_creds(GallBlock, regionCode, facilityId, cardId, issueLevel); + for (int i = 0; i < 8; i++) { + GallBlock[i + 8] = GallBlock[i] ^ 0xFF; + } //Update file with Gall access data fileIndex = LookupFileNumberIndex(SelectedApp.Slot, 0); fileType = ReadFileType(SelectedApp.Slot, fileIndex); Status = WriteDataFileSetup(fileIndex, fileType, 0x03, 0, GALL_BLOCK_LEN); + + if (Status != STATUS_OPERATION_OK) { + return false; + } + Status = WriteDataFileIterator(GallBlock, GALL_BLOCK_LEN); + if (Status != STATUS_OPERATION_OK) { + return false; + } + return true; } void SetGallagherSiteKey(uint8_t* key) { @@ -110,7 +157,7 @@ void SetGallagherSiteKey(uint8_t* key) { } void ResetGallagherSiteKey() { - key[16] = { + uint8_t key[16] = { 0x31, 0x12, 0xB7, 0x38, 0xD8, 0x86, 0x2C, 0xCD, 0x34, 0x30, 0x2E, 0xB2, 0x99, 0xAA, 0xB4, 0x56, }; diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagher.h b/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagher.h index 68cce58a..7ce824ad 100644 --- a/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagher.h +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagher.h @@ -5,6 +5,8 @@ #ifndef CHAMELEON_MINI_DESFIREGALLAGHER_H #define CHAMELEON_MINI_DESFIREGALLAGHER_H +#include "DESFireCrypto.h" + //Warning - running this function resets the AUTH state! bool CreateGallagherApp(uint32_t cardId, uint16_t facilityId, uint8_t issueLevel, uint8_t regionCode); diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagherTools.c b/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagherTools.c new file mode 100644 index 00000000..d1623a8f --- /dev/null +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagherTools.c @@ -0,0 +1,185 @@ +//----------------------------------------------------------------------------- +// Copyright (C) Proxmark3 contributors. See AUTHORS.md @ https://github.com/RfidResearchGroup/proxmark3 for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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. See the +// GNU General Public License for more details. +// +// See LICENSE.txt @ https://github.com/RfidResearchGroup/proxmark3 for the text of the license. + +//This file contains adapted Gallagher functions from https://github.com/RfidResearchGroup/proxmark3 All credit goes to this repo + +#include +#include "DESFireGallagherTools.h" + +// This function is almot like cmac(...). but with some key differences. +bool MifareKdfAn10922(uint8_t *key, uint8_t CryptoType, + const uint8_t *data, size_t len, uint8_t *diversified_key) { + if (data == NULL || len < 1 || len > 31) + return false; + + uint8_t kbs; + switch (CryptoType) { + case CRYPTO_TYPE_AES128: + kbs = CRYPTO_AES_BLOCK_SIZE; + break; + case CRYPTO_TYPE_2KTDEA: + kbs = CRYPTO_2KTDEA_BLOCK_SIZE; + break; + case CRYPTO_TYPE_3K3DES: + kbs = CRYPTO_3KTDEA_BLOCK_SIZE; + break; + default: + return false; + } + + uint8_t buffer[CRYPTO_MAX_BLOCK_SIZE * 3] = {0}; + + if (CryptoType == CRYPTO_TYPE_AES128) { + buffer[0] = 0x01; + memcpy(&buffer[1], data, len); + + uint8_t IV[CRYPTO_AES_BLOCK_SIZE]; + memset(IV, 0, CRYPTO_AES_BLOCK_SIZE); + DesfireCryptoCMAC(CryptoType, key, buffer, len + 1, IV, diversified_key); + + return true; + } else if (CryptoType == CRYPTO_TYPE_2KTDEA) { + /* TODO: Adapt this code + buffer[0] = 0x21; + memcpy(&buffer[1], data, len); + + DesfireClearIV(ctx); + DesfireCryptoCMACEx(ctx, key_type, buffer, len + 1, kbs * 2, cmac); + + buffer[0] = 0x22; + memcpy(&buffer[1], data, len); + + DesfireClearIV(ctx); + DesfireCryptoCMACEx(ctx, key_type, buffer, len + 1, kbs * 2, &cmac[kbs]); + + memcpy(ctx->key, cmac, kbs * 2);*/ + } else if (CryptoType == CRYPTO_TYPE_3K3DES) { + /* TODO: Adapt this code + buffer[0] = 0x31; + memcpy(&buffer[1], data, len); + + DesfireClearIV(ctx); + DesfireCryptoCMACEx(ctx, key_type, buffer, len + 1, kbs * 2, cmac); + + buffer[0] = 0x32; + memcpy(&buffer[1], data, len); + + DesfireClearIV(ctx); + DesfireCryptoCMACEx(ctx, key_type, buffer, len + 1, kbs * 2, &cmac[kbs]); + + buffer[0] = 0x33; + memcpy(&buffer[1], data, len); + + DesfireClearIV(ctx); + DesfireCryptoCMACEx(ctx, key_type, buffer, len + 1, kbs * 2, &cmac[kbs * 2]); + + memcpy(ctx->key, cmac, kbs * 3);*/ + } + return false; +} + +int mfdes_kdf_input_gallagher(uint8_t *uid, uint8_t uidLen, uint8_t keyNo, + uint32_t aid, uint8_t *kdfInputOut, uint8_t *kdfInputLen) { + if (uid == NULL || (uidLen != 4 && uidLen != 7) || keyNo > 2 || kdfInputOut == NULL || kdfInputLen == NULL) { + return 1; + } + + int len = 0; + // If the keyNo == 1 or the aid is 000000, then omit the UID. + // On the other hand, if the aid is 1f81f4 (config card) always include the UID. + if ((keyNo != 1 && aid != 0x000000) || (aid == 0x1f81f4)) { + if (*kdfInputLen < (4 + uidLen)) { + return 2; + } + + memcpy(kdfInputOut, uid, uidLen); + len += uidLen; + } else if (*kdfInputLen < 4) { + return 4; + } + + kdfInputOut[len++] = keyNo; + + kdfInputOut[len++] = aid & 0xff; + kdfInputOut[len++] = (aid >> 8) & 0xff; + kdfInputOut[len++] = (aid >> 16) & 0xff; + + *kdfInputLen = len; + + return 0; +} + +bool hfgal_diversify_key(uint8_t *site_key, uint8_t *uid, uint8_t uid_len, + uint8_t key_num, uint32_t aid, uint8_t *key_output) { + // Generate diversification input + uint8_t kdf_input_len = 11; + uint32_t res = mfdes_kdf_input_gallagher(uid, uid_len, key_num, aid, key_output, &kdf_input_len); + if (res) { + return false; + } + + uint8_t key[CRYPTO_AES_KEY_SIZE]; + if (site_key == NULL) { + return false; + } + memcpy(key, site_key, sizeof(key)); + + // Diversify input & copy to output buffer + uint8_t diversified_key[CRYPTO_AES_KEY_SIZE]; + bool ret = MifareKdfAn10922(key, CRYPTO_TYPE_AES128, key_output, kdf_input_len, diversified_key); + memcpy(key_output, diversified_key, CRYPTO_AES_KEY_SIZE); + + return ret; +} + +void scramble(uint8_t *arr, uint8_t len) { + const uint8_t lut[] = { + 0xa3, 0xb0, 0x80, 0xc6, 0xb2, 0xf4, 0x5c, 0x6c, 0x81, 0xf1, 0xbb, 0xeb, 0x55, 0x67, 0x3c, 0x05, + 0x1a, 0x0e, 0x61, 0xf6, 0x22, 0xce, 0xaa, 0x8f, 0xbd, 0x3b, 0x1f, 0x5e, 0x44, 0x04, 0x51, 0x2e, + 0x4d, 0x9a, 0x84, 0xea, 0xf8, 0x66, 0x74, 0x29, 0x7f, 0x70, 0xd8, 0x31, 0x7a, 0x6d, 0xa4, 0x00, + 0x82, 0xb9, 0x5f, 0xb4, 0x16, 0xab, 0xff, 0xc2, 0x39, 0xdc, 0x19, 0x65, 0x57, 0x7c, 0x20, 0xfa, + 0x5a, 0x49, 0x13, 0xd0, 0xfb, 0xa8, 0x91, 0x73, 0xb1, 0x33, 0x18, 0xbe, 0x21, 0x72, 0x48, 0xb6, + 0xdb, 0xa0, 0x5d, 0xcc, 0xe6, 0x17, 0x27, 0xe5, 0xd4, 0x53, 0x42, 0xf3, 0xdd, 0x7b, 0x24, 0xac, + 0x2b, 0x58, 0x1e, 0xa7, 0xe7, 0x86, 0x40, 0xd3, 0x98, 0x97, 0x71, 0xcb, 0x3a, 0x0f, 0x01, 0x9b, + 0x6e, 0x1b, 0xfc, 0x34, 0xa6, 0xda, 0x07, 0x0c, 0xae, 0x37, 0xca, 0x54, 0xfd, 0x26, 0xfe, 0x0a, + 0x45, 0xa2, 0x2a, 0xc4, 0x12, 0x0d, 0xf5, 0x4f, 0x69, 0xe0, 0x8a, 0x77, 0x60, 0x3f, 0x99, 0x95, + 0xd2, 0x38, 0x36, 0x62, 0xb7, 0x32, 0x7e, 0x79, 0xc0, 0x46, 0x93, 0x2f, 0xa5, 0xba, 0x5b, 0xaf, + 0x52, 0x1d, 0xc3, 0x75, 0xcf, 0xd6, 0x4c, 0x83, 0xe8, 0x3d, 0x30, 0x4e, 0xbc, 0x08, 0x2d, 0x09, + 0x06, 0xd9, 0x25, 0x9e, 0x89, 0xf2, 0x96, 0x88, 0xc1, 0x8c, 0x94, 0x0b, 0x28, 0xf0, 0x47, 0x63, + 0xd5, 0xb3, 0x68, 0x56, 0x9c, 0xf9, 0x6f, 0x41, 0x50, 0x85, 0x8b, 0x9d, 0x59, 0xbf, 0x9f, 0xe2, + 0x8e, 0x6a, 0x11, 0x23, 0xa1, 0xcd, 0xb5, 0x7d, 0xc7, 0xa9, 0xc8, 0xef, 0xdf, 0x02, 0xb8, 0x03, + 0x6b, 0x35, 0x3e, 0x2c, 0x76, 0xc9, 0xde, 0x1c, 0x4b, 0xd1, 0xed, 0x14, 0xc5, 0xad, 0xe9, 0x64, + 0x4a, 0xec, 0x8d, 0xf7, 0x10, 0x43, 0x78, 0x15, 0x87, 0xe4, 0xd7, 0x92, 0xe1, 0xee, 0xe3, 0x90 + }; + + for (int i = 0; i < len; i++) { + arr[i] = lut[arr[i]]; + } +} + +void gallagher_encode_creds(uint8_t *eight_bytes, uint8_t rc, uint16_t fc, uint32_t cn, uint8_t il) { + // put data into the correct places (Gallagher obfuscation) + eight_bytes[0] = (cn & 0xffffff) >> 16; + eight_bytes[1] = (fc & 0xfff) >> 4; + eight_bytes[2] = (cn & 0x7ff) >> 3; + eight_bytes[3] = (cn & 0x7) << 5 | (rc & 0xf) << 1; + eight_bytes[4] = (cn & 0xffff) >> 11; + eight_bytes[5] = (fc & 0xffff) >> 12; + eight_bytes[6] = 0; + eight_bytes[7] = (fc & 0xf) << 4 | (il & 0xf); + + // more obfuscation + scramble(eight_bytes, 8); +} diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagherTools.h b/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagherTools.h new file mode 100644 index 00000000..09de3608 --- /dev/null +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagherTools.h @@ -0,0 +1,21 @@ +// +// Created by Tom on 13.11.2022. +// + +#ifndef CHAMELEON_MINI_DESFIREGALLAGHERTOOLS_H +#define CHAMELEON_MINI_DESFIREGALLAGHERTOOLS_H + +#include "DESFireCrypto.h" +#include "DESFireApplicationDirectory.h" +#include "Configuration.h" +#include "DESFirePICCControl.h" +#include "DESFireStatusCodes.h" + +bool MifareKdfAn10922(uint8_t *key, uint8_t CryptoType, const uint8_t *data, size_t len, uint8_t *diversified_key); +int mfdes_kdf_input_gallagher(uint8_t *uid, uint8_t uidLen, uint8_t keyNo, uint32_t aid, uint8_t *kdfInputOut, uint8_t *kdfInputLen); +bool hfgal_diversify_key(uint8_t *site_key, uint8_t *uid, uint8_t uid_len, uint8_t key_num, uint32_t aid, uint8_t *key_output); + +void scramble(uint8_t *arr, uint8_t len); +void gallagher_encode_creds(uint8_t *eight_bytes, uint8_t rc, uint16_t fc, uint32_t cn, uint8_t il); + +#endif //CHAMELEON_MINI_DESFIREGALLAGHERTOOLS_H From 9a8a3309c018015298087a54eaf5817785668990 Mon Sep 17 00:00:00 2001 From: Tomaspre Date: Mon, 14 Nov 2022 18:23:28 +0000 Subject: [PATCH 04/12] Minimal Gallagher self-programming support. Before testing on physical device. --- .../DESFire/DESFireChameleonTerminal.c | 29 +++++++++++++++++++ .../DESFire/DESFireChameleonTerminal.h | 3 ++ .../DESFire/DESFireChameleonTerminalInclude.c | 8 +++++ 3 files changed, 40 insertions(+) diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireChameleonTerminal.c b/Firmware/Chameleon-Mini/Application/DESFire/DESFireChameleonTerminal.c index c8db3727..8f69f381 100644 --- a/Firmware/Chameleon-Mini/Application/DESFire/DESFireChameleonTerminal.c +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireChameleonTerminal.c @@ -34,6 +34,9 @@ This notice must be retained at the top of all source files where indicated. #include "DESFirePICCControl.h" #include "DESFireMemoryOperations.h" #include "DESFireLogging.h" +#include "DESFireGallagher.h" + +#include bool IsDESFireConfiguration(void) { return GlobalSettings.ActiveSettingPtr->Configuration == CONFIG_MF_DESFIRE || @@ -151,6 +154,7 @@ CommandStatusIdType CommandDESFireSetHeaderProperty(char *OutParam, const char * MemoryStoreDesfireHeaderBytes(); return COMMAND_INFO_OK_ID; } + #endif /* DISABLE_PERMISSIVE_DESFIRE_SETTINGS */ CommandStatusIdType CommandDESFireSetCommMode(char *OutParam, const char *InParams) { @@ -224,4 +228,29 @@ CommandStatusIdType CommandDESFireSetEncryptionMode(char *OutParam, const char * return COMMAND_INFO_OK; } +CommandStatusIdType CommandDESFireSetupGallagher(char *OutMessage, const char *InParams) { + + if (!IsDESFireConfiguration()) { + return COMMAND_ERR_INVALID_USAGE_ID; + } + + uint32_t cardId; + uint16_t facilityId; + uint8_t issueLevel; + uint8_t regionCode; + + if (sscanf_P(InParams, PSTR("%"SCNd32",%"SCNd16",%"SCNd8",%"SCNd8), cardId, facilityId, issueLevel, regionCode) != 4) { + return COMMAND_ERR_INVALID_PARAM_ID; + } + + bool ret = CreateGallagherApp(cardId, facilityId, issueLevel, regionCode); + + if (!ret) { + return COMMAND_ERR_INVALID_USAGE_ID; + } + + return COMMAND_INFO_OK; +} + #endif /* CONFIG_MF_DESFIRE_SUPPORT */ + diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireChameleonTerminal.h b/Firmware/Chameleon-Mini/Application/DESFire/DESFireChameleonTerminal.h index 44a8b511..b73525e1 100644 --- a/Firmware/Chameleon-Mini/Application/DESFire/DESFireChameleonTerminal.h +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireChameleonTerminal.h @@ -47,6 +47,9 @@ CommandStatusIdType CommandDESFireSetCommMode(char *OutMessage, const char *InPa #define DFCOMMAND_SET_ENCMODE "DF_ENCMODE" CommandStatusIdType CommandDESFireSetEncryptionMode(char *OutMessage, const char *InParams); +#define DFCOMMAND_SETUP_GALLAGHER "DF_SETGALL" +CommandStatusIdType CommandDESFireSetupGallagher(char *OutMessage, const char *InParams); + #endif /* DESFire Support */ #endif /* __DESFIRE_CHAMELEON_TERMINAL_H__ */ diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireChameleonTerminalInclude.c b/Firmware/Chameleon-Mini/Application/DESFire/DESFireChameleonTerminalInclude.c index 0df8437c..5ef90ed2 100644 --- a/Firmware/Chameleon-Mini/Application/DESFire/DESFireChameleonTerminalInclude.c +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireChameleonTerminalInclude.c @@ -46,8 +46,16 @@ This notice must be retained at the top of all source files where indicated. .ExecParamFunc = NO_FUNCTION, .SetFunc = CommandDESFireSetEncryptionMode, .GetFunc = NO_FUNCTION +}, { + .Command = DFCOMMAND_SETUP_GALLAGHER, + .ExecFunc = NO_FUNCTION, + .ExecParamFunc = NO_FUNCTION, + .SetFunc = CommandDESFireSetupGallagher, + .GetFunc = NO_FUNCTION }, + + #endif #endif /* CONFIG_MF_DESFIRE_SUPPORT */ From de670428357264274cb404424fde8cf18e28b2b7 Mon Sep 17 00:00:00 2001 From: Tomaspre Date: Wed, 16 Nov 2022 15:24:38 +0000 Subject: [PATCH 05/12] Fix KDF, fix argument passing --- .../DESFire/DESFireChameleonTerminal.c | 13 ++-- .../Application/DESFire/DESFireGallagher.c | 60 +++++++++++++++---- .../Application/DESFire/DESFireGallagher.h | 4 ++ .../DESFire/DESFireGallagherTools.c | 24 +++++--- .../DESFire/DESFireGallagherTools.h | 8 +-- 5 files changed, 82 insertions(+), 27 deletions(-) diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireChameleonTerminal.c b/Firmware/Chameleon-Mini/Application/DESFire/DESFireChameleonTerminal.c index 8f69f381..47a8335f 100644 --- a/Firmware/Chameleon-Mini/Application/DESFire/DESFireChameleonTerminal.c +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireChameleonTerminal.c @@ -229,17 +229,20 @@ CommandStatusIdType CommandDESFireSetEncryptionMode(char *OutParam, const char * } CommandStatusIdType CommandDESFireSetupGallagher(char *OutMessage, const char *InParams) { + DEBUG_PRINT_P(PSTR("Running DF_SETGALL")); + //for (uint8_t i = 0; i < 15; ++i) + // OutMessage[i] = InParams[i]; if (!IsDESFireConfiguration()) { return COMMAND_ERR_INVALID_USAGE_ID; } - uint32_t cardId; - uint16_t facilityId; - uint8_t issueLevel; - uint8_t regionCode; + uint32_t cardId = 0xFFFFFFFF; + uint16_t facilityId = 0xFFFF; + uint8_t issueLevel = 0xFF; + uint8_t regionCode = 0xFF; - if (sscanf_P(InParams, PSTR("%"SCNd32",%"SCNd16",%"SCNd8",%"SCNd8), cardId, facilityId, issueLevel, regionCode) != 4) { + if (sscanf_P(InParams, PSTR("C%"SCNu32"F%"SCNu16"I%"SCNu8"R%"SCNu8), &cardId, &facilityId, &issueLevel, ®ionCode) != 4) { return COMMAND_ERR_INVALID_PARAM_ID; } diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagher.c b/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagher.c index c439da0f..598efd54 100644 --- a/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagher.c +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagher.c @@ -5,6 +5,8 @@ #include #include "DESFireGallagher.h" #include "DESFireGallagherTools.h" +#include "DESFireLogging.h" +#include "DESFireUtils.h" //SelectedApp //Authenticated, wthkey, wthmasterkey //CRYPTO_AES_KEY_SIZE @@ -14,7 +16,7 @@ //Defaults to the default gallagher site key -uint8_t GallagherSiteKey[] = { +uint8_t GallagherSiteKey[16] = { 0x31, 0x12, 0xB7, 0x38, 0xD8, 0x86, 0x2C, 0xCD, 0x34, 0x30, 0x2E, 0xB2, 0x99, 0xAA, 0xB4, 0x56, }; @@ -23,38 +25,57 @@ uint8_t GallagherSiteKey[] = { bool CreateGallagherApp(uint32_t cardId, uint16_t facilityId, uint8_t issueLevel, uint8_t regionCode) { //TODO: Find a suitable AID - DESFireAidType AID = {0x20, 0x81, 0xF4}; + DESFireAidType AID = {0xF4, 0x81, 0x20}; return CreateGallagherAppWithAID(cardId, facilityId, issueLevel, regionCode, AID); } //Warning - running this function resets the AUTH state! bool CreateGallagherAppWithAID(uint32_t cardId, uint16_t facilityId, uint8_t issueLevel, uint8_t regionCode, DESFireAidType AID) { + DEBUG_PRINT_P(PSTR("Creating Gallagher App")); + DEBUG_PRINT_P(PSTR("CardId:(%u)"), cardId); + DEBUG_PRINT_P(PSTR("F:(%u)IL:(%u)RC:(%u)"), facilityId, issueLevel, regionCode); + DEBUG_PRINT_P(PSTR("AID: %02x %02x %02x"), AID[0], AID[1], AID[2]); + uint8_t Status = 0; ConfigurationUidType UID_GALL; GetPiccUid(UID_GALL); InvalidateAuthState(false); + DEBUG_PRINT_P(PSTR("UID: %02x %02x %02x %02x %02x %02x %02x"), UID_GALL[0], UID_GALL[1], UID_GALL[2], UID_GALL[3], + UID_GALL[4], UID_GALL[5], UID_GALL[6], UID_GALL[7]); + DEBUG_PRINT_P(PSTR("Resetting auth state")); //TODO: Is this needed? Authenticated = true; AuthenticatedWithKey = 0; AuthenticatedWithPICCMasterKey = true; + DEBUG_PRINT_P(PSTR("Creating CAD app")); //Create card app directory app - const DESFireAidType CADAid = {0x2F, 0x81, 0xF4}; //0x2F81F4 - Status = CreateApp(CADAid, 0x0B, 1); + DESFireAidType CADAid; + CADAid[0] = 0xF4; + CADAid[1] = 0x81; + CADAid[2] = 0x2F;//0x2F81F4 + uint8_t KeyCount = 1; + uint8_t KeySettings = 0x0B; + Status = CreateApp(CADAid, KeyCount, KeySettings); if (Status != STATUS_OPERATION_OK) { + DEBUG_PRINT_P(PSTR("Err: %u"), Status); return false; } + DEBUG_PRINT_P(PSTR("Diversifying CAD key")); //Difersify key for app directory app uint8_t CADKeyZero[CRYPTO_AES_KEY_SIZE]; - hfgal_diversify_key(GallagherSiteKey, UID_GALL, 7, 0, CADAid[0]*256*256 + CADAid[1]*256 + CADAid[2], CADKeyZero); + hfgal_diversify_key(GallagherSiteKey, UID_GALL, 7, 0, CADAid, CADKeyZero); + DEBUG_PRINT_P(PSTR("Key:")); + DesfireLogEntry(LOG_APP_AUTH_KEY, (void *) CADKeyZero, 16); //Select the app direcory app SelectApp(CADAid); + DEBUG_PRINT_P(PSTR("Vhanging CAD app key")); //Channge key uint8_t nextKeyVersion = ReadKeyVersion(SelectedApp.Slot, 0) + 1; WriteAppKey(SelectedApp.Slot, 0, CADKeyZero, CRYPTO_AES_KEY_SIZE); @@ -64,6 +85,7 @@ bool CreateGallagherAppWithAID(uint32_t cardId, uint16_t facilityId, uint8_t iss //Select the app direcory app SelectApp(CADAid); + DEBUG_PRINT_P(PSTR("Creating file in CAD app")); //Create file in CAD Status = CreateStandardFile(0x00, 0x00, 0xE000, CAD_BLOCK_LEN); @@ -77,11 +99,12 @@ bool CreateGallagherAppWithAID(uint32_t cardId, uint16_t facilityId, uint8_t iss CADBlock[0] = regionCode; CADBlock[1] = (facilityId >> 8) & 0xFF; CADBlock[2] = facilityId & 0xFF; - CADBlock[3] = CADAid[0]; - CADBlock[4] = CADAid[1]; - CADBlock[5] = CADAid[2]; + CADBlock[3] = AID[2]; + CADBlock[4] = AID[1]; + CADBlock[5] = AID[0]; memset(CADBlock+6, 0, CAD_BLOCK_LEN-6); + DEBUG_PRINT_P(PSTR("Updating file in CAD app")); //Update file in CAD uint8_t fileIndex = LookupFileNumberIndex(SelectedApp.Slot, 0); uint8_t fileType = ReadFileType(SelectedApp.Slot, fileIndex); @@ -97,31 +120,44 @@ bool CreateGallagherAppWithAID(uint32_t cardId, uint16_t facilityId, uint8_t iss return false; } + DEBUG_PRINT_P(PSTR("Creating Gallagher app")); //Create Gall app - Status = CreateApp(AID, 0x0B, 3); + KeyCount = 3; + KeySettings = 0x0B; + Status = CreateApp(AID, KeyCount, KeySettings); + + SelectApp(AID); + DEBUG_PRINT_P(PSTR("Diversifying key 2")); //Diversify and change key 2 uint8_t GallAppKeyTwo[CRYPTO_AES_KEY_SIZE]; - hfgal_diversify_key(GallagherSiteKey, UID_GALL, 7, 2, AID[0]*256*256 + AID[1]*256 + AID[2], GallAppKeyTwo); + hfgal_diversify_key(GallagherSiteKey, UID_GALL, 7, 2, AID, GallAppKeyTwo); + DEBUG_PRINT_P(PSTR("Key:")); + DesfireLogEntry(LOG_APP_AUTH_KEY, (void *) GallAppKeyTwo, 16); nextKeyVersion = ReadKeyVersion(SelectedApp.Slot, 2) + 1; WriteAppKey(SelectedApp.Slot, 2, GallAppKeyTwo, CRYPTO_AES_KEY_SIZE); WriteKeyVersion(SelectedApp.Slot, 0, nextKeyVersion); WriteKeyCryptoType(SelectedApp.Slot, 0, CRYPTO_TYPE_AES128); + DEBUG_PRINT_P(PSTR("Diversifying key 0")); //Diversify and change key 0 uint8_t GallAppKeyZero[CRYPTO_AES_KEY_SIZE]; - hfgal_diversify_key(GallagherSiteKey, UID_GALL, 7, 0, AID[0]*256*256 + AID[1]*256 + AID[2], GallAppKeyZero); + hfgal_diversify_key(GallagherSiteKey, UID_GALL, 7, 0, AID, GallAppKeyZero); + DEBUG_PRINT_P(PSTR("Key:")); + DesfireLogEntry(LOG_APP_AUTH_KEY, (void *) GallAppKeyZero, 16); nextKeyVersion = ReadKeyVersion(SelectedApp.Slot, 0) + 1; WriteAppKey(SelectedApp.Slot, 0, GallAppKeyZero, CRYPTO_AES_KEY_SIZE); WriteKeyVersion(SelectedApp.Slot, 0, nextKeyVersion); WriteKeyCryptoType(SelectedApp.Slot, 0, CRYPTO_TYPE_AES128); + DEBUG_PRINT_P(PSTR("Creating file in Gall app")); //Create file Status = CreateStandardFile(0x00, 0x03, 0x2000, GALL_BLOCK_LEN); if (Status != STATUS_OPERATION_OK) { + DEBUG_PRINT_P(PSTR("Err: %u"), Status); return false; } @@ -132,6 +168,7 @@ bool CreateGallagherAppWithAID(uint32_t cardId, uint16_t facilityId, uint8_t iss GallBlock[i + 8] = GallBlock[i] ^ 0xFF; } + DEBUG_PRINT_P(PSTR("Updating file in Gall app")); //Update file with Gall access data fileIndex = LookupFileNumberIndex(SelectedApp.Slot, 0); fileType = ReadFileType(SelectedApp.Slot, fileIndex); @@ -147,6 +184,7 @@ bool CreateGallagherAppWithAID(uint32_t cardId, uint16_t facilityId, uint8_t iss return false; } + DEBUG_PRINT_P(PSTR("Done")); return true; } diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagher.h b/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagher.h index 7ce824ad..0f1bd220 100644 --- a/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagher.h +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagher.h @@ -6,6 +6,10 @@ #define CHAMELEON_MINI_DESFIREGALLAGHER_H #include "DESFireCrypto.h" +#include "DESFireApplicationDirectory.h" +#include "Configuration.h" +#include "DESFirePICCControl.h" +#include "DESFireStatusCodes.h" //Warning - running this function resets the AUTH state! bool CreateGallagherApp(uint32_t cardId, uint16_t facilityId, uint8_t issueLevel, uint8_t regionCode); diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagherTools.c b/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagherTools.c index d1623a8f..03c0d52b 100644 --- a/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagherTools.c +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagherTools.c @@ -17,6 +17,8 @@ #include #include "DESFireGallagherTools.h" +#include "DESFireLogging.h" +#include "DESFireUtils.h" // This function is almot like cmac(...). but with some key differences. bool MifareKdfAn10922(uint8_t *key, uint8_t CryptoType, @@ -90,8 +92,8 @@ bool MifareKdfAn10922(uint8_t *key, uint8_t CryptoType, return false; } -int mfdes_kdf_input_gallagher(uint8_t *uid, uint8_t uidLen, uint8_t keyNo, - uint32_t aid, uint8_t *kdfInputOut, uint8_t *kdfInputLen) { +uint8_t mfdes_kdf_input_gallagher(uint8_t *uid, uint8_t uidLen, uint8_t keyNo, + DESFireAidType aid, uint8_t *kdfInputOut, uint8_t *kdfInputLen) { if (uid == NULL || (uidLen != 4 && uidLen != 7) || keyNo > 2 || kdfInputOut == NULL || kdfInputLen == NULL) { return 1; } @@ -99,7 +101,7 @@ int mfdes_kdf_input_gallagher(uint8_t *uid, uint8_t uidLen, uint8_t keyNo, int len = 0; // If the keyNo == 1 or the aid is 000000, then omit the UID. // On the other hand, if the aid is 1f81f4 (config card) always include the UID. - if ((keyNo != 1 && aid != 0x000000) || (aid == 0x1f81f4)) { + if ((keyNo != 1 && aid != 0x000000) || (aid[0] == 0x1f && aid[1] == 0x81 && aid[2] == 0xf4)) { if (*kdfInputLen < (4 + uidLen)) { return 2; } @@ -112,9 +114,9 @@ int mfdes_kdf_input_gallagher(uint8_t *uid, uint8_t uidLen, uint8_t keyNo, kdfInputOut[len++] = keyNo; - kdfInputOut[len++] = aid & 0xff; - kdfInputOut[len++] = (aid >> 8) & 0xff; - kdfInputOut[len++] = (aid >> 16) & 0xff; + kdfInputOut[len++] = aid[0]; + kdfInputOut[len++] = aid[1]; + kdfInputOut[len++] = aid[2]; *kdfInputLen = len; @@ -122,7 +124,7 @@ int mfdes_kdf_input_gallagher(uint8_t *uid, uint8_t uidLen, uint8_t keyNo, } bool hfgal_diversify_key(uint8_t *site_key, uint8_t *uid, uint8_t uid_len, - uint8_t key_num, uint32_t aid, uint8_t *key_output) { + uint8_t key_num, DESFireAidType aid, uint8_t *key_output) { // Generate diversification input uint8_t kdf_input_len = 11; uint32_t res = mfdes_kdf_input_gallagher(uid, uid_len, key_num, aid, key_output, &kdf_input_len); @@ -130,6 +132,14 @@ bool hfgal_diversify_key(uint8_t *site_key, uint8_t *uid, uint8_t uid_len, return false; } + DesfireLogEntry(LOG_APP_NONCE_B, (void *) uid, 7); + DesfireLogEntry(LOG_APP_NONCE_B, (void *) &uid_len, 1); + DesfireLogEntry(LOG_APP_NONCE_B, (void *) &key_num, 1); + DesfireLogEntry(LOG_APP_NONCE_B, (void *) &aid, 4); + + DEBUG_PRINT_P(PSTR("KDF input:")); + DesfireLogEntry(LOG_APP_NONCE_B, (void *) key_output, kdf_input_len); + uint8_t key[CRYPTO_AES_KEY_SIZE]; if (site_key == NULL) { return false; diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagherTools.h b/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagherTools.h index 09de3608..0aa7908b 100644 --- a/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagherTools.h +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagherTools.h @@ -11,11 +11,11 @@ #include "DESFirePICCControl.h" #include "DESFireStatusCodes.h" -bool MifareKdfAn10922(uint8_t *key, uint8_t CryptoType, const uint8_t *data, size_t len, uint8_t *diversified_key); -int mfdes_kdf_input_gallagher(uint8_t *uid, uint8_t uidLen, uint8_t keyNo, uint32_t aid, uint8_t *kdfInputOut, uint8_t *kdfInputLen); -bool hfgal_diversify_key(uint8_t *site_key, uint8_t *uid, uint8_t uid_len, uint8_t key_num, uint32_t aid, uint8_t *key_output); +//bool MifareKdfAn10922(uint8_t *key, uint8_t CryptoType, const uint8_t *data, size_t len, uint8_t *diversified_key); +//uint8_t mfdes_kdf_input_gallagher(uint8_t *uid, uint8_t uidLen, uint8_t keyNo, uint32_t aid, uint8_t *kdfInputOut, uint8_t *kdfInputLen); +bool hfgal_diversify_key(uint8_t *site_key, uint8_t *uid, uint8_t uid_len, uint8_t key_num, DESFireAidType aid, uint8_t *key_output); -void scramble(uint8_t *arr, uint8_t len); +//void scramble(uint8_t *arr, uint8_t len); void gallagher_encode_creds(uint8_t *eight_bytes, uint8_t rc, uint16_t fc, uint32_t cn, uint8_t il); #endif //CHAMELEON_MINI_DESFIREGALLAGHERTOOLS_H From c1dd107b82c30ca3cdfc4b08103a23ac7a86d0a8 Mon Sep 17 00:00:00 2001 From: Tomaspre Date: Wed, 16 Nov 2022 17:37:41 +0000 Subject: [PATCH 06/12] Basic selfprog support for Gallagher working! --- Firmware/Chameleon-Mini/Application/CryptoCMAC.c | 10 +++++++--- Firmware/Chameleon-Mini/Application/CryptoCMAC.h | 1 + .../Application/DESFire/DESFireGallagherTools.c | 4 ++-- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/Firmware/Chameleon-Mini/Application/CryptoCMAC.c b/Firmware/Chameleon-Mini/Application/CryptoCMAC.c index bb35b7ab..7971c46f 100644 --- a/Firmware/Chameleon-Mini/Application/CryptoCMAC.c +++ b/Firmware/Chameleon-Mini/Application/CryptoCMAC.c @@ -199,8 +199,12 @@ bool DesfireCMACGenerateSubkeys(uint8_t cryptoType, const uint8_t *keyData, uint return true; } +bool DesfireCryptoCMAC(uint8_t cryptoType, const uint8_t *keyData, uint8_t *bufferDataIn, uint16_t bufferSize, uint8_t *IV, uint8_t *cmac){ + return DesfireCryptoCMACEx(cryptoType, keyData, bufferDataIn, bufferSize, IV, cmac, 0); +} + //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) { +bool DesfireCryptoCMACEx(uint8_t cryptoType, const uint8_t *keyData, uint8_t *bufferDataIn, uint16_t bufferSize, uint8_t *IV, uint8_t *cmac, uint16_t minlen) { uint8_t kbs; uint8_t len = bufferSize; uint8_t * bufferData = bufferDataIn + bufferSize; @@ -223,9 +227,9 @@ bool DesfireCryptoCMAC(uint8_t cryptoType, const uint8_t *keyData, uint8_t *buff DesfireCMACGenerateSubkeys(cryptoType, keyData, sk1, sk2); - if ((!len) || (len % kbs)) { + if ((!len) || (len % kbs) || (len < minlen)) { bufferData[len++] = 0x80; - while (len % kbs) { + while (len % kbs || len < minlen) { bufferData[len++] = 0x00; } bin_xor(bufferData + len - kbs, sk2, kbs); diff --git a/Firmware/Chameleon-Mini/Application/CryptoCMAC.h b/Firmware/Chameleon-Mini/Application/CryptoCMAC.h index 8ee397cd..1494c0a9 100644 --- a/Firmware/Chameleon-Mini/Application/CryptoCMAC.h +++ b/Firmware/Chameleon-Mini/Application/CryptoCMAC.h @@ -43,5 +43,6 @@ uint16_t appendBufferMAC(const uint8_t *keyData, uint8_t *bufferData, uint16_t b 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); +bool DesfireCryptoCMACEx(uint8_t cryptoType, const uint8_t *keyData, uint8_t *bufferDataIn, uint16_t bufferSize, uint8_t *IV, uint8_t *cmac, uint16_t minlen); #endif diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagherTools.c b/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagherTools.c index 03c0d52b..cf021860 100644 --- a/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagherTools.c +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagherTools.c @@ -41,7 +41,7 @@ bool MifareKdfAn10922(uint8_t *key, uint8_t CryptoType, return false; } - uint8_t buffer[CRYPTO_MAX_BLOCK_SIZE * 3] = {0}; + uint8_t buffer[96] = {0}; if (CryptoType == CRYPTO_TYPE_AES128) { buffer[0] = 0x01; @@ -49,7 +49,7 @@ bool MifareKdfAn10922(uint8_t *key, uint8_t CryptoType, uint8_t IV[CRYPTO_AES_BLOCK_SIZE]; memset(IV, 0, CRYPTO_AES_BLOCK_SIZE); - DesfireCryptoCMAC(CryptoType, key, buffer, len + 1, IV, diversified_key); + DesfireCryptoCMACEx(CryptoType, key, buffer, len + 1, IV, diversified_key, 2*kbs); return true; } else if (CryptoType == CRYPTO_TYPE_2KTDEA) { From caee6b4da751ab906f4bd276449f6029b9202056 Mon Sep 17 00:00:00 2001 From: Tomaspre Date: Sun, 20 Nov 2022 16:50:38 +0000 Subject: [PATCH 07/12] Split to functions, add terminal commands. Before testing. --- .../DESFire/DESFireChameleonTerminal.c | 119 +++++++++++++++++- .../DESFire/DESFireChameleonTerminal.h | 17 ++- .../DESFire/DESFireChameleonTerminalInclude.c | 30 +++++ .../Application/DESFire/DESFireGallagher.c | 81 +++++++++--- .../Application/DESFire/DESFireGallagher.h | 9 +- 5 files changed, 233 insertions(+), 23 deletions(-) diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireChameleonTerminal.c b/Firmware/Chameleon-Mini/Application/DESFire/DESFireChameleonTerminal.c index 47a8335f..ae23a8c1 100644 --- a/Firmware/Chameleon-Mini/Application/DESFire/DESFireChameleonTerminal.c +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireChameleonTerminal.c @@ -38,6 +38,8 @@ This notice must be retained at the top of all source files where indicated. #include +extern DESFireAidType selectedGallagherAID; + bool IsDESFireConfiguration(void) { return GlobalSettings.ActiveSettingPtr->Configuration == CONFIG_MF_DESFIRE || GlobalSettings.ActiveSettingPtr->Configuration == CONFIG_MF_DESFIRE_2KEV1 || @@ -246,7 +248,7 @@ CommandStatusIdType CommandDESFireSetupGallagher(char *OutMessage, const char *I return COMMAND_ERR_INVALID_PARAM_ID; } - bool ret = CreateGallagherApp(cardId, facilityId, issueLevel, regionCode); + bool ret = CreateGallagher(cardId, facilityId, issueLevel, regionCode); if (!ret) { return COMMAND_ERR_INVALID_USAGE_ID; @@ -255,5 +257,120 @@ CommandStatusIdType CommandDESFireSetupGallagher(char *OutMessage, const char *I return COMMAND_INFO_OK; } +CommandStatusIdType CommandDESFireCreateGallagherApp(char *OutMessage, const char *InParams) { + if (!IsDESFireConfiguration()) { + return COMMAND_ERR_INVALID_USAGE_ID; + } + + if (selectedGallagherAID[0] == 0xFF && selectedGallagherAID[1] == 0xFF && selectedGallagherAID[2] == 0xFF) { + snprintf_P(OutMessage, TERMINAL_BUFFER_SIZE, PSTR("SET AID FIRST")); + return COMMAND_ERR_INVALID_USAGE_ID; + } + + DESFireAidType AID; + uint32_t cardId = 0xFFFFFFFF; + uint16_t facilityId = 0xFFFF; + uint8_t issueLevel = 0xFF; + uint8_t regionCode = 0xFF; + + if (sscanf_P(InParams, PSTR("C%"SCNu32"F%"SCNu16"I%"SCNu8"R%"SCNu8), + &cardId, &facilityId, &issueLevel, ®ionCode + ) != 4) { + return COMMAND_ERR_INVALID_PARAM_ID; + } + + bool ret = CreateGallagherAppWithAID(cardId, facilityId, issueLevel, regionCode, selectedGallagherAID); + + if (!ret) { + return COMMAND_ERR_INVALID_USAGE_ID; + } + + return COMMAND_INFO_OK; +} + +CommandStatusIdType CommandDESFireUpdateGallagherApp(char *OutMessage, const char *InParams) { + if (!IsDESFireConfiguration()) { + return COMMAND_ERR_INVALID_USAGE_ID; + } + + if (selectedGallagherAID[0] == 0xFF && selectedGallagherAID[1] == 0xFF && selectedGallagherAID[2] == 0xFF) { + snprintf_P(OutMessage, TERMINAL_BUFFER_SIZE, PSTR("SET AID FIRST")); + return COMMAND_ERR_INVALID_USAGE_ID; + } + + DESFireAidType AID; + uint32_t cardId = 0xFFFFFFFF; + uint16_t facilityId = 0xFFFF; + uint8_t issueLevel = 0xFF; + uint8_t regionCode = 0xFF; + + if (sscanf_P(InParams, PSTR("C%"SCNu32"F%"SCNu16"I%"SCNu8"R%"SCNu8), + &cardId, &facilityId, &issueLevel, ®ionCode + ) != 4) { + return COMMAND_ERR_INVALID_PARAM_ID; + } + + bool ret = UpdateGallagherFile(cardId, facilityId, issueLevel, regionCode, selectedGallagherAID); + + if (!ret) { + return COMMAND_ERR_INVALID_USAGE_ID; + } + + return COMMAND_INFO_OK; +} + +CommandStatusIdType CommandDESFireUpdateGallagherCardId(char *OutMessage, const char *InParams) { + if (!IsDESFireConfiguration()) { + return COMMAND_ERR_INVALID_USAGE_ID; + } + + if (selectedGallagherAID[0] == 0xFF && selectedGallagherAID[1] == 0xFF && selectedGallagherAID[2] == 0xFF) { + snprintf_P(OutMessage, TERMINAL_BUFFER_SIZE, PSTR("SET AID FIRST")); + return COMMAND_ERR_INVALID_USAGE_ID; + } + + uint32_t cardId; + + if (sscanf_P(InParams, PSTR("%"SCNu32), &cardId) != 1) { + return COMMAND_ERR_INVALID_PARAM_ID; + } + + bool ret = UpdateGallagherAppCardID(cardId); + + if (!ret) { + return COMMAND_ERR_INVALID_USAGE_ID; + } + + return COMMAND_INFO_OK; +} + +CommandStatusIdType CommandDESFireSelectGallagherApp(char *OutMessage, const char *InParams) { + if (!IsDESFireConfiguration()) { + return COMMAND_ERR_INVALID_USAGE_ID; + } + + DESFireAidType AID; + + if (sscanf_P(InParams, PSTR("%2"SCNx8"%2"SCNx8"%2"SCNx8), + &AID[0], &AID[1], &AID[2]) != 3) { + return COMMAND_ERR_INVALID_PARAM_ID; + } + + SelectGallagherAID(AID); + + return COMMAND_INFO_OK; +} + +CommandStatusIdType CommandDESFireSetGallagherSiteKey(char *OutMessage, const char *InParams) { + if (!IsDESFireConfiguration()) { + return COMMAND_ERR_INVALID_USAGE_ID; + } + + //Use the SetGallagherSiteKey and ResetGallagherSiteKey fucntions + + snprintf_P(OutMessage, TERMINAL_BUFFER_SIZE, PSTR("NOT IMPLEMENTED")); + return COMMAND_INFO_OK_WITH_TEXT_ID; +} + #endif /* CONFIG_MF_DESFIRE_SUPPORT */ diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireChameleonTerminal.h b/Firmware/Chameleon-Mini/Application/DESFire/DESFireChameleonTerminal.h index b73525e1..75c43725 100644 --- a/Firmware/Chameleon-Mini/Application/DESFire/DESFireChameleonTerminal.h +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireChameleonTerminal.h @@ -47,9 +47,24 @@ CommandStatusIdType CommandDESFireSetCommMode(char *OutMessage, const char *InPa #define DFCOMMAND_SET_ENCMODE "DF_ENCMODE" CommandStatusIdType CommandDESFireSetEncryptionMode(char *OutMessage, const char *InParams); -#define DFCOMMAND_SETUP_GALLAGHER "DF_SETGALL" +#define DFCOMMAND_SETUP_GALLAGHER "DF_SETUP_GALL" CommandStatusIdType CommandDESFireSetupGallagher(char *OutMessage, const char *InParams); +#define DFCOMMAND_CREATE_GALLAGHER_APP "DF_CRE_GALLAPP" +CommandStatusIdType CommandDESFireCreateGallagherApp(char *OutMessage, const char *InParams); + +#define DFCOMMAND_UPDATE_GALLAGHER_APP "DF_UP_GALLAPP" +CommandStatusIdType CommandDESFireUpdateGallagherApp(char *OutMessage, const char *InParams); + +#define DFCOMMAND_UPDATE_GALLAGHER_CARD_ID "DF_UP_GALL_CID" +CommandStatusIdType CommandDESFireUpdateGallagherCardId(char *OutMessage, const char *InParams); + +#define DFCOMMAND_SELECT_GALLAGHER_APP "DF_SEL_GALLAPP" +CommandStatusIdType CommandDESFireSelectGallagherApp(char *OutMessage, const char *InParams); + +#define DFCOMMAND_SET_GALLAGHER_SITE_KEY "DF_SET_GALLKEY" +CommandStatusIdType CommandDESFireSetGallagherSiteKey(char *OutMessage, const char *InParams); + #endif /* DESFire Support */ #endif /* __DESFIRE_CHAMELEON_TERMINAL_H__ */ diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireChameleonTerminalInclude.c b/Firmware/Chameleon-Mini/Application/DESFire/DESFireChameleonTerminalInclude.c index 5ef90ed2..2f062055 100644 --- a/Firmware/Chameleon-Mini/Application/DESFire/DESFireChameleonTerminalInclude.c +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireChameleonTerminalInclude.c @@ -52,6 +52,36 @@ This notice must be retained at the top of all source files where indicated. .ExecParamFunc = NO_FUNCTION, .SetFunc = CommandDESFireSetupGallagher, .GetFunc = NO_FUNCTION +}, { + .Command = DFCOMMAND_CREATE_GALLAGHER_APP, + .ExecFunc = NO_FUNCTION, + .ExecParamFunc = NO_FUNCTION, + .SetFunc = CommandDESFireCreateGallagherApp, + .GetFunc = NO_FUNCTION +}, { + .Command = DFCOMMAND_UPDATE_GALLAGHER_APP, + .ExecFunc = NO_FUNCTION, + .ExecParamFunc = NO_FUNCTION, + .SetFunc = CommandDESFireUpdateGallagherApp, + .GetFunc = NO_FUNCTION +}, { + .Command = DFCOMMAND_UPDATE_GALLAGHER_CARD_ID, + .ExecFunc = NO_FUNCTION, + .ExecParamFunc = NO_FUNCTION, + .SetFunc = CommandDESFireUpdateGallagherCardId, + .GetFunc = NO_FUNCTION +}, { + .Command = DFCOMMAND_SELECT_GALLAGHER_APP, + .ExecFunc = NO_FUNCTION, + .ExecParamFunc = NO_FUNCTION, + .SetFunc = CommandDESFireSelectGallagherApp, + .GetFunc = NO_FUNCTION +}, { + .Command = DFCOMMAND_SET_GALLAGHER_SITE_KEY, + .ExecFunc = NO_FUNCTION, + .ExecParamFunc = NO_FUNCTION, + .SetFunc = CommandDESFireSetGallagherSiteKey, + .GetFunc = NO_FUNCTION }, diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagher.c b/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagher.c index 598efd54..cd4fd108 100644 --- a/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagher.c +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagher.c @@ -14,6 +14,12 @@ #define CAD_BLOCK_LEN 0x24 #define GALL_BLOCK_LEN 0x10 +uint32_t lastCardId = 0xFFFFFFFF; +uint16_t lastFacilityId = 0xFFFF; +uint8_t lastIssueLevel = 0xFF; +uint8_t lastRegionCode = 0xFF; +DESFireAidType selectedGallagherAID = {0xFF, 0xFF, 0xFF}; + //Defaults to the default gallagher site key uint8_t GallagherSiteKey[16] = { @@ -22,7 +28,7 @@ uint8_t GallagherSiteKey[16] = { }; //Warning - running this function resets the AUTH state! -bool CreateGallagherApp(uint32_t cardId, uint16_t facilityId, uint8_t issueLevel, uint8_t regionCode) { +bool CreateGallagher(uint32_t cardId, uint16_t facilityId, uint8_t issueLevel, uint8_t regionCode) { //TODO: Find a suitable AID DESFireAidType AID = {0xF4, 0x81, 0x20}; @@ -31,7 +37,7 @@ bool CreateGallagherApp(uint32_t cardId, uint16_t facilityId, uint8_t issueLevel } //Warning - running this function resets the AUTH state! -bool CreateGallagherAppWithAID(uint32_t cardId, uint16_t facilityId, uint8_t issueLevel, uint8_t regionCode, DESFireAidType AID) { +bool CreateGallagherWithAID(uint32_t cardId, uint16_t facilityId, uint8_t issueLevel, uint8_t regionCode, DESFireAidType AID) { DEBUG_PRINT_P(PSTR("Creating Gallagher App")); DEBUG_PRINT_P(PSTR("CardId:(%u)"), cardId); DEBUG_PRINT_P(PSTR("F:(%u)IL:(%u)RC:(%u)"), facilityId, issueLevel, regionCode); @@ -120,11 +126,32 @@ bool CreateGallagherAppWithAID(uint32_t cardId, uint16_t facilityId, uint8_t iss return false; } + return CreateGallagherAppWithAID(cardId, facilityId, issueLevel, regionCode, AID); +} + +void SetGallagherSiteKey(uint8_t* key) { + for (uint8_t i = 0; i < 16; ++i) { + GallagherSiteKey[i] = key[i]; + } +} + +void ResetGallagherSiteKey() { + uint8_t key[16] = { + 0x31, 0x12, 0xB7, 0x38, 0xD8, 0x86, 0x2C, 0xCD, + 0x34, 0x30, 0x2E, 0xB2, 0x99, 0xAA, 0xB4, 0x56, + }; + SetGallagherSiteKey(key); +} + +bool CreateGallagherAppWithAID(uint32_t cardId, uint16_t facilityId, uint8_t issueLevel, uint8_t regionCode, DESFireAidType AID) { DEBUG_PRINT_P(PSTR("Creating Gallagher app")); //Create Gall app - KeyCount = 3; - KeySettings = 0x0B; - Status = CreateApp(AID, KeyCount, KeySettings); + uint8_t KeyCount = 3; + uint8_t KeySettings = 0x0B; + uint8_t Status = CreateApp(AID, KeyCount, KeySettings); + + ConfigurationUidType UID_GALL; + GetPiccUid(UID_GALL); SelectApp(AID); @@ -135,7 +162,7 @@ bool CreateGallagherAppWithAID(uint32_t cardId, uint16_t facilityId, uint8_t iss DEBUG_PRINT_P(PSTR("Key:")); DesfireLogEntry(LOG_APP_AUTH_KEY, (void *) GallAppKeyTwo, 16); - nextKeyVersion = ReadKeyVersion(SelectedApp.Slot, 2) + 1; + uint8_t nextKeyVersion = ReadKeyVersion(SelectedApp.Slot, 2) + 1; WriteAppKey(SelectedApp.Slot, 2, GallAppKeyTwo, CRYPTO_AES_KEY_SIZE); WriteKeyVersion(SelectedApp.Slot, 0, nextKeyVersion); WriteKeyCryptoType(SelectedApp.Slot, 0, CRYPTO_TYPE_AES128); @@ -161,6 +188,17 @@ bool CreateGallagherAppWithAID(uint32_t cardId, uint16_t facilityId, uint8_t iss return false; } + selectedGallagherAID[0] = AID[0]; + selectedGallagherAID[1] = AID[1]; + selectedGallagherAID[2] = AID[2]; + + return UpdateGallagherFile(cardId, facilityId, issueLevel, regionCode, AID); + +} + +bool UpdateGallagherFile(uint32_t cardId, uint16_t facilityId, uint8_t issueLevel, uint8_t regionCode, DESFireAidType AID) { + SelectApp(AID); + //Get Gallagher block to write uint8_t GallBlock[GALL_BLOCK_LEN]; gallagher_encode_creds(GallBlock, regionCode, facilityId, cardId, issueLevel); @@ -170,9 +208,9 @@ bool CreateGallagherAppWithAID(uint32_t cardId, uint16_t facilityId, uint8_t iss DEBUG_PRINT_P(PSTR("Updating file in Gall app")); //Update file with Gall access data - fileIndex = LookupFileNumberIndex(SelectedApp.Slot, 0); - fileType = ReadFileType(SelectedApp.Slot, fileIndex); - Status = WriteDataFileSetup(fileIndex, fileType, 0x03, 0, GALL_BLOCK_LEN); + uint8_t fileIndex = LookupFileNumberIndex(SelectedApp.Slot, 0); + uint8_t fileType = ReadFileType(SelectedApp.Slot, fileIndex); + uint8_t Status = WriteDataFileSetup(fileIndex, fileType, 0x03, 0, GALL_BLOCK_LEN); if (Status != STATUS_OPERATION_OK) { return false; @@ -184,20 +222,25 @@ bool CreateGallagherAppWithAID(uint32_t cardId, uint16_t facilityId, uint8_t iss return false; } - DEBUG_PRINT_P(PSTR("Done")); + lastCardId = cardId; + lastFacilityId = facilityId; + lastIssueLevel = issueLevel; + lastRegionCode = regionCode; + return true; } -void SetGallagherSiteKey(uint8_t* key) { - for (uint8_t i = 0; i < 16; ++i) { - GallagherSiteKey[i] = key[i]; +bool UpdateGallagherAppCardID(uint32_t cardId) { + if ((lastCardId == 0xFFFFFFFF && lastFacilityId == 0xFFFF && lastIssueLevel == 0xFF && lastRegionCode == 0xFF) || + (selectedGallagherAID[0] == 0xFF && selectedGallagherAID[1] == 0xFF && selectedGallagherAID[2] == 0xFF)) { + return false; } + + return UpdateGallagherFile(cardId, lastFacilityId, lastIssueLevel, lastRegionCode, selectedGallagherAID); } -void ResetGallagherSiteKey() { - uint8_t key[16] = { - 0x31, 0x12, 0xB7, 0x38, 0xD8, 0x86, 0x2C, 0xCD, - 0x34, 0x30, 0x2E, 0xB2, 0x99, 0xAA, 0xB4, 0x56, - }; - SetGallagherSiteKey(key); +void SelectGallagherAID(DESFireAidType AID) { + selectedGallagherAID[0] = AID[0]; + selectedGallagherAID[1] = AID[1]; + selectedGallagherAID[2] = AID[2]; } diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagher.h b/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagher.h index 0f1bd220..d8976918 100644 --- a/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagher.h +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagher.h @@ -12,10 +12,15 @@ #include "DESFireStatusCodes.h" //Warning - running this function resets the AUTH state! -bool CreateGallagherApp(uint32_t cardId, uint16_t facilityId, uint8_t issueLevel, uint8_t regionCode); +bool CreateGallagher(uint32_t cardId, uint16_t facilityId, uint8_t issueLevel, uint8_t regionCode); //Warning - running this function resets the AUTH state! -bool CreateGallagherAppWithAID(uint32_t cardId, uint16_t facilityId, uint8_t issueLevel, uint8_t regionCode, uint8_t* AID); +bool CreateGallagherWithAID(uint32_t cardId, uint16_t facilityId, uint8_t issueLevel, uint8_t regionCode, uint8_t* AID); + +bool CreateGallagherAppWithAID(uint32_t cardId, uint16_t facilityId, uint8_t issueLevel, uint8_t regionCode, DESFireAidType AID); +bool UpdateGallagherFile(uint32_t cardId, uint16_t facilityId, uint8_t issueLevel, uint8_t regionCode, DESFireAidType AID); +bool UpdateGallagherAppCardID(uint32_t cardId); +void SelectGallagherAID(DESFireAidType AID); void SetGallagherSiteKey(uint8_t* key); void ResetGallagherSiteKey(); From fed394c57446e5b8ed39065bd7689fc27f09ab0a Mon Sep 17 00:00:00 2001 From: Tomaspre Date: Mon, 21 Nov 2022 11:37:12 +0000 Subject: [PATCH 08/12] Fix terminal commands, fix licences --- .../DESFire/DESFireChameleonTerminal.c | 16 ++++++---- .../DESFire/DESFireChameleonTerminal.h | 4 +++ .../DESFire/DESFireChameleonTerminalInclude.c | 5 +++- .../Application/DESFire/DESFireGallagher.c | 29 +++++++++++++++---- .../Application/DESFire/DESFireGallagher.h | 27 +++++++++++++---- .../DESFire/DESFireGallagherTools.c | 5 ++-- .../DESFire/DESFireGallagherTools.h | 16 +++++++++- 7 files changed, 81 insertions(+), 21 deletions(-) diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireChameleonTerminal.c b/Firmware/Chameleon-Mini/Application/DESFire/DESFireChameleonTerminal.c index ae23a8c1..7b347505 100644 --- a/Firmware/Chameleon-Mini/Application/DESFire/DESFireChameleonTerminal.c +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireChameleonTerminal.c @@ -22,6 +22,9 @@ This notice must be retained at the top of all source files where indicated. /* * DESFireChameleonTerminal.c * Maxie D. Schmidt (github.com/maxieds) + * + * Part of this file was added by Tomas Preucil (github.com/tomaspre) + * This part is indicated in the code below */ #if defined(CONFIG_MF_DESFIRE_SUPPORT) && !defined(DISABLE_DESFIRE_TERMINAL_COMMANDS) @@ -230,6 +233,7 @@ CommandStatusIdType CommandDESFireSetEncryptionMode(char *OutParam, const char * return COMMAND_INFO_OK; } +//The rest of the file was added by tomaspre CommandStatusIdType CommandDESFireSetupGallagher(char *OutMessage, const char *InParams) { DEBUG_PRINT_P(PSTR("Running DF_SETGALL")); //for (uint8_t i = 0; i < 15; ++i) @@ -248,13 +252,13 @@ CommandStatusIdType CommandDESFireSetupGallagher(char *OutMessage, const char *I return COMMAND_ERR_INVALID_PARAM_ID; } - bool ret = CreateGallagher(cardId, facilityId, issueLevel, regionCode); + bool ret = CreateGallagherCard(cardId, facilityId, issueLevel, regionCode); if (!ret) { return COMMAND_ERR_INVALID_USAGE_ID; } - return COMMAND_INFO_OK; + return COMMAND_INFO_OK_ID; } CommandStatusIdType CommandDESFireCreateGallagherApp(char *OutMessage, const char *InParams) { @@ -285,7 +289,7 @@ CommandStatusIdType CommandDESFireCreateGallagherApp(char *OutMessage, const cha return COMMAND_ERR_INVALID_USAGE_ID; } - return COMMAND_INFO_OK; + return COMMAND_INFO_OK_ID; } CommandStatusIdType CommandDESFireUpdateGallagherApp(char *OutMessage, const char *InParams) { @@ -316,7 +320,7 @@ CommandStatusIdType CommandDESFireUpdateGallagherApp(char *OutMessage, const cha return COMMAND_ERR_INVALID_USAGE_ID; } - return COMMAND_INFO_OK; + return COMMAND_INFO_OK_ID; } CommandStatusIdType CommandDESFireUpdateGallagherCardId(char *OutMessage, const char *InParams) { @@ -341,7 +345,7 @@ CommandStatusIdType CommandDESFireUpdateGallagherCardId(char *OutMessage, const return COMMAND_ERR_INVALID_USAGE_ID; } - return COMMAND_INFO_OK; + return COMMAND_INFO_OK_ID; } CommandStatusIdType CommandDESFireSelectGallagherApp(char *OutMessage, const char *InParams) { @@ -358,7 +362,7 @@ CommandStatusIdType CommandDESFireSelectGallagherApp(char *OutMessage, const cha SelectGallagherAID(AID); - return COMMAND_INFO_OK; + return COMMAND_INFO_OK_ID; } CommandStatusIdType CommandDESFireSetGallagherSiteKey(char *OutMessage, const char *InParams) { diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireChameleonTerminal.h b/Firmware/Chameleon-Mini/Application/DESFire/DESFireChameleonTerminal.h index 75c43725..967deabf 100644 --- a/Firmware/Chameleon-Mini/Application/DESFire/DESFireChameleonTerminal.h +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireChameleonTerminal.h @@ -22,6 +22,9 @@ This notice must be retained at the top of all source files where indicated. /* * DESFireChameleonTerminal.h * Maxie D. Schmidt (github.com/maxieds) + * + * Part of this file was added by Tomas Preucil (github.com/tomaspre) + * This part is indicated in the code below */ #ifndef __DESFIRE_CHAMELEON_TERMINAL_H__ @@ -47,6 +50,7 @@ CommandStatusIdType CommandDESFireSetCommMode(char *OutMessage, const char *InPa #define DFCOMMAND_SET_ENCMODE "DF_ENCMODE" CommandStatusIdType CommandDESFireSetEncryptionMode(char *OutMessage, const char *InParams); +//The rest of the file was added by tomaspre #define DFCOMMAND_SETUP_GALLAGHER "DF_SETUP_GALL" CommandStatusIdType CommandDESFireSetupGallagher(char *OutMessage, const char *InParams); diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireChameleonTerminalInclude.c b/Firmware/Chameleon-Mini/Application/DESFire/DESFireChameleonTerminalInclude.c index 2f062055..c324cacf 100644 --- a/Firmware/Chameleon-Mini/Application/DESFire/DESFireChameleonTerminalInclude.c +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireChameleonTerminalInclude.c @@ -22,6 +22,9 @@ This notice must be retained at the top of all source files where indicated. /* * DESFireChameleonTerminalInclude.c * Maxie D. Schmidt (github.com/maxieds) + * + * Part of this file was added by Tomas Preucil (github.com/tomaspre) + * This part is indicated in the code below */ #ifdef CONFIG_MF_DESFIRE_SUPPORT @@ -46,7 +49,7 @@ This notice must be retained at the top of all source files where indicated. .ExecParamFunc = NO_FUNCTION, .SetFunc = CommandDESFireSetEncryptionMode, .GetFunc = NO_FUNCTION -}, { +}, {//The rest of the file was added by tomaspre .Command = DFCOMMAND_SETUP_GALLAGHER, .ExecFunc = NO_FUNCTION, .ExecParamFunc = NO_FUNCTION, diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagher.c b/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagher.c index cd4fd108..6a41366b 100644 --- a/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagher.c +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagher.c @@ -1,6 +1,23 @@ -// -// Created by Tom on 27.10.2022. -// +/* +This file from this firmware source +is free software written by Tomas Preucil (github.com/tomaspre): +You can redistribute it and/or modify +it under the terms of this license. + +This software is intended for demonstration and testing purposes on your own hardware only. +When setting up a Gallagher system, always use a non-default site key! + +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. + +This notice must be retained at the top of all source files where indicated. +*/ + +/* + * DESFireGallagher.c + * Tomas Preucil (github.com/tomaspre) + */ #include #include "DESFireGallagher.h" @@ -28,16 +45,16 @@ uint8_t GallagherSiteKey[16] = { }; //Warning - running this function resets the AUTH state! -bool CreateGallagher(uint32_t cardId, uint16_t facilityId, uint8_t issueLevel, uint8_t regionCode) { +bool CreateGallagherCard(uint32_t cardId, uint16_t facilityId, uint8_t issueLevel, uint8_t regionCode) { //TODO: Find a suitable AID DESFireAidType AID = {0xF4, 0x81, 0x20}; - return CreateGallagherAppWithAID(cardId, facilityId, issueLevel, regionCode, AID); + return CreateGallagherCardWithAID(cardId, facilityId, issueLevel, regionCode, AID); } //Warning - running this function resets the AUTH state! -bool CreateGallagherWithAID(uint32_t cardId, uint16_t facilityId, uint8_t issueLevel, uint8_t regionCode, DESFireAidType AID) { +bool CreateGallagherCardWithAID(uint32_t cardId, uint16_t facilityId, uint8_t issueLevel, uint8_t regionCode, DESFireAidType AID) { DEBUG_PRINT_P(PSTR("Creating Gallagher App")); DEBUG_PRINT_P(PSTR("CardId:(%u)"), cardId); DEBUG_PRINT_P(PSTR("F:(%u)IL:(%u)RC:(%u)"), facilityId, issueLevel, regionCode); diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagher.h b/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagher.h index d8976918..df044b76 100644 --- a/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagher.h +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagher.h @@ -1,6 +1,23 @@ -// -// Created by Tom on 27.10.2022. -// +/* +This file from this firmware source +is free software written by Tomas Preucil (github.com/tomaspre): +You can redistribute it and/or modify +it under the terms of this license. + +This software is intended for demonstration and testing purposes on your own hardware only. +When setting up a Gallagher system, always use a non-default site key! + +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. + +This notice must be retained at the top of all source files where indicated. +*/ + +/* + * DESFireGallagher.h + * Tomas Preucil (github.com/tomaspre) + */ #ifndef CHAMELEON_MINI_DESFIREGALLAGHER_H #define CHAMELEON_MINI_DESFIREGALLAGHER_H @@ -12,10 +29,10 @@ #include "DESFireStatusCodes.h" //Warning - running this function resets the AUTH state! -bool CreateGallagher(uint32_t cardId, uint16_t facilityId, uint8_t issueLevel, uint8_t regionCode); +bool CreateGallagherCard(uint32_t cardId, uint16_t facilityId, uint8_t issueLevel, uint8_t regionCode); //Warning - running this function resets the AUTH state! -bool CreateGallagherWithAID(uint32_t cardId, uint16_t facilityId, uint8_t issueLevel, uint8_t regionCode, uint8_t* AID); +bool CreateGallagherCardWithAID(uint32_t cardId, uint16_t facilityId, uint8_t issueLevel, uint8_t regionCode, uint8_t* AID); bool CreateGallagherAppWithAID(uint32_t cardId, uint16_t facilityId, uint8_t issueLevel, uint8_t regionCode, DESFireAidType AID); bool UpdateGallagherFile(uint32_t cardId, uint16_t facilityId, uint8_t issueLevel, uint8_t regionCode, DESFireAidType AID); diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagherTools.c b/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagherTools.c index cf021860..553fe289 100644 --- a/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagherTools.c +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagherTools.c @@ -1,3 +1,6 @@ +// This file contains adapted Gallagher functions from https://github.com/RfidResearchGroup/proxmark3 +// All credit goes to this repo + //----------------------------------------------------------------------------- // Copyright (C) Proxmark3 contributors. See AUTHORS.md @ https://github.com/RfidResearchGroup/proxmark3 for details. // @@ -13,8 +16,6 @@ // // See LICENSE.txt @ https://github.com/RfidResearchGroup/proxmark3 for the text of the license. -//This file contains adapted Gallagher functions from https://github.com/RfidResearchGroup/proxmark3 All credit goes to this repo - #include #include "DESFireGallagherTools.h" #include "DESFireLogging.h" diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagherTools.h b/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagherTools.h index 0aa7908b..a9e019a1 100644 --- a/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagherTools.h +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagherTools.h @@ -1,6 +1,20 @@ +// This file contains adapted Gallagher functions from https://github.com/RfidResearchGroup/proxmark3 +// All credit goes to this repo + +//----------------------------------------------------------------------------- +// Copyright (C) Proxmark3 contributors. See AUTHORS.md @ https://github.com/RfidResearchGroup/proxmark3 for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. // -// Created by Tom on 13.11.2022. +// 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. See the +// GNU General Public License for more details. // +// See LICENSE.txt @ https://github.com/RfidResearchGroup/proxmark3 for the text of the license. #ifndef CHAMELEON_MINI_DESFIREGALLAGHERTOOLS_H #define CHAMELEON_MINI_DESFIREGALLAGHERTOOLS_H From cd58def6ff2f8bb6a4cdc8317c239709fb4bbd83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20P=C5=99eu=C4=8Dil?= Date: Mon, 21 Nov 2022 11:50:53 +0000 Subject: [PATCH 09/12] Create DESFireGallagherReadme.md --- Doc/DESFireGallagherReadme.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 Doc/DESFireGallagherReadme.md diff --git a/Doc/DESFireGallagherReadme.md b/Doc/DESFireGallagherReadme.md new file mode 100644 index 00000000..387d6635 --- /dev/null +++ b/Doc/DESFireGallagherReadme.md @@ -0,0 +1,30 @@ +# Emulating Gallagher on MIFARE DESFire +As of November 2022, Chameleon supports emulation of Gallagher on top of MIFARE DESFire cards. However, there are few limitations. +Namely, only the AES encryption was tested. Other encryption modes (such as 3K tripple DES) may work if written on the Chameleon using a Proxmark or another reader. +They will, however, NOT work when using the commands below. + +Mainly, there is now support for Gallagher self-programming using terminal commands. The supported actions are the following: +* Create a new DESFire card with a Gallagher application +* Select a Gallagher application to perform tasks over +* Create a Gallagher application +* Update a Gallagher application +* Update the card ID of a Gallagher application + +However, these things are missing: +* Create a standalone Gallagher application directory app (however, it can be created as a part of creating the whole card) +* Changing the site key (the default site key is used) + +For performing all the following commands, you first need to select the current slot to appear as a DESFire card. Eg ``CONFIG=MF_DESFIRE_4KEV1``. + +## Create a new DESFire card with a Gallagher application (DF_SETUP_GALL) + +## Select a Gallagher application to perform tasks over (DF_SEL_GALLAPP) + +## Create a Gallagher application (DF_CRE_GALLAPP) + +## Update a Gallagher application (DF_UP_GALLAPP) + +## Update the card ID of a Gallagher application (DF_UP_GALL_CID) + +## Change the site key (DF_SET_GALLKEY) +This command will return OK WITH TEXT - NOT IMPLEMENTED From 48b3a001add04dfd2900485d41ac4a3732190662 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20P=C5=99eu=C4=8Dil?= Date: Mon, 21 Nov 2022 12:44:36 +0000 Subject: [PATCH 10/12] Update DESFireGallagherReadme.md --- Doc/DESFireGallagherReadme.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/Doc/DESFireGallagherReadme.md b/Doc/DESFireGallagherReadme.md index 387d6635..41949f01 100644 --- a/Doc/DESFireGallagherReadme.md +++ b/Doc/DESFireGallagherReadme.md @@ -17,14 +17,38 @@ However, these things are missing: For performing all the following commands, you first need to select the current slot to appear as a DESFire card. Eg ``CONFIG=MF_DESFIRE_4KEV1``. ## Create a new DESFire card with a Gallagher application (DF_SETUP_GALL) +This command sets up a new Gallagher encoded DESFire card with a single application. This is usually enough to emulate a personal access card. +If you just need a card copy, this is the only Gallagher command you need. If you need to change the UID of the Chameleon, remember to do it before running this command. + +The syntax is: ``DF_SETUP_GALL=CFIR`` eg ``DF_SETUP_GALL=C123456F1234I1R2``. + +Card ID is a 32bit unsigned integer, facility ID is a 16bit unsigned integer and issue level as well as region code are 8bit unsigned integers. ## Select a Gallagher application to perform tasks over (DF_SEL_GALLAPP) +Selects the AID of the Gallagher app to perform operations over. This is needed for ``DF_CRE_GALLAPP``, ``DF_UP_GALLAPP``, and ``DF_UP_GALL_CID``. You do not need to run this command if you ran ``DF_SETUP_GALL`` previously as the default value is the last app an operation was executed over. + +The syntax is: ``DF_SEL_GALLAPP=`` eg ``DF_SEL_GALLAPP=`` or ``DF_SEL_GALLAPP=<000100>``. + +The AID has three bytes and all six hexadecimal digits need to be present when running this command. ## Create a Gallagher application (DF_CRE_GALLAPP) +Run ``DF_SEL_GALLAPP`` or ``DF_SETUP_GALL`` first! + +This command sets up the Gallagher application only. It does not set up or update the application directory app. The syntax is the same as with ``DF_SETUP_GAL``. If you want to update data in an already existiing application, use ``DF_UP_GALLAPP``. + +Warning! You need to set up the Gallagher application directory app yoursef. However, the DESFire card application directory will be updated for you. ## Update a Gallagher application (DF_UP_GALLAPP) +Run ``DF_SEL_GALLAPP`` or ``DF_SETUP_GALL`` first! + +This command lets you update the contents of a Gallagher application. The syntax is the same as with ``DF_SETUP_GAL``. If you want to create a new application, use ``DF_CRE_GALLAPP``. ## Update the card ID of a Gallagher application (DF_UP_GALL_CID) +Run ``DF_SEL_GALLAPP`` or ``DF_SETUP_GALL`` first! + +This command lets you update the Gallagher card ID of a already existing Gallagher app. The facility ID, region and issue level are taken from the last operation. The AID is either taken from the last app create operation or from ``DF_SEL_GALLAPP``. + +The syntax is ``DF_UP_GALL_CIDP=``. Eg. ``DF_UP_GALL_CIDP=123456``. The card ID is a 32bit unsigned integer. ## Change the site key (DF_SET_GALLKEY) This command will return OK WITH TEXT - NOT IMPLEMENTED From 0e036a6306b2dda95e43e5d237872fa4f85cfea8 Mon Sep 17 00:00:00 2001 From: Tomaspre Date: Mon, 21 Nov 2022 13:02:19 +0000 Subject: [PATCH 11/12] Remove some log messages --- .../DESFire/DESFireChameleonTerminal.c | 4 ---- .../Application/DESFire/DESFireGallagher.c | 24 ------------------- .../DESFire/DESFireGallagherTools.c | 8 ------- 3 files changed, 36 deletions(-) diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireChameleonTerminal.c b/Firmware/Chameleon-Mini/Application/DESFire/DESFireChameleonTerminal.c index 7b347505..ee021810 100644 --- a/Firmware/Chameleon-Mini/Application/DESFire/DESFireChameleonTerminal.c +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireChameleonTerminal.c @@ -235,10 +235,6 @@ CommandStatusIdType CommandDESFireSetEncryptionMode(char *OutParam, const char * //The rest of the file was added by tomaspre CommandStatusIdType CommandDESFireSetupGallagher(char *OutMessage, const char *InParams) { - DEBUG_PRINT_P(PSTR("Running DF_SETGALL")); - //for (uint8_t i = 0; i < 15; ++i) - // OutMessage[i] = InParams[i]; - if (!IsDESFireConfiguration()) { return COMMAND_ERR_INVALID_USAGE_ID; } diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagher.c b/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagher.c index 6a41366b..33e0134f 100644 --- a/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagher.c +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagher.c @@ -55,25 +55,16 @@ bool CreateGallagherCard(uint32_t cardId, uint16_t facilityId, uint8_t issueLeve //Warning - running this function resets the AUTH state! bool CreateGallagherCardWithAID(uint32_t cardId, uint16_t facilityId, uint8_t issueLevel, uint8_t regionCode, DESFireAidType AID) { - DEBUG_PRINT_P(PSTR("Creating Gallagher App")); - DEBUG_PRINT_P(PSTR("CardId:(%u)"), cardId); - DEBUG_PRINT_P(PSTR("F:(%u)IL:(%u)RC:(%u)"), facilityId, issueLevel, regionCode); - DEBUG_PRINT_P(PSTR("AID: %02x %02x %02x"), AID[0], AID[1], AID[2]); - uint8_t Status = 0; ConfigurationUidType UID_GALL; GetPiccUid(UID_GALL); InvalidateAuthState(false); - DEBUG_PRINT_P(PSTR("UID: %02x %02x %02x %02x %02x %02x %02x"), UID_GALL[0], UID_GALL[1], UID_GALL[2], UID_GALL[3], - UID_GALL[4], UID_GALL[5], UID_GALL[6], UID_GALL[7]); - DEBUG_PRINT_P(PSTR("Resetting auth state")); //TODO: Is this needed? Authenticated = true; AuthenticatedWithKey = 0; AuthenticatedWithPICCMasterKey = true; - DEBUG_PRINT_P(PSTR("Creating CAD app")); //Create card app directory app DESFireAidType CADAid; CADAid[0] = 0xF4; @@ -88,17 +79,13 @@ bool CreateGallagherCardWithAID(uint32_t cardId, uint16_t facilityId, uint8_t is return false; } - DEBUG_PRINT_P(PSTR("Diversifying CAD key")); //Difersify key for app directory app uint8_t CADKeyZero[CRYPTO_AES_KEY_SIZE]; hfgal_diversify_key(GallagherSiteKey, UID_GALL, 7, 0, CADAid, CADKeyZero); - DEBUG_PRINT_P(PSTR("Key:")); - DesfireLogEntry(LOG_APP_AUTH_KEY, (void *) CADKeyZero, 16); //Select the app direcory app SelectApp(CADAid); - DEBUG_PRINT_P(PSTR("Vhanging CAD app key")); //Channge key uint8_t nextKeyVersion = ReadKeyVersion(SelectedApp.Slot, 0) + 1; WriteAppKey(SelectedApp.Slot, 0, CADKeyZero, CRYPTO_AES_KEY_SIZE); @@ -108,7 +95,6 @@ bool CreateGallagherCardWithAID(uint32_t cardId, uint16_t facilityId, uint8_t is //Select the app direcory app SelectApp(CADAid); - DEBUG_PRINT_P(PSTR("Creating file in CAD app")); //Create file in CAD Status = CreateStandardFile(0x00, 0x00, 0xE000, CAD_BLOCK_LEN); @@ -127,7 +113,6 @@ bool CreateGallagherCardWithAID(uint32_t cardId, uint16_t facilityId, uint8_t is CADBlock[5] = AID[0]; memset(CADBlock+6, 0, CAD_BLOCK_LEN-6); - DEBUG_PRINT_P(PSTR("Updating file in CAD app")); //Update file in CAD uint8_t fileIndex = LookupFileNumberIndex(SelectedApp.Slot, 0); uint8_t fileType = ReadFileType(SelectedApp.Slot, fileIndex); @@ -161,7 +146,6 @@ void ResetGallagherSiteKey() { } bool CreateGallagherAppWithAID(uint32_t cardId, uint16_t facilityId, uint8_t issueLevel, uint8_t regionCode, DESFireAidType AID) { - DEBUG_PRINT_P(PSTR("Creating Gallagher app")); //Create Gall app uint8_t KeyCount = 3; uint8_t KeySettings = 0x0B; @@ -172,31 +156,24 @@ bool CreateGallagherAppWithAID(uint32_t cardId, uint16_t facilityId, uint8_t iss SelectApp(AID); - DEBUG_PRINT_P(PSTR("Diversifying key 2")); //Diversify and change key 2 uint8_t GallAppKeyTwo[CRYPTO_AES_KEY_SIZE]; hfgal_diversify_key(GallagherSiteKey, UID_GALL, 7, 2, AID, GallAppKeyTwo); - DEBUG_PRINT_P(PSTR("Key:")); - DesfireLogEntry(LOG_APP_AUTH_KEY, (void *) GallAppKeyTwo, 16); uint8_t nextKeyVersion = ReadKeyVersion(SelectedApp.Slot, 2) + 1; WriteAppKey(SelectedApp.Slot, 2, GallAppKeyTwo, CRYPTO_AES_KEY_SIZE); WriteKeyVersion(SelectedApp.Slot, 0, nextKeyVersion); WriteKeyCryptoType(SelectedApp.Slot, 0, CRYPTO_TYPE_AES128); - DEBUG_PRINT_P(PSTR("Diversifying key 0")); //Diversify and change key 0 uint8_t GallAppKeyZero[CRYPTO_AES_KEY_SIZE]; hfgal_diversify_key(GallagherSiteKey, UID_GALL, 7, 0, AID, GallAppKeyZero); - DEBUG_PRINT_P(PSTR("Key:")); - DesfireLogEntry(LOG_APP_AUTH_KEY, (void *) GallAppKeyZero, 16); nextKeyVersion = ReadKeyVersion(SelectedApp.Slot, 0) + 1; WriteAppKey(SelectedApp.Slot, 0, GallAppKeyZero, CRYPTO_AES_KEY_SIZE); WriteKeyVersion(SelectedApp.Slot, 0, nextKeyVersion); WriteKeyCryptoType(SelectedApp.Slot, 0, CRYPTO_TYPE_AES128); - DEBUG_PRINT_P(PSTR("Creating file in Gall app")); //Create file Status = CreateStandardFile(0x00, 0x03, 0x2000, GALL_BLOCK_LEN); @@ -223,7 +200,6 @@ bool UpdateGallagherFile(uint32_t cardId, uint16_t facilityId, uint8_t issueLeve GallBlock[i + 8] = GallBlock[i] ^ 0xFF; } - DEBUG_PRINT_P(PSTR("Updating file in Gall app")); //Update file with Gall access data uint8_t fileIndex = LookupFileNumberIndex(SelectedApp.Slot, 0); uint8_t fileType = ReadFileType(SelectedApp.Slot, fileIndex); diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagherTools.c b/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagherTools.c index 553fe289..e6ad9566 100644 --- a/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagherTools.c +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagherTools.c @@ -133,14 +133,6 @@ bool hfgal_diversify_key(uint8_t *site_key, uint8_t *uid, uint8_t uid_len, return false; } - DesfireLogEntry(LOG_APP_NONCE_B, (void *) uid, 7); - DesfireLogEntry(LOG_APP_NONCE_B, (void *) &uid_len, 1); - DesfireLogEntry(LOG_APP_NONCE_B, (void *) &key_num, 1); - DesfireLogEntry(LOG_APP_NONCE_B, (void *) &aid, 4); - - DEBUG_PRINT_P(PSTR("KDF input:")); - DesfireLogEntry(LOG_APP_NONCE_B, (void *) key_output, kdf_input_len); - uint8_t key[CRYPTO_AES_KEY_SIZE]; if (site_key == NULL) { return false; From 727a363c343a63164fbe82782a15be60ce5c057a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20P=C5=99eu=C4=8Dil?= Date: Tue, 22 Nov 2022 15:47:06 +0000 Subject: [PATCH 12/12] Fix key number error when diversifying --- .../Chameleon-Mini/Application/DESFire/DESFireGallagher.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagher.c b/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagher.c index 33e0134f..16af7313 100644 --- a/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagher.c +++ b/Firmware/Chameleon-Mini/Application/DESFire/DESFireGallagher.c @@ -162,8 +162,8 @@ bool CreateGallagherAppWithAID(uint32_t cardId, uint16_t facilityId, uint8_t iss uint8_t nextKeyVersion = ReadKeyVersion(SelectedApp.Slot, 2) + 1; WriteAppKey(SelectedApp.Slot, 2, GallAppKeyTwo, CRYPTO_AES_KEY_SIZE); - WriteKeyVersion(SelectedApp.Slot, 0, nextKeyVersion); - WriteKeyCryptoType(SelectedApp.Slot, 0, CRYPTO_TYPE_AES128); + WriteKeyVersion(SelectedApp.Slot, 2, nextKeyVersion); + WriteKeyCryptoType(SelectedApp.Slot, 2, CRYPTO_TYPE_AES128); //Diversify and change key 0 uint8_t GallAppKeyZero[CRYPTO_AES_KEY_SIZE];