Merge pull request #1557 from DarkMatterMatt/feat/hf-gallagher-remove-aid-limits

Improve `hf gallagher` commands
This commit is contained in:
Iceman 2022-01-17 19:58:12 +01:00 committed by GitHub
commit 795e604ddb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 260 additions and 182 deletions

View file

@ -4,10 +4,12 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
## [unreleased][unreleased] ## [unreleased][unreleased]
- Add `nfc decode` - now NDEF vCard messages with a PHOTO in base64 format is shown (@iceman1001) - Add `nfc decode` - now NDEF vCard messages with a PHOTO in base64 format is shown (@iceman1001)
- Remove AID limitations when using Gallagher key diversification (@DarkMatterMatt)
## [Frostbit.4.14831] [2022-01-11] ## [Frostbit.4.14831] [2022-01-11]
- Changed Wiegand format lookup - now case-insensitive (@iceman1001) - Changed Wiegand format lookup - now case-insensitive (@iceman1001)
- Added new standalone mode `hf_15SNIFF` - Same as `hf_14ASNIFF` standalone mode for RDV4 - flashmem (@startrk1995) - Added new standalone mode `hf_15SNIFF` - Same as `hf_14ASNIFF` standalone mode for RDV4 - flashmem (@startrk1995)
- Added `hf gallagher` commands for read/writing DESFire cards (@DarkMatterMatt)
- Added support for MIFARE DESFire application creation without authentication (@joswr1ght) - Added support for MIFARE DESFire application creation without authentication (@joswr1ght)
- Changed drastically Hitag S ARM code to remove state machines and ease way to build new commands (@doegox) - Changed drastically Hitag S ARM code to remove state machines and ease way to build new commands (@doegox)
- Fixed Hitag S crypto mode with key or NrAr, fixed `lf hitag cc`, fixed pwd dump in hitagS dump with LKP (@doegox) - Fixed Hitag S crypto mode with key or NrAr, fixed `lf hitag cc`, fixed pwd dump in hitagS dump with LKP (@doegox)

View file

@ -49,7 +49,7 @@ static const uint8_t DEFAULT_SITE_KEY[] = {
* @param uid Card unique ID (4 or 7 bytes). * @param uid Card unique ID (4 or 7 bytes).
* @param uid_len Length of UID. * @param uid_len Length of UID.
* @param key_num Key number (0 <= key_num <= 2). * @param key_num Key number (0 <= key_num <= 2).
* @param aid Application ID (0x2?81F4 where 0 <= ? <= 0xB). * @param aid Application ID (3 bytes, e.g. 0x2081F4).
* @param key_output Buffer to copy the diversified key into (must be 16 bytes). * @param key_output Buffer to copy the diversified key into (must be 16 bytes).
* @return PM3_SUCCESS if successful, PM3_EINVARG if an argument is invalid. * @return PM3_SUCCESS if successful, PM3_EINVARG if an argument is invalid.
*/ */
@ -134,8 +134,9 @@ static int select_aid(DesfireContext_t *ctx, uint32_t aid, bool verbose) {
return 202; return 202;
} }
if (verbose) if (verbose) {
PrintAndLogEx(INFO, "Selected AID %06X", aid); PrintAndLogEx(INFO, "Selected AID %06X", aid);
}
return PM3_SUCCESS; return PM3_SUCCESS;
} }
@ -173,7 +174,7 @@ static int authenticate(DesfireContext_t *ctx, bool verbose) {
* @brief Select application ID & authenticate. * @brief Select application ID & authenticate.
* Uses existing authentication keys in context. * Uses existing authentication keys in context.
*/ */
static int select_aid_and_authenticate(DesfireContext_t *ctx, uint32_t aid, bool verbose) { static int select_aid_and_auth(DesfireContext_t *ctx, uint32_t aid, bool verbose) {
int res = select_aid(ctx, aid, verbose); int res = select_aid(ctx, aid, verbose);
PM3_RET_IF_ERR(res); PM3_RET_IF_ERR(res);
@ -183,6 +184,25 @@ static int select_aid_and_authenticate(DesfireContext_t *ctx, uint32_t aid, bool
return PM3_SUCCESS; return PM3_SUCCESS;
} }
/**
* @brief Select application ID & authenticate with specified AES key.
*/
static int select_aid_and_auth_with_key(DesfireContext_t *ctx, uint32_t aid, uint8_t *key,
uint8_t key_num, bool should_diversify, bool verbose) {
int res = select_aid(ctx, aid, verbose);
PM3_RET_IF_ERR(res);
// Set key & diversification algorithm.
uint8_t kdf_algo = should_diversify ? MFDES_KDF_ALGO_GALLAGHER : MFDES_KDF_ALGO_NONE;
DesfireSetKeyNoClear(ctx, key_num, T_AES, key);
DesfireSetKdf(ctx, kdf_algo, NULL, 0);
res = authenticate(ctx, verbose);
PM3_RET_IF_ERR(res);
return PM3_SUCCESS;
}
/** /**
* @brief Returns true if the specified application exists, false otherwise. * @brief Returns true if the specified application exists, false otherwise.
*/ */
@ -208,16 +228,55 @@ static bool aid_exists(DesfireContext_t *ctx, uint32_t aid, bool verbose) {
/** /**
* @brief Returns the lowest available Gallagher application ID. * @brief Returns the lowest available Gallagher application ID.
* @return 0 if no AID is available, or an AID in the range 0x2?81F4, where 0 <= ? <= 0xB. * @return The lowest available AID in the range 0x??81F4, where ?? >= 0x20.
*/ */
static uint32_t find_available_gallagher_aid(DesfireContext_t *ctx, bool verbose) { static uint32_t find_available_gallagher_aid(DesfireContext_t *ctx, bool verbose) {
for (uint8_t i = 0x0; i <= 0xB; i++) { // Select PICC
uint32_t aid = 0x2081F4 | (i << 16); select_aid(ctx, 0x000000, verbose);
if (aid_exists(ctx, aid, verbose) == false) {
// Retrieve the AID list
uint8_t aid_buf[DESFIRE_BUFFER_SIZE] = {0};
size_t aid_buf_len = 0;
int res = DesfireGetAIDList(ctx, aid_buf, &aid_buf_len);
if (res != PM3_SUCCESS) {
PM3_RET_ERR(0, "Failed retrieving AID list");
}
if (verbose) {
// Print what we got
PrintAndLogEx(INFO, "Retrieved AID list:" NOLF);
for (int i = 0; i < aid_buf_len; i += 3) {
PrintAndLogEx(NORMAL, "%s %06X" NOLF,
(i == 0) ? "" : ",",
DesfireAIDByteToUint(&aid_buf[i])
);
}
PrintAndLogEx(NORMAL, "");
}
// Find lowest available in range F48120 -> F481FE, excluding the CAD
for (uint8_t aid_increment = 0x20; aid_increment < 0xFF; aid_increment++) {
uint32_t aid = 0x0081F4 | (aid_increment << 16);
if (aid == CAD_AID) {
continue;
}
// Check if AID exists in aid_buf
bool aid_exists = false;
for (uint8_t idx = 0; idx < aid_buf_len; idx += 3) {
if (DesfireAIDByteToUint(&aid_buf[idx]) == aid) {
aid_exists = true;
break;
}
}
if (aid_exists == false) {
return aid; return aid;
} }
} }
return 0;
// Failed to find an available AID. This is very unlikely to occur as
// DESFire cards rarely have more than 1 application on them
PM3_RET_ERR(0, "Checked 200+ AIDs and all exist, abandoning search");
} }
/** /**
@ -229,9 +288,7 @@ static uint32_t find_available_gallagher_aid(DesfireContext_t *ctx, bool verbose
static int hfgal_delete_app(DesfireContext_t *ctx, uint8_t *site_key, static int hfgal_delete_app(DesfireContext_t *ctx, uint8_t *site_key,
uint32_t aid, bool verbose) { uint32_t aid, bool verbose) {
// Select application & authenticate // Select application & authenticate
DesfireSetKeyNoClear(ctx, 0, T_AES, site_key); int res = select_aid_and_auth_with_key(ctx, aid, site_key, 0, true, verbose);
DesfireSetKdf(ctx, MFDES_KDF_ALGO_GALLAGHER, NULL, 0);
int res = select_aid_and_authenticate(ctx, aid, verbose);
PM3_RET_IF_ERR(res); PM3_RET_IF_ERR(res);
// Delete application // Delete application
@ -258,9 +315,7 @@ static int hfgal_read_creds_app(DesfireContext_t *ctx, uint32_t aid, uint8_t *si
} }
// Select application & authenticate // Select application & authenticate
DesfireSetKeyNoClear(ctx, 2, T_AES, site_key); int res = select_aid_and_auth_with_key(ctx, aid, site_key, 0, true, verbose);
DesfireSetKdf(ctx, MFDES_KDF_ALGO_GALLAGHER, NULL, 0);
int res = select_aid_and_authenticate(ctx, aid, verbose);
PM3_RET_IF_ERR_WITH_MSG(res, "Failed selecting/authenticating to AID %06X", aid); PM3_RET_IF_ERR_WITH_MSG(res, "Failed selecting/authenticating to AID %06X", aid);
// Read file 0 (contains credentials) // Read file 0 (contains credentials)
@ -302,17 +357,18 @@ static int hfgal_read_creds_app(DesfireContext_t *ctx, uint32_t aid, uint8_t *si
* @brief Create a new application to store Gallagher cardholder credentials. * @brief Create a new application to store Gallagher cardholder credentials.
* *
* @param site_key MIFARE site key. * @param site_key MIFARE site key.
* @param aid New application ID. Should be 0x2?81F4, where 0 <= ? <= 0xB. * @param aid New application ID. 3 bytes, e.g. 0x2081F4.
*/ */
static int hfgal_create_creds_app(DesfireContext_t *ctx, uint8_t *site_key, uint32_t aid, bool verbose) { static int hfgal_create_creds_app(DesfireContext_t *ctx, uint8_t *site_key, uint32_t aid, bool verbose) {
// Select application & authenticate // Select application & authenticate
int res = select_aid_and_authenticate(ctx, 0x000000, verbose); int res = select_aid_and_auth(ctx, 0x000000, verbose);
PM3_RET_IF_ERR(res); PM3_RET_IF_ERR(res);
// UID is required for key diversification // UID is required for key diversification
if (ctx->uidlen == 0) if (ctx->uidlen == 0) {
PM3_RET_ERR(PM3_EINVARG, "UID is required for key diversification. " PM3_RET_ERR(PM3_EINVARG, "UID is required for key diversification. "
"Please fetch it before calling `hfgal_create_creds_app`"); "Please fetch it before calling `hfgal_create_creds_app`");
}
// Create application // Create application
DesfireCryptoAlgorithm app_algo = T_AES; DesfireCryptoAlgorithm app_algo = T_AES;
@ -381,9 +437,7 @@ static int hfgal_create_creds_app(DesfireContext_t *ctx, uint8_t *site_key, uint
static int hfgal_create_creds_file(DesfireContext_t *ctx, uint8_t *site_key, uint32_t aid, static int hfgal_create_creds_file(DesfireContext_t *ctx, uint8_t *site_key, uint32_t aid,
GallagherCredentials_t *creds, bool verbose) { GallagherCredentials_t *creds, bool verbose) {
// Select application & authenticate // Select application & authenticate
DesfireSetKeyNoClear(ctx, 0, T_AES, site_key); int res = select_aid_and_auth_with_key(ctx, aid, site_key, 0, true, verbose);
DesfireSetKdf(ctx, MFDES_KDF_ALGO_GALLAGHER, NULL, 0);
int res = select_aid_and_authenticate(ctx, aid, verbose);
PM3_RET_IF_ERR(res); PM3_RET_IF_ERR(res);
// Prepare create file command // Prepare create file command
@ -490,15 +544,18 @@ static int hfgal_read_cad(DesfireContext_t *ctx, uint8_t *dest_buf,
/** /**
* @brief Create the Gallagher Card Application Directory. * @brief Create the Gallagher Card Application Directory.
* *
* @param site_key MIFARE site key. * @param key MIFARE site key, or custom CAD key.
* @param should_diversify True if using a site_key, false if using a custom CAD key.
*/ */
static int hfgal_create_cad(DesfireContext_t *ctx, uint8_t *site_key, bool verbose) { static int hfgal_create_cad(DesfireContext_t *ctx, uint8_t *key,
bool should_diversify, bool verbose) {
// Check that card UID has been set // Check that card UID has been set
if (ctx->uidlen == 0) if (ctx->uidlen == 0) {
PM3_RET_ERR(PM3_EINVARG, "Card UID must be set in DesfireContext (required for key div)"); PM3_RET_ERR(PM3_EINVARG, "Card UID must be set in DesfireContext (required for key div)");
}
// Select application & authenticate // Select application & authenticate
int res = select_aid_and_authenticate(ctx, 0x000000, verbose); int res = select_aid_and_auth(ctx, 0x000000, verbose);
PM3_RET_IF_ERR(res); PM3_RET_IF_ERR(res);
// Create application // Create application
@ -524,28 +581,35 @@ static int hfgal_create_cad(DesfireContext_t *ctx, uint8_t *site_key, bool verbo
// Select application & authenticate // Select application & authenticate
uint8_t blank_key[DESFIRE_MAX_KEY_SIZE] = {0}; uint8_t blank_key[DESFIRE_MAX_KEY_SIZE] = {0};
DesfireSetKeyNoClear(ctx, 0, T_AES, blank_key); res = select_aid_and_auth_with_key(ctx, CAD_AID, blank_key, 0, false, verbose);
DesfireSetKdf(ctx, MFDES_KDF_ALGO_NONE, NULL, 0);
res = select_aid_and_authenticate(ctx, CAD_AID, verbose);
PM3_RET_IF_ERR(res); PM3_RET_IF_ERR(res);
// Diversify key
uint8_t buf[CRYPTO_AES128_KEY_SIZE] = {0}; uint8_t buf[CRYPTO_AES128_KEY_SIZE] = {0};
res = hfgal_diversify_key(site_key, ctx->uid, ctx->uidlen, 0, CAD_AID, buf); if (should_diversify) {
// Diversify key
res = hfgal_diversify_key(key, ctx->uid, ctx->uidlen, 0, CAD_AID, buf);
PM3_RET_IF_ERR_WITH_MSG(res, "Failed diversifying key 0 for AID %06X", CAD_AID); PM3_RET_IF_ERR_WITH_MSG(res, "Failed diversifying key 0 for AID %06X", CAD_AID);
PrintAndLogEx(INFO, "Diversified key " _YELLOW_("0") " for CAD (AID " _YELLOW_("%06X") "): " _GREEN_("%s"), PrintAndLogEx(INFO, "Diversified key " _YELLOW_("0") " for CAD (AID " _YELLOW_("%06X") "): " _GREEN_("%s"),
CAD_AID, CAD_AID,
sprint_hex_inrow(buf, ARRAYLEN(buf)) sprint_hex_inrow(buf, ARRAYLEN(buf))
); );
key = buf;
} else if (verbose) {
PrintAndLogEx(INFO, "Using provided key " _YELLOW_("0") " for CAD (AID " _YELLOW_("%06X") "): " _GREEN_("%s"),
CAD_AID,
sprint_hex_inrow(key, CRYPTO_AES128_KEY_SIZE)
);
}
// Change key // Change key
DesfireSetCommMode(ctx, DCMEncryptedPlain); DesfireSetCommMode(ctx, DCMEncryptedPlain);
res = DesfireChangeKey(ctx, false, 0, app_algo, 1, buf, app_algo, blank_key, verbose); res = DesfireChangeKey(ctx, false, 0, app_algo, 1, buf, app_algo, blank_key, verbose);
PM3_RET_IF_ERR_WITH_MSG(res, "Failed setting key 0 for CAD"); PM3_RET_IF_ERR_WITH_MSG(res, "Failed setting key 0 for CAD");
if (verbose) if (verbose) {
PrintAndLogEx(INFO, "Successfully set key " _YELLOW_("0") " for CAD"); PrintAndLogEx(INFO, "Successfully set key " _YELLOW_("0") " for CAD");
}
PrintAndLogEx(INFO, "Successfully created Card Application Directory (AID " _YELLOW_("%06X") ")", CAD_AID); PrintAndLogEx(INFO, "Successfully created Card Application Directory (AID " _YELLOW_("%06X") ")", CAD_AID);
return PM3_SUCCESS; return PM3_SUCCESS;
@ -554,12 +618,13 @@ static int hfgal_create_cad(DesfireContext_t *ctx, uint8_t *site_key, bool verbo
/** /**
* @brief Update the Gallagher Card Application Directory with a new entry. * @brief Update the Gallagher Card Application Directory with a new entry.
* *
* @param site_key MIFARE site key. * @param key MIFARE site key, or custom CAD key.
* @param should_diversify True if using a site_key, false if using a custom CAD key.
* @param aid Application ID to add to the CAD. * @param aid Application ID to add to the CAD.
* @param creds Gallagher cardholder credentials (region_code & facility_code are required). * @param creds Gallagher cardholder credentials (region_code & facility_code are required).
*/ */
static int hfgal_add_aid_to_cad(DesfireContext_t *ctx, uint8_t *site_key, uint32_t aid, static int hfgal_add_aid_to_cad(DesfireContext_t *ctx, uint8_t *key, bool should_diversify,
GallagherCredentials_t *creds, bool verbose) { uint32_t aid, GallagherCredentials_t *creds, bool verbose) {
// Check if CAD exists // Check if CAD exists
uint8_t cad[36 * 3] = {0}; uint8_t cad[36 * 3] = {0};
uint8_t num_entries = 0; uint8_t num_entries = 0;
@ -582,7 +647,7 @@ static int hfgal_add_aid_to_cad(DesfireContext_t *ctx, uint8_t *site_key, uint32
PrintAndLogEx(INFO, "Card Application Directory does not exist, creating it now..."); PrintAndLogEx(INFO, "Card Application Directory does not exist, creating it now...");
} }
int res = hfgal_create_cad(ctx, site_key, verbose); int res = hfgal_create_cad(ctx, key, should_diversify, verbose);
PM3_RET_IF_ERR(res); PM3_RET_IF_ERR(res);
} }
@ -592,11 +657,12 @@ static int hfgal_add_aid_to_cad(DesfireContext_t *ctx, uint8_t *site_key, uint32
// Check if facility already exists in CAD. // Check if facility already exists in CAD.
for (uint8_t i = 0; i < ARRAYLEN(cad); i += 6) { for (uint8_t i = 0; i < ARRAYLEN(cad); i += 6) {
if (cad_facility_match(&cad[i], creds->region_code, creds->facility_code)) if (cad_facility_match(&cad[i], creds->region_code, creds->facility_code)) {
PM3_RET_ERR(PM3_EFATAL, "Facility already exists in CAD, delete or update AID %06X", PM3_RET_ERR(PM3_EFATAL, "Facility already exists in CAD, delete or update AID %06X",
cad_aid_byte_to_uint(&cad[i + 3]) cad_aid_byte_to_uint(&cad[i + 3])
); );
} }
}
// Create entry // Create entry
uint8_t *entry = &cad[num_entries * 6]; uint8_t *entry = &cad[num_entries * 6];
@ -614,9 +680,7 @@ static int hfgal_add_aid_to_cad(DesfireContext_t *ctx, uint8_t *site_key, uint32
} }
// Select application & authenticate // Select application & authenticate
DesfireSetKeyNoClear(ctx, 0, T_AES, site_key); int res = select_aid_and_auth_with_key(ctx, CAD_AID, key, 0, should_diversify, verbose);
DesfireSetKdf(ctx, MFDES_KDF_ALGO_GALLAGHER, NULL, 0);
int res = select_aid_and_authenticate(ctx, CAD_AID, verbose);
PM3_RET_IF_ERR(res); PM3_RET_IF_ERR(res);
// Create file if necessary // Create file if necessary
@ -642,14 +706,16 @@ static int hfgal_add_aid_to_cad(DesfireContext_t *ctx, uint8_t *site_key, uint32
res = DesfireCreateFile(ctx, file_type, data, ARRAYLEN(data), false); res = DesfireCreateFile(ctx, file_type, data, ARRAYLEN(data), false);
PM3_RET_IF_ERR_WITH_MSG(res, "Failed creating file %d in CAD (AID %06X)", file_id, CAD_AID); PM3_RET_IF_ERR_WITH_MSG(res, "Failed creating file %d in CAD (AID %06X)", file_id, CAD_AID);
if (verbose) if (verbose) {
PrintAndLogEx(INFO, "Created file " _YELLOW_("%d") " in CAD (empty contents)", file_id); PrintAndLogEx(INFO, "Created file " _YELLOW_("%d") " in CAD (empty contents)", file_id);
}
// Write file // Write file
res = DesfireWriteFile(ctx, file_id, 0, 36, &cad[file_id * 36]); res = DesfireWriteFile(ctx, file_id, 0, 36, &cad[file_id * 36]);
} else } else {
// Write file // Write file
res = DesfireWriteFile(ctx, file_id, entry_num * 6, 6, entry); res = DesfireWriteFile(ctx, file_id, entry_num * 6, 6, entry);
}
PM3_RET_IF_ERR_WITH_MSG(res, "Failed writing data to file %d in CAD AID %06X)", file_id, CAD_AID); PM3_RET_IF_ERR_WITH_MSG(res, "Failed writing data to file %d in CAD AID %06X)", file_id, CAD_AID);
PrintAndLogEx(INFO, "Successfully added new entry for " _YELLOW_("%06X") " to the Card Application Directory", aid); PrintAndLogEx(INFO, "Successfully added new entry for " _YELLOW_("%06X") " to the Card Application Directory", aid);
@ -659,15 +725,15 @@ static int hfgal_add_aid_to_cad(DesfireContext_t *ctx, uint8_t *site_key, uint32
/** /**
* @brief Remove an entry from the Gallagher Card Application Directory. * @brief Remove an entry from the Gallagher Card Application Directory.
* *
* @param site_key MIFARE site key. * @param key MIFARE site key, or custom CAD key.
* @param aid Application ID to add to the CAD. * @param should_diversify True if using a site_key, false if using a custom CAD key.
* @param aid Application ID to remove from the CAD.
*/ */
static int hfgal_remove_aid_from_cad(DesfireContext_t *ctx, uint8_t *site_key, static int hfgal_remove_aid_from_cad(DesfireContext_t *ctx, uint8_t *key,
uint32_t aid, bool verbose) { bool should_diversify, uint32_t aid, bool verbose) {
// Check if CAD exists // Read CAD
uint8_t cad[36 * 3] = {0}; uint8_t cad[36 * 3] = {0};
uint8_t num_entries = 0; uint8_t num_entries = 0;
int res = hfgal_read_cad(ctx, cad, ARRAYLEN(cad), &num_entries, verbose); int res = hfgal_read_cad(ctx, cad, ARRAYLEN(cad), &num_entries, verbose);
PM3_RET_IF_ERR(res); PM3_RET_IF_ERR(res);
@ -691,9 +757,7 @@ static int hfgal_remove_aid_from_cad(DesfireContext_t *ctx, uint8_t *site_key,
memset(&cad[ARRAYLEN(cad) - 6], 0, 6); memset(&cad[ARRAYLEN(cad) - 6], 0, 6);
// Select application & authenticate // Select application & authenticate
DesfireSetKeyNoClear(ctx, 0, T_AES, site_key); res = select_aid_and_auth_with_key(ctx, CAD_AID, key, 0, should_diversify, verbose);
DesfireSetKdf(ctx, MFDES_KDF_ALGO_GALLAGHER, NULL, 0);
res = select_aid_and_authenticate(ctx, CAD_AID, verbose);
PM3_RET_IF_ERR(res); PM3_RET_IF_ERR(res);
// Determine what files we need to update // Determine what files we need to update
@ -784,11 +848,15 @@ static int hfgal_read_card(uint32_t aid, uint8_t *site_key, bool verbose, bool q
// Read & decode credentials // Read & decode credentials
GallagherCredentials_t creds = {0}; GallagherCredentials_t creds = {0};
res = hfgal_read_creds_app(&dctx, current_aid, site_key, &creds, verbose); res = hfgal_read_creds_app(&dctx, current_aid, site_key, &creds, verbose);
if (res == HFGAL_AUTH_FAIL) {
PrintAndLogEx(WARNING, "Invalid site key for AID %06X", current_aid);
continue;
}
PM3_RET_IF_ERR_MAYBE_MSG(res, !quiet, "Failed reading card application credentials"); PM3_RET_IF_ERR_MAYBE_MSG(res, !quiet, "Failed reading card application credentials");
PrintAndLogEx(SUCCESS, "Gallagher (AID %06X) - region: " _GREEN_("%u") PrintAndLogEx(SUCCESS, "Gallagher (AID %06X) - region: " _GREEN_("%u")
", fc: " _GREEN_("%u") ", facility: " _GREEN_("%u")
", cn: " _GREEN_("%u") ", card number: " _GREEN_("%u")
", issue level: " _GREEN_("%u"), ", issue level: " _GREEN_("%u"),
current_aid, current_aid,
creds.region_code, creds.region_code,
@ -865,89 +933,93 @@ static int CmdGallagherClone(const char *cmd) {
" DES 8 bytes\n" " DES 8 bytes\n"
" 2TDEA or AES 16 bytes\n" " 2TDEA or AES 16 bytes\n"
" 3TDEA 24 bytes\n" " 3TDEA 24 bytes\n"
"AID id, default finds lowest available in range 0x2?81F4, where 0 <= ? <= 0xB.", "AID, default finds lowest available in range 0x??81F4, where ?? >= 0x20.",
"hf gallagher clone --rc 1 --fc 22 --cn 3333 --il 4 --sitekey 00112233445566778899aabbccddeeff" "hf gallagher clone --rc 1 --fc 22 --cn 3333 --il 4 --sitekey 00112233445566778899aabbccddeeff"
); );
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_int0("n", "keynum", "<dec>", "Key number [default = 0]"), arg_int0("n", "keynum", "<dec>", "PICC key number [default = 0]"),
arg_str0("t", "algo", "<DES|2TDEA|3TDEA|AES>", "Crypt algo: DES, 2TDEA, 3TDEA, AES"), arg_str0("t", "algo", "<DES|2TDEA|3TDEA|AES>", "PICC crypt algo: DES, 2TDEA, 3TDEA, AES"),
arg_str0("k", "key", "<hex>", "Key for authentication to the PICC"), arg_str0("k", "key", "<hex>", "Key for authentication to the PICC to create applications"),
arg_u64_1(NULL, "rc", "<dec>", "Region code. 4 bits max"), arg_u64_1(NULL, "rc", "<dec>", "Region code. 4 bits max"),
arg_u64_1(NULL, "fc", "<dec>", "Facility code. 2 bytes max"), arg_u64_1(NULL, "fc", "<dec>", "Facility code. 2 bytes max"),
arg_u64_1(NULL, "cn", "<dec>", "Card number. 3 bytes max"), arg_u64_1(NULL, "cn", "<dec>", "Card number. 3 bytes max"),
arg_u64_1(NULL, "il", "<dec>", "Issue level. 4 bits max"), arg_u64_1(NULL, "il", "<dec>", "Issue level. 4 bits max"),
arg_str0(NULL, "aid", "<hex>", "Application ID to write (3 bytes)"), arg_str0(NULL, "aid", "<hex>", "Application ID to write (3 bytes) [default automatically chooses]"),
arg_str0(NULL, "sitekey", "<hex>", "Site key to compute diversified keys (16 bytes)"), arg_str0(NULL, "sitekey", "<hex>", "Site key to compute diversified keys (16 bytes)"),
arg_str0(NULL, "cadkey", "<hex>", "Custom AES key 0 to modify the Card Application Directory (16 bytes)"),
arg_lit0(NULL, "nocadupdate", "Don't modify the Card Application Directory (only creates the app)"),
arg_lit0(NULL, "noappcreate", "Don't create the application (only modifies the CAD)"),
arg_lit0(NULL, "apdu", "Show APDU requests and responses"), arg_lit0(NULL, "apdu", "Show APDU requests and responses"),
arg_lit0("v", "verbose", "Verbose mode"), arg_lit0("v", "verbose", "Verbose mode"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(ctx, cmd, argtable, false); CLIExecWithReturn(ctx, cmd, argtable, false);
uint8_t arg = 1;
int key_num = arg_get_int_def(ctx, 1, 0); int picc_key_num = arg_get_int_def(ctx, arg++, 0);
int key_algo = T_DES; int picc_key_algo = T_DES;
if (CLIGetOptionList(arg_get_str(ctx, 2), DesfireAlgoOpts, &key_algo)) { if (CLIGetOptionList(arg_get_str(ctx, arg++), DesfireAlgoOpts, &picc_key_algo)) {
CLIParserFree(ctx); CLIParserFree(ctx);
return PM3_EINVARG; return PM3_EINVARG;
} }
int key_len = 0; int picc_key_len = 0;
uint8_t key[DESFIRE_MAX_KEY_SIZE] = {0}; uint8_t picc_key[DESFIRE_MAX_KEY_SIZE] = {0};
CLIGetHexWithReturn(ctx, 3, key, &key_len); CLIGetHexWithReturn(ctx, arg++, picc_key, &picc_key_len);
if (key_len && key_len != desfire_get_key_length(key_algo)) { if (picc_key_len && picc_key_len != desfire_get_key_length(picc_key_algo)) {
PM3_RET_ERR_FREE(PM3_EINVARG, "%s key must have %d bytes length instead of %d", PM3_RET_ERR_FREE(PM3_EINVARG, "%s key must have %d bytes length instead of %d",
CLIGetOptionListStr(DesfireAlgoOpts, key_algo), CLIGetOptionListStr(DesfireAlgoOpts, picc_key_algo),
desfire_get_key_length(key_algo), desfire_get_key_length(picc_key_algo),
key_len picc_key_len
); );
} }
if (key_len == 0) { if (picc_key_len == 0) {
// Default to a key of all zeros // Default to a key of all zeros
key_len = desfire_get_key_length(key_algo); picc_key_len = desfire_get_key_length(picc_key_algo);
} }
uint64_t region_code = arg_get_u64(ctx, 4); // uint4, input will be validated later uint64_t region_code = arg_get_u64(ctx, arg++); // uint4, input will be validated later
uint64_t facility_code = arg_get_u64(ctx, 5); // uint16 uint64_t facility_code = arg_get_u64(ctx, arg++); // uint16
uint64_t card_number = arg_get_u64(ctx, 6); // uint24 uint64_t card_number = arg_get_u64(ctx, arg++); // uint24
uint64_t issue_level = arg_get_u64(ctx, 7); // uint4 uint64_t issue_level = arg_get_u64(ctx, arg++); // uint4
int aid_len = 0; int aid_len = 0;
uint8_t aid_buf[3] = {0}; uint8_t aid_buf[3] = {0};
uint32_t aid = 0; CLIGetHexWithReturn(ctx, arg++, aid_buf, &aid_len);
CLIGetHexWithReturn(ctx, 8, aid_buf, &aid_len); if (aid_len > 0 && aid_len != 3) {
if (aid_len > 0) {
if (aid_len != 3) {
PM3_RET_ERR_FREE(PM3_EINVARG, "--aid must be 3 bytes"); PM3_RET_ERR_FREE(PM3_EINVARG, "--aid must be 3 bytes");
} }
reverse_aid(aid_buf); // PM3 displays AIDs backwards reverse_aid(aid_buf); // PM3 displays AIDs backwards
aid = DesfireAIDByteToUint(aid_buf); uint32_t aid = DesfireAIDByteToUint(aid_buf);
// Check that the AID is in the expected range
if ((memcmp(aid_buf, "\xF4\x81", 2) != 0) ||
(aid_buf[2] < 0x20) ||
(aid_buf[2] > 0x2B)) {
// TODO: this should probably be a warning, but key diversification will throw an error later even if we don't
PM3_RET_ERR_FREE(PM3_EINVARG, "Invalid Gallagher AID %06X, expected 2?81F4, where 0 <= ? <= 0xB", aid);
}
}
int site_key_len = 0; int site_key_len = 0;
uint8_t site_key[16] = {0}; uint8_t site_key[16] = {0};
memcpy(site_key, DEFAULT_SITE_KEY, ARRAYLEN(site_key)); memcpy(site_key, DEFAULT_SITE_KEY, ARRAYLEN(site_key));
CLIGetHexWithReturn(ctx, 9, site_key, &site_key_len); CLIGetHexWithReturn(ctx, arg++, site_key, &site_key_len);
if (site_key_len > 0 && site_key_len != 16) { if (site_key_len > 0 && site_key_len != 16) {
PM3_RET_ERR_FREE(PM3_EINVARG, "--sitekey must be 16 bytes"); PM3_RET_ERR_FREE(PM3_EINVARG, "--sitekey must be 16 bytes");
} }
SetAPDULogging(arg_get_lit(ctx, 10)); int cad_key_len = 0;
bool verbose = arg_get_lit(ctx, 11); uint8_t cad_key[16] = {0};
CLIGetHexWithReturn(ctx, arg++, cad_key, &cad_key_len);
if (cad_key_len > 0 && cad_key_len != 16) {
PM3_RET_ERR_FREE(PM3_EINVARG, "--cadkey must be 16 bytes");
}
bool no_cad_update = arg_get_lit(ctx, arg++);
bool no_app_create = arg_get_lit(ctx, arg++);
SetAPDULogging(arg_get_lit(ctx, arg++));
bool verbose = arg_get_lit(ctx, arg++);
CLIParserFree(ctx); CLIParserFree(ctx);
if (gallagher_is_valid_creds(region_code, facility_code, card_number, issue_level) == false) if (gallagher_is_valid_creds(region_code, facility_code, card_number, issue_level) == false) {
return PM3_EINVARG; return PM3_EINVARG;
}
GallagherCredentials_t creds = { GallagherCredentials_t creds = {
.region_code = region_code, .region_code = region_code,
@ -965,23 +1037,40 @@ static int CmdGallagherClone(const char *cmd) {
int res = DesfireGetCardUID(&dctx); int res = DesfireGetCardUID(&dctx);
PM3_RET_IF_ERR_WITH_MSG(res, "Failed retrieving card UID"); PM3_RET_IF_ERR_WITH_MSG(res, "Failed retrieving card UID");
// Find available Gallagher AID if the user did not specify one
if (aid_len == 0) { if (aid_len == 0) {
// Find available Gallagher AID if the user did not specify one
aid = find_available_gallagher_aid(&dctx, verbose); aid = find_available_gallagher_aid(&dctx, verbose);
if (aid == 0) { if (aid == 0) {
PM3_RET_ERR(PM3_EFATAL, "Could not find an available AID, card is full"); PM3_RET_ERR(PM3_EFATAL, "Could not find an available AID, please specify with --aid");
} }
if (verbose) {
PrintAndLogEx(INFO, "Using available AID: %06X", aid);
}
} else if (no_app_create == false && aid_exists(&dctx, aid, verbose)) {
// AID was specified but is not available
PM3_RET_ERR(PM3_EINVARG, "AID already exists: %06X", aid);
} }
// Update Card Application Directory // Update Card Application Directory
DesfireSetKeyNoClear(&dctx, key_num, key_algo, key); if (no_cad_update == false) {
// Set keys so that hfgal_add_aid_to_cad can auth to 0x000000
// if it needs to create the CAD application.
DesfireSetKeyNoClear(&dctx, picc_key_num, picc_key_algo, picc_key);
DesfireSetKdf(&dctx, MFDES_KDF_ALGO_NONE, NULL, 0); DesfireSetKdf(&dctx, MFDES_KDF_ALGO_NONE, NULL, 0);
res = hfgal_add_aid_to_cad(&dctx, site_key, aid, &creds, verbose);
bool should_diversify = cad_key_len == 0;
uint8_t *key = should_diversify ? site_key : cad_key;
res = hfgal_add_aid_to_cad(&dctx, key, should_diversify, aid, &creds, verbose);
PM3_RET_IF_ERR_WITH_MSG(res, "Failed updating Gallagher Card Application Directory"); PM3_RET_IF_ERR_WITH_MSG(res, "Failed updating Gallagher Card Application Directory");
}
// Create application // Create application
DesfireSetKeyNoClear(&dctx, key_num, key_algo, key); if (no_app_create == false) {
// Set keys so that hfgal_create_creds_app can auth to 0x000000
// when it creates the application.
DesfireSetKeyNoClear(&dctx, picc_key_num, picc_key_algo, picc_key);
DesfireSetKdf(&dctx, MFDES_KDF_ALGO_NONE, NULL, 0); DesfireSetKdf(&dctx, MFDES_KDF_ALGO_NONE, NULL, 0);
res = hfgal_create_creds_app(&dctx, site_key, aid, verbose); res = hfgal_create_creds_app(&dctx, site_key, aid, verbose);
PM3_RET_IF_ERR_WITH_MSG(res, "Failed creating Gallagher application"); PM3_RET_IF_ERR_WITH_MSG(res, "Failed creating Gallagher application");
@ -989,6 +1078,7 @@ static int CmdGallagherClone(const char *cmd) {
// Don't need to set keys here, they're generated automatically // Don't need to set keys here, they're generated automatically
res = hfgal_create_creds_file(&dctx, site_key, aid, &creds, verbose); res = hfgal_create_creds_file(&dctx, site_key, aid, &creds, verbose);
PM3_RET_IF_ERR_WITH_MSG(res, "Failed creating Gallagher credential file"); PM3_RET_IF_ERR_WITH_MSG(res, "Failed creating Gallagher credential file");
}
PrintAndLogEx(SUCCESS, "Done"); PrintAndLogEx(SUCCESS, "Done");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf gallagher reader`") " to verify"); PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf gallagher reader`") " to verify");
@ -1007,41 +1097,45 @@ static int CmdGallagherDelete(const char *cmd) {
arg_param_begin, arg_param_begin,
arg_str1(NULL, "aid", "<hex>", "Application ID to delete (3 bytes)"), arg_str1(NULL, "aid", "<hex>", "Application ID to delete (3 bytes)"),
arg_str0(NULL, "sitekey", "<hex>", "Site key to compute diversified keys (16 bytes)"), arg_str0(NULL, "sitekey", "<hex>", "Site key to compute diversified keys (16 bytes)"),
arg_str0(NULL, "cadkey", "<hex>", "Custom AES key 0 to modify the Card Application Directory (16 bytes)"),
arg_lit0(NULL, "nocadupdate", "Don't modify the Card Application Directory (only deletes the app)"),
arg_lit0(NULL, "noappdelete", "Don't delete the application (only modifies the CAD)"),
arg_lit0(NULL, "apdu", "Show APDU requests and responses"), arg_lit0(NULL, "apdu", "Show APDU requests and responses"),
arg_lit0("v", "verbose", "Verbose mode"), arg_lit0("v", "verbose", "Verbose mode"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(ctx, cmd, argtable, false); CLIExecWithReturn(ctx, cmd, argtable, false);
uint8_t arg = 1;
int aid_len = 0; int aid_len = 0;
uint8_t aid_buf[3] = {0}; uint8_t aid_buf[3] = {0};
uint32_t aid = 0; CLIGetHexWithReturn(ctx, arg++, aid_buf, &aid_len);
CLIGetHexWithReturn(ctx, 1, aid_buf, &aid_len);
if (aid_len != 3) { if (aid_len != 3) {
PM3_RET_ERR_FREE(PM3_EINVARG, "--aid must be 3 bytes"); PM3_RET_ERR_FREE(PM3_EINVARG, "--aid must be 3 bytes");
} }
reverse_aid(aid_buf); // PM3 displays AIDs backwards reverse_aid(aid_buf); // PM3 displays AIDs backwards
aid = DesfireAIDByteToUint(aid_buf); uint32_t aid = DesfireAIDByteToUint(aid_buf);
// Check that the AID is in the expected range
if ((memcmp(aid_buf, "\xF4\x81", 2) != 0) ||
(aid_buf[2] < 0x20) ||
(aid_buf[2] > 0x2B)) {
// TODO: this should probably be a warning, but key diversification will throw an error later even if we don't
PM3_RET_ERR_FREE(PM3_EINVARG, "Invalid Gallagher AID %06X, expected 2?81F4, where 0 <= ? <= 0xB", aid);
}
int site_key_len = 0; int site_key_len = 0;
uint8_t site_key[16] = {0}; uint8_t site_key[16] = {0};
memcpy(site_key, DEFAULT_SITE_KEY, ARRAYLEN(site_key)); memcpy(site_key, DEFAULT_SITE_KEY, ARRAYLEN(site_key));
CLIGetHexWithReturn(ctx, 2, site_key, &site_key_len); CLIGetHexWithReturn(ctx, arg++, site_key, &site_key_len);
if (site_key_len > 0 && site_key_len != 16) { if (site_key_len > 0 && site_key_len != 16) {
PM3_RET_ERR_FREE(PM3_EINVARG, "--sitekey must be 16 bytes"); PM3_RET_ERR_FREE(PM3_EINVARG, "--sitekey must be 16 bytes");
} }
SetAPDULogging(arg_get_lit(ctx, 3)); int cad_key_len = 0;
bool verbose = arg_get_lit(ctx, 4); uint8_t cad_key[16] = {0};
CLIGetHexWithReturn(ctx, arg++, cad_key, &cad_key_len);
if (cad_key_len > 0 && cad_key_len != 16) {
PM3_RET_ERR_FREE(PM3_EINVARG, "--cadkey must be 16 bytes");
}
bool no_cad_update = arg_get_lit(ctx, arg++);
bool no_app_delete = arg_get_lit(ctx, arg++);
SetAPDULogging(arg_get_lit(ctx, arg++));
bool verbose = arg_get_lit(ctx, arg++);
CLIParserFree(ctx); CLIParserFree(ctx);
// Set up context // Set up context
@ -1054,12 +1148,18 @@ static int CmdGallagherDelete(const char *cmd) {
PM3_RET_IF_ERR_WITH_MSG(res, "Failed retrieving card UID"); PM3_RET_IF_ERR_WITH_MSG(res, "Failed retrieving card UID");
// Update Card Application Directory // Update Card Application Directory
res = hfgal_remove_aid_from_cad(&dctx, site_key, aid, verbose); if (no_cad_update == false) {
bool should_diversify = cad_key_len == 0;
uint8_t *key = should_diversify ? site_key : cad_key;
res = hfgal_remove_aid_from_cad(&dctx, key, should_diversify, aid, verbose);
PM3_RET_IF_ERR_WITH_MSG(res, "Failed removing %06X from the Card Application Directory", aid); PM3_RET_IF_ERR_WITH_MSG(res, "Failed removing %06X from the Card Application Directory", aid);
}
// Delete application // Delete application
if (no_app_delete == false) {
res = hfgal_delete_app(&dctx, site_key, aid, verbose); res = hfgal_delete_app(&dctx, site_key, aid, verbose);
PM3_RET_IF_ERR_WITH_MSG(res, "Failed deleting Gallagher application"); PM3_RET_IF_ERR_WITH_MSG(res, "Failed deleting Gallagher application");
}
PrintAndLogEx(SUCCESS, "Done"); PrintAndLogEx(SUCCESS, "Done");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf gallagher reader`") " to verify"); PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf gallagher reader`") " to verify");
@ -1087,23 +1187,12 @@ static int CmdGallagherDiversify(const char *cmd) {
int aid_len = 0; int aid_len = 0;
uint8_t aid_buf[3] = {0}; uint8_t aid_buf[3] = {0};
uint32_t aid = 0;
CLIGetHexWithReturn(ctx, 1, aid_buf, &aid_len); CLIGetHexWithReturn(ctx, 1, aid_buf, &aid_len);
if (aid_len != 3) { if (aid_len != 3) {
PM3_RET_ERR_FREE(PM3_EINVARG, "--aid must be 3 bytes"); PM3_RET_ERR_FREE(PM3_EINVARG, "--aid must be 3 bytes");
} }
reverse_aid(aid_buf); // PM3 displays AIDs backwards reverse_aid(aid_buf); // PM3 displays AIDs backwards
aid = DesfireAIDByteToUint(aid_buf); uint32_t aid = DesfireAIDByteToUint(aid_buf);
// Check that the AID is in the expected range
if ((memcmp(aid_buf, "\xF4\x81", 2) != 0) ||
(aid_buf[2] < 0x20) ||
(aid_buf[2] > 0x2B)) {
// TODO: this should probably be a warning, but key diversification will throw an error later even if we don't
PM3_RET_ERR_FREE(PM3_EINVARG, "Invalid Gallagher AID %06X, expected 2?81F4, where 0 <= ? <= 0xB", aid);
}
int key_num = arg_get_int_def(ctx, 2, 0); int key_num = arg_get_int_def(ctx, 2, 0);

View file

@ -40,4 +40,8 @@ int CmdHFGallagher(const char *cmd);
int hfgal_diversify_key(uint8_t *site_key, uint8_t *uid, uint8_t uid_len, int 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, uint32_t aid, uint8_t *key_output);
// The response code when an invalid key is used for authentication
// Returned in /client/src/mifare/desfirecore.c, line 1185 (if DesfireExchangeEx fails)
#define HFGAL_AUTH_FAIL 7
#endif #endif

View file

@ -63,7 +63,6 @@ const static vocabulory_t vocabulory[] = {
{ 1, "analyse crc" }, { 1, "analyse crc" },
{ 1, "analyse chksum" }, { 1, "analyse chksum" },
{ 1, "analyse dates" }, { 1, "analyse dates" },
{ 1, "analyse tea" },
{ 1, "analyse lfsr" }, { 1, "analyse lfsr" },
{ 1, "analyse a" }, { 1, "analyse a" },
{ 1, "analyse nuid" }, { 1, "analyse nuid" },

View file

@ -449,14 +449,6 @@ int mfdes_kdf_input_gallagher(uint8_t *uid, uint8_t uidLen, uint8_t keyNo, uint3
return PM3_EINVARG; return PM3_EINVARG;
} }
// Verify the AppID is a valid Gallagher AppID
if ((aid & 0xF0FFFF) != 0x2081F4) {
if (g_debugMode) {
PrintAndLogEx(WARNING, "Invalid Gallagher AID %06X", aid);
}
return PM3_EINVARG;
}
int len = 0; int len = 0;
// If the keyNo == 1, then omit the UID. // If the keyNo == 1, then omit the UID.
if (keyNo != 1) { if (keyNo != 1) {

View file

@ -97,7 +97,7 @@
}, },
"analyse help": { "analyse help": {
"command": "analyse help", "command": "analyse help",
"description": "help this help lcr generate final byte for xor lrc crc stub method for crc evaluations chksum checksum with adding, masking and one's complement dates look for datestamps in a given array of bytes tea crypto tea test lfsr lfsr tests a num bits test nuid create nuid from 7byte uid demodbuff load binary string to demodbuffer freq calc wave lengths foo muxer units convert etu <> us <> ssp_clk (3.39mhz) --------------------------------------------------------------------------------------- analyse lcr available offline: yes specifying the bytes of a uid with a known lrc will find the last byte value needed to generate that lrc with a rolling xor. all bytes should be specified in hex.", "description": "help this help lcr generate final byte for xor lrc crc stub method for crc evaluations chksum checksum with adding, masking and one's complement dates look for datestamps in a given array of bytes lfsr lfsr tests a num bits test nuid create nuid from 7byte uid demodbuff load binary string to demodbuffer freq calc wave lengths foo muxer units convert etu <> us <> ssp_clk (3.39mhz) --------------------------------------------------------------------------------------- analyse lcr available offline: yes specifying the bytes of a uid with a known lrc will find the last byte value needed to generate that lrc with a rolling xor. all bytes should be specified in hex.",
"notes": [ "notes": [
"analyse lcr -d 04008064ba -> target (ba) requires final lrc xor byte value: 5a" "analyse lcr -d 04008064ba -> target (ba) requires final lrc xor byte value: 5a"
], ],
@ -136,19 +136,6 @@
], ],
"usage": "analyse nuid [-ht] [-d <hex>]" "usage": "analyse nuid [-ht] [-d <hex>]"
}, },
"analyse tea": {
"command": "analyse tea",
"description": "crypto tea self tests",
"notes": [
"analyse tea -d 1122334455667788"
],
"offline": true,
"options": [
"-h, --help this help",
"-d, --data <hex> bytes to encrypt ( 8 hex bytes )"
],
"usage": "analyse tea [-h] -d <hex>"
},
"analyse units": { "analyse units": {
"command": "analyse units", "command": "analyse units",
"description": "experiments of unit conversions found in hf. etu (1/13.56mhz), us or ssp_clk (1/3.39mhz)", "description": "experiments of unit conversions found in hf. etu (1/13.56mhz), us or ssp_clk (1/3.39mhz)",
@ -2322,26 +2309,29 @@
}, },
"hf gallagher clone": { "hf gallagher clone": {
"command": "hf gallagher clone", "command": "hf gallagher clone",
"description": "clone gallagher credentials to a writable desfire card specify site key is required if using non-default key key, lengths for the different crypto: des 8 bytes 2tdea or aes 16 bytes 3tdea 24 bytes aid id, default finds lowest available in range 0x2?81f4, where 0 <= ? <= 0xb.", "description": "clone gallagher credentials to a writable desfire card specify site key is required if using non-default key key, lengths for the different crypto: des 8 bytes 2tdea or aes 16 bytes 3tdea 24 bytes aid, default finds lowest available in range 0x??81f4, where ?? >= 0x20.",
"notes": [ "notes": [
"hf gallagher clone --rc 1 --fc 22 --cn 3333 --il 4 --sitekey 00112233445566778899aabbccddeeff" "hf gallagher clone --rc 1 --fc 22 --cn 3333 --il 4 --sitekey 00112233445566778899aabbccddeeff"
], ],
"offline": false, "offline": false,
"options": [ "options": [
"-h, --help this help", "-h, --help this help",
"-n, --keynum <dec> key number [default = 0]", "-n, --keynum <dec> picc key number [default = 0]",
"-t, --algo <des|2tdea|3tdea|aes> crypt algo: des, 2tdea, 3tdea, aes", "-t, --algo <des|2tdea|3tdea|aes> picc crypt algo: des, 2tdea, 3tdea, aes",
"-k, --key <hex> key for authentication to the picc", "-k, --key <hex> key for authentication to the picc to create applications",
"--rc <dec> region code. 4 bits max", "--rc <dec> region code. 4 bits max",
"--fc <dec> facility code. 2 bytes max", "--fc <dec> facility code. 2 bytes max",
"--cn <dec> card number. 3 bytes max", "--cn <dec> card number. 3 bytes max",
"--il <dec> issue level. 4 bits max", "--il <dec> issue level. 4 bits max",
"--aid <hex> application id to write (3 bytes)", "--aid <hex> application id to write (3 bytes) [default automatically chooses]",
"--sitekey <hex> site key to compute diversified keys (16 bytes)", "--sitekey <hex> site key to compute diversified keys (16 bytes)",
"--cadkey <hex> custom aes key 0 to modify the card application directory (16 bytes)",
"--nocadupdate don't modify the card application directory (only creates the app)",
"--noappcreate don't create the application (only modifies the cad)",
"--apdu show apdu requests and responses", "--apdu show apdu requests and responses",
"-v, --verbose verbose mode" "-v, --verbose verbose mode"
], ],
"usage": "hf gallagher clone [-hv] [-n <dec>] [-t <des|2tdea|3tdea|aes>] [-k <hex>] --rc <dec> --fc <dec> --cn <dec> --il <dec> [--aid <hex>] [--sitekey <hex>] [--apdu]" "usage": "hf gallagher clone [-hv] [-n <dec>] [-t <des|2tdea|3tdea|aes>] [-k <hex>] --rc <dec> --fc <dec> --cn <dec> --il <dec> [--aid <hex>] [--sitekey <hex>] [--cadkey <hex>] [--nocadupdate] [--noappcreate] [--apdu]"
}, },
"hf gallagher delete": { "hf gallagher delete": {
"command": "hf gallagher delete", "command": "hf gallagher delete",
@ -2354,10 +2344,13 @@
"-h, --help this help", "-h, --help this help",
"--aid <hex> application id to delete (3 bytes)", "--aid <hex> application id to delete (3 bytes)",
"--sitekey <hex> site key to compute diversified keys (16 bytes)", "--sitekey <hex> site key to compute diversified keys (16 bytes)",
"--cadkey <hex> custom aes key 0 to modify the card application directory (16 bytes)",
"--nocadupdate don't modify the card application directory (only deletes the app)",
"--noappdelete don't delete the application (only modifies the cad)",
"--apdu show apdu requests and responses", "--apdu show apdu requests and responses",
"-v, --verbose verbose mode" "-v, --verbose verbose mode"
], ],
"usage": "hf gallagher delete [-hv] --aid <hex> [--sitekey <hex>] [--apdu]" "usage": "hf gallagher delete [-hv] --aid <hex> [--sitekey <hex>] [--cadkey <hex>] [--nocadupdate] [--noappdelete] [--apdu]"
}, },
"hf gallagher diversifykey": { "hf gallagher diversifykey": {
"command": "hf gallagher diversifykey", "command": "hf gallagher diversifykey",
@ -10210,8 +10203,8 @@
} }
}, },
"metadata": { "metadata": {
"commands_extracted": 599, "commands_extracted": 598,
"extracted_by": "PM3Help2JSON v1.00", "extracted_by": "PM3Help2JSON v1.00",
"extracted_on": "2022-01-11T01:15:20" "extracted_on": "2022-01-17T10:37:00"
} }
} }

View file

@ -74,7 +74,6 @@ Check column "offline" for their availability.
|`analyse crc `|Y |`Stub method for CRC evaluations` |`analyse crc `|Y |`Stub method for CRC evaluations`
|`analyse chksum `|Y |`Checksum with adding, masking and one's complement` |`analyse chksum `|Y |`Checksum with adding, masking and one's complement`
|`analyse dates `|Y |`Look for datestamps in a given array of bytes` |`analyse dates `|Y |`Look for datestamps in a given array of bytes`
|`analyse tea `|Y |`Crypto TEA test`
|`analyse lfsr `|Y |`LFSR tests` |`analyse lfsr `|Y |`LFSR tests`
|`analyse a `|Y |`num bits test` |`analyse a `|Y |`num bits test`
|`analyse nuid `|Y |`create NUID from 7byte UID` |`analyse nuid `|Y |`create NUID from 7byte UID`