mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-21 13:53:55 -07:00
Merge pull request #1374 from merlokk/desf_app
desfire app create/delete
This commit is contained in:
commit
4e2f836145
3 changed files with 348 additions and 334 deletions
|
@ -1518,43 +1518,6 @@ static int handler_desfire_getkeysettings(uint8_t *key_settings, uint8_t *num_ke
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
static int handler_desfire_getuid(uint8_t *uid) {
|
|
||||||
if (uid == NULL) {
|
|
||||||
PrintAndLogEx(DEBUG, "UID=NULL");
|
|
||||||
return PM3_EINVARG;
|
|
||||||
}
|
|
||||||
sAPDU apdu = {0x90, MFDES_GET_UID, 0x00, 0x00, 0x00, NULL}; //0x51
|
|
||||||
uint32_t recv_len = 0;
|
|
||||||
uint16_t sw = 0;
|
|
||||||
|
|
||||||
// Setup the pre-process to update the IV etc. (not needed in the apdu to send to card)
|
|
||||||
size_t plen = 1;
|
|
||||||
uint8_t tmp_data[100] = { 0x00 }; // Note sure on size, but 100 is more then enough
|
|
||||||
tmp_data[0] = MFDES_GET_UID;
|
|
||||||
int8_t *p = mifare_cryto_preprocess_data(tag, tmp_data, &plen, 0, MDCM_PLAIN | CMAC_COMMAND);
|
|
||||||
(void)p;
|
|
||||||
|
|
||||||
// Send request/apdu
|
|
||||||
int res = send_desfire_cmd(&apdu, false, uid, &recv_len, &sw, 0, true);
|
|
||||||
|
|
||||||
if (res != PM3_SUCCESS)
|
|
||||||
return res;
|
|
||||||
|
|
||||||
if (sw != status(MFDES_S_OPERATION_OK))
|
|
||||||
return PM3_ESOFT;
|
|
||||||
|
|
||||||
// decrypt response
|
|
||||||
size_t dlen = recv_len;
|
|
||||||
p = mifare_cryto_postprocess_data(tag, uid, &dlen, CMAC_COMMAND | CMAC_VERIFY | MAC_VERIFY | MDCM_ENCIPHERED);
|
|
||||||
(void)p;
|
|
||||||
|
|
||||||
DropFieldDesfire();
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
static int handler_desfire_commit_transaction(void) {
|
static int handler_desfire_commit_transaction(void) {
|
||||||
sAPDU apdu = {0x90, MFDES_COMMIT_TRANSACTION, 0x00, 0x00, 0x00, NULL}; //0xC7
|
sAPDU apdu = {0x90, MFDES_COMMIT_TRANSACTION, 0x00, 0x00, 0x00, NULL}; //0xC7
|
||||||
uint32_t recv_len = 0;
|
uint32_t recv_len = 0;
|
||||||
|
@ -1726,7 +1689,7 @@ static int handler_desfire_filesettings(uint8_t file_id, uint8_t *dest, uint32_t
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int handler_desfire_createapp(aidhdr_t *aidhdr, bool usename, bool usefid) {
|
/*static int handler_desfire_createapp(aidhdr_t *aidhdr, bool usename, bool usefid) {
|
||||||
if (aidhdr == NULL) return PM3_EINVARG;
|
if (aidhdr == NULL) return PM3_EINVARG;
|
||||||
|
|
||||||
sAPDU apdu = {0x90, MFDES_CREATE_APPLICATION, 0x00, 0x00, sizeof(aidhdr_t), (uint8_t *)aidhdr}; // 0xCA
|
sAPDU apdu = {0x90, MFDES_CREATE_APPLICATION, 0x00, 0x00, sizeof(aidhdr_t), (uint8_t *)aidhdr}; // 0xCA
|
||||||
|
@ -1763,22 +1726,7 @@ static int handler_desfire_createapp(aidhdr_t *aidhdr, bool usename, bool usefid
|
||||||
DropFieldDesfire();
|
DropFieldDesfire();
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
static int handler_desfire_deleteapp(const uint8_t *aid) {
|
|
||||||
if (aid == NULL) {
|
|
||||||
return PM3_EINVARG;
|
|
||||||
}
|
|
||||||
sAPDU apdu = {0x90, MFDES_DELETE_APPLICATION, 0x00, 0x00, 3, (uint8_t *)aid}; // 0xDA
|
|
||||||
uint16_t sw = 0;
|
|
||||||
uint32_t recvlen = 0;
|
|
||||||
int res = send_desfire_cmd(&apdu, false, NULL, &recvlen, &sw, 0, true);
|
|
||||||
if (res != PM3_SUCCESS) {
|
|
||||||
PrintAndLogEx(WARNING, _RED_(" Can't delete aid -> %s"), DesfireGetErrorString(res, &sw));
|
|
||||||
DropFieldDesfire();
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int handler_desfire_credit(mfdes_value_t *value, uint8_t cs) {
|
static int handler_desfire_credit(mfdes_value_t *value, uint8_t cs) {
|
||||||
sAPDU apdu = {0x90, MFDES_CREDIT, 0x00, 0x00, 1 + 4, (uint8_t *)value}; // 0x0C
|
sAPDU apdu = {0x90, MFDES_CREDIT, 0x00, 0x00, 1 + 4, (uint8_t *)value}; // 0x0C
|
||||||
|
@ -2312,51 +2260,6 @@ static int desfire_authenticate(int cmdAuthMode, int cmdAuthAlgo, uint8_t *aid,
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
static int CmdHF14ADesGetUID(const char *Cmd) {
|
|
||||||
CLIParserContext *ctx;
|
|
||||||
CLIParserInit(&ctx, "hf mfdes getuid",
|
|
||||||
"Get UID from a MIFARE DESfire tag",
|
|
||||||
"hf mfdes getuid");
|
|
||||||
|
|
||||||
void *argtable[] = {
|
|
||||||
arg_param_begin,
|
|
||||||
arg_param_end
|
|
||||||
};
|
|
||||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
|
||||||
CLIParserFree(ctx);
|
|
||||||
|
|
||||||
uint8_t uid[16] = {0};
|
|
||||||
int res = handler_desfire_getuid(uid);
|
|
||||||
if (res != PM3_SUCCESS) {
|
|
||||||
DropFieldDesfire();
|
|
||||||
PrintAndLogEx(ERR, "Error on getting uid.");
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This could be done better. by the crc calc checks.
|
|
||||||
// Extract the Card UID length (needs rework to allow for 10 Byte UID
|
|
||||||
uint8_t uidlen = 16;
|
|
||||||
|
|
||||||
// Get datalen <uid len> + <crclen> by removing padding.
|
|
||||||
while ((uidlen > 0) && (uid[uidlen - 1] == 0x00))
|
|
||||||
uidlen--;
|
|
||||||
|
|
||||||
if (tag->authentication_scheme == AS_LEGACY)
|
|
||||||
uidlen -= 2; // 2 byte crc
|
|
||||||
else
|
|
||||||
uidlen -= 4; // 4 byte crc
|
|
||||||
|
|
||||||
if (uidlen <= 4) // < incase we trimmed a CRC 00 or more
|
|
||||||
uidlen = 4;
|
|
||||||
else
|
|
||||||
uidlen = 7;
|
|
||||||
|
|
||||||
PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(uid, uidlen));
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
static int CmdHF14ADesSelectApp(const char *Cmd) {
|
static int CmdHF14ADesSelectApp(const char *Cmd) {
|
||||||
CLIParserContext *ctx;
|
CLIParserContext *ctx;
|
||||||
CLIParserInit(&ctx, "hf mfdes selectaid",
|
CLIParserInit(&ctx, "hf mfdes selectaid",
|
||||||
|
@ -2392,190 +2295,6 @@ static int CmdHF14ADesSelectApp(const char *Cmd) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int CmdHF14ADesCreateApp(const char *Cmd) {
|
|
||||||
CLIParserContext *ctx;
|
|
||||||
CLIParserInit(&ctx, "hf mfdes createaid",
|
|
||||||
"Create Application ID",
|
|
||||||
"hf mfdes createaid -a 123456 -f 1111 -k 0E -l 2E --name Test"
|
|
||||||
);
|
|
||||||
|
|
||||||
void *argtable[] = {
|
|
||||||
arg_param_begin,
|
|
||||||
arg_strx0("a", "aid", "<hex>", "App ID to create as hex bytes (3 hex bytes)"),
|
|
||||||
arg_strx0("f", "fid", "<hex>", "File ID to create"),
|
|
||||||
arg_strx0("k", "ks1", "<hex>", "Key Setting 1 (Application Master Key Settings)"),
|
|
||||||
arg_strx0("l", "ks2", "<hex>", "Key Setting 2"),
|
|
||||||
arg_str0(NULL, "name", "<ascii>", "App ISO-4 Name"),
|
|
||||||
arg_param_end
|
|
||||||
};
|
|
||||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
|
||||||
/* KeySetting 1 (AMK Setting):
|
|
||||||
0: Allow change master key
|
|
||||||
1: Free Directory list access without master key
|
|
||||||
0: AMK auth needed for GetFileSettings and GetKeySettings
|
|
||||||
1: No AMK auth needed for GetFileIDs, GetISOFileIDs, GetFileSettings, GetKeySettings
|
|
||||||
2: Free create/delete without master key
|
|
||||||
0: CreateFile/DeleteFile only with AMK auth
|
|
||||||
1: CreateFile/DeleteFile always
|
|
||||||
3: Configuration changable
|
|
||||||
0: Configuration frozen
|
|
||||||
1: Configuration changable if authenticated with AMK (default)
|
|
||||||
4-7: ChangeKey Access Rights
|
|
||||||
0: Application master key needed (default)
|
|
||||||
0x1..0xD: Auth with specific key needed to change any key
|
|
||||||
0xE: Auth with the key to be changed (same KeyNo) is necessary to change a key
|
|
||||||
0xF: All Keys within this application are frozen
|
|
||||||
|
|
||||||
*/
|
|
||||||
/* KeySetting 2:
|
|
||||||
0..3: Number of keys stored within the application (max. 14 keys)
|
|
||||||
4: RFU
|
|
||||||
5: Use of 2 byte ISO FID, 0: No, 1: Yes
|
|
||||||
6..7: Crypto Method 00: DES/3DES, 01: 3K3DES, 10: AES
|
|
||||||
Example:
|
|
||||||
2E = FID, DES, 14 keys
|
|
||||||
6E = FID, 3K3DES, 14 keys
|
|
||||||
AE = FID, AES, 14 keys
|
|
||||||
*/
|
|
||||||
int aidlength = 3;
|
|
||||||
uint8_t aid[3] = {0};
|
|
||||||
CLIGetHexWithReturn(ctx, 1, aid, &aidlength);
|
|
||||||
|
|
||||||
int fidlength = 2;
|
|
||||||
uint8_t fid[2] = {0};
|
|
||||||
CLIGetHexWithReturn(ctx, 2, fid, &fidlength);
|
|
||||||
|
|
||||||
int keylen1 = 1;
|
|
||||||
uint8_t keysetting1[1] = {0};
|
|
||||||
CLIGetHexWithReturn(ctx, 3, keysetting1, &keylen1);
|
|
||||||
|
|
||||||
int keylen2 = 1;
|
|
||||||
uint8_t keysetting2[1] = {0};
|
|
||||||
CLIGetHexWithReturn(ctx, 4, keysetting2, &keylen2);
|
|
||||||
|
|
||||||
int namelen = 16;
|
|
||||||
uint8_t name[16] = {0};
|
|
||||||
CLIGetStrWithReturn(ctx, 5, name, &namelen);
|
|
||||||
CLIParserFree(ctx);
|
|
||||||
|
|
||||||
swap24(aid);
|
|
||||||
swap16(fid);
|
|
||||||
|
|
||||||
if (aidlength != 3) {
|
|
||||||
PrintAndLogEx(ERR, "AID must have 3 bytes length");
|
|
||||||
return PM3_EINVARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fidlength != 2 && fidlength != 0) {
|
|
||||||
PrintAndLogEx(ERR, "FID must have 2 bytes length");
|
|
||||||
return PM3_EINVARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool usefid = (fidlength != 0);
|
|
||||||
|
|
||||||
if (keylen1 != 1) {
|
|
||||||
PrintAndLogEx(ERR, "Keysetting1 must have 1 byte length");
|
|
||||||
return PM3_EINVARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (keylen2 != 1) {
|
|
||||||
PrintAndLogEx(ERR, "Keysetting2 must have 1 byte length");
|
|
||||||
return PM3_EINVARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (namelen > 16) {
|
|
||||||
PrintAndLogEx(ERR, "Name has a max. of 16 bytes length");
|
|
||||||
return PM3_EINVARG;
|
|
||||||
}
|
|
||||||
bool usename = true;
|
|
||||||
if (namelen == 0) usename = false;
|
|
||||||
|
|
||||||
//90 ca 00 00 0e 3cb849 09 22 10e1 d27600 00850101 00
|
|
||||||
/*char name[]="Test";
|
|
||||||
uint8_t aid[]={0x12,0x34,0x56};
|
|
||||||
uint8_t fid[]={0x11,0x22};
|
|
||||||
uint8_t keysetting1=0xEE;
|
|
||||||
uint8_t keysetting2=0xEE;*/
|
|
||||||
|
|
||||||
if (memcmp(aid, "\x00\x00\x00", 3) == 0) {
|
|
||||||
PrintAndLogEx(WARNING, _RED_(" Creating root aid 000000 is forbidden"));
|
|
||||||
return PM3_ESOFT;
|
|
||||||
}
|
|
||||||
|
|
||||||
aidhdr_t aidhdr;
|
|
||||||
memcpy(aidhdr.aid, aid, sizeof(aid));
|
|
||||||
aidhdr.keysetting1 = keysetting1[0];
|
|
||||||
aidhdr.keysetting2 = keysetting2[0];
|
|
||||||
|
|
||||||
if (usefid)
|
|
||||||
memcpy(aidhdr.fid, fid, sizeof(aidhdr.fid));
|
|
||||||
|
|
||||||
if (usename)
|
|
||||||
memcpy(aidhdr.name, name, sizeof(aidhdr.name));
|
|
||||||
|
|
||||||
PrintAndLogEx(INFO, "Creating AID using:");
|
|
||||||
PrintAndLogEx(INFO, "AID %s", sprint_hex_inrow(aidhdr.aid, sizeof(aidhdr.aid)));
|
|
||||||
PrintAndLogEx(INFO, "Key set1 0x%02X", aidhdr.keysetting1);
|
|
||||||
PrintAndLogEx(INFO, "Key Set2 0x%02X", aidhdr.keysetting2);
|
|
||||||
if (usefid)
|
|
||||||
PrintAndLogEx(INFO, "FID %s", sprint_hex_inrow(aidhdr.fid, sizeof(aidhdr.fid)));
|
|
||||||
if (usename)
|
|
||||||
PrintAndLogEx(INFO, "DF Name %s", aidhdr.name);
|
|
||||||
|
|
||||||
/*
|
|
||||||
uint8_t rootaid[3] = {0x00, 0x00, 0x00};
|
|
||||||
int res = handler_desfire_select_application(rootaid);
|
|
||||||
if (res != PM3_SUCCESS) {
|
|
||||||
DropFieldDesfire();
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
int res = handler_desfire_createapp(&aidhdr, usename, usefid);
|
|
||||||
DropFieldDesfire();
|
|
||||||
if (res == PM3_SUCCESS) {
|
|
||||||
PrintAndLogEx(SUCCESS, "Successfully created aid.");
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int CmdHF14ADesDeleteApp(const char *Cmd) {
|
|
||||||
CLIParserContext *ctx;
|
|
||||||
CLIParserInit(&ctx, "hf mfdes deleteaid",
|
|
||||||
"Delete Application ID",
|
|
||||||
"hf mfdes deleteaid -a 123456"
|
|
||||||
);
|
|
||||||
|
|
||||||
void *argtable[] = {
|
|
||||||
arg_param_begin,
|
|
||||||
arg_strx0("a", "aid", "<hex>", "App ID to delete (3 hex bytes, big endian)"),
|
|
||||||
arg_param_end
|
|
||||||
};
|
|
||||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
|
||||||
int aidlength = 3;
|
|
||||||
uint8_t aid[3] = {0};
|
|
||||||
CLIGetHexWithReturn(ctx, 1, aid, &aidlength);
|
|
||||||
CLIParserFree(ctx);
|
|
||||||
swap24(aid);
|
|
||||||
if (aidlength != 3) {
|
|
||||||
PrintAndLogEx(ERR, "AID must have 3 bytes length.");
|
|
||||||
return PM3_EINVARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (memcmp(aid, "\x00\x00\x00", 3) == 0) {
|
|
||||||
PrintAndLogEx(WARNING, _RED_(" Deleting root aid 000000 is forbidden."));
|
|
||||||
return PM3_ESOFT;
|
|
||||||
}
|
|
||||||
|
|
||||||
int res = handler_desfire_deleteapp(aid);
|
|
||||||
DropFieldDesfire();
|
|
||||||
|
|
||||||
if (res == PM3_SUCCESS) {
|
|
||||||
PrintAndLogEx(SUCCESS, "Successfully deleted aid.");
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int selectfile(uint8_t *aid, uint8_t fileno, uint8_t *cs) {
|
static int selectfile(uint8_t *aid, uint8_t fileno, uint8_t *cs) {
|
||||||
if (handler_desfire_select_application(aid) != PM3_SUCCESS) {
|
if (handler_desfire_select_application(aid) != PM3_SUCCESS) {
|
||||||
PrintAndLogEx(ERR, _RED_(" Couldn't select aid."));
|
PrintAndLogEx(ERR, _RED_(" Couldn't select aid."));
|
||||||
|
@ -5115,8 +4834,8 @@ static int CmdDesGetSessionParameters(CLIParserContext *ctx, DesfireContext *dct
|
||||||
static int CmdHF14ADesDefault(const char *Cmd) {
|
static int CmdHF14ADesDefault(const char *Cmd) {
|
||||||
CLIParserContext *ctx;
|
CLIParserContext *ctx;
|
||||||
CLIParserInit(&ctx, "hf mfdes default",
|
CLIParserInit(&ctx, "hf mfdes default",
|
||||||
"Get Application IDs, ISO IDs and DF names from card. Master key needs to be provided.",
|
"Set default parameters for access to desfire card.",
|
||||||
"hf mfdes getappnames -n 0 -t des -k 0000000000000000 -f none -> execute with default factory setup");
|
"hf mfdes default -n 0 -t des -k 0000000000000000 -f none -> save to the default parameters");
|
||||||
|
|
||||||
void *argtable[] = {
|
void *argtable[] = {
|
||||||
arg_param_begin,
|
arg_param_begin,
|
||||||
|
@ -5166,6 +4885,265 @@ static int CmdHF14ADesDefault(const char *Cmd) {
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int CmdHF14ADesCreateApp(const char *Cmd) {
|
||||||
|
CLIParserContext *ctx;
|
||||||
|
CLIParserInit(&ctx, "hf mfdes createapp",
|
||||||
|
"Create application. Master key needs to be provided.",
|
||||||
|
"option rawdata have priority over the rest settings, and options ks1 and ks2 have priority over corresponded key settings\n"
|
||||||
|
"\n"\
|
||||||
|
"KeySetting 1 (AMK Setting, ks1):\n"\
|
||||||
|
" 0: Allow change master key. 1 - allow, 0 - frozen\n"\
|
||||||
|
" 1: Free Directory list access without master key\n"\
|
||||||
|
" 0: AMK auth needed for GetFileSettings and GetKeySettings\n"\
|
||||||
|
" 1: No AMK auth needed for GetFileIDs, GetISOFileIDs, GetFileSettings, GetKeySettings\n"\
|
||||||
|
" 2: Free create/delete without master key\n"\
|
||||||
|
" 0: CreateFile/DeleteFile only with AMK auth\n"\
|
||||||
|
" 1: CreateFile/DeleteFile always\n"\
|
||||||
|
" 3: Configuration changable\n"\
|
||||||
|
" 0: Configuration frozen\n"\
|
||||||
|
" 1: Configuration changable if authenticated with AMK (default)\n"\
|
||||||
|
" 4-7: ChangeKey Access Rights\n"\
|
||||||
|
" 0: Application master key needed (default)\n"\
|
||||||
|
" 0x1..0xD: Auth with specific key needed to change any key\n"\
|
||||||
|
" 0xE: Auth with the key to be changed (same KeyNo) is necessary to change a key\n"\
|
||||||
|
" 0xF: All Keys within this application are frozen\n"\
|
||||||
|
"\n"\
|
||||||
|
"KeySetting 2 (ks2):\n"\
|
||||||
|
" 0..3: Number of keys stored within the application (max. 14 keys)\n"\
|
||||||
|
" 4: ks3 is present\n"\
|
||||||
|
" 5: Use of 2 byte ISO FID, 0: No, 1: Yes\n"\
|
||||||
|
" 6..7: Crypto Method 00: DES/2TDEA, 01: 3TDEA, 10: AES, 11: RFU\n"\
|
||||||
|
" Example:\n"\
|
||||||
|
" 2E = with FID, DES/2TDEA, 14 keys\n"\
|
||||||
|
" 6E = with FID, 3TDEA, 14 keys\n"\
|
||||||
|
" AE = with FID, AES, 14 keys\n"\
|
||||||
|
"\n"\
|
||||||
|
"hf mfdes createapp --rawdata 5634122F2E4523616964313233343536 -> execute create by rawdata\n"\
|
||||||
|
"hf mfdes createapp --aid 123456 --fid 2345 --dfname aid123456 -> app aid, iso file id, and iso df name is specified\n"
|
||||||
|
"hf mfdes createapp --aid 123456 --fid 2345 --dfname aid123456 --dstalgo aes -> with algorithm for key AES");
|
||||||
|
|
||||||
|
void *argtable[] = {
|
||||||
|
arg_param_begin,
|
||||||
|
arg_lit0("a", "apdu", "show APDU requests and responses"),
|
||||||
|
arg_lit0("v", "verbose", "show technical data"),
|
||||||
|
arg_int0("n", "keyno", "<keyno>", "Key number"),
|
||||||
|
arg_str0("t", "algo", "<DES/2TDEA/3TDEA/AES>", "Crypt algo: DES, 2TDEA, 3TDEA, AES"),
|
||||||
|
arg_str0("k", "key", "<Key>", "Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"),
|
||||||
|
arg_str0("f", "kdf", "<none/AN10922/gallagher>", "Key Derivation Function (KDF): None, AN10922, Gallagher"),
|
||||||
|
arg_str0("i", "kdfi", "<kdfi>", "KDF input (HEX 1-31 bytes)"),
|
||||||
|
arg_str0("m", "cmode", "<plain/mac/encrypt>", "Communicaton mode: plain/mac/encrypt"),
|
||||||
|
arg_str0("c", "ccset", "<native/niso/iso>", "Communicaton command set: native/niso/iso"),
|
||||||
|
arg_str0("s", "schann", "<d40/ev1/ev2>", "Secure channel: d40/ev1/ev2"),
|
||||||
|
arg_str0(NULL, "rawdata", "<rawdata hex>", "Rawdata that sends to command"),
|
||||||
|
arg_str0(NULL, "aid", "<app id hex>", "Application ID for create. Mandatory. (3 hex bytes, big endian)"),
|
||||||
|
arg_str0(NULL, "fid", "<file id hex>", "ISO file ID. Forbidden values: 0000 3F00, 3FFF, FFFF. (2 hex bytes, big endian). If specified - enable iso file id over all the files in the app."),
|
||||||
|
arg_str0(NULL, "dfname", "<df name str>", "ISO DF Name 1..16 chars string"),
|
||||||
|
arg_str0(NULL, "ks1", "<key settings HEX>", "Key settings 1 (HEX 1 byte). Application Master Key Settings. default 0x2f"),
|
||||||
|
arg_str0(NULL, "ks2", "<key settings HEX>", "Key settings 2 (HEX 1 byte). default 0x0e"),
|
||||||
|
arg_str0(NULL, "dstalgo", "<DES/2TDEA/3TDEA/AES>", "Application key crypt algo: DES, 2TDEA, 3TDEA, AES. default DES"),
|
||||||
|
arg_int0(NULL, "numkeys", "<number of keys>", "Keys count. 0x00..0x0e. default 0x0e"),
|
||||||
|
arg_param_end
|
||||||
|
};
|
||||||
|
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||||
|
|
||||||
|
bool APDULogging = arg_get_lit(ctx, 1);
|
||||||
|
bool verbose = arg_get_lit(ctx, 2);
|
||||||
|
|
||||||
|
DesfireContext dctx;
|
||||||
|
int securechann = defaultSecureChannel;
|
||||||
|
uint32_t appid = 0x000000;
|
||||||
|
int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 12, &securechann, DCMPlain, &appid);
|
||||||
|
if (res) {
|
||||||
|
CLIParserFree(ctx);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t rawdata[250] = {0};
|
||||||
|
int rawdatalen = sizeof(rawdata);
|
||||||
|
CLIGetHexWithReturn(ctx, 11, rawdata, &rawdatalen);
|
||||||
|
|
||||||
|
uint32_t fileid = 0x0000;
|
||||||
|
res = arg_get_u32_hexstr_def_nlen(ctx, 13, 0x0000, &fileid, 2, true);
|
||||||
|
bool fileidpresent = (res == 1);
|
||||||
|
if (res == 2) {
|
||||||
|
PrintAndLogEx(ERR, "ISO file ID must have 2 bytes length");
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t dfname[250] = {0};
|
||||||
|
int dfnamelen = 16;
|
||||||
|
CLIGetStrWithReturn(ctx, 14, dfname, &dfnamelen);
|
||||||
|
|
||||||
|
uint32_t ks1 = 0x2f;
|
||||||
|
res = arg_get_u32_hexstr_def_nlen(ctx, 15, 0x2f, &ks1, 1, true);
|
||||||
|
if (res == 2) {
|
||||||
|
PrintAndLogEx(ERR, "Key settings 1 must have 1 byte length");
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ks2 = 0x0e;
|
||||||
|
res = arg_get_u32_hexstr_def_nlen(ctx, 16, 0x0e, &ks2, 1, true);
|
||||||
|
bool ks2present = (res == 1);
|
||||||
|
if (res == 2) {
|
||||||
|
PrintAndLogEx(ERR, "Key settings 2 must have 1 byte length");
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dstalgo = T_DES;
|
||||||
|
if (CLIGetOptionList(arg_get_str(ctx, 17), DesfireAlgoOpts, &dstalgo))
|
||||||
|
return PM3_ESOFT;
|
||||||
|
|
||||||
|
int keycount = arg_get_int_def(ctx, 18, 0x0e);
|
||||||
|
|
||||||
|
SetAPDULogging(APDULogging);
|
||||||
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
|
if (rawdatalen == 0 && appid == 0x000000) {
|
||||||
|
PrintAndLogEx(ERR, "Creating the root aid (0x000000) is " _RED_("forbidden"));
|
||||||
|
return PM3_ESOFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rawdatalen == 0 && (fileidpresent || (ks2 & 0x20) != 0) && fileid == 0x0000) {
|
||||||
|
PrintAndLogEx(ERR, "Creating the application with ISO file ID 0x0000 is " _RED_("forbidden"));
|
||||||
|
return PM3_ESOFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keycount > 0x0e || keycount < 1) {
|
||||||
|
PrintAndLogEx(ERR, "Key count must be in the range 1..14");
|
||||||
|
return PM3_ESOFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dfnamelen > 16) {
|
||||||
|
PrintAndLogEx(ERR, "DF name must be a maximum of 16 bytes in length");
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = DesfireSelectAndAuthenticate(&dctx, securechann, 0x000000, verbose);
|
||||||
|
if (res != PM3_SUCCESS) {
|
||||||
|
DropField();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t data[250] = {0};
|
||||||
|
size_t datalen = 0;
|
||||||
|
if (rawdatalen > 0) {
|
||||||
|
memcpy(data, rawdata, rawdatalen);
|
||||||
|
datalen = rawdatalen;
|
||||||
|
} else {
|
||||||
|
DesfireAIDUintToByte(appid, &data[0]);
|
||||||
|
data[3] = ks1 & 0xff;
|
||||||
|
data[4] = ks2 & 0xff;
|
||||||
|
|
||||||
|
if (!ks2present) {
|
||||||
|
if (keycount > 0) {
|
||||||
|
data[4] &= 0xf0;
|
||||||
|
data[4] |= keycount & 0x0f;
|
||||||
|
}
|
||||||
|
uint8_t kt = DesfireKeyAlgoToType(dstalgo);
|
||||||
|
data[4] &= 0x3f;
|
||||||
|
data[4] |= (kt & 0x03) << 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
datalen = 5;
|
||||||
|
if (fileidpresent || (data[4] & 0x20) != 0) {
|
||||||
|
data[5] = fileid & 0xff;
|
||||||
|
data[6] = (fileid >> 8) & 0xff;
|
||||||
|
data[4] |= 0x20; // set bit FileID in the ks2
|
||||||
|
memcpy(&data[7], dfname, dfnamelen);
|
||||||
|
datalen = 7 + dfnamelen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (verbose) {
|
||||||
|
PrintAndLogEx(INFO, "---------------------------");
|
||||||
|
PrintAndLogEx(INFO, _CYAN_("Creating Application using:"));
|
||||||
|
PrintAndLogEx(INFO, "AID 0x%02X%02X%02X", data[2], data[1], data[0]);
|
||||||
|
PrintAndLogEx(INFO, "Key Set 1 0x%02X", data[3]);
|
||||||
|
PrintAndLogEx(INFO, "Key Set 2 0x%02X", data[4]);
|
||||||
|
PrintAndLogEx(INFO, "ISO file ID %s", (data[4] & 0x20) ? "enabled" : "disabled");
|
||||||
|
if ((data[4] & 0x20)) {
|
||||||
|
PrintAndLogEx(INFO, "FID 0x%02x%02x", data[6], data[5]);
|
||||||
|
PrintAndLogEx(INFO, "DF Name[%02d] %s\n", strnlen((char *)&data[7], 16), (char *)&data[7]);
|
||||||
|
}
|
||||||
|
PrintKeySettings(data[3], data[4], true, true);
|
||||||
|
PrintAndLogEx(INFO, "---------------------------");
|
||||||
|
}
|
||||||
|
|
||||||
|
res = DesfireCreateApplication(&dctx, data, datalen);
|
||||||
|
if (res != PM3_SUCCESS) {
|
||||||
|
PrintAndLogEx(ERR, "Desfire CreateApplication command " _RED_("error") ". Result: %d", res);
|
||||||
|
DropField();
|
||||||
|
return PM3_ESOFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
PrintAndLogEx(SUCCESS, "Desfire application %06x successfully " _GREEN_("created"), appid);
|
||||||
|
|
||||||
|
DropField();
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int CmdHF14ADesDeleteApp(const char *Cmd) {
|
||||||
|
CLIParserContext *ctx;
|
||||||
|
CLIParserInit(&ctx, "hf mfdes deleteapp",
|
||||||
|
"Delete application by its 3-byte AID. Master key needs to be provided. ",
|
||||||
|
"hf mfdes deleteapp --aid 123456 -> execute with default factory setup");
|
||||||
|
|
||||||
|
void *argtable[] = {
|
||||||
|
arg_param_begin,
|
||||||
|
arg_lit0("a", "apdu", "show APDU requests and responses"),
|
||||||
|
arg_lit0("v", "verbose", "show technical data"),
|
||||||
|
arg_int0("n", "keyno", "<keyno>", "Key number"),
|
||||||
|
arg_str0("t", "algo", "<DES/2TDEA/3TDEA/AES>", "Crypt algo: DES, 2TDEA, 3TDEA, AES"),
|
||||||
|
arg_str0("k", "key", "<Key>", "Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"),
|
||||||
|
arg_str0("f", "kdf", "<none/AN10922/gallagher>", "Key Derivation Function (KDF): None, AN10922, Gallagher"),
|
||||||
|
arg_str0("i", "kdfi", "<kdfi>", "KDF input (HEX 1-31 bytes)"),
|
||||||
|
arg_str0("m", "cmode", "<plain/mac/encrypt>", "Communicaton mode: plain/mac/encrypt"),
|
||||||
|
arg_str0("c", "ccset", "<native/niso/iso>", "Communicaton command set: native/niso/iso"),
|
||||||
|
arg_str0("s", "schann", "<d40/ev1/ev2>", "Secure channel: d40/ev1/ev2"),
|
||||||
|
arg_str0(NULL, "aid", "<app id hex>", "Application ID of delegated application (3 hex bytes, big endian)"),
|
||||||
|
arg_param_end
|
||||||
|
};
|
||||||
|
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||||
|
|
||||||
|
bool APDULogging = arg_get_lit(ctx, 1);
|
||||||
|
bool verbose = arg_get_lit(ctx, 2);
|
||||||
|
|
||||||
|
DesfireContext dctx;
|
||||||
|
int securechann = defaultSecureChannel;
|
||||||
|
uint32_t appid = 0x000000;
|
||||||
|
int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, &securechann, DCMPlain, &appid);
|
||||||
|
if (res) {
|
||||||
|
CLIParserFree(ctx);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetAPDULogging(APDULogging);
|
||||||
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
|
if (appid == 0x000000) {
|
||||||
|
PrintAndLogEx(WARNING, "Deleting the root aid (0x000000) is " _RED_("forbidden"));
|
||||||
|
return PM3_ESOFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = DesfireSelectAndAuthenticate(&dctx, securechann, appid, verbose);
|
||||||
|
if (res != PM3_SUCCESS) {
|
||||||
|
DropField();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = DesfireDeleteApplication(&dctx, appid);
|
||||||
|
if (res != PM3_SUCCESS) {
|
||||||
|
PrintAndLogEx(ERR, "Desfire DeleteApplication command " _RED_("error") ". Result: %d", res);
|
||||||
|
DropField();
|
||||||
|
return PM3_ESOFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
PrintAndLogEx(SUCCESS, "Desfire application %06x " _GREEN_("deleted"), appid);
|
||||||
|
|
||||||
|
DropField();
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
static int CmdHF14ADesGetUID(const char *Cmd) {
|
static int CmdHF14ADesGetUID(const char *Cmd) {
|
||||||
CLIParserContext *ctx;
|
CLIParserContext *ctx;
|
||||||
CLIParserInit(&ctx, "hf mfdes getuid",
|
CLIParserInit(&ctx, "hf mfdes getuid",
|
||||||
|
@ -5213,7 +5191,7 @@ static int CmdHF14ADesGetUID(const char *Cmd) {
|
||||||
|
|
||||||
res = DesfireGetUID(&dctx, buf, &buflen);
|
res = DesfireGetUID(&dctx, buf, &buflen);
|
||||||
if (res != PM3_SUCCESS) {
|
if (res != PM3_SUCCESS) {
|
||||||
PrintAndLogEx(ERR, "Desfire DesfireGetUID command " _RED_("error") ". Result: %d", res);
|
PrintAndLogEx(ERR, "Desfire GetUID command " _RED_("error") ". Result: %d", res);
|
||||||
DropField();
|
DropField();
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
@ -5270,7 +5248,7 @@ static int CmdHF14ADesFormatPICC(const char *Cmd) {
|
||||||
|
|
||||||
res = DesfireFormatPICC(&dctx);
|
res = DesfireFormatPICC(&dctx);
|
||||||
if (res != PM3_SUCCESS) {
|
if (res != PM3_SUCCESS) {
|
||||||
PrintAndLogEx(ERR, "Desfire DesfireFormatPICC command " _RED_("error") ". Result: %d", res);
|
PrintAndLogEx(ERR, "Desfire FormatPICC command " _RED_("error") ". Result: %d", res);
|
||||||
DropField();
|
DropField();
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
@ -5284,7 +5262,7 @@ static int CmdHF14ADesFormatPICC(const char *Cmd) {
|
||||||
static int CmdHF14ADesGetFreeMem(const char *Cmd) {
|
static int CmdHF14ADesGetFreeMem(const char *Cmd) {
|
||||||
CLIParserContext *ctx;
|
CLIParserContext *ctx;
|
||||||
CLIParserInit(&ctx, "hf mfdes getfreemem",
|
CLIParserInit(&ctx, "hf mfdes getfreemem",
|
||||||
"Get card's free memory. Can be doe with ot without authentication. Master key may be provided. ",
|
"Get card's free memory. Can be done with ot without authentication. Master key may be provided.",
|
||||||
"hf mfdes getfreemem -> execute with default factory setup");
|
"hf mfdes getfreemem -> execute with default factory setup");
|
||||||
|
|
||||||
void *argtable[] = {
|
void *argtable[] = {
|
||||||
|
@ -5339,7 +5317,7 @@ static int CmdHF14ADesGetFreeMem(const char *Cmd) {
|
||||||
|
|
||||||
res = DesfireGetFreeMem(&dctx, &freemem);
|
res = DesfireGetFreeMem(&dctx, &freemem);
|
||||||
if (res != PM3_SUCCESS) {
|
if (res != PM3_SUCCESS) {
|
||||||
PrintAndLogEx(ERR, "Desfire DesfireGetFreeMem command " _RED_("error") ". Result: %d", res);
|
PrintAndLogEx(ERR, "Desfire GetFreeMem command " _RED_("error") ". Result: %d", res);
|
||||||
DropField();
|
DropField();
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
@ -5352,10 +5330,10 @@ static int CmdHF14ADesGetFreeMem(const char *Cmd) {
|
||||||
|
|
||||||
static int CmdHF14ADesChKeySettings(const char *Cmd) {
|
static int CmdHF14ADesChKeySettings(const char *Cmd) {
|
||||||
CLIParserContext *ctx;
|
CLIParserContext *ctx;
|
||||||
CLIParserInit(&ctx, "hf mfdes chkeysetings",
|
CLIParserInit(&ctx, "hf mfdes chkeysettings",
|
||||||
"Change key settings for card level or application level. WARNING: card level changes may block card!",
|
"Change key settings for card level or application level. WARNING: card level changes may block the card!",
|
||||||
"hf mfdes chkeysetings -d 0e -> set picc key settings with default key/channel setup\n"\
|
"hf mfdes chkeysettings -d 0f -> set picc key settings with default key/channel setup\n"\
|
||||||
"hf mfdes chkeysetings --aid 123456 -d 0e -> set app 123456 key settings with default key/channel setup");
|
"hf mfdes chkeysettings --aid 123456 -d 0f -> set app 123456 key settings with default key/channel setup");
|
||||||
|
|
||||||
void *argtable[] = {
|
void *argtable[] = {
|
||||||
arg_param_begin,
|
arg_param_begin,
|
||||||
|
@ -5373,7 +5351,7 @@ static int CmdHF14ADesChKeySettings(const char *Cmd) {
|
||||||
arg_str0("d", "data", "<key settings HEX>", "Key settings (HEX 1 byte)"),
|
arg_str0("d", "data", "<key settings HEX>", "Key settings (HEX 1 byte)"),
|
||||||
arg_param_end
|
arg_param_end
|
||||||
};
|
};
|
||||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||||
|
|
||||||
bool APDULogging = arg_get_lit(ctx, 1);
|
bool APDULogging = arg_get_lit(ctx, 1);
|
||||||
bool verbose = arg_get_lit(ctx, 2);
|
bool verbose = arg_get_lit(ctx, 2);
|
||||||
|
@ -5388,7 +5366,7 @@ static int CmdHF14ADesChKeySettings(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t ksett32 = 0;
|
uint32_t ksett32 = 0;
|
||||||
res = arg_get_u32_hexstr_def_nlen(ctx, 12, 0x000000, &ksett32, 1, false);
|
res = arg_get_u32_hexstr_def_nlen(ctx, 12, 0x0f, &ksett32, 1, false);
|
||||||
if (res == 0) {
|
if (res == 0) {
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
|
@ -5413,10 +5391,10 @@ static int CmdHF14ADesChKeySettings(const char *Cmd) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t keysett = ksett32 & 0x0f;
|
uint8_t keysett = ksett32 & 0xff;
|
||||||
res = DesfireChangeKeySettings(&dctx, &keysett, 1);
|
res = DesfireChangeKeySettings(&dctx, &keysett, 1);
|
||||||
if (res != PM3_SUCCESS) {
|
if (res != PM3_SUCCESS) {
|
||||||
PrintAndLogEx(ERR, "Desfire DesfireChangeKeySettings command " _RED_("error") ". Result: %d", res);
|
PrintAndLogEx(ERR, "Desfire ChangeKeySettings command " _RED_("error") ". Result: %d", res);
|
||||||
DropField();
|
DropField();
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
@ -5515,13 +5493,13 @@ static int CmdHF14ADesGetKeyVersions(const char *Cmd) {
|
||||||
|
|
||||||
res = DesfireGetKeyVersion(&dctx, data, (keysetpresent) ? 2 : 1, buf, &buflen);
|
res = DesfireGetKeyVersion(&dctx, data, (keysetpresent) ? 2 : 1, buf, &buflen);
|
||||||
if (res != PM3_SUCCESS) {
|
if (res != PM3_SUCCESS) {
|
||||||
PrintAndLogEx(ERR, "Desfire DesfireGetKeyVersion command " _RED_("error") ". Result: %d", res);
|
PrintAndLogEx(ERR, "Desfire GetKeyVersion command " _RED_("error") ". Result: %d", res);
|
||||||
DropField();
|
DropField();
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
PrintAndLogEx(INFO, "DesfireGetKeyVersion[%zu]: %s", buflen, sprint_hex(buf, buflen));
|
PrintAndLogEx(INFO, "GetKeyVersion[%zu]: %s", buflen, sprint_hex(buf, buflen));
|
||||||
|
|
||||||
if (buflen > 0) {
|
if (buflen > 0) {
|
||||||
PrintAndLogEx(INFO, "----------------------- " _CYAN_("Key Versions") " -----------------------");
|
PrintAndLogEx(INFO, "----------------------- " _CYAN_("Key Versions") " -----------------------");
|
||||||
|
@ -5537,10 +5515,10 @@ static int CmdHF14ADesGetKeyVersions(const char *Cmd) {
|
||||||
|
|
||||||
static int CmdHF14ADesGetKeySettings(const char *Cmd) {
|
static int CmdHF14ADesGetKeySettings(const char *Cmd) {
|
||||||
CLIParserContext *ctx;
|
CLIParserContext *ctx;
|
||||||
CLIParserInit(&ctx, "hf mfdes getkeysetings",
|
CLIParserInit(&ctx, "hf mfdes getkeysettings",
|
||||||
"Get key settings for card level or application level.",
|
"Get key settings for card level or application level.",
|
||||||
"hf mfdes getkeysetings -> get picc key settings with default key/channel setup\n"\
|
"hf mfdes getkeysettings -> get picc key settings with default key/channel setup\n"\
|
||||||
"hf mfdes getkeysetings --aid 123456 -> get app 123456 key settings with default key/channel setup");
|
"hf mfdes getkeysettings --aid 123456 -> get app 123456 key settings with default key/channel setup");
|
||||||
|
|
||||||
void *argtable[] = {
|
void *argtable[] = {
|
||||||
arg_param_begin,
|
arg_param_begin,
|
||||||
|
@ -5585,16 +5563,16 @@ static int CmdHF14ADesGetKeySettings(const char *Cmd) {
|
||||||
|
|
||||||
res = DesfireGetKeySettings(&dctx, buf, &buflen);
|
res = DesfireGetKeySettings(&dctx, buf, &buflen);
|
||||||
if (res != PM3_SUCCESS) {
|
if (res != PM3_SUCCESS) {
|
||||||
PrintAndLogEx(ERR, "Desfire DesfireGetKeySettings command " _RED_("error") ". Result: %d", res);
|
PrintAndLogEx(ERR, "Desfire GetKeySettings command " _RED_("error") ". Result: %d", res);
|
||||||
DropField();
|
DropField();
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
PrintAndLogEx(INFO, "DesfireGetKeySettings[%zu]: %s", buflen, sprint_hex(buf, buflen));
|
PrintAndLogEx(INFO, "GetKeySettings[%zu]: %s", buflen, sprint_hex(buf, buflen));
|
||||||
|
|
||||||
if (buflen < 2) {
|
if (buflen < 2) {
|
||||||
PrintAndLogEx(ERR, "Command DesfireGetKeySettings returned wrong length: %zu", buflen);
|
PrintAndLogEx(ERR, "Command GetKeySettings returned wrong length: %zu", buflen);
|
||||||
DropField();
|
DropField();
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
@ -5617,7 +5595,7 @@ static int CmdHF14ADesGetKeySettings(const char *Cmd) {
|
||||||
static int CmdHF14ADesGetAIDs(const char *Cmd) {
|
static int CmdHF14ADesGetAIDs(const char *Cmd) {
|
||||||
CLIParserContext *ctx;
|
CLIParserContext *ctx;
|
||||||
CLIParserInit(&ctx, "hf mfdes getaids",
|
CLIParserInit(&ctx, "hf mfdes getaids",
|
||||||
"Get Application IDs list from card. Master key needs to be provided.",
|
"Get Application IDs list from card. Master key needs to be provided or flag --no-auth set.",
|
||||||
"hf mfdes getaids -n 0 -t des -k 0000000000000000 -f none -> execute with default factory setup");
|
"hf mfdes getaids -n 0 -t des -k 0000000000000000 -f none -> execute with default factory setup");
|
||||||
|
|
||||||
void *argtable[] = {
|
void *argtable[] = {
|
||||||
|
@ -5632,12 +5610,14 @@ static int CmdHF14ADesGetAIDs(const char *Cmd) {
|
||||||
arg_str0("m", "cmode", "<plain/mac/encrypt>", "Communicaton mode: plain/mac/encrypt"),
|
arg_str0("m", "cmode", "<plain/mac/encrypt>", "Communicaton mode: plain/mac/encrypt"),
|
||||||
arg_str0("c", "ccset", "<native/niso/iso>", "Communicaton command set: native/niso/iso"),
|
arg_str0("c", "ccset", "<native/niso/iso>", "Communicaton command set: native/niso/iso"),
|
||||||
arg_str0("s", "schann", "<d40/ev1/ev2>", "Secure channel: d40/ev1/ev2"),
|
arg_str0("s", "schann", "<d40/ev1/ev2>", "Secure channel: d40/ev1/ev2"),
|
||||||
|
arg_lit0(NULL, "no-auth", "execute without authentication"),
|
||||||
arg_param_end
|
arg_param_end
|
||||||
};
|
};
|
||||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||||
|
|
||||||
bool APDULogging = arg_get_lit(ctx, 1);
|
bool APDULogging = arg_get_lit(ctx, 1);
|
||||||
bool verbose = arg_get_lit(ctx, 2);
|
bool verbose = arg_get_lit(ctx, 2);
|
||||||
|
bool noauth = arg_get_lit(ctx, 11);
|
||||||
|
|
||||||
DesfireContext dctx;
|
DesfireContext dctx;
|
||||||
int securechann = defaultSecureChannel;
|
int securechann = defaultSecureChannel;
|
||||||
|
@ -5650,10 +5630,19 @@ static int CmdHF14ADesGetAIDs(const char *Cmd) {
|
||||||
SetAPDULogging(APDULogging);
|
SetAPDULogging(APDULogging);
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
res = DesfireSelectAndAuthenticate(&dctx, securechann, 0x000000, verbose);
|
if (noauth) {
|
||||||
if (res != PM3_SUCCESS) {
|
res = DesfireSelectAIDHex(&dctx, 0x000000, false, 0);
|
||||||
DropField();
|
if (res != PM3_SUCCESS) {
|
||||||
return res;
|
PrintAndLogEx(ERR, "Desfire select " _RED_("error") ".");
|
||||||
|
DropField();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
res = DesfireSelectAndAuthenticate(&dctx, securechann, 0x000000, verbose);
|
||||||
|
if (res != PM3_SUCCESS) {
|
||||||
|
DropField();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t buf[APDU_RES_LEN] = {0};
|
uint8_t buf[APDU_RES_LEN] = {0};
|
||||||
|
@ -5681,7 +5670,7 @@ static int CmdHF14ADesGetAIDs(const char *Cmd) {
|
||||||
static int CmdHF14ADesGetAppNames(const char *Cmd) {
|
static int CmdHF14ADesGetAppNames(const char *Cmd) {
|
||||||
CLIParserContext *ctx;
|
CLIParserContext *ctx;
|
||||||
CLIParserInit(&ctx, "hf mfdes getappnames",
|
CLIParserInit(&ctx, "hf mfdes getappnames",
|
||||||
"Get Application IDs, ISO IDs and DF names from card. Master key needs to be provided.",
|
"Get Application IDs, ISO IDs and DF names from card. Master key needs to be provided or flag --no-auth set.",
|
||||||
"hf mfdes getappnames -n 0 -t des -k 0000000000000000 -f none -> execute with default factory setup");
|
"hf mfdes getappnames -n 0 -t des -k 0000000000000000 -f none -> execute with default factory setup");
|
||||||
|
|
||||||
void *argtable[] = {
|
void *argtable[] = {
|
||||||
|
@ -5696,12 +5685,14 @@ static int CmdHF14ADesGetAppNames(const char *Cmd) {
|
||||||
arg_str0("m", "cmode", "<plain/mac/encrypt>", "Communicaton mode: plain/mac/encrypt"),
|
arg_str0("m", "cmode", "<plain/mac/encrypt>", "Communicaton mode: plain/mac/encrypt"),
|
||||||
arg_str0("c", "ccset", "<native/niso/iso>", "Communicaton command set: native/niso/iso"),
|
arg_str0("c", "ccset", "<native/niso/iso>", "Communicaton command set: native/niso/iso"),
|
||||||
arg_str0("s", "schann", "<d40/ev1/ev2>", "Secure channel: d40/ev1/ev2"),
|
arg_str0("s", "schann", "<d40/ev1/ev2>", "Secure channel: d40/ev1/ev2"),
|
||||||
|
arg_lit0(NULL, "no-auth", "execute without authentication"),
|
||||||
arg_param_end
|
arg_param_end
|
||||||
};
|
};
|
||||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||||
|
|
||||||
bool APDULogging = arg_get_lit(ctx, 1);
|
bool APDULogging = arg_get_lit(ctx, 1);
|
||||||
bool verbose = arg_get_lit(ctx, 2);
|
bool verbose = arg_get_lit(ctx, 2);
|
||||||
|
bool noauth = arg_get_lit(ctx, 11);
|
||||||
|
|
||||||
DesfireContext dctx;
|
DesfireContext dctx;
|
||||||
int securechann = defaultSecureChannel;
|
int securechann = defaultSecureChannel;
|
||||||
|
@ -5714,13 +5705,19 @@ static int CmdHF14ADesGetAppNames(const char *Cmd) {
|
||||||
SetAPDULogging(APDULogging);
|
SetAPDULogging(APDULogging);
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
if (verbose)
|
if (noauth) {
|
||||||
DesfirePrintContext(&dctx);
|
res = DesfireSelectAIDHex(&dctx, 0x000000, false, 0);
|
||||||
|
if (res != PM3_SUCCESS) {
|
||||||
res = DesfireSelectAndAuthenticate(&dctx, securechann, 0x000000, verbose);
|
PrintAndLogEx(ERR, "Desfire select " _RED_("error") ".");
|
||||||
if (res != PM3_SUCCESS) {
|
DropField();
|
||||||
DropField();
|
return res;
|
||||||
return res;
|
}
|
||||||
|
} else {
|
||||||
|
res = DesfireSelectAndAuthenticate(&dctx, securechann, 0x000000, verbose);
|
||||||
|
if (res != PM3_SUCCESS) {
|
||||||
|
DropField();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t buf[APDU_RES_LEN] = {0};
|
uint8_t buf[APDU_RES_LEN] = {0};
|
||||||
|
@ -5729,7 +5726,7 @@ static int CmdHF14ADesGetAppNames(const char *Cmd) {
|
||||||
// result bytes: 3, 2, 1-16. total record size = 24
|
// result bytes: 3, 2, 1-16. total record size = 24
|
||||||
res = DesfireGetDFList(&dctx, buf, &buflen);
|
res = DesfireGetDFList(&dctx, buf, &buflen);
|
||||||
if (res != PM3_SUCCESS) {
|
if (res != PM3_SUCCESS) {
|
||||||
PrintAndLogEx(ERR, "Desfire DesfireGetDFList command " _RED_("error") ". Result: %d", res);
|
PrintAndLogEx(ERR, "Desfire GetDFList command " _RED_("error") ". Result: %d", res);
|
||||||
DropField();
|
DropField();
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
@ -5771,13 +5768,13 @@ static command_t CommandTable[] = {
|
||||||
// {"mad", CmdHF14aDesMAD, IfPm3Iso14443a, "Prints MAD records from card"},
|
// {"mad", CmdHF14aDesMAD, IfPm3Iso14443a, "Prints MAD records from card"},
|
||||||
{"-----------", CmdHelp, IfPm3Iso14443a, "------------------------ " _CYAN_("Keys") " -----------------------"},
|
{"-----------", CmdHelp, IfPm3Iso14443a, "------------------------ " _CYAN_("Keys") " -----------------------"},
|
||||||
{"changekey", CmdHF14ADesChangeKey, IfPm3Iso14443a, "Change Key"},
|
{"changekey", CmdHF14ADesChangeKey, IfPm3Iso14443a, "Change Key"},
|
||||||
{"chkeysetings", CmdHF14ADesChKeySettings, IfPm3Iso14443a, "[new]Change Key Settings"},
|
{"chkeysettings", CmdHF14ADesChKeySettings, IfPm3Iso14443a, "[new]Change Key Settings"},
|
||||||
{"getkeysetings", CmdHF14ADesGetKeySettings, IfPm3Iso14443a, "[new]Get Key Settings"},
|
{"getkeysettings", CmdHF14ADesGetKeySettings, IfPm3Iso14443a, "[new]Get Key Settings"},
|
||||||
{"getkeyversions", CmdHF14ADesGetKeyVersions, IfPm3Iso14443a, "[new]Get Key Versions"},
|
{"getkeyversions", CmdHF14ADesGetKeyVersions, IfPm3Iso14443a, "[new]Get Key Versions"},
|
||||||
{"-----------", CmdHelp, IfPm3Iso14443a, "-------------------- " _CYAN_("Applications") " -------------------"},
|
{"-----------", CmdHelp, IfPm3Iso14443a, "-------------------- " _CYAN_("Applications") " -------------------"},
|
||||||
{"bruteaid", CmdHF14ADesBruteApps, IfPm3Iso14443a, "Recover AIDs by bruteforce"},
|
{"bruteaid", CmdHF14ADesBruteApps, IfPm3Iso14443a, "Recover AIDs by bruteforce"},
|
||||||
{"createaid", CmdHF14ADesCreateApp, IfPm3Iso14443a, "Create Application ID"},
|
{"createapp", CmdHF14ADesCreateApp, IfPm3Iso14443a, "[new]Create Application"},
|
||||||
{"deleteaid", CmdHF14ADesDeleteApp, IfPm3Iso14443a, "Delete Application ID"},
|
{"deleteapp", CmdHF14ADesDeleteApp, IfPm3Iso14443a, "[new]Delete Application"},
|
||||||
{"selectaid", CmdHF14ADesSelectApp, IfPm3Iso14443a, "Select Application ID"},
|
{"selectaid", CmdHF14ADesSelectApp, IfPm3Iso14443a, "Select Application ID"},
|
||||||
{"getaids", CmdHF14ADesGetAIDs, IfPm3Iso14443a, "[new]Get Application IDs list"},
|
{"getaids", CmdHF14ADesGetAIDs, IfPm3Iso14443a, "[new]Get Application IDs list"},
|
||||||
{"getappnames", CmdHF14ADesGetAppNames, IfPm3Iso14443a, "[new]Get Applications list"},
|
{"getappnames", CmdHF14ADesGetAppNames, IfPm3Iso14443a, "[new]Get Applications list"},
|
||||||
|
|
|
@ -919,7 +919,7 @@ static int DesfireCommandEx(DesfireContext *dctx, uint8_t cmd, uint8_t *data, si
|
||||||
if (resplen)
|
if (resplen)
|
||||||
*resplen = xresplen;
|
*resplen = xresplen;
|
||||||
if (resp)
|
if (resp)
|
||||||
memcpy(resp, xresp, xresplen);
|
memcpy(resp, xresp, (splitbysize == 0) ? xresplen : xresplen * splitbysize);
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -988,6 +988,19 @@ int DesfireChangeKeySettings(DesfireContext *dctx, uint8_t *data, size_t len) {
|
||||||
return DesfireCommandTxData(dctx, MFDES_CHANGE_KEY_SETTINGS, data, len);
|
return DesfireCommandTxData(dctx, MFDES_CHANGE_KEY_SETTINGS, data, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t DesfireKeyAlgoToType(DesfireCryptoAlgorythm keyType) {
|
||||||
|
switch (keyType) {
|
||||||
|
case T_DES:
|
||||||
|
return 0x00;
|
||||||
|
case T_3DES:
|
||||||
|
return 0x00;
|
||||||
|
case T_3K3DES:
|
||||||
|
return 0x01;
|
||||||
|
case T_AES:
|
||||||
|
return 0x02;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
static void PrintKeyType(uint8_t keytype) {
|
static void PrintKeyType(uint8_t keytype) {
|
||||||
switch (keytype) {
|
switch (keytype) {
|
||||||
case 00:
|
case 00:
|
||||||
|
@ -1049,6 +1062,9 @@ static void PrintKeySettingsApp(uint8_t keysettings, uint8_t numkeys, bool print
|
||||||
if (print2ndbyte) {
|
if (print2ndbyte) {
|
||||||
PrintKeyType(numkeys >> 6);
|
PrintKeyType(numkeys >> 6);
|
||||||
PrintAndLogEx(SUCCESS, "key count: %d", numkeys & 0x0f);
|
PrintAndLogEx(SUCCESS, "key count: %d", numkeys & 0x0f);
|
||||||
|
if (numkeys & 0x20)
|
||||||
|
PrintAndLogEx(SUCCESS, "iso file id: enabled");
|
||||||
|
PrintAndLogEx(SUCCESS, "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -53,5 +53,6 @@ int DesfireGetKeyVersion(DesfireContext *dctx, uint8_t *data, size_t len, uint8_
|
||||||
int DesfireGetKeySettings(DesfireContext *dctx, uint8_t *resp, size_t *resplen);
|
int DesfireGetKeySettings(DesfireContext *dctx, uint8_t *resp, size_t *resplen);
|
||||||
int DesfireChangeKeySettings(DesfireContext *dctx, uint8_t *data, size_t len);
|
int DesfireChangeKeySettings(DesfireContext *dctx, uint8_t *data, size_t len);
|
||||||
void PrintKeySettings(uint8_t keysettings, uint8_t numkeys, bool applevel, bool print2ndbyte);
|
void PrintKeySettings(uint8_t keysettings, uint8_t numkeys, bool applevel, bool print2ndbyte);
|
||||||
|
uint8_t DesfireKeyAlgoToType(DesfireCryptoAlgorythm keyType);
|
||||||
|
|
||||||
#endif // __DESFIRECORE_H
|
#endif // __DESFIRECORE_H
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue