diff --git a/client/src/cmdhfgallagher.c b/client/src/cmdhfgallagher.c index 4a7c23f29..055a310f6 100644 --- a/client/src/cmdhfgallagher.c +++ b/client/src/cmdhfgallagher.c @@ -39,9 +39,9 @@ static int CmdHelp(const char *cmd); // Application ID for the Gallagher Card Application Directory -static const uint32_t DESFIRE_CAD_AID = 0x2F81F4; -static const uint32_t CLASSIC_CAD_AID = 0x4811; -static const uint16_t CLASSIC_CRED_AID = 0x4812; +#define DESFIRE_CAD_AID 0x2F81F4 +#define CLASSIC_CAD_AID 0x4811 +#define CLASSIC_CRED_AID 0x4812 // Default MIFARE site key (16 bytes) static const uint8_t DEFAULT_SITE_KEY[] = { @@ -887,14 +887,14 @@ static int hfgal_read_desfire_card(uint32_t aid, uint8_t *site_key, bool verbose // Gallagher MIFARE Classic fixed keys -static const uint8_t GALLAGHER_MFC_KEY_A[MIFARE_KEY_SIZE] = {0x16, 0x0A, 0x91, 0xD2, 0x9A, 0x9C}; -static const uint8_t GALLAGHER_MFC_KEY_B[MIFARE_KEY_SIZE] = {0xB7, 0xBF, 0x0C, 0x13, 0x06, 0x6E}; +static const uint8_t GALLAGHER_MFC_KEY_A[] = {0x16, 0x0A, 0x91, 0xD2, 0x9A, 0x9C}; +static const uint8_t GALLAGHER_MFC_KEY_B[] = {0xB7, 0xBF, 0x0C, 0x13, 0x06, 0x6E}; // Gallagher MIFARE Classic access bits: 0x787788 -static const uint8_t GALLAGHER_ACCESS_BITS[3] = {0x78, 0x77, 0x88}; +static const uint8_t GALLAGHER_ACCESS_BITS[] = {0x78, 0x77, 0x88}; // "www.cardax.com " string for block 1 -static const uint8_t CARDAX_STRING[MFBLOCK_SIZE] = { +static const uint8_t CARDAX_STRING[] = { 0x77, 0x77, 0x77, 0x2E, 0x63, 0x61, 0x72, 0x64, 0x61, 0x78, 0x2E, 0x63, 0x6F, 0x6D, 0x20, 0x20 }; @@ -1180,8 +1180,10 @@ static int hfgal_read_classic_card(uint8_t *site_key, bool verbose, bool quiet) SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT, 0, 0, NULL, 0); PacketResponseNG resp; if (WaitForResponseTimeout(CMD_ACK, &resp, 2500) == false) { - PrintAndLogEx(DEBUG, "iso14443a card select timeout"); - return 0; + if (!quiet) { + PrintAndLogEx(DEBUG, "iso14443a card select timeout"); + } + return PM3_ETIMEOUT; } iso14a_card_select_t card; @@ -1196,23 +1198,17 @@ static int hfgal_read_classic_card(uint8_t *site_key, bool verbose, bool quiet) uint64_t select_status = resp.oldarg[0]; if (select_status == 0) { - PrintAndLogEx(DEBUG, "iso14443a card select failed"); + if (!quiet) { + PrintAndLogEx(DEBUG, "iso14443a card select failed"); + } return select_status; } - // card.uid, card.uidlen - - // Read MAD - - // Read CAD - - // Check credential count - - // Read credentials + // Brute Force reading all blocks and printing credentials, for (uint8_t i = 0; i < MIFARE_1K_MAXSECTOR; i++) { hfgal_read_site_specific_sector(i, creds, card.uid, site_key, true); } - return PM3_ENOTIMPL; + return PM3_SUCCESS; } static int CmdGallagherReader(const char *cmd) { diff --git a/client/src/mifare/gallaghercore.c b/client/src/mifare/gallaghercore.c index f033d02a7..7f97525be 100644 --- a/client/src/mifare/gallaghercore.c +++ b/client/src/mifare/gallaghercore.c @@ -74,7 +74,7 @@ static void descramble(uint8_t *arr, uint8_t len) { int gallagher_diversify_classic_key(uint8_t *site_key, uint8_t *csn, size_t csn_len, uint8_t *key_output) { memcpy(key_output, site_key, 16); for (int i = 0; i < csn_len; i++) { - key_output[i] = site_key[i] ^ csn[i]; + key_output[i] ^= csn[i]; } return PM3_SUCCESS; } @@ -90,7 +90,7 @@ int gallagher_construct_credential(GallagherCredentials_t *creds, uint8_t region return PM3_SUCCESS; } -int gallagher_read_cad(uint8_t *cad, uint8_t region, uint16_t facility) { +int gallagher_parse_cad(uint8_t *cad, uint8_t region, uint16_t facility) { // CAD entries are 3.5 bytes each (28 bits: 4-bit RC, 16-bit FC, 8-bit sector). // Packed in pairs of 7 bytes starting at byte 4, up to 6 pairs (12 entries). for (int pair = 0; pair < 6; pair++) { @@ -155,6 +155,12 @@ void gallagher_encode_creds(uint8_t *eight_bytes, GallagherCredentials_t *creds) } int gallagher_encode_mes(uint8_t *sixteen_bytes, GallagherCredentials_t *creds) { + + if (creds->csn_len > 4) { + PrintAndLogEx(ERR, "Credential could not be encoded into a Mifare Enhanced Encryption block. only 4 byte UUID's are supported"); + return PM3_ENOTIMPL; + } + // unknown parameters from the research these might be for UUID's longer than 4 bytes? uint8_t UB = 0x00; uint8_t UC = 0x00; @@ -167,11 +173,6 @@ int gallagher_encode_mes(uint8_t *sixteen_bytes, GallagherCredentials_t *creds) uint8_t mes[16]; uint8_t diversified_site_key[16]; - if (creds->csn_len > 4) { - PrintAndLogEx(ERR, "Credential could not be encoded into a Mifare Enhanced Encryption block. only 4 byte UUID's are supported"); - return PM3_ENOTIMPL; - } - mes[0] = 0x01; mes[1] = (creds->card_number & 0xFF0000) >> 16; mes[2] = (creds->card_number & 0x00FF00) >> 8; @@ -195,8 +196,13 @@ int gallagher_encode_mes(uint8_t *sixteen_bytes, GallagherCredentials_t *creds) mbedtls_aes_context actx; mbedtls_aes_init(&actx); - if (mbedtls_aes_setkey_enc(&actx, diversified_site_key, 128) != 0) return PM3_ENOKEY; - if (mbedtls_aes_crypt_ecb(&actx, MBEDTLS_AES_ENCRYPT, mes, sixteen_bytes) != 0) return PM3_ENOKEY;; + if (mbedtls_aes_setkey_enc(&actx, diversified_site_key, 128) != 0) { + return PM3_ENOKEY; + } + + if (mbedtls_aes_crypt_ecb(&actx, MBEDTLS_AES_ENCRYPT, mes, sixteen_bytes) != 0) { + return PM3_ENOKEY; + } mbedtls_aes_free(&actx); PrintAndLogEx(DEBUG, "MES after encryption %s", sprint_hex_ascii(sixteen_bytes, 16)); @@ -223,8 +229,12 @@ int gallagher_decode_mes(uint8_t *block, GallagherCredentials_t *creds) { // AES decrypt 16 bytes mbedtls_aes_context actx; mbedtls_aes_init(&actx); - if (mbedtls_aes_setkey_dec(&actx, diversified_site_key, 128) != 0) return PM3_ENOKEY; - if (mbedtls_aes_crypt_ecb(&actx, MBEDTLS_AES_DECRYPT, block, mes) != 0) return PM3_ENOKEY;; + if (mbedtls_aes_setkey_dec(&actx, diversified_site_key, 128) != 0) { + return PM3_ENOKEY; + } + if (mbedtls_aes_crypt_ecb(&actx, MBEDTLS_AES_DECRYPT, block, mes) != 0) { + return PM3_ENOKEY; + } mbedtls_aes_free(&actx); PrintAndLogEx(DEBUG, "MES after decryption %s", sprint_hex_ascii(mes, 16)); diff --git a/client/src/mifare/gallaghercore.h b/client/src/mifare/gallaghercore.h index ef3e6d077..5f6d8fccc 100644 --- a/client/src/mifare/gallaghercore.h +++ b/client/src/mifare/gallaghercore.h @@ -33,7 +33,7 @@ typedef struct { int gallagher_diversify_classic_key(uint8_t *site_key, uint8_t *csn, size_t csn_len, uint8_t *key_output); -int gallagher_read_cad(uint8_t *cad, uint8_t region, uint16_t facility); +int gallagher_parse_cad(uint8_t *cad, uint8_t region, uint16_t facility); void gallagher_encode_creds(uint8_t *eight_bytes, GallagherCredentials_t *creds); diff --git a/client/src/mifare/gallaghertest.c b/client/src/mifare/gallaghertest.c index a75531cd9..27508399b 100644 --- a/client/src/mifare/gallaghertest.c +++ b/client/src/mifare/gallaghertest.c @@ -23,21 +23,21 @@ static bool test_CAD(void) { }; // Entry 0: RC=0xC, FC=0x1337, Sector=0x0F - int result = gallagher_read_cad(cad, 0xC, 0x1337); + int result = gallagher_parse_cad(cad, 0xC, 0x1337); if (result != 0x0F) { PrintAndLogEx(INFO, "Gallagher CAD test 1 failed: expected sector 0x0F, got 0x%02X", result); return false; } // Entry 1: RC=0xD, FC=0x1338, Sector=0x0D - result = gallagher_read_cad(cad, 0xD, 0x1338); + result = gallagher_parse_cad(cad, 0xD, 0x1338); if (result != 0x0D) { PrintAndLogEx(INFO, "Gallagher CAD test 2 failed: expected sector 0x0D, got 0x%02X", result); return false; } // Non-existent entry should return -1 - result = gallagher_read_cad(cad, 0xA, 0x1234); + result = gallagher_parse_cad(cad, 0xA, 0x1234); if (result != -1) { PrintAndLogEx(INFO, "Gallagher CAD test 3 failed: expected -1, got %d", result); return false;