Feedback from Iceman.

Now respecting quiet flag for continuous reads.
Return Correct PM3 _* return codes.
This commit is contained in:
pingu2211
2026-03-11 09:38:13 +11:00
parent 68ff5c3b28
commit 7d7903deed
4 changed files with 41 additions and 35 deletions
+16 -20
View File
@@ -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) {
+21 -11
View File
@@ -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));
+1 -1
View File
@@ -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);
+3 -3
View File
@@ -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;