This commit is contained in:
merlokk 2022-02-07 23:52:54 +02:00
commit 01761cc273
12 changed files with 1163 additions and 929 deletions

View file

@ -3,6 +3,10 @@ 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... 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] ## [unreleased][unreleased]
- Changed `hf_mf_uidbruteforce` - added support for S70, enhance UID length management (@cactuschibre)
- Fixed build issues that may happen from building `mfd_aes_brute` (@linuxgemini)
- Added silicon data parsing logic for NXP chips in `hf mfu info` (@linuxgemini)
- Addes luascript `hf_mf_em_util.lua` - Script for emulator configuration (@nisgola)
- Fixes `hf mf restore` - now takes bin/eml/json as dump files (@iceman1001) - Fixes `hf mf restore` - now takes bin/eml/json as dump files (@iceman1001)
- Fixes `script run some_python_script` segfault on armhf architecture (@doegox) - Fixes `script run some_python_script` segfault on armhf architecture (@doegox)
- Added `trace extract` - extract authentication parts from trace (@iceman1001) - Added `trace extract` - extract authentication parts from trace (@iceman1001)

View file

@ -0,0 +1,108 @@
local getopt = require('getopt')
local ansicolors = require('ansicolors')
--Copyright
copyright = ''
author = 'nisgola'
version = 'v1'
-- Script description
desc = [[
This is a script that write Sector Trailers to the emulator memory.
By default, both keys A and B are set to 0xFFFFFFFFFFFF.
The Access Bytes are set to 0xFF0780 and User Bytes to 0x00.
]]
example = [[
-- Use default formatting
1. script run hf_mf_em_util
-- Change keys A and B
2. script run hf_mf_em_util -a 112233445566 -b AABBCCDDEEFF
-- Define access bits and User byte
3. script run hf_mf_em_util -x 00f0ff -u 12
]]
-- Usage info
usage = [[
script run hf_mf_em_util [-h] [-4] [-a <hex>] [-b <hex>] [-x <hex>] [-u <hex>]
]]
-- Arguments
arguments = [[
-h this help
-4 format as 4K card
-a <hex> define key A
-b <hex> define key B
-x <hex> define Access Bytes
-u <hex> define User Byte
]]
-- Help function
local function help()
print(copyright)
print(author)
print(version)
print(desc)
print(ansicolors.cyan..'Usage'..ansicolors.reset)
print(usage)
print(ansicolors.cyan..'Arguments'..ansicolors.reset)
print(arguments)
print(ansicolors.cyan..'Example usage'..ansicolors.reset)
print(example)
end
-- Print error
local function oops(err)
print('ERROR:', err)
return nil,err
end
-- Memory formatting
local function card_format(key_a,key_b,ab,user,s70)
local blocks = {3,7,11,15,19,23,27,31,35,39,43,47,51,55,59,63,67,71,75,79,83,87,91,95,99,103,107,111,115,119,123,127,143,159,175,191,207,223,239,255}
for k,v in ipairs(blocks) do
local cmd = string.format("hf mf esetblk --blk %s -d %s%s%s%s",v,key_a,ab,user,key_b)
core.console(cmd)
print(cmd)
core.clearCommandBuffer()
if s70 == false and k > 15 then
return
end
end
end
local function main(args)
-- Receive parameters
for o, a in getopt.getopt(args, 'ha:b:x:u:4') do
if o == 'h' then return help() end
if o == 'a' then KeyA = a end
if o == 'b' then KeyB = a end
if o == 'x' then Accessbit = a end
if o == 'u' then User = a end
if o == '4' then kkkk = true end
end
local KeyA = KeyA or 'FFFFFFFFFFFF'
if #(KeyA) ~= 12 then
return oops( string.format('Wrong length of the Key A, receveid %d, expected 12', #KeyA))
end
local KeyB = KeyB or 'FFFFFFFFFFFF'
if #(KeyB) ~= 12 then
return oops( string.format('Wrong length of the Key B, received %d, expected 12', #KeyB))
end
local Accessbit = Accessbit or 'FF0780'
if #(Accessbit) ~= 6 then
return oops( string.format('Wrong length of the Access bit, received %d, expected 6', #Accessbit))
end
local User = User or '00'
if #(User) ~= 2 then
return oops( string.format('Wrong lenght for the user defined byte, received %d, expected 2', #User))
end
local kkkk = kkkk or false
-- Call card_format function
card_format(KeyA,KeyB,Accessbit,User,kkkk)
end
main (args)

View file

@ -11,11 +11,11 @@ desc =[[
This script bruteforces 4 or 7 byte UID Mifare classic card numbers. This script bruteforces 4 or 7 byte UID Mifare classic card numbers.
]] ]]
example =[[ example =[[
Bruteforce a 4 byte UID Mifare classic card number, starting at 11223344, ending at 11223346. Bruteforce a 4 bytes UID Mifare classic card number, starting at 11223344, ending at 11223346.
script run hf_mf_uidbruteforce -s 0x11223344 -e 0x11223346 -t 1000 -x mfc script run hf_mf_uidbruteforce -s 0x11223344 -e 0x11223346 -t 1000 -x mfc
Bruteforce a 7 byte UID Mifare Ultralight card number, starting at 11223344556677, ending at 11223344556679. Bruteforce a 7 bytes UID Mifare Ultralight card number, starting at 11223344556677, ending at 11223344556679.
script run hf_mf_uidbruteforce -s 0x11223344556677 -e 0x11223344556679 -t 1000 -x mfu script run hf_mf_uidbruteforce -s 0x11223344556677 -e 0x11223344556679 -t 1000 -x mfu
]] ]]
@ -28,8 +28,9 @@ arguments = [[
-e 0-0xFFFFFFFF end id -e 0-0xFFFFFFFF end id
-t 0-99999, pause timeout (ms) between cards -t 0-99999, pause timeout (ms) between cards
(use the word 'pause' to wait for user input) (use the word 'pause' to wait for user input)
-x mfc, mfu mifare type: -x mfc, mfc4, mfu mifare type:
mfc for Mifare Classic (default) mfc for Mifare Classic (default)
mfc4 for Mifare Classic 4K
mfu for Mifare Ultralight EV1 mfu for Mifare Ultralight EV1
]] ]]
@ -86,23 +87,32 @@ local function main(args)
local start_id = 0 local start_id = 0
local end_id = 0xFFFFFFFFFFFFFF local end_id = 0xFFFFFFFFFFFFFF
local mftype = 'mfc' local mftype = 'mfc'
local uid_format = '%14x'
for o, a in getopt.getopt(args, 'e:s:t:x:h') do for o, a in getopt.getopt(args, 'e:s:t:x:h') do
if o == 's' then start_id = a end if o == 's' then start_id = a end
if o == 'e' then end_id = a end if o == 'e' then end_id = a end
if o == 't' then timeout = a end if o == 't' then timeout = a end
if o == 'x' then mftype = a end if o == 'x' then mftype = a end
if o == 'h' then return print(usage) end if o == 'h' then return help() end
end end
-- template -- template
local command = '' local command = ''
-- if the end_id is equals or inferior to 0xFFFFFFFF then use the 4 bytes UID format by default
if string.len(end_id) <= 10 then
uid_format = '%08x'
end
if mftype == 'mfc' then if mftype == 'mfc' then
command = 'hf 14a sim -t 1 -u %014x' command = 'hf 14a sim -t 1 -u ' .. uid_format
msg('Bruteforcing Mifare Classic card numbers') msg('Bruteforcing Mifare Classic card numbers')
elseif mftype == 'mfc4' then
command = 'hf 14a sim -t 8 -u ' .. uid_format
msg('Bruteforcing Mifare Classic 4K card numbers')
elseif mftype == 'mfu' then elseif mftype == 'mfu' then
command = 'hf 14a sim -t 2 -u %014x' command = 'hf 14a sim -t 2 -u ' .. uid_format
msg('Bruteforcing Mifare Ultralight card numbers') msg('Bruteforcing Mifare Ultralight card numbers')
else else
return print(usage) return print(usage)

View file

@ -200,25 +200,30 @@ static int CLIParseCommandParametersEx(CLIParserContext *ctx, size_t keyid, size
uint8_t hdata[250] = {0}; uint8_t hdata[250] = {0};
int hdatalen = sizeof(hdata); int hdatalen = sizeof(hdata);
if (keyid) { if (keyid) {
if (CLIParamHexToBuf(arg_get_str(ctx, keyid), hdata, hdatalen, &hdatalen)) if (CLIParamHexToBuf(arg_get_str(ctx, keyid), hdata, hdatalen, &hdatalen)) {
return PM3_ESOFT; return PM3_ESOFT;
}
if (hdatalen && hdatalen != 16) { if (hdatalen && hdatalen != 16) {
PrintAndLogEx(ERR, _RED_("ERROR:") " key length for AES128 must be 16 bytes only"); PrintAndLogEx(ERR, _RED_("ERROR:") " key length for AES128 must be 16 bytes only");
return PM3_EINVARG; return PM3_EINVARG;
} }
if (hdatalen) if (hdatalen)
memcpy(key, hdata, CIPURSE_AES_KEY_LENGTH); memcpy(key, hdata, CIPURSE_AES_KEY_LENGTH);
else else
memcpy(key, defaultKey, sizeof(defaultKey)); memcpy(key, defaultKey, sizeof(defaultKey));
} }
if (useaid) if (useaid) {
*useaid = false; *useaid = false;
}
if (aidid && aid && aidlen) { if (aidid && aid && aidlen) {
hdatalen = sizeof(hdata); hdatalen = sizeof(hdata);
if (CLIParamHexToBuf(arg_get_str(ctx, aidid), hdata, hdatalen, &hdatalen)) if (CLIParamHexToBuf(arg_get_str(ctx, aidid), hdata, hdatalen, &hdatalen)) {
return PM3_ESOFT; return PM3_ESOFT;
}
if (hdatalen && (hdatalen < 1 || hdatalen > 16)) { if (hdatalen && (hdatalen < 1 || hdatalen > 16)) {
PrintAndLogEx(ERR, _RED_("ERROR:") " application id length must be 1-16 bytes only"); PrintAndLogEx(ERR, _RED_("ERROR:") " application id length must be 1-16 bytes only");
@ -229,16 +234,19 @@ static int CLIParseCommandParametersEx(CLIParserContext *ctx, size_t keyid, size
if (hdatalen) { if (hdatalen) {
memcpy(aid, hdata, hdatalen); memcpy(aid, hdata, hdatalen);
*aidlen = hdatalen; *aidlen = hdatalen;
if (useaid) if (useaid) {
*useaid = true; *useaid = true;
}
} else { } else {
memcpy(aid, defaultAID, defaultAIDLength); memcpy(aid, defaultAID, defaultAIDLength);
*aidlen = defaultAIDLength; *aidlen = defaultAIDLength;
} }
} }
if (usefid) if (usefid) {
*usefid = false; *usefid = false;
}
if (fidid && fid) { if (fidid && fid) {
hdatalen = sizeof(hdata); hdatalen = sizeof(hdata);
if (CLIParamHexToBuf(arg_get_str(ctx, fidid), hdata, hdatalen, &hdatalen)) if (CLIParamHexToBuf(arg_get_str(ctx, fidid), hdata, hdatalen, &hdatalen))
@ -337,56 +345,75 @@ static int SelectCommandEx(bool selectDefaultFile, bool useAID, uint8_t *aid, si
int res = 0; int res = 0;
if (verbose && selChildFile) if (verbose && selChildFile)
PrintAndLogEx(INFO, "Select top level application/file"); PrintAndLogEx(INFO, "Select top level application/file");
if (useAID && aidLen > 0) { if (useAID && aidLen > 0) {
res = CIPURSESelectAID(true, true, aid, aidLen, buf, bufSize, len, sw); res = CIPURSESelectAID(true, true, aid, aidLen, buf, bufSize, len, sw);
if (res != 0 || *sw != 0x9000) { if (res != 0 || *sw != 0x9000) {
if (verbose) if (verbose) {
PrintAndLogEx(ERR, "Cipurse select application " _GREEN_("%s ") _RED_("error") ". Card returns 0x%04x", sprint_hex_inrow(aid, aidLen), *sw); PrintAndLogEx(ERR, "Cipurse select application " _GREEN_("%s ") _RED_("error") ". Card returns 0x%04x", sprint_hex_inrow(aid, aidLen), *sw);
}
return PM3_ESOFT; return PM3_ESOFT;
} }
if (verbose) if (verbose) {
PrintAndLogEx(INFO, "Cipurse select application " _CYAN_("%s ") _GREEN_("OK"), sprint_hex_inrow(aid, aidLen)); PrintAndLogEx(INFO, "Cipurse select application " _CYAN_("%s ") _GREEN_("OK"), sprint_hex_inrow(aid, aidLen));
}
} else if (useFID) { } else if (useFID) {
res = CIPURSESelectFileEx(true, true, fileId, buf, bufSize, len, sw); res = CIPURSESelectFileEx(true, true, fileId, buf, bufSize, len, sw);
if (res != 0 || *sw != 0x9000) { if (res != 0 || *sw != 0x9000) {
if (verbose) if (verbose) {
PrintAndLogEx(ERR, "Cipurse select file 0x%04x " _RED_("error") ". Card returns 0x%04x", fileId, *sw); PrintAndLogEx(ERR, "Cipurse select file 0x%04x " _RED_("error") ". Card returns 0x%04x", fileId, *sw);
}
return PM3_ESOFT; return PM3_ESOFT;
} }
if (verbose) if (verbose) {
PrintAndLogEx(INFO, "Cipurse select file " _CYAN_("0x%04x ") _GREEN_("OK"), fileId); PrintAndLogEx(INFO, "Cipurse select file " _CYAN_("0x%04x ") _GREEN_("OK"), fileId);
}
} else if (selectDefaultFile) { } else if (selectDefaultFile) {
res = CIPURSESelectMFDefaultFileEx(true, true, buf, bufSize, len, sw); res = CIPURSESelectMFDefaultFileEx(true, true, buf, bufSize, len, sw);
if (res != 0 || *sw != 0x9000) { if (res != 0 || *sw != 0x9000) {
if (verbose) if (verbose) {
PrintAndLogEx(ERR, "Cipurse select default file " _RED_("error") ". Card returns 0x%04x", *sw); PrintAndLogEx(ERR, "Cipurse select default file " _RED_("error") ". Card returns 0x%04x", *sw);
}
return PM3_ESOFT; return PM3_ESOFT;
} }
if (verbose) if (verbose) {
PrintAndLogEx(INFO, "Cipurse select default file " _GREEN_("OK")); PrintAndLogEx(INFO, "Cipurse select default file " _GREEN_("OK"));
}
} else { } else {
res = CIPURSESelect(true, true, buf, bufSize, len, sw); res = CIPURSESelect(true, true, buf, bufSize, len, sw);
if (res != 0 || *sw != 0x9000) { if (res != 0 || *sw != 0x9000) {
if (verbose) if (verbose) {
PrintAndLogEx(ERR, "Cipurse select default application " _RED_("error") ". Card returns 0x%04x", *sw); PrintAndLogEx(ERR, "Cipurse select default application " _RED_("error") ". Card returns 0x%04x", *sw);
}
return PM3_ESOFT; return PM3_ESOFT;
} }
if (verbose) if (verbose) {
PrintAndLogEx(INFO, "Cipurse select default application " _GREEN_("OK")); PrintAndLogEx(INFO, "Cipurse select default application " _GREEN_("OK"));
}
} }
if (selChildFile) { if (selChildFile) {
if (verbose) if (verbose) {
PrintAndLogEx(INFO, "Select child file"); PrintAndLogEx(INFO, "Select child file");
}
res = CIPURSESelectFileEx(false, true, childFileId, buf, bufSize, len, sw); res = CIPURSESelectFileEx(false, true, childFileId, buf, bufSize, len, sw);
if (res != 0 || *sw != 0x9000) { if (res != 0 || *sw != 0x9000) {
if (verbose) if (verbose) {
PrintAndLogEx(ERR, "Select child file 0x%04x " _RED_("error") ". Card returns 0x%04x", childFileId, *sw); PrintAndLogEx(ERR, "Select child file 0x%04x " _RED_("error") ". Card returns 0x%04x", childFileId, *sw);
}
return PM3_ESOFT; return PM3_ESOFT;
} }
if (verbose) if (verbose) {
PrintAndLogEx(INFO, "Select child file " _CYAN_("0x%04x ") _GREEN_("OK"), childFileId); PrintAndLogEx(INFO, "Select child file " _CYAN_("0x%04x ") _GREEN_("OK"), childFileId);
}
} }
return PM3_SUCCESS; return PM3_SUCCESS;
@ -408,13 +435,13 @@ static int CmdHFCipurseSelect(const char *Cmd) {
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_lit0("a", "apdu", "show APDU requests and responses"), arg_lit0("a", "apdu", "Show APDU requests and responses"),
arg_lit0("v", "verbose", "show technical data"), arg_lit0("v", "verbose", "Verbose mode"),
arg_lit0("t", "tlv", "TLV decode returned data"), arg_lit0("t", "tlv", "TLV decode returned data"),
arg_str0(NULL, "aid", "<hex 1..16 bytes>", "application ID (AID)"), arg_str0(NULL, "aid", "<hex>", "Application ID (AID) 1..16 bytes"),
arg_str0(NULL, "fid", "<hex 2 bytes>", "top level file (or application) ID (FID)"), arg_str0(NULL, "fid", "<hex>", "Top level file (or application) ID (FID) 2 bytes"),
arg_lit0(NULL, "mfd", "select masterfile by empty id"), arg_lit0(NULL, "mfd", "Select masterfile by empty id"),
arg_str0(NULL, "chfid", "<hex 2 bytes>", "child file ID (EF under application/master file)"), arg_str0(NULL, "chfid", "<hex>", "Child file ID (EF under application/master file) 2 bytes"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(ctx, Cmd, argtable, true); CLIExecWithReturn(ctx, Cmd, argtable, true);
@ -474,12 +501,12 @@ static int CmdHFCipurseAuth(const char *Cmd) {
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_lit0("a", "apdu", "show APDU requests and responses"), arg_lit0("a", "apdu", "Show APDU requests and responses"),
arg_lit0("v", "verbose", "show technical data"), arg_lit0("v", "verbose", "Verbose mode"),
arg_str0(NULL, "aid", "<hex 1..16 bytes>", "application ID (AID)"), arg_str0(NULL, "aid", "<hex>", "Application ID (AID) ( 1..16 bytes )"),
arg_str0(NULL, "fid", "<hex 2 bytes>", "top file/application ID (FID)"), arg_str0(NULL, "fid", "<hex>", "Top file/application ID (FID) ( 2 bytes )"),
arg_lit0(NULL, "mfd", "select masterfile by empty id"), arg_lit0(NULL, "mfd", "Select masterfile by empty id"),
arg_int0("n", NULL, "<dec>", "key ID"), arg_int0("n", NULL, "<dec>", "Key ID"),
arg_str0("k", "key", "<hex>", "Auth key"), arg_str0("k", "key", "<hex>", "Auth key"),
arg_param_end arg_param_end
}; };
@ -545,21 +572,21 @@ static int CmdHFCipurseReadFile(const char *Cmd) {
CLIParserInit(&ctx, "hf cipurse read", CLIParserInit(&ctx, "hf cipurse read",
"Read file in the application by file ID with key ID and key. If no key is supplied, default key of 737373...7373 will be used", "Read file in the application by file ID with key ID and key. If no key is supplied, default key of 737373...7373 will be used",
"hf cipurse read --fid 2ff7 -> Authenticate with keyID 1, read file with id 2ff7\n" "hf cipurse read --fid 2ff7 -> Authenticate with keyID 1, read file with id 2ff7\n"
"hf cipurse read -n 2 -k 65656565656565656565656565656565 --fid 2ff7 -> Authenticate keyID 2 and read file\n" "hf cipurse read -n 2 -k 65656565656565656565656565656565 --fid 2ff7 -> Authenticate keyID 2 and read file\n"
"hf cipurse read --aid 4144204631 --fid 0102 -> read file with id 0102 from application 4144204631\n"); "hf cipurse read --aid 4144204631 --fid 0102 -> read file with id 0102 from application 4144204631\n");
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_lit0("a", "apdu", "show APDU requests and responses"), arg_lit0("a", "apdu", "Show APDU requests and responses"),
arg_lit0("v", "verbose", "show technical data"), arg_lit0("v", "verbose", "Verbose mode"),
arg_int0("n", NULL, "<dec>", "key ID"), arg_int0("n", NULL, "<dec>", "Key ID"),
arg_str0("k", "key", "<hex>", "Auth key"), arg_str0("k", "key", "<hex>", "Auth key"),
arg_str0(NULL, "aid", "<hex 1..16 bytes>", "application ID (AID)"), arg_str0(NULL, "aid", "<hex>", "Application ID (AID) ( 1..16 bytes )"),
arg_str0(NULL, "fid", "<hex>", "file ID"), arg_str0(NULL, "fid", "<hex>", "File ID"),
arg_int0("o", "offset", "<dec>", "offset for reading data from file"), arg_int0("o", "offset", "<dec>", "Offset for reading data from file"),
arg_lit0(NULL, "noauth", "read file without authentication"), arg_lit0(NULL, "noauth", "Read file without authentication"),
arg_str0(NULL, "sreq", "<plain|mac(default)|encode>", "communication reader-PICC security level"), arg_str0(NULL, "sreq", "<plain|mac|encode>", "Communication reader-PICC security level (def: mac)"),
arg_str0(NULL, "sresp", "<plain|mac(default)|encode>", "communication PICC-reader security level"), arg_str0(NULL, "sresp", "<plain|mac|encode>", "Communication PICC-reader security level (def: mac)"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(ctx, Cmd, argtable, true); CLIExecWithReturn(ctx, Cmd, argtable, true);
@ -660,18 +687,18 @@ static int CmdHFCipurseWriteFile(const char *Cmd) {
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_lit0("a", "apdu", "show APDU requests and responses"), arg_lit0("a", "apdu", "Show APDU requests and responses"),
arg_lit0("v", "verbose", "show technical data"), arg_lit0("v", "verbose", "Verbose mode"),
arg_int0("n", NULL, "<dec>", "key ID"), arg_int0("n", NULL, "<dec>", "Key ID"),
arg_str0("k", "key", "<hex>", "Auth key"), arg_str0("k", "key", "<hex>", "Auth key"),
arg_str0(NULL, "aid", "<hex 1..16 bytes>", "application ID (AID)"), arg_str0(NULL, "aid", "<hex>", "Application ID (AID) ( 1..16 bytes )"),
arg_str0(NULL, "fid", "<hex>", "file ID"), arg_str0(NULL, "fid", "<hex>", "File ID"),
arg_int0("o", "offset", "<dec>", "offset for reading data from file"), arg_int0("o", "offset", "<dec>", "Offset for reading data from file"),
arg_lit0(NULL, "noauth", "read file without authentication"), arg_lit0(NULL, "noauth", "Read file without authentication"),
arg_str0(NULL, "sreq", "<plain|mac(default)|encode>", "communication reader-PICC security level"), arg_str0(NULL, "sreq", "<plain|mac|encode>", "communication reader-PICC security level (def: mac)"),
arg_str0(NULL, "sresp", "<plain|mac(default)|encode>", "communication PICC-reader security level"), arg_str0(NULL, "sresp", "<plain|mac|encode>", "communication PICC-reader security level (def: mac)"),
arg_str0("d", "data", "<hex>", "hex data to write to new file"), arg_str0("d", "data", "<hex>", "Data to write to new file"),
arg_lit0(NULL, "commit", "need commit after write"), arg_lit0(NULL, "commit", "Commit after write"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(ctx, Cmd, argtable, true); CLIExecWithReturn(ctx, Cmd, argtable, true);
@ -797,17 +824,17 @@ static int CmdHFCipurseReadFileAttr(const char *Cmd) {
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_lit0("a", "apdu", "show APDU requests and responses"), arg_lit0("a", "apdu", "Show APDU requests and responses"),
arg_lit0("v", "verbose", "show technical data"), arg_lit0("v", "verbose", "Verbose mode"),
arg_int0("n", NULL, "<dec>", "key ID"), arg_int0("n", NULL, "<dec>", "Key ID"),
arg_str0("k", "key", "<hex>", "Auth key"), arg_str0("k", "key", "<hex>", "Auth key"),
arg_lit0(NULL, "mfd", "show info about master file"), arg_lit0(NULL, "mfd", "Show info about master file"),
arg_str0(NULL, "aid", "<hex 1..16 bytes>", "select application ID (AID)"), arg_str0(NULL, "aid", "<hex>", "Select application ID (AID) ( 1..16 bytes )"),
arg_str0(NULL, "fid", "<hex>", "file ID"), arg_str0(NULL, "fid", "<hex>", "File ID"),
arg_str0(NULL, "chfid", "<hex 2 bytes>", "child file ID (EF under application/master file)"), arg_str0(NULL, "chfid", "<hex>", "Child file ID (EF under application/master file) ( 2 bytes )"),
arg_lit0(NULL, "noauth", "read file attributes without authentication"), arg_lit0(NULL, "noauth", "Read file attributes without authentication"),
arg_str0(NULL, "sreq", "<plain|mac(default)|encode>", "communication reader-PICC security level"), arg_str0(NULL, "sreq", "<plain|mac|encode>", "Communication reader-PICC security level (def: mac)"),
arg_str0(NULL, "sresp", "<plain|mac(default)|encode>", "communication PICC-reader security level"), arg_str0(NULL, "sresp", "<plain|mac|encode>", "Communication PICC-reader security level (def: mac)"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(ctx, Cmd, argtable, true); CLIExecWithReturn(ctx, Cmd, argtable, true);
@ -909,26 +936,26 @@ static int CmdHFCipurseWriteFileAttr(const char *Cmd) {
CLIParserContext *ctx; CLIParserContext *ctx;
CLIParserInit(&ctx, "hf cipurse awrite", CLIParserInit(&ctx, "hf cipurse awrite",
"Write file attributes by file ID with key ID and key. If no key is supplied, default key of 737373...7373 will be used", "Write file attributes by file ID with key ID and key. If no key is supplied, default key of 737373...7373 will be used",
"hf cipurse awrite --fid 2ff7 -d 080000C1C1C1C1C1C1C1C1C1 -> write default file attributes with id 2ff7\n" "hf cipurse awrite --fid 2ff7 -d 080000C1C1C1C1C1C1C1C1C1 -> write default file attributes with id 2ff7\n"
"hf cipurse awrite --mfd -d 080000FFFFFFFFFFFFFFFFFF86023232 --commit -> write file attributes for master file (MF)\n" "hf cipurse awrite --mfd -d 080000FFFFFFFFFFFFFFFFFF86023232 --commit -> write file attributes for master file (MF)\n"
"hf cipurse awrite --chfid 0102 -d 020000ffffff -> write file 0102 attributes in the default application to full access\n" "hf cipurse awrite --chfid 0102 -d 020000ffffff -> write file 0102 attributes in the default application to full access\n"
"hf cipurse awrite --chfid 0102 -d 02000040ffff -> write file 0102 attributes in the default application to full access with keys 1 and 2\n"); "hf cipurse awrite --chfid 0102 -d 02000040ffff -> write file 0102 attributes in the default application to full access with keys 1 and 2\n");
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_lit0("a", "apdu", "show APDU requests and responses"), arg_lit0("a", "apdu", "Show APDU requests and responses"),
arg_lit0("v", "verbose", "show technical data"), arg_lit0("v", "verbose", "Verbose mode"),
arg_int0("n", NULL, "<dec>", "key ID"), arg_int0("n", NULL, "<dec>", "Key ID"),
arg_str0("k", "key", "<hex>", "Auth key"), arg_str0("k", "key", "<hex>", "Auth key"),
arg_lit0(NULL, "mfd", "show info about master file"), arg_lit0(NULL, "mfd", "Show info about master file"),
arg_str0(NULL, "aid", "<hex 1..16 bytes>", "select application ID (AID)"), arg_str0(NULL, "aid", "<hex>", "Select application ID (AID) ( 1..16 bytes )"),
arg_str0(NULL, "fid", "<hex>", "file ID"), arg_str0(NULL, "fid", "<hex>", "File ID"),
arg_str0(NULL, "chfid", "<hex 2 bytes>", "child file ID (EF under application/master file)"), arg_str0(NULL, "chfid", "<hex>", "Child file ID (EF under application/master file) ( 2 bytes )"),
arg_lit0(NULL, "noauth", "read file attributes without authentication"), arg_lit0(NULL, "noauth", "Read file attributes without authentication"),
arg_str0(NULL, "sreq", "<plain|mac(default)|encode>", "communication reader-PICC security level"), arg_str0(NULL, "sreq", "<plain|mac|encode>", "Communication reader-PICC security level (def: mac)"),
arg_str0(NULL, "sresp", "<plain|mac(default)|encode>", "communication PICC-reader security level"), arg_str0(NULL, "sresp", "<plain|mac|encode>", "Communication PICC-reader security level (def: mac)"),
arg_str0("d", "data", "<hex>", "file attributes"), arg_str0("d", "data", "<hex>", "File attributes"),
arg_lit0(NULL, "commit", "need commit after write"), arg_lit0(NULL, "commit", "Commit after write"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(ctx, Cmd, argtable, false); CLIExecWithReturn(ctx, Cmd, argtable, false);
@ -1053,13 +1080,13 @@ static int CmdHFCipurseFormatAll(const char *Cmd) {
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_lit0("a", "apdu", "show APDU requests and responses"), arg_lit0("a", "apdu", "Show APDU requests and responses"),
arg_lit0("v", "verbose", "show technical data"), arg_lit0("v", "verbose", "Verbose mode"),
arg_int0("n", NULL, "<dec>", "key ID"), arg_int0("n", NULL, "<dec>", "Key ID"),
arg_str0("k", "key", "<hex>", "Auth key"), arg_str0("k", "key", "<hex>", "Auth key"),
arg_str0(NULL, "sreq", "<plain|mac(default)|encode>", "communication reader-PICC security level"), arg_str0(NULL, "sreq", "<plain|mac|encode>", "Communication reader-PICC security level (def: mac)"),
arg_str0(NULL, "sresp", "<plain|mac(default)|encode>", "communication PICC-reader security level"), arg_str0(NULL, "sresp", "<plain|mac|encode>", "Communication PICC-reader security level (def: mac)"),
arg_lit0(NULL, "no-auth", "execute without authentication"), arg_lit0(NULL, "no-auth", "Execute without authentication"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(ctx, Cmd, argtable, true); CLIExecWithReturn(ctx, Cmd, argtable, true);
@ -1138,20 +1165,20 @@ static int CmdHFCipurseCreateDGI(const char *Cmd) {
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_lit0("a", "apdu", "show APDU requests and responses"), arg_lit0("a", "apdu", "Show APDU requests and responses"),
arg_lit0("v", "verbose", "show technical data"), arg_lit0("v", "verbose", "Verbose mode"),
arg_int0("n", NULL, "<dec>", "key ID"), arg_int0("n", NULL, "<dec>", "Key ID"),
arg_str0("k", "key", "<hex>", "Auth key"), arg_str0("k", "key", "<hex>", "Auth key"),
arg_str0(NULL, "aid", "<hex 1..16 bytes>", "application ID (AID)"), arg_str0(NULL, "aid", "<hex>", "Application ID (AID) ( 1..16 bytes )"),
arg_str0(NULL, "fid", "<hex 2 bytes>", "file ID (FID)"), arg_str0(NULL, "fid", "<hex>", "file ID (FID) ( 2 bytes )"),
arg_lit0(NULL, "mfd", "select masterfile by empty id"), arg_lit0(NULL, "mfd", "Select masterfile by empty id"),
arg_str0("d", "data", "<hex>", "data with DGI for create"), arg_str0("d", "data", "<hex>", "Data with DGI for create"),
arg_str0(NULL, "sreq", "<plain|mac(default)|encode>", "communication reader-PICC security level"), arg_str0(NULL, "sreq", "<plain|mac|encode>", "Communication reader-PICC security level (def: mac)"),
arg_str0(NULL, "sresp", "<plain|mac(default)|encode>", "communication PICC-reader security level"), arg_str0(NULL, "sresp", "<plain|mac|encode>", "Communication PICC-reader security level (def: mac)"),
arg_lit0(NULL, "no-auth", "execute without authentication"), arg_lit0(NULL, "no-auth", "Execute without authentication"),
arg_lit0(NULL, "commit", "need commit after create"), arg_lit0(NULL, "commit", "Commit after create"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(ctx, Cmd, argtable, false); CLIExecWithReturn(ctx, Cmd, argtable, false);
@ -1272,17 +1299,17 @@ static int CmdHFCipurseDeleteFile(const char *Cmd) {
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_lit0("a", "apdu", "show APDU requests and responses"), arg_lit0("a", "apdu", "Show APDU requests and responses"),
arg_lit0("v", "verbose", "show technical data"), arg_lit0("v", "verbose", "Verbose mode"),
arg_int0("n", NULL, "<dec>", "key ID"), arg_int0("n", NULL, "<dec>", "Key ID"),
arg_str0("k", "key", "<hex>", "Auth key"), arg_str0("k", "key", "<hex>", "Auth key"),
arg_str0(NULL, "fid", "<hex>", "file/application ID under MF for delete"), arg_str0(NULL, "fid", "<hex>", "File/application ID under MF for delete"),
arg_str0(NULL, "aid", "<hex 1..16 bytes>", "application ID (AID) for delete"), arg_str0(NULL, "aid", "<hex>", "Application ID (AID) for delete ( 1..16 bytes )"),
arg_str0(NULL, "chfid", "<hex 2 bytes>", "child file ID (EF under application/master file)"), arg_str0(NULL, "chfid", "<hex>", "Child file ID (EF under application/master file) ( 2 bytes )"),
arg_str0(NULL, "sreq", "<plain|mac(default)|encode>", "communication reader-PICC security level"), arg_str0(NULL, "sreq", "<plain|mac|encode>", "Communication reader-PICC security level (def: mac)"),
arg_str0(NULL, "sresp", "<plain|mac(default)|encode>", "communication PICC-reader security level"), arg_str0(NULL, "sresp", "<plain|mac|encode>", "Communication PICC-reader security level (def: mac)"),
arg_lit0(NULL, "no-auth", "execute without authentication"), arg_lit0(NULL, "no-auth", "Execute without authentication"),
arg_lit0(NULL, "commit", "commit "), arg_lit0(NULL, "commit", "commit after delete"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(ctx, Cmd, argtable, false); CLIExecWithReturn(ctx, Cmd, argtable, false);
@ -1582,11 +1609,11 @@ static int CmdHFCipurseDefault(const char *Cmd) {
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_lit0(NULL, "clear", "resets to defaults"), arg_lit0(NULL, "clear", "Resets to defaults"),
arg_int0("n", NULL, "<dec>", "Key ID"), arg_int0("n", NULL, "<dec>", "Key ID"),
arg_str0("k", "key", "<hex>", "Authentication key"), arg_str0("k", "key", "<hex>", "Authentication key"),
arg_str0(NULL, "aid", "<hex 1..16 bytes>", "application ID (AID)"), arg_str0(NULL, "aid", "<hex>", "Application ID (AID) ( 1..16 bytes )"),
arg_str0(NULL, "fid", "<hex 2 bytes>", "File ID"), arg_str0(NULL, "fid", "<hex>", "File ID ( 2 bytes )"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(ctx, Cmd, argtable, true); CLIExecWithReturn(ctx, Cmd, argtable, true);

View file

@ -137,22 +137,22 @@ static int CmdHFFidoRegister(const char *cmd) {
"challenge parameter (32b) and application parameter (32b).\n" "challenge parameter (32b) and application parameter (32b).\n"
"The default config filename is `fido2_defparams.json`\n" "The default config filename is `fido2_defparams.json`\n"
"\n", "\n",
"hf fido reg -> execute command with 2 parameters, filled 0x00\n" "hf fido reg -> execute command with 2 parameters, filled 0x00\n"
"hf fido reg --cp s0 --ap s1 -> execute command with plain parameters\n" "hf fido reg --cp s0 --ap s1 -> execute command with plain parameters\n"
"hf fido reg --cpx 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f --apx 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f\n" "hf fido reg --cpx 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f --apx 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f\n"
"hf fido reg -f fido2-params -> execute command with custom config file\n" "hf fido reg -f fido2-params -> execute command with custom config file\n"
); );
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_lit0("a", "apdu", "show APDU requests and responses"), arg_lit0("a", "apdu", "Show APDU requests and responses"),
arg_litn("v", "verbose", 0, 2, "show technical data. vv - show full certificates data"), arg_litn("v", "verbose", 0, 2, "Verbose mode. vv - show full certificates data"),
arg_lit0("t", "tlv", "Show DER certificate contents in TLV representation"), arg_lit0("t", "tlv", "Show DER certificate contents in TLV representation"),
arg_str0("f", "file", "<fn>", "JSON input file name for parameters"), arg_str0("f", "file", "<fn>", "JSON input file name for parameters"),
arg_str0(NULL, "cp", "<ascii>", "challenge parameter (1..16 chars)"), arg_str0(NULL, "cp", "<str>", "Challenge parameter (1..16 chars)"),
arg_str0(NULL, "ap", "<ascii>", "application parameter (1..16 chars)"), arg_str0(NULL, "ap", "<str>", "Application parameter (1..16 chars)"),
arg_str0(NULL, "cpx", "<hex>", "challenge parameter (32 bytes hex)"), arg_str0(NULL, "cpx", "<hex>", "Challenge parameter (32 bytes hex)"),
arg_str0(NULL, "apx", "<hex>", "application parameter (32 bytes hex)"), arg_str0(NULL, "apx", "<hex>", "Application parameter (32 bytes hex)"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(ctx, cmd, argtable, true); CLIExecWithReturn(ctx, cmd, argtable, true);
@ -409,18 +409,18 @@ static int CmdHFFidoAuthenticate(const char *cmd) {
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_lit0("a", "apdu", "show APDU reqests and responses"), arg_lit0("a", "apdu", "Show APDU reqests and responses"),
arg_lit0("v", "verbose", "show technical data"), arg_lit0("v", "verbose", "Verbose mode"),
arg_rem("default mode:", "dont-enforce-user-presence-and-sign"), arg_rem("default mode:", "dont-enforce-user-presence-and-sign"),
arg_lit0("u", "user", "mode: enforce-user-presence-and-sign"), arg_lit0("u", "user", "mode: enforce-user-presence-and-sign"),
arg_lit0("c", "check", "mode: check-only"), arg_lit0("c", "check", "mode: check-only"),
arg_str0("f", "file", "<fn>", "JSON input file name for parameters"), arg_str0("f", "file", "<fn>", "JSON file name for parameters"),
arg_str0("k", "key", "<hex>", "public key to verify signature"), arg_str0("k", "key", "<hex>", "Public key to verify signature"),
arg_str0(NULL, "kh", "<hex>", "key handle (var 0..255b)"), arg_str0(NULL, "kh", "<hex>", "Key handle (var 0..255b)"),
arg_str0(NULL, "cp", "<ascii>", "challenge parameter (1..16 chars)"), arg_str0(NULL, "cp", "<str>", "Challenge parameter (1..16 chars)"),
arg_str0(NULL, "ap", "<ascii>", "application parameter (1..16 chars)"), arg_str0(NULL, "ap", "<str>", "Application parameter (1..16 chars)"),
arg_str0(NULL, "cpx", "<hex>", "challenge parameter (32 bytes hex)"), arg_str0(NULL, "cpx", "<hex>", "Challenge parameter (32 bytes hex)"),
arg_str0(NULL, "apx", "<hex>", "application parameter (32 bytes hex)"), arg_str0(NULL, "apx", "<hex>", "Application parameter (32 bytes hex)"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(ctx, cmd, argtable, true); CLIExecWithReturn(ctx, cmd, argtable, true);
@ -671,11 +671,11 @@ static int CmdHFFido2MakeCredential(const char *cmd) {
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_lit0("a", "apdu", "show APDU reqests and responses"), arg_lit0("a", "apdu", "Show APDU reqests and responses"),
arg_litn("v", "verbose", 0, 2, "show technical data. vv - show full certificates data"), arg_litn("v", "verbose", 0, 2, "Verbose mode. vv - show full certificates data"),
arg_lit0("t", "tlv", "Show DER certificate contents in TLV representation"), arg_lit0("t", "tlv", "Show DER certificate contents in TLV representation"),
arg_lit0("c", "cbor", "show CBOR decoded data"), arg_lit0("c", "cbor", "Show CBOR decoded data"),
arg_str0("f", "file", "<fn>", "parameter JSON file name"), arg_str0("f", "file", "<fn>", "Parameter JSON file name"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(ctx, cmd, argtable, true); CLIExecWithReturn(ctx, cmd, argtable, true);
@ -790,11 +790,11 @@ static int CmdHFFido2GetAssertion(const char *cmd) {
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_lit0("a", "apdu", "show APDU reqests and responses"), arg_lit0("a", "apdu", "Show APDU reqests and responses"),
arg_litn("v", "verbose", 0, 2, "show technical data. vv - show full certificates data"), arg_litn("v", "verbose", 0, 2, "Verbose mode. vv - show full certificates data"),
arg_lit0("c", "cbor", "show CBOR decoded data"), arg_lit0("c", "cbor", "Show CBOR decoded data"),
arg_lit0("l", "list", "add CredentialId from json to allowList"), arg_lit0("l", "list", "Add CredentialId from json to allowList"),
arg_str0("f", "file", "<fn>", "parameter JSON file name"), arg_str0("f", "file", "<fn>", "Parameter JSON file name"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(ctx, cmd, argtable, true); CLIExecWithReturn(ctx, cmd, argtable, true);

View file

@ -3008,7 +3008,7 @@ static int CmdHF14AMfChk(const char *Cmd) {
arg_param_begin, arg_param_begin,
arg_strx0("k", "key", "<hex>", "Key specified as 12 hex symbols"), arg_strx0("k", "key", "<hex>", "Key specified as 12 hex symbols"),
arg_int0(NULL, "blk", "<dec>", "Input block number"), arg_int0(NULL, "blk", "<dec>", "Input block number"),
arg_lit0("a", NULL, "Target Key A, if found also check Key B for duplicate"), arg_lit0("a", NULL, "Target Key A"),
arg_lit0("b", NULL, "Target Key B"), arg_lit0("b", NULL, "Target Key B"),
arg_lit0("*", "all", "Target both key A & B (default)"), arg_lit0("*", "all", "Target both key A & B (default)"),
arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"), arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"),
@ -3017,7 +3017,7 @@ static int CmdHF14AMfChk(const char *Cmd) {
arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"), arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"),
arg_lit0(NULL, "emu", "Fill simulator keys from found keys"), arg_lit0(NULL, "emu", "Fill simulator keys from found keys"),
arg_lit0(NULL, "dump", "Dump found keys to binary file"), arg_lit0(NULL, "dump", "Dump found keys to binary file"),
arg_str0("f", "file", "<fn>", "filename of dictionary"), arg_str0("f", "file", "<fn>", "Filename of dictionary"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(ctx, Cmd, argtable, true); CLIExecWithReturn(ctx, Cmd, argtable, true);

File diff suppressed because it is too large Load diff

View file

@ -461,9 +461,9 @@ static int CmdHFMFPWritePerso(const char *Cmd) {
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_lit0("v", "verbose", "show internal data."), arg_lit0("v", "verbose", "Verbose mode"),
arg_str1(NULL, "ki", "<hex>", " key number, 2 hex bytes"), arg_str1(NULL, "ki", "<hex>", " Key number, 2 hex bytes"),
arg_str0(NULL, "key", "<hex>", " key, 16 hex bytes"), arg_str0(NULL, "key", "<hex>", " Key, 16 hex bytes"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(ctx, Cmd, argtable, true); CLIExecWithReturn(ctx, Cmd, argtable, true);
@ -527,8 +527,8 @@ static int CmdHFMFPInitPerso(const char *Cmd) {
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_litn("v", "verbose", 0, 2, "show internal data."), arg_litn("v", "verbose", 0, 2, "Verbose mode"),
arg_str0("k", "key", "<hex>", "key, 16 hex bytes"), arg_str0("k", "key", "<hex>", "Key, 16 hex bytes"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(ctx, Cmd, argtable, true); CLIExecWithReturn(ctx, Cmd, argtable, true);
@ -602,7 +602,7 @@ static int CmdHFMFPCommitPerso(const char *Cmd) {
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_lit0("v", "verbose", "show internal data."), arg_lit0("v", "verbose", "Verbose mode"),
// arg_int0(NULL, "sl", "<dec>", "SL mode"), // arg_int0(NULL, "sl", "<dec>", "SL mode"),
arg_param_end arg_param_end
}; };
@ -649,9 +649,9 @@ static int CmdHFMFPAuth(const char *Cmd) {
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_lit0("v", "verbose", "show internal data."), arg_lit0("v", "verbose", "Verbose mode"),
arg_str1(NULL, "ki", "<hex>", "key number, 2 hex bytes"), arg_str1(NULL, "ki", "<hex>", "Key number, 2 hex bytes"),
arg_str1(NULL, "key", "<hex>", "key, 16 hex bytes"), arg_str1(NULL, "key", "<hex>", "Key, 16 hex bytes"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(ctx, Cmd, argtable, true); CLIExecWithReturn(ctx, Cmd, argtable, true);
@ -683,11 +683,11 @@ static int CmdHFMFPRdbl(const char *Cmd) {
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_lit0("v", "verbose", "show internal data"), arg_lit0("v", "verbose", "Verbose mode"),
arg_int0("n", "count", "<dec>", "blocks count (by default 1)"), arg_int0("n", "count", "<dec>", "Blocks count (def: 1)"),
arg_lit0("b", "keyb", "use key B (by default keyA)"), arg_lit0("b", "keyb", "Use key B (def: keyA)"),
arg_lit0("p", "plain", "plain communication mode between reader and card"), arg_lit0("p", "plain", "Plain communication mode between reader and card"),
arg_int1(NULL, "blk", "<dec>", "block number (0..255)"), arg_int1(NULL, "blk", "<0..255>", "Block number"),
arg_str0(NULL, "key", "<hex>", "Key, 16 hex bytes"), arg_str0(NULL, "key", "<hex>", "Key, 16 hex bytes"),
arg_param_end arg_param_end
}; };
@ -790,17 +790,17 @@ static int CmdHFMFPRdbl(const char *Cmd) {
static int CmdHFMFPRdsc(const char *Cmd) { static int CmdHFMFPRdsc(const char *Cmd) {
CLIParserContext *ctx; CLIParserContext *ctx;
CLIParserInit(&ctx, "hf mfp rdsc", CLIParserInit(&ctx, "hf mfp rdsc",
"Reads one sector from Mifare Plus card", "Reads one sector from MIFARE Plus card",
"hf mfp rdsc -s 0 --key 000102030405060708090a0b0c0d0e0f -> executes authentication and read sector 0 data\n" "hf mfp rdsc -s 0 --key 000102030405060708090a0b0c0d0e0f -> executes authentication and read sector 0 data\n"
"hf mfp rdsc -s 1 -v -> executes authentication and shows sector 1 data with default key"); "hf mfp rdsc -s 1 -v -> executes authentication and shows sector 1 data with default key");
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_lit0("v", "verbose", "show internal data."), arg_lit0("v", "verbose", "Verbose mode"),
arg_lit0("b", "keyb", "use key B (by default keyA)."), arg_lit0("b", "keyb", "Use key B (def: keyA)"),
arg_lit0("p", "plain", "plain communication mode between reader and card."), arg_lit0("p", "plain", "Plain communication mode between reader and card"),
arg_int1("s", "sn", "<dec>", "sector number (0..255)"), arg_int1("s", "sn", "<0..255>", "Sector number"),
arg_str0("k", "key", "<hex>", "key, 16 hex bytes"), arg_str0("k", "key", "<hex>", "Key, 16 hex bytes"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(ctx, Cmd, argtable, false); CLIExecWithReturn(ctx, Cmd, argtable, false);
@ -893,11 +893,11 @@ static int CmdHFMFPWrbl(const char *Cmd) {
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_lit0("v", "verbose", "show internal data."), arg_lit0("v", "verbose", "Verbose mode"),
arg_lit0("b", "keyb", "use key B (by default keyA)."), arg_lit0("b", "keyb", "Use key B (def: keyA)"),
arg_int1(NULL, "blk", "<dec>", "block number (0..255)"), arg_int1(NULL, "blk", "<0..255>", "Block number"),
arg_str1("d", "data", "<hex>", "data, 16 hex bytes"), arg_str1("d", "data", "<hex>", "Data, 16 hex bytes"),
arg_str0("k", "key", "<hex>", "key, 16 hex bytes"), arg_str0("k", "key", "<hex>", "Key, 16 hex bytes"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(ctx, Cmd, argtable, false); CLIExecWithReturn(ctx, Cmd, argtable, false);
@ -1097,7 +1097,7 @@ static int CmdHFMFPChk(const char *Cmd) {
CLIParserContext *ctx; CLIParserContext *ctx;
CLIParserInit(&ctx, "hf mfp chk", CLIParserInit(&ctx, "hf mfp chk",
"Checks keys with Mifare Plus card.", "Checks keys on MIFARE Plus card",
"hf mfp chk -k 000102030405060708090a0b0c0d0e0f -> check key on sector 0 as key A and B\n" "hf mfp chk -k 000102030405060708090a0b0c0d0e0f -> check key on sector 0 as key A and B\n"
"hf mfp chk -s 2 -a -> check default key list on sector 2, key A\n" "hf mfp chk -s 2 -a -> check default key list on sector 2, key A\n"
"hf mfp chk -d mfp_default_keys -s0 -e6 -> check keys from dictionary against sectors 0-6\n" "hf mfp chk -d mfp_default_keys -s0 -e6 -> check keys from dictionary against sectors 0-6\n"
@ -1106,17 +1106,17 @@ static int CmdHFMFPChk(const char *Cmd) {
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_lit0("a", "keya", "check only key A (by default check all keys)."), arg_lit0("a", "keya", "Check only key A (def: check all keys)"),
arg_lit0("b", "keyb", "check only key B (by default check all keys)."), arg_lit0("b", "keyb", "Check only key B (def: check all keys)"),
arg_int0("s", "startsec", "Start sector Num (0..255)", NULL), arg_int0("s", "startsec", "<0..255>", "Start sector number"),
arg_int0("e", "endsec", "End sector Num (0..255)", NULL), arg_int0("e", "endsec", "<0..255>", "End sector number"),
arg_str0("k", "key", "<Key>", "Key for checking (HEX 16 bytes)"), arg_str0("k", "key", "<hex>", "Key for checking (HEX 16 bytes)"),
arg_str0("d", "dict", "<file>", "file with keys dictionary"), arg_str0("d", "dict", "<fn>", "Dictionary file with keys"),
arg_lit0(NULL, "pattern1b", "check all 1-byte combinations of key (0000...0000, 0101...0101, 0202...0202, ...)"), arg_lit0(NULL, "pattern1b", "Check all 1-byte combinations of key (0000...0000, 0101...0101, 0202...0202, ...)"),
arg_lit0(NULL, "pattern2b", "check all 2-byte combinations of key (0000...0000, 0001...0001, 0002...0002, ...)"), arg_lit0(NULL, "pattern2b", "Check all 2-byte combinations of key (0000...0000, 0001...0001, 0002...0002, ...)"),
arg_str0(NULL, "startp2b", "<Pattern>", "Start key (2-byte HEX) for 2-byte search (use with `--pattern2b`)"), arg_str0(NULL, "startp2b", "<pattern>", "Start key (2-byte HEX) for 2-byte search (use with `--pattern2b`)"),
arg_str0("j", "json", "<file>", "json file to save keys"), arg_str0("j", "json", "<fn>", "Json filename to save keys"),
arg_lit0("v", "verbose", "verbose mode."), arg_lit0("v", "verbose", "Verbose mode"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(ctx, Cmd, argtable, true); CLIExecWithReturn(ctx, Cmd, argtable, true);
@ -1339,12 +1339,12 @@ static int CmdHFMFPMAD(const char *Cmd) {
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_lit0("v", "verbose", "show technical data"), arg_lit0("v", "verbose", "Show technical data"),
arg_str0(NULL, "aid", "<aid>", "print all sectors with aid"), arg_str0(NULL, "aid", "<hex>", "Print all sectors with aid"),
arg_str0("k", "key", "<key>", "key for printing sectors"), arg_str0("k", "key", "<hex>", "Key for printing sectors"),
arg_lit0("b", "keyb", "use key B for access printing sectors (by default: key A)"), arg_lit0("b", "keyb", "Use key B for access printing sectors (def: key A)"),
arg_lit0(NULL, "be", "(optional, BigEndian)"), arg_lit0(NULL, "be", "(optional: BigEndian)"),
arg_lit0(NULL, "dch", "decode Card Holder information"), arg_lit0(NULL, "dch", "Decode Card Holder information"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(ctx, Cmd, argtable, true); CLIExecWithReturn(ctx, Cmd, argtable, true);

View file

@ -123,6 +123,39 @@ static char *getProductTypeStr(uint8_t id) {
return buf; return buf;
} }
static int ul_print_nxp_silicon_info(uint8_t *card_uid) {
if (card_uid[0] != 0x04) {
return PM3_SUCCESS;
}
uint8_t uid[7];
memcpy(&uid, card_uid, 7);
uint16_t waferCoordX = ((uid[6] & 3) << 8) | uid[1];
uint16_t waferCoordY = ((uid[6] & 12) << 6) | uid[2];
uint32_t waferCounter = (
(uid[4] << 5) |
((uid[6] & 0xF0) << 17) |
(uid[5] << 13) |
(uid[3] >> 3)
);
uint8_t testSite = uid[3] & 7;
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "--- " _CYAN_("Tag Silicon Information"));
PrintAndLogEx(INFO, " Wafer Counter: %" PRId32 " ( 0x%02" PRIX32 " )", waferCounter, waferCounter);
PrintAndLogEx(INFO, " Wafer Coordinates: x %" PRId16 ", y %" PRId16 " (0x%02" PRIX16 ", 0x%02" PRIX16 ")"
, waferCoordX
, waferCoordY
, waferCoordX
, waferCoordY
);
PrintAndLogEx(INFO, " Test Site: %u", testSite);
return PM3_SUCCESS;
}
/* /*
The 7 MSBits (=n) code the storage size itself based on 2^n, The 7 MSBits (=n) code the storage size itself based on 2^n,
the LSBit is set to '0' if the size is exactly 2^n the LSBit is set to '0' if the size is exactly 2^n
@ -456,16 +489,16 @@ static int ul_print_default(uint8_t *data, uint8_t *real_uid) {
// CT (cascade tag byte) 0x88 xor SN0 xor SN1 xor SN2 // CT (cascade tag byte) 0x88 xor SN0 xor SN1 xor SN2
int crc0 = 0x88 ^ uid[0] ^ uid[1] ^ uid[2]; int crc0 = 0x88 ^ uid[0] ^ uid[1] ^ uid[2];
if (data[3] == crc0) if (data[3] == crc0)
PrintAndLogEx(SUCCESS, " BCC0: %02X (" _GREEN_("ok") ")", data[3]); PrintAndLogEx(SUCCESS, " BCC0: %02X ( " _GREEN_("ok") " )", data[3]);
else else
PrintAndLogEx(NORMAL, " BCC0: %02X, crc should be %02X", data[3], crc0); PrintAndLogEx(NORMAL, " BCC0: %02X, crc should be %02X", data[3], crc0);
int crc1 = uid[3] ^ uid[4] ^ uid[5] ^ uid[6]; int crc1 = uid[3] ^ uid[4] ^ uid[5] ^ uid[6];
if (data[8] == crc1) if (data[8] == crc1)
PrintAndLogEx(SUCCESS, " BCC1: %02X (" _GREEN_("ok") ")", data[8]); PrintAndLogEx(SUCCESS, " BCC1: %02X ( " _GREEN_("ok") " )", data[8]);
else else
PrintAndLogEx(NORMAL, " BCC1: %02X, crc should be %02X", data[8], crc1); PrintAndLogEx(NORMAL, " BCC1: %02X, crc should be %02X", data[8], crc1);
PrintAndLogEx(SUCCESS, " Internal: %02X (%s)", data[9], (data[9] == 0x48) ? _GREEN_("default") : _RED_("not default")); PrintAndLogEx(SUCCESS, " Internal: %02X ( %s )", data[9], (data[9] == 0x48) ? _GREEN_("default") : _RED_("not default"));
} else { } else {
PrintAndLogEx(SUCCESS, "Blocks 0-2: %s", sprint_hex(data + 0, 12)); PrintAndLogEx(SUCCESS, "Blocks 0-2: %s", sprint_hex(data + 0, 12));
} }
@ -579,10 +612,10 @@ static int ndef_print_CC(uint8_t *data) {
PrintAndLogEx(SUCCESS, " Additional feature information"); PrintAndLogEx(SUCCESS, " Additional feature information");
PrintAndLogEx(SUCCESS, " %02X", data[3]); PrintAndLogEx(SUCCESS, " %02X", data[3]);
PrintAndLogEx(SUCCESS, " 00000000"); PrintAndLogEx(SUCCESS, " 00000000");
PrintAndLogEx(SUCCESS, " xxx - %02X: RFU (%s)", msb3, (msb3 == 0) ? _GREEN_("ok") : _RED_("fail")); PrintAndLogEx(SUCCESS, " xxx - %02X: RFU ( %s )", msb3, (msb3 == 0) ? _GREEN_("ok") : _RED_("fail"));
PrintAndLogEx(SUCCESS, " x - %02X: %s special frame", sf, (sf) ? "support" : "don\'t support"); PrintAndLogEx(SUCCESS, " x - %02X: %s special frame", sf, (sf) ? "support" : "don\'t support");
PrintAndLogEx(SUCCESS, " x - %02X: %s lock block", lb, (lb) ? "support" : "don\'t support"); PrintAndLogEx(SUCCESS, " x - %02X: %s lock block", lb, (lb) ? "support" : "don\'t support");
PrintAndLogEx(SUCCESS, " xx - %02X: RFU (%s)", mlrule, (mlrule == 0) ? _GREEN_("ok") : _RED_("fail")); PrintAndLogEx(SUCCESS, " xx - %02X: RFU ( %s )", mlrule, (mlrule == 0) ? _GREEN_("ok") : _RED_("fail"));
PrintAndLogEx(SUCCESS, " x - %02X: IC %s multiple block reads", mbread, (mbread) ? "support" : "don\'t support"); PrintAndLogEx(SUCCESS, " x - %02X: IC %s multiple block reads", mbread, (mbread) ? "support" : "don\'t support");
return PM3_SUCCESS; return PM3_SUCCESS;
} }
@ -1644,6 +1677,9 @@ static int CmdHF14AMfUInfo(const char *Cmd) {
} }
} }
// print silicon info
ul_print_nxp_silicon_info(card.uid);
// Get Version // Get Version
uint8_t version[10] = {0x00}; uint8_t version[10] = {0x00};
status = ulev1_getVersion(version, sizeof(version)); status = ulev1_getVersion(version, sizeof(version));

View file

@ -97,6 +97,27 @@ static uint8_t extract_epurse[8] = {0};
#define SKIP_TO_NEXT(a) (TRACELOG_HDR_LEN + (a)->data_len + TRACELOG_PARITY_LEN((a))) #define SKIP_TO_NEXT(a) (TRACELOG_HDR_LEN + (a)->data_len + TRACELOG_PARITY_LEN((a)))
static uint16_t extractChall_ev2(uint16_t tracepos, uint8_t *trace, uint8_t cmdpos, uint8_t long_jmp) {
tracelog_hdr_t *next_hdr = (tracelog_hdr_t *)(trace + tracepos);
if (next_hdr->data_len != 21) {
return 0;
}
tracepos += TRACELOG_HDR_LEN + next_hdr->data_len + TRACELOG_PARITY_LEN(next_hdr);
PrintAndLogEx(INFO, "1499999999 %s " NOLF, sprint_hex_inrow(next_hdr->frame + 1, 16));
next_hdr = (tracelog_hdr_t *)(trace + tracepos);
tracepos += TRACELOG_HDR_LEN + next_hdr->data_len + TRACELOG_PARITY_LEN(next_hdr);
if (next_hdr->frame[cmdpos] == MFDES_ADDITIONAL_FRAME) {
PrintAndLogEx(NORMAL, "%s", sprint_hex_inrow(next_hdr->frame + cmdpos + long_jmp, 32));
} else {
PrintAndLogEx(NORMAL, "");
}
return tracepos;
}
static uint16_t extractChallenges(uint16_t tracepos, uint16_t traceLen, uint8_t *trace) { static uint16_t extractChallenges(uint16_t tracepos, uint16_t traceLen, uint8_t *trace) {
// sanity check // sanity check
@ -270,6 +291,10 @@ static uint16_t extractChallenges(uint16_t tracepos, uint16_t traceLen, uint8_t
return tracepos; return tracepos;
} }
if (hdr->isResponse) {
return tracepos;
}
// PCB [CID] [NAD] [INF] CRC CRC // PCB [CID] [NAD] [INF] CRC CRC
uint8_t pos = calc_pos(frame); uint8_t pos = calc_pos(frame);
uint8_t long_jmp = (data_len > 6) ? 4 : 1; uint8_t long_jmp = (data_len > 6) ? 4 : 1;
@ -279,93 +304,103 @@ static uint16_t extractChallenges(uint16_t tracepos, uint16_t traceLen, uint8_t
switch (frame[pos]) { switch (frame[pos]) {
case MFDES_AUTHENTICATE: { case MFDES_AUTHENTICATE: {
// Assume wrapped or unwrapped // Assume wrapped or unwrapped
PrintAndLogEx(INFO, "AUTH NATIVE (keyNo %d)", frame[pos + long_jmp]); PrintAndLogEx(INFO, "AUTH NATIVE (keyNo %d)", frame[pos + long_jmp]);
if (next_record_is_response(tracepos, trace) == false) {
if (hdr->isResponse == false && next_record_is_response(tracepos, trace)) { break;
tracelog_hdr_t *next_hdr = (tracelog_hdr_t *)(trace + tracepos);
tracepos += TRACELOG_HDR_LEN + next_hdr->data_len + TRACELOG_PARITY_LEN(next_hdr);
if (next_hdr->data_len < 7) {
break;
}
PrintAndLogEx(INFO, "DES 1499999999 %s " NOLF, sprint_hex_inrow(next_hdr->frame + 1, 8));
next_hdr = (tracelog_hdr_t *)(trace + tracepos);
tracepos += TRACELOG_HDR_LEN + next_hdr->data_len + TRACELOG_PARITY_LEN(next_hdr);
if (next_hdr->frame[pos] == MFDES_ADDITIONAL_FRAME) {
PrintAndLogEx(NORMAL, "%s", sprint_hex_inrow(next_hdr->frame + pos + long_jmp, 16));
}
return tracepos;
} }
break; // AUTHENTICATE_NATIVE
tracelog_hdr_t *next_hdr = (tracelog_hdr_t *)(trace + tracepos);
if (next_hdr->data_len < 7) {
break;
}
tracepos += TRACELOG_HDR_LEN + next_hdr->data_len + TRACELOG_PARITY_LEN(next_hdr);
PrintAndLogEx(INFO, "DES 1499999999 %s " NOLF, sprint_hex_inrow(next_hdr->frame + 1, 8));
next_hdr = (tracelog_hdr_t *)(trace + tracepos);
tracepos += TRACELOG_HDR_LEN + next_hdr->data_len + TRACELOG_PARITY_LEN(next_hdr);
if (next_hdr->frame[pos] == MFDES_ADDITIONAL_FRAME) {
PrintAndLogEx(NORMAL, "%s", sprint_hex_inrow(next_hdr->frame + pos + long_jmp, 16));
} else {
PrintAndLogEx(NORMAL, "");
}
return tracepos; // AUTHENTICATE_NATIVE
} }
case MFDES_AUTHENTICATE_ISO: { case MFDES_AUTHENTICATE_ISO: {
// Assume wrapped or unwrapped // Assume wrapped or unwrapped
PrintAndLogEx(INFO, "AUTH ISO (keyNo %d)", frame[pos + long_jmp]); PrintAndLogEx(INFO, "AUTH ISO (keyNo %d)", frame[pos + long_jmp]);
if (hdr->isResponse == false && next_record_is_response(tracepos, trace)) { if (next_record_is_response(tracepos, trace) == false) {
break;
tracelog_hdr_t *next_hdr = (tracelog_hdr_t *)(trace + tracepos);
tracepos += TRACELOG_HDR_LEN + next_hdr->data_len + TRACELOG_PARITY_LEN(next_hdr);
if (next_hdr->data_len < 7) {
break;
}
uint8_t tdea = 8;
if (next_hdr->data_len > 20) {
tdea = 16;
PrintAndLogEx(INFO, "3TDEA 1499999999 %s " NOLF, sprint_hex_inrow(next_hdr->frame + 1, tdea));
} else {
PrintAndLogEx(INFO, "2TDEA 1499999999 %s " NOLF, sprint_hex_inrow(next_hdr->frame + 1, tdea));
}
next_hdr = (tracelog_hdr_t *)(trace + tracepos);
tracepos += TRACELOG_HDR_LEN + next_hdr->data_len + TRACELOG_PARITY_LEN(next_hdr);
if (next_hdr->frame[pos] == MFDES_ADDITIONAL_FRAME) {
PrintAndLogEx(NORMAL, "%s", sprint_hex_inrow(next_hdr->frame + pos + long_jmp, (tdea << 1)));
}
return tracepos;
} }
break; // AUTHENTICATE_STANDARD tracelog_hdr_t *next_hdr = (tracelog_hdr_t *)(trace + tracepos);
tracepos += TRACELOG_HDR_LEN + next_hdr->data_len + TRACELOG_PARITY_LEN(next_hdr);
if (next_hdr->data_len < 7) {
break;
}
uint8_t tdea = 8;
if (next_hdr->data_len > 20) {
tdea = 16;
PrintAndLogEx(INFO, "3TDEA 1499999999 %s " NOLF, sprint_hex_inrow(next_hdr->frame + 1, tdea));
} else {
PrintAndLogEx(INFO, "2TDEA 1499999999 %s " NOLF, sprint_hex_inrow(next_hdr->frame + 1, tdea));
}
next_hdr = (tracelog_hdr_t *)(trace + tracepos);
tracepos += TRACELOG_HDR_LEN + next_hdr->data_len + TRACELOG_PARITY_LEN(next_hdr);
if (next_hdr->frame[pos] == MFDES_ADDITIONAL_FRAME) {
PrintAndLogEx(NORMAL, "%s", sprint_hex_inrow(next_hdr->frame + pos + long_jmp, (tdea << 1)));
} else {
PrintAndLogEx(NORMAL, "");
}
return tracepos; // AUTHENTICATE_STANDARD
} }
case MFDES_AUTHENTICATE_AES: { case MFDES_AUTHENTICATE_AES: {
// Assume wrapped or unwrapped // Assume wrapped or unwrapped
PrintAndLogEx(INFO, "AUTH AES (keyNo %d)", frame[pos + long_jmp]); PrintAndLogEx(INFO, "AUTH AES (keyNo %d)", frame[pos + long_jmp]);
if (hdr->isResponse == false && next_record_is_response(tracepos, trace)) { if (next_record_is_response(tracepos, trace)) {
break;
tracelog_hdr_t *next_hdr = (tracelog_hdr_t *)(trace + tracepos);
tracepos += TRACELOG_HDR_LEN + next_hdr->data_len + TRACELOG_PARITY_LEN(next_hdr);
if (next_hdr->data_len < 7) {
break;
}
PrintAndLogEx(INFO, "AES 1499999999 %s " NOLF, sprint_hex_inrow(next_hdr->frame + 1, 8));
next_hdr = (tracelog_hdr_t *)(trace + tracepos);
tracepos += TRACELOG_HDR_LEN + next_hdr->data_len + TRACELOG_PARITY_LEN(next_hdr);
if (next_hdr->frame[pos] == MFDES_ADDITIONAL_FRAME) {
PrintAndLogEx(NORMAL, "%s", sprint_hex_inrow(next_hdr->frame + pos + long_jmp, 16));
}
return tracepos;
} }
break;
tracelog_hdr_t *next_hdr = (tracelog_hdr_t *)(trace + tracepos);
tracepos += TRACELOG_HDR_LEN + next_hdr->data_len + TRACELOG_PARITY_LEN(next_hdr);
if (next_hdr->data_len < 7) {
break;
}
PrintAndLogEx(INFO, "AES 1499999999 %s " NOLF, sprint_hex_inrow(next_hdr->frame + 1, 8));
next_hdr = (tracelog_hdr_t *)(trace + tracepos);
tracepos += TRACELOG_HDR_LEN + next_hdr->data_len + TRACELOG_PARITY_LEN(next_hdr);
if (next_hdr->frame[pos] == MFDES_ADDITIONAL_FRAME) {
PrintAndLogEx(NORMAL, "%s", sprint_hex_inrow(next_hdr->frame + pos + long_jmp, 16));
} else {
PrintAndLogEx(NORMAL, "");
}
return tracepos;
} }
case MFDES_AUTHENTICATE_EV2F: { case MFDES_AUTHENTICATE_EV2F: {
if (hdr->isResponse == false) { PrintAndLogEx(INFO, "AUTH EV2 First");
PrintAndLogEx(INFO, "AUTH EV2 First"); uint16_t tmp = extractChall_ev2(tracepos, trace, pos, long_jmp);
} if (tmp == 0)
break; break;
else
return tmp;
} }
case MFDES_AUTHENTICATE_EV2NF: { case MFDES_AUTHENTICATE_EV2NF: {
if (hdr->isResponse == false) { PrintAndLogEx(INFO, "AUTH EV2 Non First");
PrintAndLogEx(INFO, "AUTH EV2 Non First"); uint16_t tmp = extractChall_ev2(tracepos, trace, pos, long_jmp);
} if (tmp == 0)
break; break;
else
return tmp;
} }
} }
} }

View file

@ -87,11 +87,11 @@ static int CmdEMVSelect(const char *Cmd) {
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_lit0("sS", "select", "activate field and select card"), arg_lit0("sS", "select", "Activate field and select card"),
arg_lit0("kK", "keep", "keep field for next command"), arg_lit0("kK", "keep", "Keep field for next command"),
arg_lit0("aA", "apdu", "show APDU requests and responses"), arg_lit0("aA", "apdu", "Show APDU requests and responses"),
arg_lit0("tT", "tlv", "TLV decode results"), arg_lit0("tT", "tlv", "TLV decode results"),
arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."), arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. (def: Contactless interface)"),
arg_str1(NULL, NULL, "<hex>", "Applet AID"), arg_str1(NULL, NULL, "<hex>", "Applet AID"),
arg_param_end arg_param_end
}; };
@ -138,11 +138,11 @@ static int CmdEMVSearch(const char *Cmd) {
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_lit0("sS", "select", "activate field and select card"), arg_lit0("sS", "select", "Activate field and select card"),
arg_lit0("kK", "keep", "keep field ON for next command"), arg_lit0("kK", "keep", "Keep field ON for next command"),
arg_lit0("aA", "apdu", "show APDU reqests and responses"), arg_lit0("aA", "apdu", "Show APDU reqests and responses"),
arg_lit0("tT", "tlv", "TLV decode results of selected applets"), arg_lit0("tT", "tlv", "TLV decode results of selected applets"),
arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."), arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. (def: Contactless interface)"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(ctx, Cmd, argtable, true); CLIExecWithReturn(ctx, Cmd, argtable, true);
@ -192,13 +192,13 @@ static int CmdEMVPPSE(const char *Cmd) {
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_lit0("sS", "select", "activate field and select card"), arg_lit0("sS", "select", "Activate field and select card"),
arg_lit0("kK", "keep", "keep field ON for next command"), arg_lit0("kK", "keep", "Keep field ON for next command"),
arg_lit0("1", "pse", "pse (1PAY.SYS.DDF01) mode"), arg_lit0("1", "pse", "PSE (1PAY.SYS.DDF01) mode"),
arg_lit0("2", "ppse", "ppse (2PAY.SYS.DDF01) mode (default mode)"), arg_lit0("2", "ppse", "PPSE (2PAY.SYS.DDF01) mode (def)"),
arg_lit0("aA", "apdu", "show APDU reqests and responses"), arg_lit0("aA", "apdu", "Show APDU reqests and responses"),
arg_lit0("tT", "tlv", "TLV decode results of selected applets"), arg_lit0("tT", "tlv", "TLV decode results of selected applets"),
arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."), arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. (def: Contactless interface)"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(ctx, Cmd, argtable, true); CLIExecWithReturn(ctx, Cmd, argtable, true);
@ -252,12 +252,12 @@ static int CmdEMVGPO(const char *Cmd) {
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_lit0("kK", "keep", "keep field ON for next command"), arg_lit0("kK", "keep", "Keep field ON for next command"),
arg_lit0("pP", "params", "load parameters from `emv_defparams.json` file for PDOLdata making from PDOL and parameters"), arg_lit0("pP", "params", "Load parameters from `emv_defparams.json` file for PDOLdata making from PDOL and parameters"),
arg_lit0("mM", "make", "make PDOLdata from PDOL (tag 9F38) and parameters (by default uses default parameters)"), arg_lit0("mM", "make", "Make PDOLdata from PDOL (tag 9F38) and parameters (def: uses default parameters)"),
arg_lit0("aA", "apdu", "show APDU reqests and responses"), arg_lit0("aA", "apdu", "Show APDU reqests and responses"),
arg_lit0("tT", "tlv", "TLV decode results of selected applets"), arg_lit0("tT", "tlv", "TLV decode results of selected applets"),
arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."), arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. (def: Contactless interface)"),
arg_strx0(NULL, NULL, "<hex>", "PDOLdata/PDOL"), arg_strx0(NULL, NULL, "<hex>", "PDOLdata/PDOL"),
arg_param_end arg_param_end
}; };
@ -361,10 +361,10 @@ static int CmdEMVReadRecord(const char *Cmd) {
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_lit0("kK", "keep", "keep field ON for next command"), arg_lit0("kK", "keep", "Keep field ON for next command"),
arg_lit0("aA", "apdu", "show APDU reqests and responses"), arg_lit0("aA", "apdu", "Show APDU reqests and responses"),
arg_lit0("tT", "tlv", "TLV decode results of selected applets"), arg_lit0("tT", "tlv", "TLV decode results of selected applets"),
arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."), arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. (def: Contactless interface)"),
arg_strx1(NULL, NULL, "<hex>", "<SFI 1 byte><SFIrecord 1 byte"), arg_strx1(NULL, NULL, "<hex>", "<SFI 1 byte><SFIrecord 1 byte"),
arg_param_end arg_param_end
}; };
@ -421,14 +421,14 @@ static int CmdEMVAC(const char *Cmd) {
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_lit0("kK", "keep", "keep field ON for next command"), arg_lit0("kK", "keep", "Keep field ON for next command"),
arg_lit0("cC", "cda", "executes CDA transaction. Needs to get SDAD in results."), arg_lit0("cC", "cda", "Executes CDA transaction. Needs to get SDAD in results."),
arg_str0("dD", "decision", "<aac|tc|arqc>", "Terminal decision. aac - declined, tc - approved, arqc - online authorisation requested"), arg_str0("dD", "decision", "<aac|tc|arqc>", "Terminal decision. aac - declined, tc - approved, arqc - online authorisation requested"),
arg_lit0("pP", "params", "load parameters from `emv_defparams.json` file for CDOLdata making from CDOL and parameters"), arg_lit0("pP", "params", "Load parameters from `emv_defparams.json` file for CDOLdata making from CDOL and parameters"),
arg_lit0("mM", "make", "make CDOLdata from CDOL (tag 8C and 8D) and parameters (by default uses default parameters)"), arg_lit0("mM", "make", "Make CDOLdata from CDOL (tag 8C and 8D) and parameters (def: use default parameters)"),
arg_lit0("aA", "apdu", "show APDU reqests and responses"), arg_lit0("aA", "apdu", "Show APDU reqests and responses"),
arg_lit0("tT", "tlv", "TLV decode results of selected applets"), arg_lit0("tT", "tlv", "TLV decode results of selected applets"),
arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."), arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. (def: Contactless interface)"),
arg_strx1(NULL, NULL, "<hex>", "CDOLdata/CDOL"), arg_strx1(NULL, NULL, "<hex>", "CDOLdata/CDOL"),
arg_param_end arg_param_end
}; };
@ -543,9 +543,9 @@ static int CmdEMVGenerateChallenge(const char *Cmd) {
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_lit0("kK", "keep", "keep field ON for next command"), arg_lit0("kK", "keep", "Keep field ON for next command"),
arg_lit0("aA", "apdu", "show APDU reqests and responses"), arg_lit0("aA", "apdu", "Show APDU reqests and responses"),
arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."), arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. (def: Contactless interface)"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(ctx, Cmd, argtable, true); CLIExecWithReturn(ctx, Cmd, argtable, true);
@ -595,12 +595,12 @@ static int CmdEMVInternalAuthenticate(const char *Cmd) {
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_lit0("kK", "keep", "keep field ON for next command"), arg_lit0("kK", "keep", "Keep field ON for next command"),
arg_lit0("pP", "params", "load parameters from `emv_defparams.json` file for DDOLdata making from DDOL and parameters"), arg_lit0("pP", "params", "Load parameters from `emv_defparams.json` file for DDOLdata making from DDOL and parameters"),
arg_lit0("mM", "make", "make DDOLdata from DDOL (tag 9F49) and parameters (by default uses default parameters)"), arg_lit0("mM", "make", "Make DDOLdata from DDOL (tag 9F49) and parameters (def: use default parameters)"),
arg_lit0("aA", "apdu", "show APDU reqests and responses"), arg_lit0("aA", "apdu", "Show APDU reqests and responses"),
arg_lit0("tT", "tlv", "TLV decode results of selected applets"), arg_lit0("tT", "tlv", "TLV decode results of selected applets"),
arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."), arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. (def: Contactless interface)"),
arg_strx1(NULL, NULL, "<hex>", "DDOLdata/DDOL"), arg_strx1(NULL, NULL, "<hex>", "DDOLdata/DDOL"),
arg_param_end arg_param_end
}; };
@ -822,17 +822,17 @@ static int CmdEMVExec(const char *Cmd) {
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_lit0("sS", "select", "activate field and select card."), arg_lit0("sS", "select", "Activate field and select card"),
arg_lit0("aA", "apdu", "show APDU reqests and responses."), arg_lit0("aA", "apdu", "Show APDU reqests and responses"),
arg_lit0("tT", "tlv", "TLV decode results."), arg_lit0("tT", "tlv", "TLV decode results"),
arg_lit0("jJ", "jload", "Load transaction parameters from `emv_defparams.json` file."), arg_lit0("jJ", "jload", "Load transaction parameters from `emv_defparams.json` file"),
arg_lit0("fF", "forceaid", "Force search AID. Search AID instead of execute PPSE."), arg_lit0("fF", "forceaid", "Force search AID. Search AID instead of execute PPSE"),
arg_rem("By default:", "Transaction type - MSD"), arg_rem("By default:", "Transaction type - MSD"),
arg_lit0("vV", "qvsdc", "Transaction type - qVSDC or M/Chip."), arg_lit0("vV", "qvsdc", "Transaction type - qVSDC or M/Chip"),
arg_lit0("cC", "qvsdccda", "Transaction type - qVSDC or M/Chip plus CDA (SDAD generation)."), arg_lit0("cC", "qvsdccda", "Transaction type - qVSDC or M/Chip plus CDA (SDAD generation)"),
arg_lit0("xX", "vsdc", "Transaction type - VSDC. For test only. Not a standard behavior."), arg_lit0("xX", "vsdc", "Transaction type - VSDC. For test only. Not a standard behavior"),
arg_lit0("gG", "acgpo", "VISA. generate AC from GPO."), arg_lit0("gG", "acgpo", "VISA. generate AC from GPO"),
arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."), arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. (def: Contactless interface)"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(ctx, Cmd, argtable, true); CLIExecWithReturn(ctx, Cmd, argtable, true);
@ -1448,17 +1448,17 @@ static int CmdEMVScan(const char *Cmd) {
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_lit0("aA", "apdu", "show APDU reqests and responses."), arg_lit0("aA", "apdu", "Show APDU reqests and responses"),
arg_lit0("tT", "tlv", "TLV decode results."), arg_lit0("tT", "tlv", "TLV decode results"),
arg_lit0("eE", "extract", "Extract TLV elements and fill Application Data"), arg_lit0("eE", "extract", "Extract TLV elements and fill Application Data"),
arg_lit0("jJ", "jload", "Load transaction parameters from `emv_defparams.json` file."), arg_lit0("jJ", "jload", "Load transaction parameters from `emv_defparams.json` file"),
arg_rem("By default:", "Transaction type - MSD"), arg_rem("By default:", "Transaction type - MSD"),
arg_lit0("vV", "qvsdc", "Transaction type - qVSDC or M/Chip."), arg_lit0("vV", "qvsdc", "Transaction type - qVSDC or M/Chip"),
arg_lit0("cC", "qvsdccda", "Transaction type - qVSDC or M/Chip plus CDA (SDAD generation)."), arg_lit0("cC", "qvsdccda", "Transaction type - qVSDC or M/Chip plus CDA (SDAD generation)"),
arg_lit0("xX", "vsdc", "Transaction type - VSDC. For test only. Not a standard behavior."), arg_lit0("xX", "vsdc", "Transaction type - VSDC. For test only. Not a standard behavior"),
arg_lit0("gG", "acgpo", "VISA. generate AC from GPO."), arg_lit0("gG", "acgpo", "VISA. generate AC from GPO"),
arg_lit0("mM", "merge", "Merge output file with card's data. (warning: the file may be corrupted!)"), arg_lit0("mM", "merge", "Merge output file with card's data. (warning: the file may be corrupted!)"),
arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."), arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. (def: Contactless interface)"),
arg_str1(NULL, NULL, "<fn>", "JSON output filename"), arg_str1(NULL, NULL, "<fn>", "JSON output filename"),
arg_param_end arg_param_end
}; };
@ -1839,8 +1839,8 @@ static int CmdEMVTest(const char *Cmd) {
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_lit0("i", "ignore", "ignore timing tests for VM"), arg_lit0("i", "ignore", "Ignore timing tests for VM"),
arg_lit0("l", "long", "run long tests too"), arg_lit0("l", "long", "Run long tests too"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(ctx, Cmd, argtable, true); CLIExecWithReturn(ctx, Cmd, argtable, true);
@ -1871,9 +1871,9 @@ static int CmdEMVRoca(const char *Cmd) {
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_lit0("tT", "selftest", "self test"), arg_lit0("tT", "selftest", "Self test"),
arg_lit0("aA", "apdu", "show APDU reqests and responses"), arg_lit0("aA", "apdu", "Show APDU reqests and responses"),
arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default"), arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. (def: Contactless interface)"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(ctx, Cmd, argtable, true); CLIExecWithReturn(ctx, Cmd, argtable, true);
@ -2124,17 +2124,17 @@ out:
static command_t CommandTable[] = { static command_t CommandTable[] = {
{"help", CmdHelp, AlwaysAvailable, "This help"}, {"help", CmdHelp, AlwaysAvailable, "This help"},
{"exec", CmdEMVExec, IfPm3Iso14443, "Executes EMV contactless transaction."}, {"exec", CmdEMVExec, IfPm3Iso14443, "Executes EMV contactless transaction"},
{"pse", CmdEMVPPSE, IfPm3Iso14443, "Execute PPSE. It selects 2PAY.SYS.DDF01 or 1PAY.SYS.DDF01 directory."}, {"pse", CmdEMVPPSE, IfPm3Iso14443, "Execute PPSE. It selects 2PAY.SYS.DDF01 or 1PAY.SYS.DDF01 directory"},
{"search", CmdEMVSearch, IfPm3Iso14443, "Try to select all applets from applets list and print installed applets."}, {"search", CmdEMVSearch, IfPm3Iso14443, "Try to select all applets from applets list and print installed applets"},
{"select", CmdEMVSelect, IfPm3Iso14443, "Select applet."}, {"select", CmdEMVSelect, IfPm3Iso14443, "Select applet"},
{"gpo", CmdEMVGPO, IfPm3Iso14443, "Execute GetProcessingOptions."}, {"gpo", CmdEMVGPO, IfPm3Iso14443, "Execute GetProcessingOptions"},
{"readrec", CmdEMVReadRecord, IfPm3Iso14443, "Read files from card."}, {"readrec", CmdEMVReadRecord, IfPm3Iso14443, "Read files from card"},
{"genac", CmdEMVAC, IfPm3Iso14443, "Generate ApplicationCryptogram."}, {"genac", CmdEMVAC, IfPm3Iso14443, "Generate ApplicationCryptogram"},
{"challenge", CmdEMVGenerateChallenge, IfPm3Iso14443, "Generate challenge."}, {"challenge", CmdEMVGenerateChallenge, IfPm3Iso14443, "Generate challenge"},
{"intauth", CmdEMVInternalAuthenticate, IfPm3Iso14443, "Internal authentication."}, {"intauth", CmdEMVInternalAuthenticate, IfPm3Iso14443, "Internal authentication"},
{"scan", CmdEMVScan, IfPm3Iso14443, "Scan EMV card and save it contents to json file for emulator."}, {"scan", CmdEMVScan, IfPm3Iso14443, "Scan EMV card and save it contents to json file for emulator"},
{"test", CmdEMVTest, AlwaysAvailable, "Crypto logic test."}, {"test", CmdEMVTest, AlwaysAvailable, "Crypto logic test"},
/* /*
{"getrng", CmdEMVGetrng, IfPm3Iso14443, "get random number from terminal"}, {"getrng", CmdEMVGetrng, IfPm3Iso14443, "get random number from terminal"},
{"eload", CmdEmvELoad, IfPm3Iso14443, "load EMV tag into device"}, {"eload", CmdEmvELoad, IfPm3Iso14443, "load EMV tag into device"},
@ -2142,7 +2142,7 @@ static command_t CommandTable[] = {
{"sim", CmdEmvSim, IfPm3Iso14443, "simulate EMV tag"}, {"sim", CmdEmvSim, IfPm3Iso14443, "simulate EMV tag"},
{"clone", CmdEmvClone, IfPm3Iso14443, "clone an EMV tag"}, {"clone", CmdEmvClone, IfPm3Iso14443, "clone an EMV tag"},
*/ */
{"list", CmdEMVList, AlwaysAvailable, "List ISO7816 history"}, {"list", CmdEMVList, AlwaysAvailable, "List ISO7816 history"},
{"roca", CmdEMVRoca, IfPm3Iso14443, "Extract public keys and run ROCA test"}, {"roca", CmdEMVRoca, IfPm3Iso14443, "Extract public keys and run ROCA test"},
{NULL, NULL, NULL, NULL} {NULL, NULL, NULL, NULL}
}; };

View file

@ -2252,10 +2252,11 @@ static const DesfireCreateFileCommands_t DesfireFileCommands[] = {
}; };
const DesfireCreateFileCommands_t *GetDesfireFileCmdRec(uint8_t type) { const DesfireCreateFileCommands_t *GetDesfireFileCmdRec(uint8_t type) {
for (int i = 0; i < ARRAYLEN(DesfireFileCommands); i++) for (int i = 0; i < ARRAYLEN(DesfireFileCommands); i++) {
if (DesfireFileCommands[i].id == type) if (DesfireFileCommands[i].id == type) {
return &DesfireFileCommands[i]; return &DesfireFileCommands[i];
}
}
return NULL; return NULL;
} }
@ -2303,6 +2304,7 @@ const char *GetDesfireAccessRightStr(uint8_t right) {
sprintf(int_access_str, "key 0x%02x", right); sprintf(int_access_str, "key 0x%02x", right);
return int_access_str; return int_access_str;
} }
if (right == 0x0e) if (right == 0x0e)
return DesfireFreeStr; return DesfireFreeStr;
@ -2332,8 +2334,9 @@ const char *AccessRightShortStr[] = {
}; };
const char *GetDesfireAccessRightShortStr(uint8_t right) { const char *GetDesfireAccessRightShortStr(uint8_t right) {
if (right > 0x0f) if (right > 0x0F) {
return DesfireNAStr; return DesfireNAStr;
}
return AccessRightShortStr[right]; return AccessRightShortStr[right];
} }
@ -2346,23 +2349,20 @@ void DesfireEncodeFileAcessMode(uint8_t *mode, uint8_t r, uint8_t w, uint8_t rw,
void DesfireDecodeFileAcessMode(const uint8_t *mode, uint8_t *r, uint8_t *w, uint8_t *rw, uint8_t *ch) { void DesfireDecodeFileAcessMode(const uint8_t *mode, uint8_t *r, uint8_t *w, uint8_t *rw, uint8_t *ch) {
// read // read
if (r) if (r)
*r = (mode[1] >> 4) & 0x0f; // hi 2b *r = (mode[1] >> 4) & 0x0F; // hi 2b
// write // write
if (w) if (w)
*w = mode[1] & 0x0f; *w = mode[1] & 0x0F;
// read/write // read/write
if (rw) if (rw)
*rw = (mode[0] >> 4) & 0x0f; // low 2b *rw = (mode[0] >> 4) & 0x0F; // low 2b
// change // change
if (ch) if (ch)
*ch = mode[0] & 0x0f; *ch = mode[0] & 0x0F;
} }
void DesfirePrintAccessRight(uint8_t *data) { void DesfirePrintAccessRight(uint8_t *data) {
uint8_t r = 0; uint8_t r = 0, w = 0, rw = 0, ch = 0;
uint8_t w = 0;
uint8_t rw = 0;
uint8_t ch = 0;
DesfireDecodeFileAcessMode(data, &r, &w, &rw, &ch); DesfireDecodeFileAcessMode(data, &r, &w, &rw, &ch);
PrintAndLogEx(SUCCESS, "read : %s", GetDesfireAccessRightStr(r)); PrintAndLogEx(SUCCESS, "read : %s", GetDesfireAccessRightStr(r));
PrintAndLogEx(SUCCESS, "write : %s", GetDesfireAccessRightStr(w)); PrintAndLogEx(SUCCESS, "write : %s", GetDesfireAccessRightStr(w));