Merge pull request #3217 from kormax/mfdes-getdelegateappinfo

Implement DESFire delegated app info retrieval
This commit is contained in:
Iceman
2026-04-07 06:22:18 +07:00
committed by GitHub
6 changed files with 108 additions and 0 deletions

View File

@@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file.
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
## [unreleased][unreleased]
- Added `hf mfdes getdelegateappinfo` command (@kormax)
- Added `hf secc info` command to retrieve the Card Recognition Template(@antiklesys)
- Added `hf mfdes createdelegateapp` command (@kormax)
- Optimized `hf iclass legbrute` throughput: replaced recursive `suc()`/`output()` cipher functions with iterative loops, added 256-entry LUT for the `select()` function eliminating redundant bit arithmetic and halving key lookups per state step, switched successor state to in-place pointer update removing per-call struct copies, added `doMAC_brute()` with byte-wise LSB-first processing and direct output bit packing eliminating all bitstream struct overhead and output reversal calls per key candidate, and replaced per-iteration 64-bit modulo progress check with a countdown counter (@antiklesys)

View File

@@ -3852,6 +3852,101 @@ static int CmdHF14ADesCreateDelegateApp(const char *Cmd) {
return PM3_SUCCESS;
}
static int CmdHF14ADesGetDelegateAppInfo(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf mfdes getdelegateappinfo",
"Get delegated application information for DAM slot (GetDelegatedInfo / 0x69).",
"By default authentication is performed with PICC key number 0x00.\n"
"Use --keyno to pick another key number, or --no-auth to skip authentication.\n"
"hf mfdes getdelegateappinfo --damslot 0001 --algo 2TDEA --key 00000000000000000000000000000000\n"
"hf mfdes getdelegateappinfo --damslot 0001 --no-auth");
void *argtable[] = {
arg_param_begin,
arg_lit0("a", "apdu", "Show APDU requests and responses"),
arg_lit0("v", "verbose", "Verbose output"),
arg_int0("n", "keyno", "<dec>", "Key number (default: 0 / PICC key)"),
arg_str0("t", "algo", "<DES|2TDEA|3TDEA|AES>", "Crypt algo"),
arg_str0("k", "key", "<hex>", "Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"),
arg_str0(NULL, "kdf", "<none|AN10922|gallagher>", "Key Derivation Function (KDF)"),
arg_str0("i", "kdfi", "<hex>", "KDF input (1-31 hex bytes)"),
arg_str0("m", "cmode", "<plain|mac|encrypt>", "Communicaton mode"),
arg_str0("c", "ccset", "<native|niso|iso>", "Communicaton command set"),
arg_str0(NULL, "schann", "<d40|ev1|ev2|lrp>", "Secure channel"),
arg_str0(NULL, "damslot", "<hex>", "DAM slot number (2 hex bytes, little endian on card)"),
arg_lit0(NULL, "no-auth", "Execute without authentication"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
bool APDULogging = arg_get_lit(ctx, 1);
bool verbose = arg_get_lit(ctx, 2);
bool noauth = arg_get_lit(ctx, 12);
int keynum = arg_get_int_def(ctx, 3, 0x00);
if (keynum < 0 || keynum > 0xFF) {
CLIParserFree(ctx);
PrintAndLogEx(ERR, "Key number must be in range 0..255");
return PM3_EINVARG;
}
DesfireContext_t dctx = {0};
int securechann = defaultSecureChannel;
int res = CmdDesGetSessionParameters(ctx, &dctx, 0, 4, 5, 6, 7, 8, 9, 10, 0, 0, 0, &securechann, (noauth) ? DCMPlain : DCMMACed, NULL, NULL);
if (res) {
CLIParserFree(ctx);
return res;
}
dctx.keyNum = keynum & 0xFF;
uint32_t damslot = 0x0000;
bool damslotpresent = false;
if (CLIGetUint32Hex(ctx, 11, 0x0000, &damslot, &damslotpresent, 2, "DAM slot number must have 2 bytes length")) {
CLIParserFree(ctx);
return PM3_EINVARG;
}
SetAPDULogging(APDULogging);
CLIParserFree(ctx);
if (!damslotpresent) {
PrintAndLogEx(ERR, "DAM slot number is mandatory");
return PM3_EINVARG;
}
res = DesfireSelectAndAuthenticateEx(&dctx, securechann, 0x000000, noauth, verbose);
if (res != PM3_SUCCESS) {
DropField();
return res;
}
uint8_t resp[16] = {0};
size_t resplen = 0;
res = DesfireGetDelegatedInfo(&dctx, damslot & 0xffff, resp, &resplen);
if (res != PM3_SUCCESS) {
PrintAndLogEx(ERR, "Desfire GetDelegatedInfo command " _RED_("error") ". Result: %d", res);
DropField();
return PM3_ESOFT;
}
if (verbose)
PrintAndLogEx(SUCCESS, "received data[%zu]: %s", resplen, sprint_hex(resp, resplen));
uint16_t quota = MemLeToUint2byte(&resp[1]);
uint16_t freeblocks = MemLeToUint2byte(&resp[3]);
uint32_t delegatedaid = MemLeToUint3byte(&resp[5]);
PrintAndLogEx(SUCCESS, "DAM slot 0x%04x", damslot & 0xffff);
PrintAndLogEx(SUCCESS, "DAM slot ver 0x%02x", resp[0]);
PrintAndLogEx(SUCCESS, "Quota limit 0x%04x (%u blocks)", quota, (unsigned int)quota);
PrintAndLogEx(SUCCESS, "Free blocks 0x%04x (%u blocks)", freeblocks, (unsigned int)freeblocks);
PrintAndLogEx(SUCCESS, "Delegated AID 0x%06x", delegatedaid);
DropField();
return PM3_SUCCESS;
}
static int CmdHF14ADesDeleteApp(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf mfdes deleteapp",
@@ -6962,6 +7057,7 @@ static command_t CommandTable[] = {
{"bruteaid", CmdHF14ADesBruteApps, IfPm3Iso14443a, "Recover AIDs by bruteforce"},
{"createapp", CmdHF14ADesCreateApp, IfPm3Iso14443a, "Create Application"},
{"createdelegateapp", CmdHF14ADesCreateDelegateApp, IfPm3Iso14443a, "Create Delegated Application"},
{"getdelegateappinfo", CmdHF14ADesGetDelegateAppInfo, IfPm3Iso14443a, "Get Delegated Application info by DAM slot"},
{"deleteapp", CmdHF14ADesDeleteApp, IfPm3Iso14443a, "Delete Application"},
{"selectapp", CmdHF14ADesSelectApp, IfPm3Iso14443a, "Select Application ID"},
{"selectisofid", CmdHF14ADesSelectISOFID, IfPm3Iso14443a, "Select file by ISO ID"},

View File

@@ -2249,6 +2249,12 @@ int DesfireCreateDelegatedApplication(DesfireContext_t *dctx, uint8_t *appdata,
return PM3_SUCCESS;
}
int DesfireGetDelegatedInfo(DesfireContext_t *dctx, uint16_t damslot, uint8_t *resp, size_t *resplen) {
uint8_t data[2] = {0};
Uint2byteToMemLe(data, damslot);
return DesfireCommand(dctx, MFDES_GET_DELEGATE_INFO, data, sizeof(data), resp, resplen, 8);
}
int DesfireDeleteApplication(DesfireContext_t *dctx, uint32_t aid) {
uint8_t data[3] = {0};
DesfireAIDUintToByte(aid, data);

View File

@@ -210,6 +210,7 @@ void DesfirePrintAppList(DesfireContext_t *dctx, PICCInfo_t *PICCInfo, AppListS
int DesfireCreateApplication(DesfireContext_t *dctx, uint8_t *appdata, size_t appdatalen);
int DesfireCreateDelegatedApplication(DesfireContext_t *dctx, uint8_t *appdata, size_t appdatalen, uint8_t *contdata, size_t contdatalen);
int DesfireGetDelegatedInfo(DesfireContext_t *dctx, uint16_t damslot, uint8_t *resp, size_t *resplen);
int DesfireDeleteApplication(DesfireContext_t *dctx, uint32_t aid);
int DesfireGetKeyVersion(DesfireContext_t *dctx, uint8_t *data, size_t len, uint8_t *resp, size_t *resplen);

View File

@@ -68,6 +68,7 @@ static const AllowedChannelModes_t AllowedChannelModes[] = {
{MFDES_GET_DF_NAMES, DACd40, DCCNative, DCMMACed},
{MFDES_GET_KEY_SETTINGS, DACd40, DCCNative, DCMMACed},
{MFDES_GET_KEY_VERSION, DACd40, DCCNative, DCMMACed},
{MFDES_GET_DELEGATE_INFO, DACd40, DCCNative, DCMMACed},
{MFDES_GET_FREE_MEMORY, DACd40, DCCNative, DCMMACed},
{MFDES_CREATE_STD_DATA_FILE, DACd40, DCCNative, DCMMACed},
{MFDES_CREATE_BACKUP_DATA_FILE, DACd40, DCCNative, DCMMACed},
@@ -107,6 +108,7 @@ static const AllowedChannelModes_t AllowedChannelModes[] = {
{MFDES_SELECT_APPLICATION, DACEV1, DCCNative, DCMPlain},
{MFDES_GET_KEY_VERSION, DACEV1, DCCNative, DCMMACed},
{MFDES_GET_DELEGATE_INFO, DACEV1, DCCNative, DCMMACed},
{MFDES_GET_FREE_MEMORY, DACEV1, DCCNative, DCMMACed},
{MFDES_CREATE_APPLICATION, DACEV1, DCCNative, DCMMACed},
{MFDES_CREATE_DELEGATE_APP, DACEV1, DCCNative, DCMMACed},
@@ -188,6 +190,7 @@ static const AllowedChannelModes_t AllowedChannelModes[] = {
static const CmdHeaderLengths_t CmdHeaderLengths[] = {
{MFDES_CREATE_APPLICATION, CMD_HEADER_LEN_ALL},
{MFDES_CREATE_DELEGATE_APP, CMD_HEADER_LEN_ALL},
{MFDES_GET_DELEGATE_INFO, 2},
{MFDES_DELETE_APPLICATION, CMD_HEADER_LEN_ALL},
{MFDES_CHANGE_KEY, 1},
{MFDES_CHANGE_KEY_EV2, 2},

View File

@@ -496,6 +496,7 @@ const static vocabulary_t vocabulary[] = {
{ 0, "hf mfdes bruteaid" },
{ 0, "hf mfdes createapp" },
{ 0, "hf mfdes createdelegateapp" },
{ 0, "hf mfdes getdelegateappinfo" },
{ 0, "hf mfdes deleteapp" },
{ 0, "hf mfdes selectapp" },
{ 0, "hf mfdes selectisofid" },