make style

This commit is contained in:
Philippe Teuwen
2026-06-07 23:01:20 +02:00
parent ff04e1ea9a
commit efcc34a698
9 changed files with 910 additions and 197 deletions
+1 -1
View File
@@ -133,7 +133,7 @@ static size_t ansi_byte_count(const char *s) {
n += 2;
s += 2;
while (*s) {
unsigned char c = (unsigned char)*s++;
unsigned char c = (unsigned char) * s++;
n++;
if (c >= 0x40 && c <= 0x7E) {
break;
+28 -27
View File
@@ -844,9 +844,9 @@ int mfp_data_crypt(mf4Session_t *mf4session, uint8_t *dati, uint8_t *dato, bool
}
if (rev) {
aes_decode(IV, kenc, dati, dato, MFBLOCK_SIZE*bc);
aes_decode(IV, kenc, dati, dato, MFBLOCK_SIZE * bc);
} else {
aes_encode(IV, kenc, dati, dato, MFBLOCK_SIZE*bc);
aes_encode(IV, kenc, dati, dato, MFBLOCK_SIZE * bc);
}
return PM3_SUCCESS;
@@ -2244,10 +2244,10 @@ static int CmdHFMFPDump(const char *Cmd) {
int STRead;
uint8_t mac[8] = {0};
chunkCycle:
ki_pA[1] = sl3Count*2;
ki_pA[1] = sl3Count * 2;
MifareAuth4(&_session, ki_pA, &aesFoundKeys[MF_KEY_A][sl3Count][1], nonfirst, !nonfirst, true, true, verbose, false);
nonfirst = true;
MFPReadBlock(&_session, false, false, true, 3+sl3Count*4, 1, false, true, STBuffer, sizeof(STBuffer), &STRead, mac);
MFPReadBlock(&_session, false, false, true, 3 + sl3Count * 4, 1, false, true, STBuffer, sizeof(STBuffer), &STRead, mac);
if (STRead && STBuffer[0] != 0x90) {
PrintAndLogEx(ERR, "\nTrailer read error: %02x %s", STBuffer[0], mfpGetErrorDescription(STBuffer[0]));
goto chunkBlank;
@@ -2257,17 +2257,17 @@ chunkCycle:
}
mfp_data_crypt(&_session, &STBuffer[1], &STBuffer[1], true, 1);
// Multiblock reads do not allow reading out STs, as such this is the time to save them into the final dump
memcpy(carddata + ((3+4*sl3Count) * MFBLOCK_SIZE), &STBuffer[1], 1 * MFBLOCK_SIZE);
memcpy(carddata + ((3 + 4 * sl3Count) * MFBLOCK_SIZE), &STBuffer[1], 1 * MFBLOCK_SIZE);
// Check if any block is encrypted only
ki_pB[1] = 0x01+sl3Count*2;
ki_pB[1] = 0x01+sl3Count * 2;
MifareAuth4(&_session, ki_pB, &aesFoundKeys[MF_KEY_B][sl3Count][1], true, false, true, true, verbose, false);
if (STBuffer[6] & 0xF0) { // At least one bit is set to force enc. only
MFPReadBlock(&_session, false, false, true, sl3Count*4, 3, false, true, STBuffer, sizeof(STBuffer), &STRead, mac);
MFPReadBlock(&_session, false, false, true, sl3Count * 4, 3, false, true, STBuffer, sizeof(STBuffer), &STRead, mac);
if (STRead && STBuffer[0] != 0x90) {
chunkBlank:
PrintAndLogEx(ERR, "\nChunk read error: %02x %s", STBuffer[0], mfpGetErrorDescription(STBuffer[0]));
memcpy(carddata + (sl3Count * 4 * MFBLOCK_SIZE), nullChunk, 3 * MFBLOCK_SIZE);
memcpy(carddata + ((3+4*sl3Count) * MFBLOCK_SIZE), nullBlock, 1 * MFBLOCK_SIZE);
memcpy(carddata + ((3 + 4 * sl3Count) * MFBLOCK_SIZE), nullBlock, 1 * MFBLOCK_SIZE);
PrintAndLogEx(WARNING, "Quick-reading sector %3d / %3d ( " _RED_("fail") " )", sl3Count, numSectors - 1);
// Restart auth since a read failure resets it
nonfirst = false;
@@ -2285,7 +2285,7 @@ chunkBlank:
sectorsRead++;
sl3Count++;
} else {
MFPReadBlock(&_session, true, false, true, sl3Count*4, 3, false, true, STBuffer, sizeof(STBuffer), &STRead, mac);
MFPReadBlock(&_session, true, false, true, sl3Count * 4, 3, false, true, STBuffer, sizeof(STBuffer), &STRead, mac);
if (STRead && STBuffer[0] != 0x90) {
PrintAndLogEx(ERR, "Chunk read error: %02x %s", STBuffer[0], mfpGetErrorDescription(STBuffer[0]));
memcpy(carddata + (sl3Count * 4 * MFBLOCK_SIZE), nullChunk, 3 * MFBLOCK_SIZE);
@@ -2308,12 +2308,12 @@ chunkCycleClean:
if (numSectors>32){
if (numSectors > 32) {
chunkCycle2:
ki_pA[1] = sl3Count*2;
ki_pA[1] = sl3Count * 2;
MifareAuth4(&_session, ki_pA, &aesFoundKeys[MF_KEY_A][sl3Count][1], nonfirst, !nonfirst, true, true, verbose, false);
nonfirst = true;
MFPReadBlock(&_session, false, false, true, 128+(sl3Count-31)*16-1, 1, false, true, STBuffer, sizeof(STBuffer), &STRead, mac);
MFPReadBlock(&_session, false, false, true, 128 + (sl3Count - 31) * 16 - 1, 1, false, true, STBuffer, sizeof(STBuffer), &STRead, mac);
if (STRead && STBuffer[0] != 0x90) {
PrintAndLogEx(ERR, "Trailer read error: %02x %s", STBuffer[0], mfpGetErrorDescription(STBuffer[0]));
goto chunkBlank2;
@@ -2324,22 +2324,23 @@ chunkCycle2:
}
mfp_data_crypt(&_session, &STBuffer[1], &STBuffer[1], true, 1);
// Multiblock reads do not allow reading out STs, as such this is the time to save them into the final dump
memcpy(carddata + ((128+(sl3Count-31)*16-1) * MFBLOCK_SIZE), &STBuffer[1], 1 * MFBLOCK_SIZE);
memcpy(carddata + ((128 + (sl3Count - 31) * 16 - 1) * MFBLOCK_SIZE), &STBuffer[1], 1 * MFBLOCK_SIZE);
int c = 0;
// Check if any block is encrypted only
ki_pB[1] = 0x01+sl3Count*2;
ki_pB[1] = 0x01+sl3Count * 2;
MifareAuth4(&_session, ki_pB, &aesFoundKeys[MF_KEY_B][sl3Count][1], true, false, true, true, verbose, false);
if (STBuffer[6] & 0xF0) { // At least one bit is set to force enc. only
chunkBlank2: // Jumping here will start the cycle which will blank out the remaining 5 chunks anyway
for (c=0; c<5; ++c) {
MFPReadBlock(&_session, false, false, true, 128+(sl3Count-32)*16+c*3, 3, false, true, STBuffer, sizeof(STBuffer), &STRead, mac);
for (c = 0; c < 5; ++c) {
MFPReadBlock(&_session, false, false, true, 128 + (sl3Count - 32) * 16 + c * 3, 3, false, true, STBuffer, sizeof(STBuffer), &STRead, mac);
if (STRead && STBuffer[0] != 0x90) {
PrintAndLogEx(ERR, "Chunk read error: %02x %s", STBuffer[0], mfpGetErrorDescription(STBuffer[0]));
PrintAndLogEx(WARNING, "Quick-reading sector %3d / %3d chunk %d ( " _RED_("fail") " )", sl3Count, numSectors - 1, c);
memcpy(carddata + ((128+(sl3Count-31)*16-1) * MFBLOCK_SIZE), nullBlock, 1 * MFBLOCK_SIZE);
memcpy(carddata + ((128 + 16*(sl3Count-32)+c*3) * MFBLOCK_SIZE), nullChunk, 3 * MFBLOCK_SIZE);
memcpy(carddata + ((128 + (sl3Count - 31) * 16 - 1) * MFBLOCK_SIZE), nullBlock, 1 * MFBLOCK_SIZE);
memcpy(carddata + ((128 + 16 * (sl3Count - 32) + c * 3) * MFBLOCK_SIZE), nullChunk, 3 * MFBLOCK_SIZE);
nonfirst = false;
if (c<5) {continue;} else {sl3Count++; goto chunkCycleClean2;};
if (c < 5) {continue;}
else {sl3Count++; goto chunkCycleClean2;};
}
if (STRead != 1 + 48 + 2) {
PrintAndLogEx(ERR, "Error return length: %d", STRead);
@@ -2348,16 +2349,16 @@ chunkBlank2: // Jumping here will start the cycle which will blank out the remai
}
mfp_data_crypt(&_session, &STBuffer[1], &STBuffer[1], true, 3);
PrintAndLogEx(INPLACE, "Quick-reading sector %3d / %3d ( " _GREEN_("ok") " )", sl3Count, numSectors - 1);
memcpy(carddata + ((128 + 16*(sl3Count-32)+c*3) * MFBLOCK_SIZE), &STBuffer[1], 3 * MFBLOCK_SIZE);
memcpy(carddata + ((128 + 16 * (sl3Count - 32) + c * 3) * MFBLOCK_SIZE), &STBuffer[1], 3 * MFBLOCK_SIZE);
}
sectorsRead++;
sl3Count++;
} else {
for (c=0; c<5; ++c) {
MFPReadBlock(&_session, true, false, true, 128+(sl3Count-32)*16+c*3, 3, false, true, STBuffer, sizeof(STBuffer), &STRead, mac);
for (c = 0; c < 5; ++c) {
MFPReadBlock(&_session, true, false, true, 128 + (sl3Count - 32) * 16 + c * 3, 3, false, true, STBuffer, sizeof(STBuffer), &STRead, mac);
if (STRead && STBuffer[0] != 0x90) {
PrintAndLogEx(ERR, "Chunk read error: %02x %s", STBuffer[0], mfpGetErrorDescription(STBuffer[0]));
memcpy(carddata + ((128 + 16*(sl3Count-32)+c*3) * MFBLOCK_SIZE), nullChunk, 3 * MFBLOCK_SIZE);
memcpy(carddata + ((128 + 16 * (sl3Count - 32) + c * 3) * MFBLOCK_SIZE), nullChunk, 3 * MFBLOCK_SIZE);
PrintAndLogEx(WARNING, "Quick-reading sector %3d / %3d ( " _RED_("fail") " )", sl3Count, numSectors - 1);
continue;
}
@@ -2367,8 +2368,8 @@ chunkBlank2: // Jumping here will start the cycle which will blank out the remai
return PM3_ESOFT;
}
PrintAndLogEx(INPLACE, "Quick-reading sector %3d / %3d ( " _GREEN_("ok") " )", sl3Count, numSectors - 1);
memcpy(carddata + ((128 + 16*(sl3Count-32)+c*3) * MFBLOCK_SIZE), &STBuffer[1], 3 * MFBLOCK_SIZE);
memcpy(carddata + ((128 + 16 * (sl3Count - 32) + c * 3) * MFBLOCK_SIZE), &STBuffer[1], 3 * MFBLOCK_SIZE);
}
sectorsRead++;
sl3Count++;
@@ -2445,7 +2446,7 @@ chunkCycleClean2:
DropField();
t1 = msclock() - t1;
// ========================================
// Print sector summary
// ========================================
@@ -2546,7 +2547,7 @@ chunkCycleClean2:
PrintAndLogEx(HINT, "Partial dump: %d of %d sectors read", sectorsRead, numSectors);
PrintAndLogEx(HINT, "Hint: Try " _YELLOW_("`hf mfp chk --dump`") " and/or " _YELLOW_("`hf mf chk`") " to find more keys");
}
PrintAndLogEx(INFO, "\ntime in dump " _YELLOW_("%.0f") " seconds\n", (float)t1 / 1000.0);
free(carddata);
return PM3_SUCCESS;
+6 -4
View File
@@ -224,7 +224,8 @@ int MifareAuth4(mf4Session_t *mf4session, const uint8_t *keyn, uint8_t *key, boo
}
uint8_t cmd1[4];
if (nonfirst) { cmd1[0] = 0x76; cmd1[1] = keyn[1]; cmd1[2] = keyn[0]; } else { cmd1[0] = 0x70; cmd1[1] = keyn[1]; cmd1[2] = keyn[0]; cmd1[3] = 0x00; }
if (nonfirst) { cmd1[0] = 0x76; cmd1[1] = keyn[1]; cmd1[2] = keyn[0]; }
else { cmd1[0] = 0x70; cmd1[1] = keyn[1]; cmd1[2] = keyn[0]; cmd1[3] = 0x00; }
int res = ExchangeRAW14a(cmd1, nonfirst ? 3 : 4, activateField, true, data, sizeof(data), &datalen, silentMode);
if (res != PM3_SUCCESS) {
@@ -307,7 +308,7 @@ int MifareAuth4(mf4Session_t *mf4session, const uint8_t *keyn, uint8_t *key, boo
memcpy(&IVW[12], &mf4session->R_Ctr, 2);
memcpy(&IVW[14], &mf4session->W_Ctr, 2);
memcpy(IVW, mf4session->TI, 4);
aes_decode(IVR, key, &data[1], RndB, 16);
RndB[16] = RndB[0];
if (verbose) {
@@ -353,7 +354,7 @@ int MifareAuth4(mf4Session_t *mf4session, const uint8_t *keyn, uint8_t *key, boo
PrintAndLogEx(INFO, "< phase2: %s", sprint_hex(data, datalen));
}
if (data[0]!=0x90) {
if (data[0] != 0x90) {
if (silentMode == false) {
PrintAndLogEx(ERR, "\nAuthentication FAILED. Card did not ACK response");
}
@@ -364,7 +365,8 @@ int MifareAuth4(mf4Session_t *mf4session, const uint8_t *keyn, uint8_t *key, boo
return PM3_EWRONGANSWER;
}
if (nonfirst) { aes_decode(IVR, key, &data[1], raw, 16); } else { aes_decode(NULL, key, &data[1], raw, 32); }
if (nonfirst) { aes_decode(IVR, key, &data[1], raw, 16); }
else { aes_decode(NULL, key, &data[1], raw, 32); }
if (verbose) {
if (nonfirst) {
+35
View File
@@ -276,6 +276,40 @@ const static vocabulary_t vocabulary[] = {
{ 0, "hf fido auth" },
{ 0, "hf fido make" },
{ 0, "hf fido assert" },
{ 1, "hf fmcos help" },
{ 0, "hf fmcos info" },
{ 0, "hf fmcos select" },
{ 0, "hf fmcos erase" },
{ 0, "hf fmcos createdir" },
{ 0, "hf fmcos createfile" },
{ 0, "hf fmcos createkeyfile" },
{ 0, "hf fmcos readbinary" },
{ 0, "hf fmcos readrecord" },
{ 0, "hf fmcos writebinary" },
{ 0, "hf fmcos writerecord" },
{ 0, "hf fmcos append" },
{ 0, "hf fmcos authexternal" },
{ 0, "hf fmcos authinternal" },
{ 0, "hf fmcos key" },
{ 0, "hf fmcos pinverify" },
{ 0, "hf fmcos pinchange" },
{ 0, "hf fmcos pinreset" },
{ 0, "hf fmcos pinunblock" },
{ 0, "hf fmcos balance" },
{ 0, "hf fmcos credit" },
{ 0, "hf fmcos purchase" },
{ 0, "hf fmcos overdraft" },
{ 0, "hf fmcos history" },
{ 0, "hf fmcos block" },
{ 0, "hf fmcos unblock" },
{ 0, "hf fmcos tidsetcard" },
{ 0, "hf fmcos tidsetuid" },
{ 0, "hf fmcos tidsetauth" },
{ 0, "hf fmcos tiderase" },
{ 0, "hf fmcos tidprovision" },
{ 0, "hf fmcos tidcreatedf" },
{ 0, "hf fmcos tidcreatebin" },
{ 0, "hf fmcos tidcreaterec" },
{ 1, "hf fudan help" },
{ 0, "hf fudan reader" },
{ 0, "hf fudan dump" },
@@ -357,6 +391,7 @@ const static vocabulary_t vocabulary[] = {
{ 0, "hf legic reader" },
{ 0, "hf legic restore" },
{ 0, "hf legic clone" },
{ 0, "hf legic migrate" },
{ 0, "hf legic wipe" },
{ 0, "hf legic wrbl" },
{ 0, "hf legic sim" },
+659 -27
View File
@@ -1433,9 +1433,10 @@
"--sk Fill simulator keys from found keys",
"-v, --verbose verbose output",
"--1a1 <hex> <8|16> hex bytes ULC/ULAES Auth reply step1: ek(RndB)",
"--1a2 <hex> <8|16> hex bytes ULC/ULAES Auth reply step2: ek(RndA')"
"--1a2 <hex> <8|16> hex bytes ULC/ULAES Auth reply step2: ek(RndA')",
"--1a2-mirror Mirror ek(RndA) from step1 reply into step2 reply"
],
"usage": "hf 14a sim [-hxv] -t <1-15> [-u <hex>] [-n <dec>] [--sk] [--1a1 <hex>] [--1a2 <hex>]"
"usage": "hf 14a sim [-hxv] -t <1-15> [-u <hex>] [-n <dec>] [--sk] [--1a1 <hex>] [--1a2 <hex>] [--1a2-mirror]"
},
"hf 14a simaid": {
"command": "hf 14a simaid",
@@ -2289,22 +2290,22 @@
},
"hf calypso dump": {
"command": "hf calypso dump",
"description": "Dump readable files and records from Calypso DFs",
"description": "Dump Calypso nodes by first scanning available application profiles",
"notes": [
"hf calypso dump",
"hf calypso dump --aid 315449432E494341",
"hf calypso dump --preset brute",
"hf calypso dump -f my-calypso-dump",
"hf calypso dump --ns -v"
],
"offline": false,
"options": [
"-h, --help This help",
"--aid <hex> Calypso application AID or AID prefix (5..16 bytes)",
"-f, --file <fn> Specify a filename for JSON dump file",
"--preset <known|brute> candidate preset (`known` default, `brute` also bruteforces LID candidates)",
"--ns no save to file",
"-v, --verbose verbose output"
],
"usage": "hf calypso dump [-hv] [--aid <hex>] [-f <fn>] [--ns]"
"usage": "hf calypso dump [-hv] [-f <fn>] [--preset <known|brute>] [--ns]"
},
"hf calypso help": {
"command": "hf calypso help",
@@ -3257,6 +3258,612 @@
],
"usage": "hf fido reg [-havt] [-f <fn>] [--cp <str>] [--ap <str>] [--cpx <hex>] [--apx <hex>]"
},
"hf fmcos append": {
"command": "hf fmcos append",
"description": "APPEND RECORD to a cyclic or linear EF Protection: none(def) mac enc",
"notes": [
"hf fmcos append --fid 01 --data 0102030405060708",
"hf fmcos append --fid 01 --data 01020304 --prot mac --key aabbccddeeff0011"
],
"offline": false,
"options": [
"-h, --help This help",
"--fid <hex> SFI reference byte (1 byte, 1-30)",
"--data <hex> record data to append",
"--prot <type> protection: none(def) mac enc",
"--key <hex> line-protection key (8 or 16 bytes)",
"-k, --keep keep field ON after command",
"-a, --apdu show APDU requests and responses"
],
"usage": "hf fmcos append [-hka] --fid <hex> --data <hex> [--prot <type>] [--key <hex>]"
},
"hf fmcos authexternal": {
"command": "hf fmcos authexternal",
"description": "EXTERNAL AUTHENTICATE. Requests a challenge from the card, encrypts it with the provided DES (8-byte) or 3DES (16-byte) key, then sends EXTERNAL AUTHENTICATE.",
"notes": [
"hf fmcos authexternal --id 0 --key ffffffffffffffff",
"hf fmcos authexternal --id 1 --key 0102030405060708090a0b0c0d0e0f10"
],
"offline": false,
"options": [
"-h, --help This help",
"--id <hex> key ID (P2 in EXTERNAL AUTHENTICATE)",
"--key <hex> DES key (8 bytes) or 3DES key (16 bytes)",
"-k, --keep keep field ON after command",
"-a, --apdu show APDU requests and responses"
],
"usage": "hf fmcos authexternal [-hka] --id <hex> --key <hex>"
},
"hf fmcos authinternal": {
"command": "hf fmcos authinternal",
"description": "INTERNAL AUTHENTICATE. Sends a challenge to the card and the card proves it knows the key.",
"notes": [
"hf fmcos authinternal --p1 00 --p2 00 --data 0102030405060708"
],
"offline": false,
"options": [
"-h, --help This help",
"--p1 <0-255> P1 parameter (default 0)",
"--p2 <0-255> P2 parameter / key ID (default 0)",
"--data <hex> challenge data (8 bytes)",
"-k, --keep keep field ON after command",
"-a, --apdu show APDU requests and responses"
],
"usage": "hf fmcos authinternal [-hka] [--p1 <0-255>] [--p2 <0-255>] --data <hex>"
},
"hf fmcos balance": {
"command": "hf fmcos balance",
"description": "GET BALANCE - read wallet or passbook balance",
"notes": [
"hf fmcos balance --type wallet",
"hf fmcos balance --type passbook"
],
"offline": false,
"options": [
"-h, --help This help",
"--type <type> balance type: wallet, passbook",
"-k, --keep keep field ON after command"
],
"usage": "hf fmcos balance [-hk] --type <type>"
},
"hf fmcos block": {
"command": "hf fmcos block",
"description": "BLOCK the card or an application. Uses the line-protection key to generate a MAC. One of --card or --app is required. Application block type: --perm (permanent) or --temp (temporary, default).",
"notes": [
"hf fmcos block --card --key aabbccddeeff0011",
"hf fmcos block --app --perm --key aabbccddeeff001122334455667788aa"
],
"offline": false,
"options": [
"-h, --help This help",
"--card block the entire card (CARD BLOCK, INS 16)",
"--app block the current application (APP BLOCK, INS 1E)",
"--perm permanent application block (default is temporary)",
"--key <hex> line-protection key (8 or 16 bytes)",
"-k, --keep keep field ON after command",
"-a, --apdu show APDU requests and responses"
],
"usage": "hf fmcos block [-hka] [--card] [--app] [--perm] --key <hex>"
},
"hf fmcos createdir": {
"command": "hf fmcos createdir",
"description": "CREATE DIRECTORY (DF) inside the currently selected directory",
"notes": [
"hf fmcos createdir --id 3F01 --space 200 --cperm F0 --eperm F0 --appid 95 --name 77616C6C6574546573740A"
],
"offline": false,
"options": [
"-h, --help This help",
"--id <4hex> 2-byte file ID",
"--space <hex> space to allocate for DF (bytes, hex, e.g. 200 = 512)",
"--cperm <hex> create permission byte",
"--eperm <hex> erase permission byte",
"--appid <hex> application ID byte",
"--name <hex> DF name / AID, 0-16 bytes",
"-k, --keep keep field ON after command",
"-a, --apdu show APDU requests and responses"
],
"usage": "hf fmcos createdir [-hka] --id <4hex> --space <hex> --cperm <hex> --eperm <hex> --appid <hex> [--name <hex>]"
},
"hf fmcos createfile": {
"command": "hf fmcos createfile",
"description": "CREATE EF in the current DF Types: bin(0x28) fix(0x2A) var(0x2C) loop(0x2E) wallet(0x2F) Prot: none mac(0x80) enc(0xC0) -- ORed into the type byte For wallet/passbook type: --rperm=usage rights, --wperm ignored (EDEP write always 0x00), --access=loop file link (low byte of the linked loop EF's file ID)",
"notes": [
"hf fmcos createfile --id 0101 --type bin --size 32 --rperm FF --wperm FF --access 00",
"hf fmcos createfile --id 0018 --type loop --size 0517 --rperm F0 --wperm EF --access FF",
"hf fmcos createfile --id 0002 --type wallet --size 0208 --rperm F0 --wperm 00 --access 18"
],
"offline": false,
"options": [
"-h, --help This help",
"--id <4hex> 2-byte file ID",
"--type <type> file type: bin fix var loop wallet",
"--size <hex> file size in bytes (hex, e.g. 0208 = 520)",
"--rperm <hex> read permission byte",
"--wperm <hex> write permission byte",
"--access <hex> access rights byte",
"--prot <type> line protection: none(def) mac enc",
"-k, --keep keep field ON after command",
"-a, --apdu show APDU requests and responses"
],
"usage": "hf fmcos createfile [-hka] --id <4hex> --type <type> --size <hex> --rperm <hex> --wperm <hex> --access <hex> [--prot <type>]"
},
"hf fmcos createkeyfile": {
"command": "hf fmcos createkeyfile",
"description": "CREATE KEYFILE in the current DF",
"notes": [
"hf fmcos createkeyfile --id 0000 --space 200 --dfsid 95 --perm F0"
],
"offline": false,
"options": [
"-h, --help This help",
"--id <4hex> 2-byte file ID (usually 0000)",
"--space <hex> space to allocate (bytes, hex, e.g. 200 = 512)",
"--dfsid <hex> DF SID byte",
"--perm <hex> key permission byte",
"-k, --keep keep field ON after command",
"-a, --apdu show APDU requests and responses"
],
"usage": "hf fmcos createkeyfile [-hka] --id <4hex> --space <hex> --dfsid <hex> --perm <hex>"
},
"hf fmcos credit": {
"command": "hf fmcos credit",
"description": "ADD CREDIT to wallet or passbook (two-phase with MAC/TAC verification). Phase 1: card returns old balance, serial, RNG; derive process key, verify MAC1. Phase 2: send date/time and MAC2; card returns TAC which is verified.",
"notes": [
"hf fmcos credit --type wallet --id 01 --amount 1000",
"--terminal 010203040506",
"--key 00112233445566778899aabbccddeeff",
"--ikey aabbccddeeff00112233445566778899"
],
"offline": false,
"options": [
"-h, --help This help",
"--type <type> balance type: wallet, passbook",
"--id <hex> credit key file ID (1 byte)",
"--amount <n> credit amount",
"--terminal <hex> terminal ID (6 bytes)",
"--key <hex> credit key (16 bytes)",
"--ikey <hex> internal key (16 bytes, for TAC verification)",
"-k, --keep keep field ON after command"
],
"usage": "hf fmcos credit [-hk] --type <type> --id <hex> --amount <n> --terminal <hex> --key <hex> --ikey <hex>"
},
"hf fmcos erase": {
"command": "hf fmcos erase",
"description": "ERASE DF - erase all EFs in the currently selected DF",
"notes": [
"hf fmcos erase"
],
"offline": false,
"options": [
"-h, --help This help",
"-k, --keep keep field ON after command",
"-a, --apdu show APDU requests and responses"
],
"usage": "hf fmcos erase [-hka]"
},
"hf fmcos help": {
"command": "hf fmcos help",
"description": "help This help -------- --------- Card information --------- -------- --------- File management ---------- -------- --------- Data access -------------- -------- --------- Authentication ----------- -------- --------- PIN management ----------- -------- --------- Financial ---------------- -------- --------- TID provisioning ---------- -------- --------- TID file creation --------- --------------------------------------------------------------------------------------- hf fmcos info available offline: no Detect and print information about an FMCOS CPU card. Selects the Master File (3F00) and parses the FCI TLV response.",
"notes": [
"hf fmcos info",
"hf fmcos info -a"
],
"offline": true,
"options": [
"-h, --help This help",
"-a, --apdu show APDU requests and responses"
],
"usage": "hf fmcos info [-ha]"
},
"hf fmcos history": {
"command": "hf fmcos history",
"description": "Read transaction history records from a loop (cyclic) EF. Each record is 23 bytes: serial[2] | od_limit[3] | amount[4] | type[1] | terminal[6] | date[4] | time[3] Record 1 is the most recent. Reading stops when the card returns a non-9000 SW.",
"notes": [
"hf fmcos history --fid 18",
"hf fmcos history --fid 19 --count 20"
],
"offline": false,
"options": [
"-h, --help This help",
"--fid <hex> loop file SFI (1 byte, e.g. 18 for wallet, 19 for passbook)",
"--count <n> max records to read (default 10, 0=read all up to 255)",
"-k, --keep keep field ON after command",
"-a, --apdu show APDU requests and responses"
],
"usage": "hf fmcos history [-hka] --fid <hex> [--count <n>]"
},
"hf fmcos key": {
"command": "hf fmcos key",
"description": "WRITE KEY to the currently selected keyfile (INS D4) Key types - Group A (need --change --version --algo): desenc desdec desmac internal overdraft debit purchase credit Group B (need --followup --errcount; extauth also needs --change): extauth pin Group C (need --change --errcount): lineprotect unlockpin changepin Use --authkey with --prot mac|enc to protect the command.",
"notes": [
"hf fmcos key --op 01 --id 00 --type internal --usage F0 --change 02 --version 00 --algo 01 --key 3434343434343434343434343434343",
"hf fmcos key --op 01 --id 00 --type pin --usage F0 --followup 01 --errcount 33 --key 123456"
],
"offline": false,
"options": [
"-h, --help This help",
"--op <hex> authorization key slot (P1), e.g. 01",
"--id <hex> key slot to write (P2), e.g. 00",
"--type <type> key type (see above)",
"--usage <hex> usage rights byte",
"--change <hex> change rights byte (Group A/B-extauth/C)",
"--version <hex> key version byte (Group A)",
"--algo <hex> algorithm ID byte (Group A)",
"--followup <hex> follow-up status byte (Group B)",
"--errcount <hex> error counter byte (Group B/C)",
"--key <hex> key value (8 or 16 bytes; 2-6 bytes for pin type)",
"--authkey <hex> line-protect key for MAC/enc (8 or 16 bytes)",
"--prot <type> protection: none(def) mac enc",
"-k, --keep keep field ON after command",
"-a, --apdu show APDU requests and responses"
],
"usage": "hf fmcos key [-hka] --op <hex> --id <hex> --type <type> --usage <hex> [--change <hex>] [--version <hex>] [--algo <hex>] [--followup <hex>] [--errcount <hex>] --key <hex> [--authkey <hex>] [--prot <type>]"
},
"hf fmcos overdraft": {
"command": "hf fmcos overdraft",
"description": "UPDATE OVERDRAFT LIMIT on passbook (two-phase with MAC1/MAC2 verification). Phase 1: card returns balance, serial, old limit, RNG, MAC1; verify MAC1. Phase 2: send new limit, date/time, MAC2; card returns TAC (4 bytes). Provide --ikey (internal key DTK) to verify the TAC returned by the card.",
"notes": [
"hf fmcos overdraft --id 01 --limit 5000 --terminal 010203040506",
"--key 00112233445566778899aabbccddeeff",
"hf fmcos overdraft --id 01 --limit 5000 --terminal 010203040506",
"--key 00112233445566778899aabbccddeeff --ikey aabbccddeeff00112233445566778899"
],
"offline": false,
"options": [
"-h, --help This help",
"--id <hex> overdraft key file ID (1 byte)",
"--limit <n> new overdraft limit (24-bit max 16777215)",
"--terminal <hex> terminal ID (6 bytes)",
"--key <hex> overdraft key (16 bytes)",
"--ikey <hex> internal key DTK (16 bytes) for TAC verification (optional)",
"-k, --keep keep field ON after command"
],
"usage": "hf fmcos overdraft [-hk] --id <hex> --limit <n> --terminal <hex> --key <hex> [--ikey <hex>]"
},
"hf fmcos pinchange": {
"command": "hf fmcos pinchange",
"description": "CHANGE PIN (INS 5E P1=01) - change PIN with old PIN authorization Data sent: old_pin + 0xFF + new_pin",
"notes": [
"hf fmcos pinchange --id 00 --old 123456 --new 13371337"
],
"offline": false,
"options": [
"-h, --help This help",
"--id <hex> key slot (P2), 1 byte",
"--old <hex> old PIN bytes (2-6 bytes)",
"--new <hex> new PIN bytes (2-6 bytes)",
"-k, --keep keep field ON after command",
"-a, --apdu show APDU requests and responses"
],
"usage": "hf fmcos pinchange [-hka] --id <hex> --old <hex> --new <hex>"
},
"hf fmcos pinreset": {
"command": "hf fmcos pinreset",
"description": "RESET PIN (INS 5E P1=00) - set new PIN using change-PIN key Appends DES-MAC(new_pin, key_left XOR key_right) to the data.",
"notes": [
"hf fmcos pinreset --id 00 --pin 123456 --key aabbccddeeff001122334455667788aa"
],
"offline": false,
"options": [
"-h, --help This help",
"--id <hex> key slot (P2), 1 byte",
"--pin <hex> new PIN bytes (2-6 bytes)",
"--key <hex> change-PIN key (16 bytes)",
"-k, --keep keep field ON after command",
"-a, --apdu show APDU requests and responses"
],
"usage": "hf fmcos pinreset [-hka] --id <hex> --pin <hex> --key <hex>"
},
"hf fmcos pinunblock": {
"command": "hf fmcos pinunblock",
"description": "UNBLOCK PIN (INS 24) - unblock a locked PIN using the unlock-PIN key Data = encrypt([len|new_pin], unlock_key) + packet_MAC",
"notes": [
"hf fmcos pinunblock --id 00 --pin 123456 --key aabbccddeeff001122334455667788aa"
],
"offline": false,
"options": [
"-h, --help This help",
"--id <hex> PIN key slot (P1), 1 byte",
"--pin <hex> new PIN bytes (2-6 bytes)",
"--key <hex> unlock-PIN key (8 or 16 bytes)",
"-k, --keep keep field ON after command",
"-a, --apdu show APDU requests and responses"
],
"usage": "hf fmcos pinunblock [-hka] --id <hex> --pin <hex> --key <hex>"
},
"hf fmcos pinverify": {
"command": "hf fmcos pinverify",
"description": "VERIFY PIN (INS 20) - present PIN to the card",
"notes": [
"hf fmcos pinverify --id 00 --pin 123456",
"hf fmcos pinverify --id 00 --pin 1234"
],
"offline": false,
"options": [
"-h, --help This help",
"--id <hex> key slot (P2), 1 byte",
"--pin <hex> PIN bytes (2-6 bytes)",
"-k, --keep keep field ON after command",
"-a, --apdu show APDU requests and responses"
],
"usage": "hf fmcos pinverify [-hka] --id <hex> --pin <hex>"
},
"hf fmcos purchase": {
"command": "hf fmcos purchase",
"description": "PURCHASE from wallet or passbook (two-phase with process key/TAC verification). Phase 1: card returns balance, serial, RNG; derive process key, compute MAC1. Phase 2: send tx serial, date/time, MAC1; card returns TAC which is verified.",
"notes": [
"hf fmcos purchase --type wallet --id 02 --amount 100",
"--terminal 010203040506",
"--key 00112233445566778899aabbccddeeff",
"--ikey aabbccddeeff00112233445566778899",
"--serial 01020304"
],
"offline": false,
"options": [
"-h, --help This help",
"--type <type> balance type: wallet, passbook",
"--id <hex> purchase key file ID (1 byte)",
"--amount <n> purchase amount",
"--terminal <hex> terminal ID (6 bytes)",
"--key <hex> purchase key (16 bytes)",
"--ikey <hex> internal key (16 bytes, for TAC verification)",
"--serial <hex> transaction serial (4 bytes, default 00000001)",
"-k, --keep keep field ON after command"
],
"usage": "hf fmcos purchase [-hk] --type <type> --id <hex> --amount <n> --terminal <hex> --key <hex> --ikey <hex> [--serial <hex>]"
},
"hf fmcos readbinary": {
"command": "hf fmcos readbinary",
"description": "READ BINARY from the current transparent EF p1/p2 encode the file offset (p1=offset_hi, p2=offset_lo). Protection: none(def) mac enc",
"notes": [
"hf fmcos readbinary --p1 00 --p2 00 --len 16",
"hf fmcos readbinary --p1 00 --p2 00 --len 16 --prot mac --key aabbccddeeff0011"
],
"offline": false,
"options": [
"-h, --help This help",
"--p1 <hex> P1 byte (offset high)",
"--p2 <hex> P2 byte (offset low)",
"--len <n> number of bytes to read (0 = read all)",
"--prot <type> protection: none(def) mac enc",
"--key <hex> line-protection key (8 or 16 bytes)",
"-k, --keep keep field ON after command",
"-a, --apdu show APDU requests and responses"
],
"usage": "hf fmcos readbinary [-hka] --p1 <hex> --p2 <hex> --len <n> [--prot <type>] [--key <hex>]"
},
"hf fmcos readrecord": {
"command": "hf fmcos readrecord",
"description": "READ RECORD from the current record-based EF Protection: none(def) mac enc Use --tlv for variable-length (VAR) files: requests 2 extra bytes and strips the 00[len] TLV prefix from the response.",
"notes": [
"hf fmcos readrecord --rec 01 --fid 01 --len 20",
"hf fmcos readrecord --rec 01 --fid 06 --len 16 --tlv",
"hf fmcos readrecord --rec 01 --fid 01 --len 20 --prot mac --key aabbccddeeff0011"
],
"offline": false,
"options": [
"-h, --help This help",
"--rec <n> record number (1-based)",
"--fid <hex> SFI reference byte (1 byte, 1-30)",
"--len <n> record data length in bytes (without TLV overhead)",
"--prot <type> protection: none(def) mac enc",
"--key <hex> line-protection key (8 or 16 bytes)",
"--tlv wrap/unwrap TLV (00[len][data]) for variable-length records",
"-k, --keep keep field ON after command",
"-a, --apdu show APDU requests and responses"
],
"usage": "hf fmcos readrecord [-hka] --rec <n> --fid <hex> --len <n> [--prot <type>] [--key <hex>] [--tlv]"
},
"hf fmcos select": {
"command": "hf fmcos select",
"description": "SELECT FILE by 2-byte ID or AID name. Activates the RF field, selects the file, then drops the field.",
"notes": [
"hf fmcos select --id 3f00",
"hf fmcos select --id 5f00 -v",
"hf fmcos select --name 325041592e5359532e4444463031"
],
"offline": false,
"options": [
"-h, --help This help",
"--id <hex> 2-byte file ID (4 hex chars)",
"--name <hex> AID / DF name bytes (up to 16 bytes)",
"-k, --keep keep field ON after command",
"-v, --verbose print full FCI TLV response",
"-a, --apdu show APDU requests and responses"
],
"usage": "hf fmcos select [-hkva] [--id <hex>] [--name <hex>]"
},
"hf fmcos tidcreatebin": {
"command": "hf fmcos tidcreatebin",
"description": "CREATE binary EF or KEYFILE using TID format (P1=02, FID in data, fixed Lc=11). Use --type keyfile to create the fixed TID keyfile in the currently selected DF. Note: TID CREATE EF has a different layout from standard 'hf fmcos createfile'.",
"notes": [
"hf fmcos tidcreatebin --id 0001 --size 0100 --sfi 01",
"hf fmcos tidcreatebin --id 0002 --size 0040 --sfi 02 --rperm 20 --wperm f0",
"hf fmcos tidcreatebin --type keyfile"
],
"offline": false,
"options": [
"-h, --help This help",
"--type <type> file type: bin (default) or keyfile",
"--id <4hex> 2-byte file ID (required for type bin)",
"--size <hex> file size in bytes (required for type bin)",
"--sfi <hex> short file ID, 1 byte (required for type bin)",
"--rperm <hex> read permission byte (default F0, bin only)",
"--wperm <hex> write permission byte (default F0, bin only)",
"-k, --keep keep field ON after command"
],
"usage": "hf fmcos tidcreatebin [-hk] [--type <type>] [--id <4hex>] [--size <hex>] [--sfi <hex>] [--rperm <hex>] [--wperm <hex>]"
},
"hf fmcos tidcreatedf": {
"command": "hf fmcos tidcreatedf",
"description": "CREATE sub-DF using TID format (P1=01, FID in data). Note: TID CREATE DF has a different layout from standard 'hf fmcos createdir'.",
"notes": [
"hf fmcos tidcreatedf --id 3f01 --size 0f00 --sfi 96 --name 44444630 31"
],
"offline": false,
"options": [
"-h, --help This help",
"--id <4hex> 2-byte file ID",
"--size <hex> DF space in bytes (hex, e.g. 0f00)",
"--sfi <hex> short file ID (1 byte)",
"--name <hex> DF name bytes (variable, 0-16 bytes)",
"-k, --keep keep field ON after command"
],
"usage": "hf fmcos tidcreatedf [-hk] --id <4hex> --size <hex> --sfi <hex> [--name <hex>]"
},
"hf fmcos tidcreaterec": {
"command": "hf fmcos tidcreaterec",
"description": "CREATE fixed-length record EF using TID format (P1=02, subtype=01, FID in data, fixed Lc=11). Note: TID CREATE EF has a different layout from standard 'hf fmcos createfile'.",
"notes": [
"hf fmcos tidcreaterec --id 0003 --count 04 --reclen 08 --sfi 03",
"hf fmcos tidcreaterec --id 0003 --count 04 --reclen 10 --sfi 03 --rperm 20 --wperm f0"
],
"offline": false,
"options": [
"-h, --help This help",
"--id <4hex> 2-byte file ID",
"--count <hex> number of records (1 byte)",
"--reclen <hex> bytes per record (1 byte)",
"--sfi <hex> short file ID (1 byte)",
"--rperm <hex> read permission byte (default F0)",
"--wperm <hex> write permission byte (default F0)",
"-k, --keep keep field ON after command"
],
"usage": "hf fmcos tidcreaterec [-hk] --id <4hex> --count <hex> --reclen <hex> --sfi <hex> [--rperm <hex>] [--wperm <hex>]"
},
"hf fmcos tiderase": {
"command": "hf fmcos tiderase",
"description": "Erase the TID card file system (CLA=E0 INS=EC -- irreversible).",
"notes": [
"hf fmcos tiderase"
],
"offline": false,
"options": [
"-h, --help This help",
"-k, --keep keep field ON after command"
],
"usage": "hf fmcos tiderase [-hk]"
},
"hf fmcos tidprovision": {
"command": "hf fmcos tidprovision",
"description": "Full TID card provisioning sequence: SET CARD -> SET UID -> SET INTERNAL AUTH -> ERASE -> SELECT MF -> CREATE MF (3F00, 1PAY.SYS.DDF01) -> SELECT MF -> CREATE KEYFILE",
"notes": [
"hf fmcos tidprovision --uid 13371337 --key 1122334455667788",
"hf fmcos tidprovision --uid 13371337 --key 1122334455667788 --lock"
],
"offline": false,
"options": [
"-h, --help This help",
"--uid <hex> UID bytes (4-7 bytes)",
"--key <hex> internal auth key (8 bytes)",
"--lock lock the auth key permanently",
"-k, --keep keep field ON after command"
],
"usage": "hf fmcos tidprovision [-hk] --uid <hex> --key <hex> [--lock]"
},
"hf fmcos tidsetauth": {
"command": "hf fmcos tidsetauth",
"description": "Write the TID internal authentication key and set the lock state. Lock byte: 0xAA = locked (permanent), 0x55 = unlocked (default).",
"notes": [
"hf fmcos tidsetauth --key 1122334455667788",
"hf fmcos tidsetauth --key 1122334455667788 --lock"
],
"offline": false,
"options": [
"-h, --help This help",
"--key <hex> internal auth key (8 bytes)",
"--lock lock the key permanently (0xAA); default unlocked (0x55)",
"-k, --keep keep field ON after command"
],
"usage": "hf fmcos tidsetauth [-hk] --key <hex> [--lock]"
},
"hf fmcos tidsetcard": {
"command": "hf fmcos tidsetcard",
"description": "Send the TID SET CARD configuration APDU (fixed 39-byte payload).",
"notes": [
"hf fmcos tidsetcard"
],
"offline": false,
"options": [
"-h, --help This help",
"-k, --keep keep field ON after command"
],
"usage": "hf fmcos tidsetcard [-hk]"
},
"hf fmcos tidsetuid": {
"command": "hf fmcos tidsetuid",
"description": "Program the TID card UID (4-7 bytes).",
"notes": [
"hf fmcos tidsetuid --uid 13371337",
"hf fmcos tidsetuid --uid 0102030405060708"
],
"offline": false,
"options": [
"-h, --help This help",
"--uid <hex> UID bytes (4-7 bytes)",
"-k, --keep keep field ON after command"
],
"usage": "hf fmcos tidsetuid [-hk] --uid <hex>"
},
"hf fmcos unblock": {
"command": "hf fmcos unblock",
"description": "UNBLOCK the current application (APP UNBLOCK, INS 18). Uses the line-protection key to generate a MAC.",
"notes": [
"hf fmcos unblock --key aabbccddeeff0011",
"hf fmcos unblock --key aabbccddeeff001122334455667788aa"
],
"offline": false,
"options": [
"-h, --help This help",
"--key <hex> line-protection key (8 or 16 bytes)",
"-k, --keep keep field ON after command",
"-a, --apdu show APDU requests and responses"
],
"usage": "hf fmcos unblock [-hka] --key <hex>"
},
"hf fmcos writebinary": {
"command": "hf fmcos writebinary",
"description": "UPDATE BINARY in the current transparent EF Protection: none(def) mac enc",
"notes": [
"hf fmcos writebinary --p1 00 --p2 00 --data 0102030405060708",
"hf fmcos writebinary --p1 00 --p2 00 --data 01020304 --prot mac --key aabbccddeeff0011"
],
"offline": false,
"options": [
"-h, --help This help",
"--p1 <hex> P1 byte (offset high)",
"--p2 <hex> P2 byte (offset low)",
"--data <hex> data to write",
"--prot <type> protection: none(def) mac enc",
"--key <hex> line-protection key (8 or 16 bytes)",
"-k, --keep keep field ON after command",
"-a, --apdu show APDU requests and responses"
],
"usage": "hf fmcos writebinary [-hka] --p1 <hex> --p2 <hex> --data <hex> [--prot <type>] [--key <hex>]"
},
"hf fmcos writerecord": {
"command": "hf fmcos writerecord",
"description": "UPDATE RECORD in the current record-based EF Protection: none(def) mac enc Use --tlv for variable-length (VAR) files: wraps data as 00[len][data] before sending.",
"notes": [
"hf fmcos writerecord --rec 01 --fid 01 --data 0102030405060708",
"hf fmcos writerecord --rec 01 --fid 06 --data 0102030405060708 --tlv",
"hf fmcos writerecord --rec 01 --fid 01 --data 01020304 --prot mac --key aabbccddeeff0011"
],
"offline": false,
"options": [
"-h, --help This help",
"--rec <n> record number (1-based)",
"--fid <hex> SFI reference byte (1 byte, 1-30)",
"--data <hex> record data to write",
"--prot <type> protection: none(def) mac enc",
"--key <hex> line-protection key (8 or 16 bytes)",
"--tlv wrap data as 00[len][data] TLV for variable-length records",
"-k, --keep keep field ON after command",
"-a, --apdu show APDU requests and responses"
],
"usage": "hf fmcos writerecord [-hka] --rec <n> --fid <hex> --data <hex> [--prot <type>] [--key <hex>] [--tlv]"
},
"hf fudan dump": {
"command": "hf fudan dump",
"description": "Dump FUDAN tag to file (bin/json) If no <name> given, UID will be used as filename",
@@ -3537,7 +4144,7 @@
},
"hf help": {
"command": "hf help",
"description": "-------- ----------------------- High Frequency ----------------------- 14a { ISO14443A RFIDs... } 14b { ISO14443B RFIDs... } 15 { ISO15693 RFIDs... } aliro { ALIRO digital access credentials... } calypso { Calypso transport cards... } cipurse { Cipurse transport Cards... } epa { German Identification Card... } emrtd { Machine Readable Travel Document... } felica { ISO18092 / FeliCa RFIDs... } fido { FIDO and FIDO2 authenticators... } fudan { Fudan RFIDs... } gallagher { Gallagher DESFire RFIDs... } gst { Google Smart Tap passes... } secc { iClass SE Config Card Emulator... } iclass { ICLASS RFIDs... } ict { ICT MFC/DESfire RFIDs... } jooki { Jooki RFIDs... } ksx6924 { KS X 6924 (T-Money, Snapper+) RFIDs } legic { LEGIC RFIDs... } lto { LTO Cartridge Memory RFIDs... } mf { MIFARE RFIDs... } mfp { MIFARE Plus RFIDs... } mfu { MIFARE Ultralight RFIDs... } mfdes { MIFARE Desfire RFIDs... } ntag424 { NXP NTAG 4242 DNA RFIDs... } saflok { Saflok MFC RFIDs... } seos { SEOS RFIDs... } st25ta { ST25TA RFIDs... } tesla { TESLA Cards... } texkom { Texkom RFIDs... } thinfilm { Thinfilm RFIDs... } topaz { TOPAZ (NFC Type 1) RFIDs... } vas { Apple Value Added Service... } waveshare { Waveshare NFC ePaper... } xerox { Fuji/Xerox cartridge RFIDs... } ----------- --------------------- General --------------------- help This help list List protocol data in trace buffer search Search for known HF tags --------------------------------------------------------------------------------------- hf list available offline: yes Alias of `trace list -t raw` with selected protocol data to annotate trace buffer You can load a trace from file (see `trace load -h`) or it be downloaded from device by default It accepts all other arguments of `trace list`. Note that some might not be relevant for this specific protocol",
"description": "-------- ----------------------- High Frequency ----------------------- 14a { ISO14443A RFIDs... } 14b { ISO14443B RFIDs... } 15 { ISO15693 RFIDs... } aliro { ALIRO digital access credentials... } calypso { Calypso transport cards... } cipurse { Cipurse transport Cards... } epa { German Identification Card... } emrtd { Machine Readable Travel Document... } felica { ISO18092 / FeliCa RFIDs... } fido { FIDO and FIDO2 authenticators... } fmcos { FMCOS CPU cards... } fudan { Fudan RFIDs... } gallagher { Gallagher DESFire RFIDs... } gst { Google Smart Tap passes... } secc { iClass SE Config Card Emulator... } iclass { ICLASS RFIDs... } ict { ICT MFC/DESfire RFIDs... } jooki { Jooki RFIDs... } ksx6924 { KS X 6924 (T-Money, Snapper+) RFIDs } legic { LEGIC RFIDs... } lto { LTO Cartridge Memory RFIDs... } mf { MIFARE RFIDs... } mfp { MIFARE Plus RFIDs... } mfu { MIFARE Ultralight RFIDs... } mfdes { MIFARE Desfire RFIDs... } ntag424 { NXP NTAG 4242 DNA RFIDs... } saflok { Saflok MFC RFIDs... } seos { SEOS RFIDs... } st25ta { ST25TA RFIDs... } tesla { TESLA Cards... } texkom { Texkom RFIDs... } thinfilm { Thinfilm RFIDs... } topaz { TOPAZ (NFC Type 1) RFIDs... } vas { Apple Value Added Service... } waveshare { Waveshare NFC ePaper... } xerox { Fuji/Xerox cartridge RFIDs... } ----------- --------------------- General --------------------- help This help list List protocol data in trace buffer search Search for known HF tags --------------------------------------------------------------------------------------- hf list available offline: yes Alias of `trace list -t raw` with selected protocol data to annotate trace buffer You can load a trace from file (see `trace load -h`) or it be downloaded from device by default It accepts all other arguments of `trace list`. Note that some might not be relevant for this specific protocol",
"notes": [
"hf list --frame -> show frame delay times",
"hf list -1 -> use trace buffer"
@@ -3662,7 +4269,7 @@
},
"hf iclass decrypt": {
"command": "hf iclass decrypt",
"description": "3DES decrypt data This is a naive implementation, it tries to decrypt every block after block 6. Correct behaviour would be to decrypt only the application areas where the key is valid, which is defined by the configuration block. OBS! In order to use this function, the file `iclass_decryptionkey.bin` must reside in the resources directory. The file must be 16 bytes binary data or... make sure your cardhelper is placed in the sim module",
"description": "DES/3DES decrypt data This is a naive implementation, it tries to decrypt every block after block 6. Correct behaviour would be to decrypt only the application areas where the key is valid, which is defined by the configuration block. OBS! In order to use this function, the file `iclass_decryptionkey.bin` must reside in the resources directory. The file must be 16 bytes binary data or... make sure your cardhelper is placed in the sim module",
"notes": [
"hf iclass decrypt -f hf-iclass-AA162D30F8FF12F1-dump.bin",
"hf iclass decrypt -f hf-iclass-AA162D30F8FF12F1-dump.bin -k 000102030405060708090a0b0c0d0e0f",
@@ -3672,14 +4279,15 @@
"options": [
"-h, --help This help",
"-f, --file <fn> Specify a filename for dump file",
"-d, --data <hex> 3DES encrypted data",
"-k, --key <hex> 3DES transport key",
"-d, --data <hex> DES/3DES encrypted data",
"-k, --key <hex> DES/3DES transport key",
"--enc [des|2k3des] transport encryption mode",
"-v, --verbose verbose output",
"--d6 decode as block 6",
"-z, --dense dense dump output style",
"--ns no save to file"
],
"usage": "hf iclass decrypt [-hvz] [-f <fn>] [-d <hex>] [-k <hex>] [--d6] [--ns]"
"usage": "hf iclass decrypt [-hvz] [-f <fn>] [-d <hex>] [-k <hex>] [--enc [des|2k3des]] [--d6] [--ns]"
},
"hf iclass dump": {
"command": "hf iclass dump",
@@ -3752,13 +4360,14 @@
"-w, --wiegand <format> see `wiegand list` for available formats",
"--emu Write to emulation memory instead of card",
"--shallow use shallow (ASK) reader modulation instead of OOK",
"-v verbose (print encoded blocks)"
"-v verbose (print encoded blocks)",
"--enc [none|des|2k3des] transport encryption mode"
],
"usage": "hf iclass encode [-hv] [--bin <bin>] [--ki <dec>] [-k <hex>] [--credit] [--elite] [--raw] [--enckey <hex>] [--fc <dec>] [--cn <dec>] [--issue <dec>] [-w <format>] [--emu] [--shallow]"
"usage": "hf iclass encode [-hv] [--bin <bin>] [--ki <dec>] [-k <hex>] [--credit] [--elite] [--raw] [--enckey <hex>] [--fc <dec>] [--cn <dec>] [--issue <dec>] [-w <format>] [--emu] [--shallow] [--enc [none|des|2k3des]]"
},
"hf iclass encrypt": {
"command": "hf iclass encrypt",
"description": "3DES encrypt data OBS! In order to use this function, the file 'iclass_decryptionkey.bin' must reside in the resources directory. The file should be 16 hex bytes of binary data",
"description": "DES/3DES encrypt data OBS! In order to use this function, the file 'iclass_decryptionkey.bin' must reside in the resources directory. The file should be 16 hex bytes of binary data",
"notes": [
"hf iclass encrypt -d 0102030405060708",
"hf iclass encrypt -d 0102030405060708 -k 00112233445566778899AABBCCDDEEFF"
@@ -3767,10 +4376,11 @@
"options": [
"-h, --help This help",
"-d, --data <hex> data to encrypt",
"-k, --key <hex> 3DES transport key",
"-k, --key <hex> DES/3DES transport key",
"--enc [des|2k3des] transport encryption mode",
"-v, --verbose verbose output"
],
"usage": "hf iclass encrypt [-hv] -d <hex> [-k <hex>]"
"usage": "hf iclass encrypt [-hv] -d <hex> [-k <hex>] [--enc [des|2k3des]]"
},
"hf iclass esave": {
"command": "hf iclass esave",
@@ -4102,6 +4712,8 @@
"notes": [
"hf iclass tagsim --fc 101 --cn 1337",
"hf iclass tagsim -w H10301 --fc 101 --cn 1337 --ki 0",
"hf iclass tagsim -w H10301 --fc 101 --cn 1337 --enc none",
"hf iclass tagsim -w H10301 --fc 101 --cn 1337 --enc des",
"hf iclass tagsim -w H10301 --fc 101 --cn 1337 --kd 0102030405060708 --elite",
"hf iclass tagsim --bin 10001111100000001010100011 --ki 0",
"hf iclass tagsim -w H10301 --fc 101 --cn 1337 --ki 0 --enckey 00000000000000000000000000000000"
@@ -4121,9 +4733,10 @@
"--elite Elite key diversification",
"--raw Keys are already diversified, skip diversification",
"--csn <hex> Custom CSN, 8 hex bytes (auto-generated if omitted)",
"--enckey <hex> 3DES transport key, 16 hex bytes"
"--enckey <hex> 3DES transport key, 16 hex bytes",
"--enc <none|des|2k3des> credential transport mode (default: 2k3des)"
],
"usage": "hf iclass tagsim [-h] [-w <format>] [--fc <dec>] [--cn <dec>] [--issue <dec>] [--bin <bin>] [--kd <hex>] [--kc <hex>] [--ki <dec>] [--ci <dec>] [--elite] [--raw] [--csn <hex>] [--enckey <hex>]"
"usage": "hf iclass tagsim [-h] [-w <format>] [--fc <dec>] [--cn <dec>] [--issue <dec>] [--bin <bin>] [--kd <hex>] [--kc <hex>] [--ki <dec>] [--ci <dec>] [--elite] [--raw] [--csn <hex>] [--enckey <hex>] [--enc <none|des|2k3des>]"
},
"hf iclass tear": {
"command": "hf iclass tear",
@@ -4559,6 +5172,22 @@
],
"usage": "hf legic list [-h1crux] [--frame] [-f <fn>]"
},
"hf legic migrate": {
"command": "hf legic migrate",
"description": "Clone a LEGIC Prime dump to the currently attached tag. Optionally apply a DCF update after cloning, but only when explicitly requested.",
"notes": [
"hf legic migrate -f src.bin",
"hf legic migrate -f src.bin --dcf 60EA --danger"
],
"offline": false,
"options": [
"-h, --help This help",
"-f, --file <fn> Source dump file",
"--dcf <hex> Optional DCF bytes to write after clone",
"--danger Allow the explicit DCF write"
],
"usage": "hf legic migrate [-h] -f <fn> [--dcf <hex>] [--danger]"
},
"hf legic rdbl": {
"command": "hf legic rdbl",
"description": "Read data from a LEGIC Prime tag",
@@ -4591,7 +5220,7 @@
},
"hf legic restore": {
"command": "hf legic restore",
"description": "Reads (bin/eml/json) file and it autodetects card type and verifies that the file has the same size Then write the data back to card. All bytes except the first 7bytes [UID(4) MCC(1) DCF(2)]",
"description": "Restore an exact LEGIC Prime dump back to the same card family. This writes the dump bytes back as-is (except the first 7 bytes [UID(4) MCC(1) DCF(2)] are preserved from the target card).",
"notes": [
"hf legic restore -f myfile -> use user specified filename",
"hf legic restore -f myfile --ob -> use UID as filename and obfuscate data"
@@ -7578,7 +8207,7 @@
"description": "Executes AES authentication command for MIFARE Plus card",
"notes": [
"hf mfp auth --ki 4000 --key 000102030405060708090a0b0c0d0e0f -> executes authentication",
"hf mfp auth --ki 9003 --key FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF -v -> executes authentication and shows all the system data"
"hf mfp auth --ki 9003 --key FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF -v -> upgrades tag to SL3 and shows all the system data"
],
"offline": false,
"options": [
@@ -7692,10 +8321,11 @@
"--keys <fn> AES key file from `hf mfp chk --dump` (JSON)",
"-k, --key <hex> AES key for all sectors (16 hex bytes)",
"--mfc-keys <fn> MFC key file for SL1 sectors (.bin from `hf mf chk`)",
"--1k Chip is 1KB in size (Mifare Plus SE)",
"--ns No save to file",
"-v, --verbose Verbose output"
],
"usage": "hf mfp dump [-hv] [-f <fn>] [--keys <fn>] [-k <hex>] [--mfc-keys <fn>] [--ns]"
"usage": "hf mfp dump [-hv] [-f <fn>] [--keys <fn>] [-k <hex>] [--mfc-keys <fn>] [--1k] [--ns]"
},
"hf mfp help": {
"command": "hf mfp help",
@@ -7981,9 +8611,10 @@
"-k Keep field on (only if a key is provided)",
"-r, --retries <n> Number of retries with provided key (def: 0)",
"-n, --nocheck Skip checking tag answer correctness (only if a key is provided)",
"-0, --read0 Use fast READ0 (skip anticol)"
"-0, --read0 Use fast READ0 (skip anticol)",
"-c, --collect <n> Collect <n> nonces and show top 10 (def: 0, no collection)"
],
"usage": "hf mfu cauth [-hlkn0] [--key <hex>] [-r <n>]"
"usage": "hf mfu cauth [-hlkn0] [--key <hex>] [-r <n>] [-c <n>]"
},
"hf mfu cchk": {
"command": "hf mfu cchk",
@@ -8341,9 +8972,10 @@
"-n, --num <dec> Exit simulation after <numreads> blocks. 0 = infinite",
"-v, --verbose Verbose output",
"--1a1 <hex> <8|16> hex bytes ULC/ULAES Auth reply step1: ek(RndB)",
"--1a2 <hex> <8|16> hex bytes ULC/ULAES Auth reply step2: ek(RndA')"
"--1a2 <hex> <8|16> hex bytes ULC/ULAES Auth reply step2: ek(RndA')",
"--1a2-mirror Mirror ek(RndA) from step1 reply into step2 reply"
],
"usage": "hf mfu sim [-hv] -t <1..14> [-u <hex>] [-n <dec>] [--1a1 <hex>] [--1a2 <hex>]"
"usage": "hf mfu sim [-hv] -t <1..14> [-u <hex>] [-n <dec>] [--1a1 <hex>] [--1a2 <hex>] [--1a2-mirror]"
},
"hf mfu tamper": {
"command": "hf mfu tamper",
@@ -14739,8 +15371,8 @@
}
},
"metadata": {
"commands_extracted": 830,
"commands_extracted": 865,
"extracted_by": "PM3Help2JSON v1.00",
"extracted_on": "2026-05-21T19:04:15+00:00"
"extracted_on": "2026-06-07T20:59:30+00:00"
}
}
+43 -1
View File
@@ -296,7 +296,7 @@ Check column "offline" for their availability.
|------- |------- |-----------
|`hf calypso help `|Y |`This help`
|`hf calypso info `|N |`Tag information`
|`hf calypso dump `|N |`Dump readable files and records`
|`hf calypso dump `|N |`Dump nodes after application profile scan`
|`hf calypso probecmdcompat`|N |`Probe SELECT command compatibility`
|`hf calypso list `|Y |`List Calypso history`
@@ -393,6 +393,48 @@ Check column "offline" for their availability.
|`hf fido assert `|N |`FIDO2 GetAssertion command.`
### hf fmcos
{ FMCOS CPU cards... }
|command |offline |description
|------- |------- |-----------
|`hf fmcos help `|Y |`This help`
|`hf fmcos info `|N |`Detect card and print file-system info`
|`hf fmcos select `|N |`SELECT FILE by 2-byte ID or AID name`
|`hf fmcos erase `|N |`ERASE DF contents`
|`hf fmcos createdir `|N |`CREATE DIRECTORY (DF)`
|`hf fmcos createfile `|N |`CREATE EF (binary / fixed / variable / loop / wallet)`
|`hf fmcos createkeyfile `|N |`CREATE KEYFILE`
|`hf fmcos readbinary `|N |`READ BINARY from transparent EF`
|`hf fmcos readrecord `|N |`READ RECORD from record-based EF`
|`hf fmcos writebinary `|N |`UPDATE BINARY in transparent EF`
|`hf fmcos writerecord `|N |`UPDATE RECORD in record-based EF`
|`hf fmcos append `|N |`APPEND RECORD to cyclic / linear EF`
|`hf fmcos authexternal `|N |`EXTERNAL AUTHENTICATE using DES/3DES key`
|`hf fmcos authinternal `|N |`INTERNAL AUTHENTICATE (card proves key knowledge)`
|`hf fmcos key `|N |`WRITE KEY to keyfile`
|`hf fmcos pinverify `|N |`VERIFY PIN (present PIN to card)`
|`hf fmcos pinchange `|N |`CHANGE PIN (old + new, requires old PIN)`
|`hf fmcos pinreset `|N |`RESET PIN (new PIN + change-PIN key MAC)`
|`hf fmcos pinunblock `|N |`UNBLOCK PIN (encrypted new PIN + MAC)`
|`hf fmcos balance `|N |`GET BALANCE (wallet or passbook)`
|`hf fmcos credit `|N |`ADD CREDIT to wallet or passbook`
|`hf fmcos purchase `|N |`PURCHASE from wallet or passbook`
|`hf fmcos overdraft `|N |`UPDATE OVERDRAFT LIMIT`
|`hf fmcos history `|N |`READ transaction history from loop EF`
|`hf fmcos block `|N |`BLOCK card or application`
|`hf fmcos unblock `|N |`UNBLOCK application`
|`hf fmcos tidsetcard `|N |`SET CARD configuration block`
|`hf fmcos tidsetuid `|N |`SET UID`
|`hf fmcos tidsetauth `|N |`SET INTERNAL AUTH key`
|`hf fmcos tiderase `|N |`ERASE TID card file system`
|`hf fmcos tidprovision `|N |`Full TID provisioning sequence`
|`hf fmcos tidcreatedf `|N |`CREATE sub-DF (TID format)`
|`hf fmcos tidcreatebin `|N |`CREATE binary EF (TID format)`
|`hf fmcos tidcreaterec `|N |`CREATE record EF (TID format)`
### hf fudan
{ Fudan RFIDs... }
+63 -63
View File
@@ -176,79 +176,79 @@ static void *worker(void *arg) {
end = pool->total;
for (uint32_t idx = start; idx < end; idx++) {
if (key_found && !BENCHMARK_FULL_KEYSPACE)
break; // Some other thread already found the key.
// Convert the candidate index (28 bits) into 4 bytes.
// Each candidate byte is constructed from a 7-bit chunk shifted left by 1 so that the LSB is zero.
uint8_t b0 = ((idx) & 0x7F) << 1;
uint8_t b1 = ((idx >> 7) & 0x7F) << 1;
uint8_t b2 = ((idx >> 14) & 0x7F) << 1;
uint8_t b3 = ((idx >> 21) & 0x7F) << 1;
// Build the candidate half key by starting with the fixed base half and substituting candidate bytes.
DES_cblock candidate_half = {0};
memcpy(candidate_half, base_half, 8);
candidate_half[var_offset ] = b0;
candidate_half[var_offset + 1] = b1;
candidate_half[var_offset + 2] = b2;
candidate_half[var_offset + 3] = b3;
if (key_found && !BENCHMARK_FULL_KEYSPACE)
break; // Some other thread already found the key.
// Convert the candidate index (28 bits) into 4 bytes.
// Each candidate byte is constructed from a 7-bit chunk shifted left by 1 so that the LSB is zero.
uint8_t b0 = ((idx) & 0x7F) << 1;
uint8_t b1 = ((idx >> 7) & 0x7F) << 1;
uint8_t b2 = ((idx >> 14) & 0x7F) << 1;
uint8_t b3 = ((idx >> 21) & 0x7F) << 1;
// Build the candidate half key by starting with the fixed base half and substituting candidate bytes.
DES_cblock candidate_half = {0};
memcpy(candidate_half, base_half, 8);
candidate_half[var_offset ] = b0;
candidate_half[var_offset + 1] = b1;
candidate_half[var_offset + 2] = b2;
candidate_half[var_offset + 3] = b3;
// Compute the candidate half's DES key schedule.
DES_key_schedule candidate_schedule;
DES_set_key_unchecked(&candidate_half, &candidate_schedule);
// Compute the candidate half's DES key schedule.
DES_key_schedule candidate_schedule;
DES_set_key_unchecked(&candidate_half, &candidate_schedule);
// Perform 2-key triple DES decryption on the ciphertext.
// If candidate is in K1: decryption = DES_ecb3_encrypt(cipher, out, candidate, fixed, candidate, DES_DECRYPT)
// If candidate is in K2: decryption = DES_ecb3_encrypt(cipher, out, fixed, candidate, fixed, DES_DECRYPT)
if (candidate_in_K1) {
DES_ecb3_encrypt((DES_cblock *)targs->ciphertext, (DES_cblock *)&out,
&candidate_schedule, &fixed_schedule, &candidate_schedule, DES_DECRYPT);
} else {
DES_ecb3_encrypt((DES_cblock *)targs->ciphertext, (DES_cblock *)&out,
&fixed_schedule, &candidate_schedule, &fixed_schedule, DES_DECRYPT);
}
bool match = false;
if (targs->is_reader_mode) {
// In reader mode, also decrypt init_ciphertext and check for rotation relationship
// Apply XOR block to the second decrypted block (for CBC mode)
// Perform 2-key triple DES decryption on the ciphertext.
// If candidate is in K1: decryption = DES_ecb3_encrypt(cipher, out, candidate, fixed, candidate, DES_DECRYPT)
// If candidate is in K2: decryption = DES_ecb3_encrypt(cipher, out, fixed, candidate, fixed, DES_DECRYPT)
if (candidate_in_K1) {
DES_ecb3_encrypt((DES_cblock *)targs->init_ciphertext, (DES_cblock *)&init_out,
DES_ecb3_encrypt((DES_cblock *)targs->ciphertext, (DES_cblock *)&out,
&candidate_schedule, &fixed_schedule, &candidate_schedule, DES_DECRYPT);
} else {
DES_ecb3_encrypt((DES_cblock *)targs->init_ciphertext, (DES_cblock *)&init_out,
DES_ecb3_encrypt((DES_cblock *)targs->ciphertext, (DES_cblock *)&out,
&fixed_schedule, &candidate_schedule, &fixed_schedule, DES_DECRYPT);
}
// Apply XOR block to the second decrypted block (for CBC mode)
out ^= targs->prev_ciphertext_u64;
// Check if out is 8-bit (1-byte) left rotated version of init_out
// Need to convert to big-endian for byte rotation, then back to little-endian
uint64_t init_be = __builtin_bswap64(init_out);
uint64_t rotated_be = (init_be << 8) | (init_be >> 56);
uint64_t rotated = __builtin_bswap64(rotated_be);
match = (out == rotated);
} else {
// In counterfeit mode, check the resulting plaintext against LFSR
match = valid_lfsr(out, targs->lfsr_type);
}
bool match = false;
if (targs->is_reader_mode) {
// In reader mode, also decrypt init_ciphertext and check for rotation relationship
// Apply XOR block to the second decrypted block (for CBC mode)
if (candidate_in_K1) {
DES_ecb3_encrypt((DES_cblock *)targs->init_ciphertext, (DES_cblock *)&init_out,
&candidate_schedule, &fixed_schedule, &candidate_schedule, DES_DECRYPT);
} else {
DES_ecb3_encrypt((DES_cblock *)targs->init_ciphertext, (DES_cblock *)&init_out,
&fixed_schedule, &candidate_schedule, &fixed_schedule, DES_DECRYPT);
}
// Apply XOR block to the second decrypted block (for CBC mode)
out ^= targs->prev_ciphertext_u64;
if (match) {
key_found = 1; // signal to other threads
// Check if out is 8-bit (1-byte) left rotated version of init_out
// Need to convert to big-endian for byte rotation, then back to little-endian
uint64_t init_be = __builtin_bswap64(init_out);
uint64_t rotated_be = (init_be << 8) | (init_be >> 56);
uint64_t rotated = __builtin_bswap64(rotated_be);
match = (out == rotated);
} else {
// In counterfeit mode, check the resulting plaintext against LFSR
match = valid_lfsr(out, targs->lfsr_type);
}
// Build the full 16-byte key: start with the base key and substitute the candidate 4 bytes.
unsigned char full_key[KEY_SIZE];
memcpy(full_key, targs->base_key, KEY_SIZE);
int seg_offset = key_mode * 4; // key_mode: 0->bytes0, 1->bytes4, 2->bytes8, 3->bytes12.
full_key[seg_offset] = b0;
full_key[seg_offset + 1] = b1;
full_key[seg_offset + 2] = b2;
full_key[seg_offset + 3] = b3;
printf("Thread %d: Found key index: %u\n", targs->thread_id, idx);
printf("Full key (hex): ");
print_hex(full_key, KEY_SIZE);
if (!BENCHMARK_FULL_KEYSPACE)
break;
}
if (match) {
key_found = 1; // signal to other threads
// Build the full 16-byte key: start with the base key and substitute the candidate 4 bytes.
unsigned char full_key[KEY_SIZE];
memcpy(full_key, targs->base_key, KEY_SIZE);
int seg_offset = key_mode * 4; // key_mode: 0->bytes0, 1->bytes4, 2->bytes8, 3->bytes12.
full_key[seg_offset] = b0;
full_key[seg_offset + 1] = b1;
full_key[seg_offset + 2] = b2;
full_key[seg_offset + 3] = b3;
printf("Thread %d: Found key index: %u\n", targs->thread_id, idx);
printf("Full key (hex): ");
print_hex(full_key, KEY_SIZE);
if (!BENCHMARK_FULL_KEYSPACE)
break;
}
} // end slot inner loop
} // end pool slot loop
return NULL;
+1 -1
View File
@@ -12,4 +12,4 @@ $(TARGET): $(SOURCES) desbrute.h des_host.h
$(NVCC) $(NVCCFLAGS) -o $@ $(SOURCES)
clean:
rm -f $(TARGET)
rm -f $(TARGET)
+74 -73
View File
@@ -15,84 +15,92 @@
/* -------------------------------------------------------------------------- */
static const uint8_t H_PC1[56] = {
57,49,41,33,25,17, 9, 1, 58,50,42,34,26,18,
10, 2,59,51,43,35,27,19, 11, 3,60,52,44,36,
63,55,47,39,31,23,15, 7, 62,54,46,38,30,22,
14, 6,61,53,45,37,29,21, 13, 5,28,20,12, 4
57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18,
10, 2, 59, 51, 43, 35, 27, 19, 11, 3, 60, 52, 44, 36,
63, 55, 47, 39, 31, 23, 15, 7, 62, 54, 46, 38, 30, 22,
14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 28, 20, 12, 4
};
static const uint8_t H_PC2[48] = {
14,17,11,24, 1, 5, 3,28,15, 6,21,10,
23,19,12, 4,26, 8, 16, 7,27,20,13, 2,
41,52,31,37,47,55, 30,40,51,45,33,48,
44,49,39,56,34,53, 46,42,50,36,29,32
14, 17, 11, 24, 1, 5, 3, 28, 15, 6, 21, 10,
23, 19, 12, 4, 26, 8, 16, 7, 27, 20, 13, 2,
41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48,
44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32
};
static const uint8_t H_SHIFTS[16] = {
1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1
1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
};
static const uint8_t H_IP[64] = {
58,50,42,34,26,18,10, 2, 60,52,44,36,28,20,12, 4,
62,54,46,38,30,22,14, 6, 64,56,48,40,32,24,16, 8,
57,49,41,33,25,17, 9, 1, 59,51,43,35,27,19,11, 3,
61,53,45,37,29,21,13, 5, 63,55,47,39,31,23,15, 7
58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4,
62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48, 40, 32, 24, 16, 8,
57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, 27, 19, 11, 3,
61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7
};
static const uint8_t H_FP[64] = {
40, 8,48,16,56,24,64,32, 39, 7,47,15,55,23,63,31,
38, 6,46,14,54,22,62,30, 37, 5,45,13,53,21,61,29,
36, 4,44,12,52,20,60,28, 35, 3,43,11,51,19,59,27,
34, 2,42,10,50,18,58,26, 33, 1,41, 9,49,17,57,25
40, 8, 48, 16, 56, 24, 64, 32, 39, 7, 47, 15, 55, 23, 63, 31,
38, 6, 46, 14, 54, 22, 62, 30, 37, 5, 45, 13, 53, 21, 61, 29,
36, 4, 44, 12, 52, 20, 60, 28, 35, 3, 43, 11, 51, 19, 59, 27,
34, 2, 42, 10, 50, 18, 58, 26, 33, 1, 41, 9, 49, 17, 57, 25
};
static const uint8_t H_E[48] = {
32, 1, 2, 3, 4, 5, 4, 5, 6, 7, 8, 9,
8, 9,10,11,12,13, 12,13,14,15,16,17,
16,17,18,19,20,21, 20,21,22,23,24,25,
24,25,26,27,28,29, 28,29,30,31,32, 1
8, 9, 10, 11, 12, 13, 12, 13, 14, 15, 16, 17,
16, 17, 18, 19, 20, 21, 20, 21, 22, 23, 24, 25,
24, 25, 26, 27, 28, 29, 28, 29, 30, 31, 32, 1
};
static const uint8_t H_P[32] = {
16, 7,20,21,29,12,28,17,
1,15,23,26, 5,18,31,10,
2, 8,24,14,32,27, 3, 9,
19,13,30, 6,22,11, 4,25
16, 7, 20, 21, 29, 12, 28, 17,
1, 15, 23, 26, 5, 18, 31, 10,
2, 8, 24, 14, 32, 27, 3, 9,
19, 13, 30, 6, 22, 11, 4, 25
};
static const uint8_t H_SBOX[8][4][16] = {
{ {14,4,13,1,2,15,11,8,3,10,6,12,5,9,0,7}, /* S1 */
{0,15,7,4,14,2,13,1,10,6,12,11,9,5,3,8},
{4,1,14,8,13,6,2,11,15,12,9,7,3,10,5,0},
{15,12,8,2,4,9,1,7,5,11,3,14,10,0,6,13} },
{ {15,1,8,14,6,11,3,4,9,7,2,13,12,0,5,10}, /* S2 */
{3,13,4,7,15,2,8,14,12,0,1,10,6,9,11,5},
{0,14,7,11,10,4,13,1,5,8,12,6,9,3,2,15},
{13,8,10,1,3,15,4,2,11,6,7,12,0,5,14,9} },
{ {10,0,9,14,6,3,15,5,1,13,12,7,11,4,2,8}, /* S3 */
{13,7,0,9,3,4,6,10,2,8,5,14,12,11,15,1},
{13,6,4,9,8,15,3,0,11,1,2,12,5,10,14,7},
{1,10,13,0,6,9,8,7,4,15,14,3,11,5,2,12} },
{ {7,13,14,3,0,6,9,10,1,2,8,5,11,12,4,15}, /* S4 */
{13,8,11,5,6,15,0,3,4,7,2,12,1,10,14,9},
{10,6,9,0,12,11,7,13,15,1,3,14,5,2,8,4},
{3,15,0,6,10,1,13,8,9,4,5,11,12,7,2,14} },
{ {2,12,4,1,7,10,11,6,8,5,3,15,13,0,14,9}, /* S5 */
{14,11,2,12,4,7,13,1,5,0,15,10,3,9,8,6},
{4,2,1,11,10,13,7,8,15,9,12,5,6,3,0,14},
{11,8,12,7,1,14,2,13,6,15,0,9,10,4,5,3} },
{ {12,1,10,15,9,2,6,8,0,13,3,4,14,7,5,11}, /* S6 */
{10,15,4,2,7,12,9,5,6,1,13,14,0,11,3,8},
{9,14,15,5,2,8,12,3,7,0,4,10,1,13,11,6},
{4,3,2,12,9,5,15,10,11,14,1,7,6,0,8,13} },
{ {4,11,2,14,15,0,8,13,3,12,9,7,5,10,6,1}, /* S7 */
{13,0,11,7,4,9,1,10,14,3,5,12,2,15,8,6},
{1,4,11,13,12,3,7,14,10,15,6,8,0,5,9,2},
{6,11,13,8,1,4,10,7,9,5,0,15,14,2,3,12} },
{ {13,2,8,4,6,15,11,1,10,9,3,14,5,0,12,7}, /* S8 */
{1,15,13,8,10,3,7,4,12,5,6,11,0,14,9,2},
{7,11,4,1,9,12,14,2,0,6,10,13,15,3,5,8},
{2,1,14,7,4,10,8,13,15,12,9,0,3,5,6,11} }
{ {14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7}, /* S1 */
{0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8},
{4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0},
{15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13}
},
{ {15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10}, /* S2 */
{3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5},
{0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15},
{13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9}
},
{ {10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8}, /* S3 */
{13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1},
{13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7},
{1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12}
},
{ {7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15}, /* S4 */
{13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9},
{10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4},
{3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14}
},
{ {2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9}, /* S5 */
{14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6},
{4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14},
{11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3}
},
{ {12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11}, /* S6 */
{10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8},
{9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6},
{4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13}
},
{ {4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1}, /* S7 */
{13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6},
{1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2},
{6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12}
},
{ {13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7}, /* S8 */
{1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2},
{7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8},
{2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11}
}
};
/* -------------------------------------------------------------------------- */
@@ -100,8 +108,7 @@ static const uint8_t H_SBOX[8][4][16] = {
/* -------------------------------------------------------------------------- */
/* Convert 8-byte array (big-endian) → packed uint64 (byte 0 in bits 63-56) */
static inline uint64_t bytes_to_u64(const uint8_t *b)
{
static inline uint64_t bytes_to_u64(const uint8_t *b) {
return ((uint64_t)b[0] << 56) | ((uint64_t)b[1] << 48) |
((uint64_t)b[2] << 40) | ((uint64_t)b[3] << 32) |
((uint64_t)b[4] << 24) | ((uint64_t)b[5] << 16) |
@@ -112,8 +119,7 @@ static inline uint64_t bytes_to_u64(const uint8_t *b)
/* CPU DES primitives */
/* -------------------------------------------------------------------------- */
static inline uint64_t h_perm(uint64_t src, int src_bits, const uint8_t *tbl, int n)
{
static inline uint64_t h_perm(uint64_t src, int src_bits, const uint8_t *tbl, int n) {
uint64_t dst = 0;
int i;
for (i = 0; i < n; i++) {
@@ -123,8 +129,7 @@ static inline uint64_t h_perm(uint64_t src, int src_bits, const uint8_t *tbl, in
return dst;
}
static inline void h_des_keyschedule(uint64_t key64, uint64_t sk[16])
{
static inline void h_des_keyschedule(uint64_t key64, uint64_t sk[16]) {
uint64_t key56 = h_perm(key64, 64, H_PC1, 56);
uint32_t C = (uint32_t)(key56 >> 28) & 0x0FFFFFFFU;
uint32_t D = (uint32_t)(key56) & 0x0FFFFFFFU;
@@ -137,8 +142,7 @@ static inline void h_des_keyschedule(uint64_t key64, uint64_t sk[16])
}
}
static inline uint64_t h_des_crypt(uint64_t block, const uint64_t sk[16])
{
static inline uint64_t h_des_crypt(uint64_t block, const uint64_t sk[16]) {
uint64_t ip = h_perm(block, 64, H_IP, 64);
uint32_t L = (uint32_t)(ip >> 32);
uint32_t R = (uint32_t)(ip);
@@ -156,13 +160,13 @@ static inline uint64_t h_des_crypt(uint64_t block, const uint64_t sk[16])
}
uint32_t f = (uint32_t)h_perm((uint64_t)sout, 32, H_P, 32);
uint32_t nR = L ^ f;
L = R; R = nR;
L = R;
R = nR;
}
return h_perm(((uint64_t)R << 32) | L, 64, H_FP, 64);
}
static inline uint64_t h_des_decrypt(uint64_t block, const uint64_t sk[16])
{
static inline uint64_t h_des_decrypt(uint64_t block, const uint64_t sk[16]) {
uint64_t rsk[16];
int i;
for (i = 0; i < 16; i++) rsk[i] = sk[15 - i];
@@ -173,8 +177,7 @@ static inline uint64_t h_des_decrypt(uint64_t block, const uint64_t sk[16])
/* LFSR validators (input: BE uint64, byte 0 in bits 63-56) */
/* -------------------------------------------------------------------------- */
static inline int h_valid_lfsr_ulcg(uint64_t x64)
{
static inline int h_valid_lfsr_ulcg(uint64_t x64) {
/* x64 is already B0=MSB; original code bswap'd from OpenSSL LE, we skip that */
uint16_t x16 = (uint16_t)(x64 >> 48);
x16 = (uint16_t)(x16 << 15 | ((x16 >> 1) ^ ((x16 >> 3 ^ x16 >> 4 ^ x16 >> 6) & 1)));
@@ -186,8 +189,7 @@ static inline int h_valid_lfsr_ulcg(uint64_t x64)
return 1;
}
static inline int h_valid_lfsr_mfc(uint64_t x64)
{
static inline int h_valid_lfsr_mfc(uint64_t x64) {
uint16_t x16 = (uint16_t)(x64 & 0xFFFF);
int i;
for (i = 0; i < 16; i++)
@@ -207,8 +209,7 @@ static inline int h_valid_lfsr_mfc(uint64_t x64)
* Decrypts with the all-zero DES key and checks LFSR structure.
* Returns 1=ULCG, 2=MFC, 0=unknown.
*/
static inline int h_detect_lfsr(const uint8_t init_ciphertext[8])
{
static inline int h_detect_lfsr(const uint8_t init_ciphertext[8]) {
uint8_t zero_key[8];
uint64_t sk[16];
uint64_t ct, out;