Make style

This commit is contained in:
Bjoern Kerler 2020-04-10 01:18:48 +02:00
commit 82323b14e2
7 changed files with 1859 additions and 295 deletions

View file

@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file.
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... 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]
- Updated 'legic.lua' and 'legic_clone.lua' script - works with current command set (@Pizza_4u)
- Rewrote `hf mfdes` functions and added apdu debugging (@bkerler) - Rewrote `hf mfdes` functions and added apdu debugging (@bkerler)
- Add Mifare Desfire GetDFNames and improve HF MFDES Enum output (@bkerler) - Add Mifare Desfire GetDFNames and improve HF MFDES Enum output (@bkerler)
- Fix Mifare Desfire select appid handling (@bkerler) - Fix Mifare Desfire select appid handling (@bkerler)

View file

@ -104,7 +104,7 @@ void MifareDesfireGetInformation() {
uint8_t versionSW[7]; uint8_t versionSW[7];
uint8_t details[14]; uint8_t details[14];
} PACKED payload; } PACKED payload;
/* /*
1 = PCB 1 1 = PCB 1
2 = cid 2 2 = cid 2
@ -179,7 +179,7 @@ void MifareDesfireGetInformation() {
LED_B_ON(); LED_B_ON();
reply_ng(CMD_HF_DESFIRE_INFO, PM3_SUCCESS, (uint8_t *)&payload, sizeof(payload)); reply_ng(CMD_HF_DESFIRE_INFO, PM3_SUCCESS, (uint8_t *)&payload, sizeof(payload));
LED_B_OFF(); LED_B_OFF();
// reset the pcb_blocknum, // reset the pcb_blocknum,
pcb_blocknum = 0; pcb_blocknum = 0;
OnSuccess(); OnSuccess();
@ -314,8 +314,8 @@ void MifareDES_Auth1(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
cmd[3] = 0x00; cmd[3] = 0x00;
cmd[4] = 0x10; cmd[4] = 0x10;
memcpy(cmd + 5, both, 16); memcpy(cmd + 5, both, 16);
cmd[16+5]=0x0; cmd[16 + 5] = 0x0;
len = DesfireAPDU(cmd, 5+16+1, resp); len = DesfireAPDU(cmd, 5 + 16 + 1, resp);
if (!len) { if (!len) {
if (DBGLEVEL >= DBG_ERROR) { if (DBGLEVEL >= DBG_ERROR) {
DbpString("Authentication failed. Card timeout."); DbpString("Authentication failed. Card timeout.");
@ -324,7 +324,7 @@ void MifareDES_Auth1(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
return; return;
} }
if (resp[len-3] == 0x00) { if (resp[len - 3] == 0x00) {
struct desfire_key sessionKey = {0}; struct desfire_key sessionKey = {0};
desfirekey_t skey = &sessionKey; desfirekey_t skey = &sessionKey;
@ -450,8 +450,7 @@ void MifareDES_Auth1(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
} }
} }
break; break;
case 2: case 2: {
{
//SendDesfireCommand(AUTHENTICATE_ISO, &arg2, resp); //SendDesfireCommand(AUTHENTICATE_ISO, &arg2, resp);
uint8_t keybytes[16]; uint8_t keybytes[16];
uint8_t RndA[8] = {0x00}; uint8_t RndA[8] = {0x00};
@ -540,7 +539,7 @@ void MifareDES_Auth1(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
cmd[0] = ADDITIONAL_FRAME; cmd[0] = ADDITIONAL_FRAME;
memcpy(cmd + 1, both, 16); memcpy(cmd + 1, both, 16);
len = DesfireAPDU(cmd, 1+16, resp); len = DesfireAPDU(cmd, 1 + 16, resp);
if (!len) { if (!len) {
if (DBGLEVEL >= DBG_ERROR) { if (DBGLEVEL >= DBG_ERROR) {
DbpString("Authentication failed. Card timeout."); DbpString("Authentication failed. Card timeout.");
@ -580,9 +579,9 @@ void MifareDES_Auth1(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
DbpString("Authentication failed."); DbpString("Authentication failed.");
OnError(6); OnError(6);
return; return;
}
} }
break; }
break;
case 3: { case 3: {
//defaultkey //defaultkey
uint8_t keybytes[16] = {0x00}; uint8_t keybytes[16] = {0x00};
@ -655,9 +654,9 @@ void MifareDES_Auth1(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
cmd[3] = 0x00; cmd[3] = 0x00;
cmd[4] = 0x20; cmd[4] = 0x20;
memcpy(cmd + 5, encBoth, 32); memcpy(cmd + 5, encBoth, 32);
cmd[32+5]=0x0; cmd[32 + 5] = 0x0;
len = DesfireAPDU(cmd, 5+32+1, resp); len = DesfireAPDU(cmd, 5 + 32 + 1, resp);
if (!len) { if (!len) {
if (DBGLEVEL >= DBG_ERROR) { if (DBGLEVEL >= DBG_ERROR) {
DbpString("Authentication failed. Card timeout."); DbpString("Authentication failed. Card timeout.");
@ -666,7 +665,7 @@ void MifareDES_Auth1(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
return; return;
} }
if ((resp[1+16] == 0x91)&&(resp[1+16+1] == 0x00)) { if ((resp[1 + 16] == 0x91) && (resp[1 + 16 + 1] == 0x00)) {
// Create AES Session key // Create AES Session key
struct desfire_key sessionKey = {0}; struct desfire_key sessionKey = {0};
desfirekey_t skey = &sessionKey; desfirekey_t skey = &sessionKey;
@ -713,10 +712,10 @@ int DesfireAPDU(uint8_t *cmd, size_t cmd_len, uint8_t *dataout) {
// if we received an I- or R(ACK)-Block with a block number equal to the // if we received an I- or R(ACK)-Block with a block number equal to the
// current block number, toggle the current block number // current block number, toggle the current block number
if (len >= 4 // PCB+CID+CRC = 4 bytes if (len >= 4 // PCB+CID+CRC = 4 bytes
&& ((resp[0] & 0xC0) == 0 // I-Block && ((resp[0] & 0xC0) == 0 // I-Block
|| (resp[0] & 0xD0) == 0x80) // R-Block with ACK bit set to 0 || (resp[0] & 0xD0) == 0x80) // R-Block with ACK bit set to 0
&& (resp[0] & 0x01) == pcb_blocknum) { // equal block numbers && (resp[0] & 0x01) == pcb_blocknum) { // equal block numbers
pcb_blocknum ^= 1; //toggle next block pcb_blocknum ^= 1; //toggle next block
} }
memcpy(dataout, resp, len); memcpy(dataout, resp, len);
@ -734,18 +733,18 @@ size_t CreateAPDU(uint8_t *datain, size_t len, uint8_t *dataout) {
cmd[0] = 0x02; // 0x0A = send cid, 0x02 = no cid. cmd[0] = 0x02; // 0x0A = send cid, 0x02 = no cid.
cmd[0] |= pcb_blocknum; // OR the block number into the PCB cmd[0] |= pcb_blocknum; // OR the block number into the PCB
if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("pcb_blocknum %d == %d ", pcb_blocknum, cmd[0] ); if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("pcb_blocknum %d == %d ", pcb_blocknum, cmd[0]);
//cmd[1] = 0x90; // CID: 0x00 //TODO: allow multiple selected cards //cmd[1] = 0x90; // CID: 0x00 //TODO: allow multiple selected cards
memcpy(cmd + 1, datain, len); memcpy(cmd + 1, datain, len);
AddCrc14A(cmd, len + 1); AddCrc14A(cmd, len + 1);
/* /*
hf 14a apdu -sk 90 60 00 00 00 hf 14a apdu -sk 90 60 00 00 00
hf 14a apdu -k 90 AF 00 00 00 hf 14a apdu -k 90 AF 00 00 00
hf 14a apdu 90AF000000 hf 14a apdu 90AF000000
*/ */
memcpy(dataout, cmd, cmdlen); memcpy(dataout, cmd, cmdlen);
return cmdlen; return cmdlen;
} }

View file

@ -675,7 +675,7 @@ void annotateMfDesfire(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) {
// it's basically a ISO14443a tag, so try annotation from there // it's basically a ISO14443a tag, so try annotation from there
if (applyIso14443a(exp, size, cmd, cmdsize) == 0) { if (applyIso14443a(exp, size, cmd, cmdsize) == 0) {
// S-block 11xxx010 // S-block 11xxx010
if ((cmd[0] & 0xC0) && (cmdsize == 3)) { if ((cmd[0] & 0xC0) && (cmdsize == 3)) {
switch ((cmd[0] & 0x30)) { switch ((cmd[0] & 0x30)) {
@ -707,9 +707,9 @@ void annotateMfDesfire(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) {
if ((cmd[0] & 0x04) == 0x04) // nad byte following if ((cmd[0] & 0x04) == 0x04) // nad byte following
pos++; pos++;
for (uint8_t i = 0; i < 2; i++, pos++) { for (uint8_t i = 0; i < 2; i++, pos++) {
switch (cmd[pos]) { switch (cmd[pos]) {
case MFDES_CREATE_APPLICATION: case MFDES_CREATE_APPLICATION:
snprintf(exp, size, "CREATE APPLICATION"); snprintf(exp, size, "CREATE APPLICATION");

View file

@ -64,6 +64,7 @@ static int CmdHelp(const char *Cmd);
*/ */
int DESFIRESendApdu(bool activate_field, bool leavefield_on, sAPDU apdu, uint8_t *result, int max_result_len, int *result_len, uint16_t *sw) { int DESFIRESendApdu(bool activate_field, bool leavefield_on, sAPDU apdu, uint8_t *result, int max_result_len, int *result_len, uint16_t *sw) {
*result_len = 0; *result_len = 0;
if (sw) *sw = 0; if (sw) *sw = 0;
@ -120,11 +121,10 @@ int DESFIRESendApdu(bool activate_field, bool leavefield_on, sAPDU apdu, uint8_t
return PM3_SUCCESS; return PM3_SUCCESS;
} }
static char* getstatus(uint16_t * sw) static char *getstatus(uint16_t *sw) {
{ if (sw == NULL) return "--> sw argument error. This should never happen !";
if (sw==NULL) return "--> sw argument error. This should never happen !"; if (((*sw >> 8) & 0xFF) == 0x91) {
if (((*sw>>8)&0xFF)==0x91){ switch (*sw & 0xFF) {
switch (*sw&0xFF){
case MFDES_E_OUT_OF_EEPROM: case MFDES_E_OUT_OF_EEPROM:
return "Out of Eeprom, insufficient NV-Memory to complete command"; return "Out of Eeprom, insufficient NV-Memory to complete command";
case MFDES_E_ILLEGAL_COMMAND_CODE: case MFDES_E_ILLEGAL_COMMAND_CODE:
@ -188,9 +188,8 @@ static char* getstatus(uint16_t * sw)
return "Unknown error"; return "Unknown error";
} }
static char* GetErrorString(int res,uint16_t* sw) static char *GetErrorString(int res, uint16_t *sw) {
{ switch (res) {
switch(res){
case PM3_EAPDU_FAIL: case PM3_EAPDU_FAIL:
return getstatus(sw); return getstatus(sw);
case PM3_EUNDEF: case PM3_EUNDEF:
@ -242,15 +241,14 @@ static char* GetErrorString(int res,uint16_t* sw)
} }
static int send_desfire_cmd(sAPDU *apdu, bool select, uint8_t *dest, int *recv_len, uint16_t *sw, int splitbysize,bool readalldata) { static int send_desfire_cmd(sAPDU *apdu, bool select, uint8_t *dest, int *recv_len, uint16_t *sw, int splitbysize, bool readalldata) {
if (g_debugMode>1) if (g_debugMode > 1) {
{ if (apdu == NULL) PrintAndLogEx(ERR, "APDU=NULL");
if (apdu==NULL) PrintAndLogEx(ERR, "APDU=NULL"); if (dest == NULL) PrintAndLogEx(ERR, "DEST=NULL");
if (dest==NULL) PrintAndLogEx(ERR, "DEST=NULL"); if (sw == NULL) PrintAndLogEx(ERR, "SW=NULL");
if (sw==NULL) PrintAndLogEx(ERR, "SW=NULL"); if (recv_len == NULL) PrintAndLogEx(ERR, "RECV_LEN=NULL");
if (recv_len==NULL) PrintAndLogEx(ERR, "RECV_LEN=NULL");
} }
if (apdu==NULL || sw==NULL || recv_len==NULL) return PM3_EINVARG; if (apdu == NULL || sw == NULL || recv_len == NULL) return PM3_EINVARG;
*sw = 0; *sw = 0;
uint8_t data[255 * 5] = {0x00}; uint8_t data[255 * 5] = {0x00};
@ -259,7 +257,7 @@ static int send_desfire_cmd(sAPDU *apdu, bool select, uint8_t *dest, int *recv_l
int i = 1; int i = 1;
int res = DESFIRESendApdu(select, true, *apdu, data, sizeof(data), &resplen, sw); int res = DESFIRESendApdu(select, true, *apdu, data, sizeof(data), &resplen, sw);
if (res != PM3_SUCCESS) { if (res != PM3_SUCCESS) {
if (g_debugMode>1) GetErrorString(res,sw); if (g_debugMode > 1) GetErrorString(res, sw);
return res; return res;
} }
if (dest != NULL) { if (dest != NULL) {
@ -267,9 +265,8 @@ static int send_desfire_cmd(sAPDU *apdu, bool select, uint8_t *dest, int *recv_l
} }
pos += resplen; pos += resplen;
if (!readalldata) if (!readalldata) {
{ if (*sw == status(MFDES_ADDITIONAL_FRAME)) {
if (*sw==status(MFDES_ADDITIONAL_FRAME)) {
apdu->INS = MFDES_ABORT_TRANSACTION; apdu->INS = MFDES_ABORT_TRANSACTION;
apdu->Lc = 0; apdu->Lc = 0;
apdu->P1 = 0; apdu->P1 = 0;
@ -281,13 +278,13 @@ static int send_desfire_cmd(sAPDU *apdu, bool select, uint8_t *dest, int *recv_l
} }
while (*sw == status(MFDES_ADDITIONAL_FRAME)) { while (*sw == status(MFDES_ADDITIONAL_FRAME)) {
apdu->INS = MFDES_ADDITIONAL_FRAME; //0xAF apdu->INS = MFDES_ADDITIONAL_FRAME; //0xAF
apdu->Lc=0; apdu->Lc = 0;
apdu->P1=0; apdu->P1 = 0;
apdu->P2=0; apdu->P2 = 0;
res = DESFIRESendApdu(false, true, *apdu, data, sizeof(data), &resplen, sw); res = DESFIRESendApdu(false, true, *apdu, data, sizeof(data), &resplen, sw);
if (res != PM3_SUCCESS){ if (res != PM3_SUCCESS) {
if (g_debugMode>1) GetErrorString(res,sw); if (g_debugMode > 1) GetErrorString(res, sw);
return res; return res;
} }
if (dest != NULL) { if (dest != NULL) {
@ -299,7 +296,7 @@ static int send_desfire_cmd(sAPDU *apdu, bool select, uint8_t *dest, int *recv_l
} }
} }
pos += resplen; pos += resplen;
if (*sw!=status(MFDES_ADDITIONAL_FRAME)) break; if (*sw != status(MFDES_ADDITIONAL_FRAME)) break;
} }
if (splitbysize) *recv_len = i; if (splitbysize) *recv_len = i;
else { else {
@ -327,29 +324,29 @@ static desfire_cardtype_t getCardType(uint8_t major, uint8_t minor) {
//none, verified //none, verified
static int test_desfire_authenticate() { static int test_desfire_authenticate() {
uint8_t c = 0x00; uint8_t data[] = {0x00};
sAPDU apdu = {0x90, MFDES_AUTHENTICATE, 0x00, 0x00, 0x01, &c}; // 0x0A, KEY 0 sAPDU apdu = {0x90, MFDES_AUTHENTICATE, 0x00, 0x00, 0x01, data}; // 0x0A, KEY 0
int recv_len = 0; int recv_len = 0;
uint16_t sw = 0; uint16_t sw = 0;
return send_desfire_cmd(&apdu, false, NULL, &recv_len, &sw, 0,false); return send_desfire_cmd(&apdu, false, NULL, &recv_len, &sw, 0, false);
} }
// none, verified // none, verified
static int test_desfire_authenticate_iso() { static int test_desfire_authenticate_iso() {
uint8_t c = 0x00; uint8_t data[] = {0x00};
sAPDU apdu = {0x90, MFDES_AUTHENTICATE_ISO, 0x00, 0x00, 0x01, &c}; // 0x1A, KEY 0 sAPDU apdu = {0x90, MFDES_AUTHENTICATE_ISO, 0x00, 0x00, 0x01, data}; // 0x1A, KEY 0
int recv_len = 0; int recv_len = 0;
uint16_t sw = 0; uint16_t sw = 0;
return send_desfire_cmd(&apdu, false, NULL, &recv_len, &sw, 0,false); return send_desfire_cmd(&apdu, false, NULL, &recv_len, &sw, 0, false);
} }
//none, verified //none, verified
static int test_desfire_authenticate_aes() { static int test_desfire_authenticate_aes() {
uint8_t c = 0x00; uint8_t data[] = {0x00};
sAPDU apdu = {0x90, MFDES_AUTHENTICATE_AES, 0x00, 0x00, 0x01, &c}; // 0xAA, KEY 0 sAPDU apdu = {0x90, MFDES_AUTHENTICATE_AES, 0x00, 0x00, 0x01, data}; // 0xAA, KEY 0
int recv_len = 0; int recv_len = 0;
uint16_t sw = 0; uint16_t sw = 0;
return send_desfire_cmd(&apdu, false, NULL, &recv_len, &sw, 0,false); return send_desfire_cmd(&apdu, false, NULL, &recv_len, &sw, 0, false);
} }
// --- FREE MEM, verified // --- FREE MEM, verified
@ -360,13 +357,13 @@ static int desfire_print_freemem(uint32_t free_mem) {
// init / disconnect, verified // init / disconnect, verified
static int get_desfire_freemem(uint32_t *free_mem) { static int get_desfire_freemem(uint32_t *free_mem) {
if (free_mem==NULL) return PM3_EINVARG; if (free_mem == NULL) return PM3_EINVARG;
sAPDU apdu = {0x90, MFDES_GET_FREE_MEMORY, 0x00, 0x00, 0x00, NULL}; // 0x6E sAPDU apdu = {0x90, MFDES_GET_FREE_MEMORY, 0x00, 0x00, 0x00, NULL}; // 0x6E
int recv_len = 0; int recv_len = 0;
uint16_t sw = 0; uint16_t sw = 0;
uint8_t fmem[4] = {0}; uint8_t fmem[4] = {0};
int res = send_desfire_cmd(&apdu, true, fmem, &recv_len, &sw, 0,true); int res = send_desfire_cmd(&apdu, true, fmem, &recv_len, &sw, 0, true);
if (res == PM3_SUCCESS) { if (res == PM3_SUCCESS) {
*free_mem = le24toh(fmem); *free_mem = le24toh(fmem);
return res; return res;
@ -378,12 +375,11 @@ static int get_desfire_freemem(uint32_t *free_mem) {
// --- GET SIGNATURE, verified // --- GET SIGNATURE, verified
static int desfire_print_signature(uint8_t *uid, uint8_t *signature, size_t signature_len, desfire_cardtype_t card_type) { static int desfire_print_signature(uint8_t *uid, uint8_t *signature, size_t signature_len, desfire_cardtype_t card_type) {
if (g_debugMode>1) if (g_debugMode > 1) {
{ if (uid == NULL) PrintAndLogEx(ERR, "UID=NULL");
if (uid==NULL) PrintAndLogEx(ERR, "UID=NULL"); if (signature == NULL) PrintAndLogEx(ERR, "SIGNATURE=NULL");
if (signature==NULL) PrintAndLogEx(ERR, "SIGNATURE=NULL");
} }
if (uid==NULL || signature==NULL) return PM3_EINVARG; if (uid == NULL || signature == NULL) return PM3_EINVARG;
// DESFire Ev3 - wanted // DESFire Ev3 - wanted
// ref: MIFARE Desfire Originality Signature Validation // ref: MIFARE Desfire Originality Signature Validation
@ -435,17 +431,16 @@ static int desfire_print_signature(uint8_t *uid, uint8_t *signature, size_t sign
// init / disconnect, verified // init / disconnect, verified
static int get_desfire_signature(uint8_t *signature, size_t *signature_len) { static int get_desfire_signature(uint8_t *signature, size_t *signature_len) {
if (g_debugMode>1) if (g_debugMode > 1) {
{ if (signature == NULL) PrintAndLogEx(ERR, "SIGNATURE=NULL");
if (signature==NULL) PrintAndLogEx(ERR, "SIGNATURE=NULL"); if (signature_len == NULL) PrintAndLogEx(ERR, "SIGNATURE_LEN=NULL");
if (signature_len==NULL) PrintAndLogEx(ERR, "SIGNATURE_LEN=NULL");
} }
if (signature==NULL || signature_len==NULL) return PM3_EINVARG; if (signature == NULL || signature_len == NULL) return PM3_EINVARG;
uint8_t c = 0x00; uint8_t c = 0x00;
sAPDU apdu = {0x90, MFDES_READSIG, 0x00, 0x00, 0x01, &c}; // 0x3C sAPDU apdu = {0x90, MFDES_READSIG, 0x00, 0x00, 0x01, &c}; // 0x3C
int recv_len = 0; int recv_len = 0;
uint16_t sw = 0; uint16_t sw = 0;
int res = send_desfire_cmd(&apdu, true, signature, &recv_len, &sw, 0,true); int res = send_desfire_cmd(&apdu, true, signature, &recv_len, &sw, 0, true);
if (res == PM3_SUCCESS) { if (res == PM3_SUCCESS) {
if (recv_len != 56) { if (recv_len != 56) {
*signature_len = 0; *signature_len = 0;
@ -497,17 +492,16 @@ static int desfire_print_keysetting(uint8_t key_settings, uint8_t num_keys) {
// none, verified // none, verified
static int get_desfire_keysettings(uint8_t *key_settings, uint8_t *num_keys) { static int get_desfire_keysettings(uint8_t *key_settings, uint8_t *num_keys) {
if (g_debugMode>1) if (g_debugMode > 1) {
{ if (key_settings == NULL) PrintAndLogEx(ERR, "KEY_SETTINGS=NULL");
if (key_settings==NULL) PrintAndLogEx(ERR, "KEY_SETTINGS=NULL"); if (num_keys == NULL) PrintAndLogEx(ERR, "NUM_KEYS=NULL");
if (num_keys==NULL) PrintAndLogEx(ERR, "NUM_KEYS=NULL");
} }
if (key_settings==NULL || num_keys==NULL) return PM3_EINVARG; if (key_settings == NULL || num_keys == NULL) return PM3_EINVARG;
sAPDU apdu = {0x90, MFDES_GET_KEY_SETTINGS, 0x00, 0x00, 0x00, NULL}; //0x45 sAPDU apdu = {0x90, MFDES_GET_KEY_SETTINGS, 0x00, 0x00, 0x00, NULL}; //0x45
int recv_len = 0; int recv_len = 0;
uint16_t sw = 0; uint16_t sw = 0;
uint8_t data[2] = {0}; uint8_t data[2] = {0};
int res = send_desfire_cmd(&apdu, false, data, &recv_len, &sw, 0,true); int res = send_desfire_cmd(&apdu, false, data, &recv_len, &sw, 0, true);
if (res != PM3_SUCCESS) return res; if (res != PM3_SUCCESS) return res;
*key_settings = data[0]; *key_settings = data[0];
@ -523,31 +517,29 @@ static int desfire_print_keyversion(uint8_t key_idx, uint8_t key_version) {
// none, verified // none, verified
static int get_desfire_keyversion(uint8_t curr_key, uint8_t *num_versions) { static int get_desfire_keyversion(uint8_t curr_key, uint8_t *num_versions) {
if (g_debugMode>1) if (g_debugMode > 1) {
{ if (num_versions == NULL) PrintAndLogEx(ERR, "NUM_VERSIONS=NULL");
if (num_versions==NULL) PrintAndLogEx(ERR, "NUM_VERSIONS=NULL");
} }
if (num_versions==NULL) return PM3_EINVARG; if (num_versions == NULL) return PM3_EINVARG;
sAPDU apdu = {0x90, MFDES_GET_KEY_VERSION, 0x00, 0x00, 0x01, &curr_key}; //0x64 sAPDU apdu = {0x90, MFDES_GET_KEY_VERSION, 0x00, 0x00, 0x01, &curr_key}; //0x64
int recv_len = 0; int recv_len = 0;
uint16_t sw = 0; uint16_t sw = 0;
int res = send_desfire_cmd(&apdu, false, num_versions, &recv_len, &sw, 0,true); int res = send_desfire_cmd(&apdu, false, num_versions, &recv_len, &sw, 0, true);
return res; return res;
} }
// init / disconnect, verified // init / disconnect, verified
static int get_desfire_appids(uint8_t *dest, uint8_t *app_ids_len) { static int get_desfire_appids(uint8_t *dest, uint8_t *app_ids_len) {
if (g_debugMode>1) if (g_debugMode > 1) {
{ if (dest == NULL) PrintAndLogEx(ERR, "DEST=NULL");
if (dest==NULL) PrintAndLogEx(ERR, "DEST=NULL"); if (app_ids_len == NULL) PrintAndLogEx(ERR, "APP_IDS_LEN=NULL");
if (app_ids_len==NULL) PrintAndLogEx(ERR, "APP_IDS_LEN=NULL");
} }
if (dest==NULL || app_ids_len==NULL) return PM3_EINVARG; if (dest == NULL || app_ids_len == NULL) return PM3_EINVARG;
sAPDU apdu = {0x90, MFDES_GET_APPLICATION_IDS, 0x00, 0x00, 0x00, NULL}; //0x6a sAPDU apdu = {0x90, MFDES_GET_APPLICATION_IDS, 0x00, 0x00, 0x00, NULL}; //0x6a
int recv_len = 0; int recv_len = 0;
uint16_t sw = 0; uint16_t sw = 0;
int res = send_desfire_cmd(&apdu, true, dest, &recv_len, &sw, 0,true); int res = send_desfire_cmd(&apdu, true, dest, &recv_len, &sw, 0, true);
if (res != PM3_SUCCESS) return res; if (res != PM3_SUCCESS) return res;
*app_ids_len = (uint8_t)recv_len & 0xFF; *app_ids_len = (uint8_t)recv_len & 0xFF;
return res; return res;
@ -555,16 +547,15 @@ static int get_desfire_appids(uint8_t *dest, uint8_t *app_ids_len) {
// init, verified // init, verified
static int get_desfire_dfnames(dfname_t *dest, uint8_t *dfname_count) { static int get_desfire_dfnames(dfname_t *dest, uint8_t *dfname_count) {
if (g_debugMode>1) if (g_debugMode > 1) {
{ if (dest == NULL) PrintAndLogEx(ERR, "DEST=NULL");
if (dest==NULL) PrintAndLogEx(ERR, "DEST=NULL"); if (dfname_count == NULL) PrintAndLogEx(ERR, "DFNAME_COUNT=NULL");
if (dfname_count==NULL) PrintAndLogEx(ERR, "DFNAME_COUNT=NULL");
} }
if (dest==NULL || dfname_count==NULL) return PM3_EINVARG; if (dest == NULL || dfname_count == NULL) return PM3_EINVARG;
sAPDU apdu = {0x90, MFDES_GET_DF_NAMES, 0x00, 0x00, 0x00, NULL}; //0x6d sAPDU apdu = {0x90, MFDES_GET_DF_NAMES, 0x00, 0x00, 0x00, NULL}; //0x6d
int recv_len = 0; int recv_len = 0;
uint16_t sw = 0; uint16_t sw = 0;
int res = send_desfire_cmd(&apdu, true, (uint8_t *)dest, &recv_len, &sw, sizeof(dfname_t),true); int res = send_desfire_cmd(&apdu, true, (uint8_t *)dest, &recv_len, &sw, sizeof(dfname_t), true);
if (res != PM3_SUCCESS) return res; if (res != PM3_SUCCESS) return res;
*dfname_count = recv_len; *dfname_count = recv_len;
return res; return res;
@ -573,17 +564,16 @@ static int get_desfire_dfnames(dfname_t *dest, uint8_t *dfname_count) {
// init, verified // init, verified
static int get_desfire_select_application(uint8_t *aid) { static int get_desfire_select_application(uint8_t *aid) {
if (g_debugMode>1) if (g_debugMode > 1) {
{ if (aid == NULL) PrintAndLogEx(ERR, "AID=NULL");
if (aid==NULL) PrintAndLogEx(ERR, "AID=NULL");
} }
if (aid==NULL) return PM3_EINVARG; if (aid == NULL) return PM3_EINVARG;
sAPDU apdu = {0x90, MFDES_SELECT_APPLICATION, 0x00, 0x00, 0x03, aid}; //0x5a sAPDU apdu = {0x90, MFDES_SELECT_APPLICATION, 0x00, 0x00, 0x03, aid}; //0x5a
int recv_len = 0; int recv_len = 0;
uint16_t sw = 0; uint16_t sw = 0;
int res=send_desfire_cmd(&apdu, true, NULL, &recv_len, &sw, sizeof(dfname_t),true); int res = send_desfire_cmd(&apdu, true, NULL, &recv_len, &sw, sizeof(dfname_t), true);
if (res != PM3_SUCCESS) { if (res != PM3_SUCCESS) {
PrintAndLogEx(WARNING, _RED_(" Can't select AID 0x%X -> %s"),(aid[0]<<16)+(aid[1]<<8)+aid[2],GetErrorString(res,&sw)); PrintAndLogEx(WARNING, _RED_(" Can't select AID 0x%X -> %s"), (aid[0] << 16) + (aid[1] << 8) + aid[2], GetErrorString(res, &sw));
DropField(); DropField();
return res; return res;
} }
@ -592,19 +582,18 @@ static int get_desfire_select_application(uint8_t *aid) {
// none, verified // none, verified
static int get_desfire_fileids(uint8_t *dest, uint8_t *file_ids_len) { static int get_desfire_fileids(uint8_t *dest, uint8_t *file_ids_len) {
if (g_debugMode>1) if (g_debugMode > 1) {
{ if (dest == NULL) PrintAndLogEx(ERR, "DEST=NULL");
if (dest==NULL) PrintAndLogEx(ERR, "DEST=NULL"); if (file_ids_len == NULL) PrintAndLogEx(ERR, "FILE_IDS_LEN=NULL");
if (file_ids_len==NULL) PrintAndLogEx(ERR, "FILE_IDS_LEN=NULL");
} }
if (dest==NULL || file_ids_len==NULL) return PM3_EINVARG; if (dest == NULL || file_ids_len == NULL) return PM3_EINVARG;
sAPDU apdu = {0x90, MFDES_GET_FILE_IDS, 0x00, 0x00, 0x00, NULL}; //0x6f sAPDU apdu = {0x90, MFDES_GET_FILE_IDS, 0x00, 0x00, 0x00, NULL}; //0x6f
int recv_len = 0; int recv_len = 0;
uint16_t sw = 0; uint16_t sw = 0;
*file_ids_len = 0; *file_ids_len = 0;
int res = send_desfire_cmd(&apdu, false, dest, &recv_len, &sw, 0,true); int res = send_desfire_cmd(&apdu, false, dest, &recv_len, &sw, 0, true);
if (res != PM3_SUCCESS) { if (res != PM3_SUCCESS) {
PrintAndLogEx(WARNING, _RED_(" Can't get file ids -> %s"),GetErrorString(res,&sw)); PrintAndLogEx(WARNING, _RED_(" Can't get file ids -> %s"), GetErrorString(res, &sw));
DropField(); DropField();
return res; return res;
} }
@ -614,17 +603,16 @@ static int get_desfire_fileids(uint8_t *dest, uint8_t *file_ids_len) {
// none, verified // none, verified
static int get_desfire_filesettings(uint8_t file_id, uint8_t *dest, int *destlen) { static int get_desfire_filesettings(uint8_t file_id, uint8_t *dest, int *destlen) {
if (g_debugMode>1) if (g_debugMode > 1) {
{ if (dest == NULL) PrintAndLogEx(ERR, "DEST=NULL");
if (dest==NULL) PrintAndLogEx(ERR, "DEST=NULL"); if (destlen == NULL) PrintAndLogEx(ERR, "DESTLEN=NULL");
if (destlen==NULL) PrintAndLogEx(ERR, "DESTLEN=NULL");
} }
if (dest==NULL || destlen==NULL) return PM3_EINVARG; if (dest == NULL || destlen == NULL) return PM3_EINVARG;
sAPDU apdu = {0x90, MFDES_GET_FILE_SETTINGS, 0x00, 0x00, 0x01, &file_id}; // 0xF5 sAPDU apdu = {0x90, MFDES_GET_FILE_SETTINGS, 0x00, 0x00, 0x01, &file_id}; // 0xF5
uint16_t sw = 0; uint16_t sw = 0;
int res=send_desfire_cmd(&apdu, false, dest, destlen, &sw, 0,true); int res = send_desfire_cmd(&apdu, false, dest, destlen, &sw, 0, true);
if (res != PM3_SUCCESS) { if (res != PM3_SUCCESS) {
PrintAndLogEx(WARNING, _RED_(" Can't get file settings -> %s"),GetErrorString(res,&sw)); PrintAndLogEx(WARNING, _RED_(" Can't get file settings -> %s"), GetErrorString(res, &sw));
DropField(); DropField();
return res; return res;
} }
@ -639,28 +627,28 @@ typedef struct {
uint8_t name[16]; uint8_t name[16];
} aidhdr_t; } aidhdr_t;
static int get_desfire_createapp(aidhdr_t* aidhdr) { static int get_desfire_createapp(aidhdr_t *aidhdr) {
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
uint16_t sw = 0; uint16_t sw = 0;
int recvlen=0; int recvlen = 0;
int res=send_desfire_cmd(&apdu, false, NONE, &recvlen, &sw, 0,true); int res = send_desfire_cmd(&apdu, false, NONE, &recvlen, &sw, 0, true);
if (res != PM3_SUCCESS) { if (res != PM3_SUCCESS) {
PrintAndLogEx(WARNING, _RED_(" Can't create aid -> %s"),GetErrorString(res,&sw)); PrintAndLogEx(WARNING, _RED_(" Can't create aid -> %s"), GetErrorString(res, &sw));
DropField(); DropField();
return res; return res;
} }
return res; return res;
} }
static int get_desfire_deleteapp(uint8_t* aid) { static int get_desfire_deleteapp(uint8_t *aid) {
if (aid==NULL) return PM3_EINVARG; if (aid == NULL) return PM3_EINVARG;
sAPDU apdu = {0x90, MFDES_DELETE_APPLICATION, 0x00, 0x00, 3, aid}; // 0xDA sAPDU apdu = {0x90, MFDES_DELETE_APPLICATION, 0x00, 0x00, 3, aid}; // 0xDA
uint16_t sw = 0; uint16_t sw = 0;
int recvlen=0; int recvlen = 0;
int res=send_desfire_cmd(&apdu, false, NONE, &recvlen, &sw, 0,true); int res = send_desfire_cmd(&apdu, false, NONE, &recvlen, &sw, 0, true);
if (res != PM3_SUCCESS) { if (res != PM3_SUCCESS) {
PrintAndLogEx(WARNING, _RED_(" Can't delete aid -> %s"),GetErrorString(res,&sw)); PrintAndLogEx(WARNING, _RED_(" Can't delete aid -> %s"), GetErrorString(res, &sw));
DropField(); DropField();
return res; return res;
} }
@ -674,16 +662,16 @@ static int CmdHF14ADesCreateApp(const char *Cmd) {
"Create Application ID", "Create Application ID",
"Usage:\n\t-m Auth type (1=normal, 2=iso, 3=aes)\n\t-t Crypt algo (1=DES, 2=3DES, 3=3K3DES, 4=aes)\n\t-a aid (3 bytes)\n\t-n keyno\n\t-k key (8-24 bytes)\n\n" "Usage:\n\t-m Auth type (1=normal, 2=iso, 3=aes)\n\t-t Crypt algo (1=DES, 2=3DES, 3=3K3DES, 4=aes)\n\t-a aid (3 bytes)\n\t-n keyno\n\t-k key (8-24 bytes)\n\n"
"Example:\n\thf mfdes createaid -a 123456 -f 1122 -k 0F -l 2E -n AppName\n" "Example:\n\thf mfdes createaid -a 123456 -f 1122 -k 0F -l 2E -n AppName\n"
); );
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_strx0("aA", "aid", "<aid>", "App ID to create"), arg_strx0("aA", "aid", "<aid>", "App ID to create"),
arg_strx0("fF", "fid", "<fid>", "File ID"), arg_strx0("fF", "fid", "<fid>", "File ID"),
arg_strx0("kK", "keysetting1", "<keysetting1>", "Key Setting 1 (Application Master Key Settings)"), arg_strx0("kK", "keysetting1", "<keysetting1>", "Key Setting 1 (Application Master Key Settings)"),
arg_strx0("lL", "keysetting2", "<keysetting2>", "Key Setting 2"), arg_strx0("lL", "keysetting2", "<keysetting2>", "Key Setting 2"),
arg_str0("nN", "name", "<name>", "App ISO-4 Name"), arg_str0("nN", "name", "<name>", "App ISO-4 Name"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(Cmd, argtable, true); CLIExecWithReturn(Cmd, argtable, true);
/* KeySetting 1 (AMK Setting): /* KeySetting 1 (AMK Setting):
@ -719,11 +707,11 @@ static int CmdHF14ADesCreateApp(const char *Cmd) {
uint8_t aid[3] = {0}; uint8_t aid[3] = {0};
uint8_t fid[2] = {0}; uint8_t fid[2] = {0};
uint8_t name[16] = {0}; uint8_t name[16] = {0};
uint8_t keysetting1=0; uint8_t keysetting1 = 0;
uint8_t keysetting2=0; uint8_t keysetting2 = 0;
int keylen1=1; int keylen1 = 1;
int keylen2=1; int keylen2 = 1;
int namelen=16; int namelen = 16;
CLIGetHexWithReturn(1, aid, &aidlength); CLIGetHexWithReturn(1, aid, &aidlength);
CLIGetHexWithReturn(2, fid, &fidlength); CLIGetHexWithReturn(2, fid, &fidlength);
CLIGetHexWithReturn(3, &keysetting1, &keylen1); CLIGetHexWithReturn(3, &keysetting1, &keylen1);
@ -769,15 +757,15 @@ static int CmdHF14ADesCreateApp(const char *Cmd) {
} }
aidhdr_t aidhdr; aidhdr_t aidhdr;
memcpy(aidhdr.aid,aid,sizeof(aid)); memcpy(aidhdr.aid, aid, sizeof(aid));
aidhdr.keysetting1=keysetting1; aidhdr.keysetting1 = keysetting1;
aidhdr.keysetting2=keysetting2; aidhdr.keysetting2 = keysetting2;
memcpy(aidhdr.fid,fid,sizeof(fid)); memcpy(aidhdr.fid, fid, sizeof(fid));
memcpy(aidhdr.name,name,sizeof(name)); memcpy(aidhdr.name, name, sizeof(name));
uint8_t rootaid[3]={0x00,0x00,0x00}; uint8_t rootaid[3] = {0x00, 0x00, 0x00};
int res=get_desfire_select_application(rootaid); int res = get_desfire_select_application(rootaid);
if (res!=PM3_SUCCESS) return res; if (res != PM3_SUCCESS) return res;
return get_desfire_createapp(&aidhdr); return get_desfire_createapp(&aidhdr);
} }
@ -789,12 +777,12 @@ static int CmdHF14ADesDeleteApp(const char *Cmd) {
"Delete Application ID", "Delete Application ID",
"Usage:\n\t-a aid (3 bytes)\n\n" "Usage:\n\t-a aid (3 bytes)\n\n"
"Example:\n\thf mfdes deleteaid -a 123456\n" "Example:\n\thf mfdes deleteaid -a 123456\n"
); );
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_strx0("aA", "aid", "<aid>", "App ID to delete"), arg_strx0("aA", "aid", "<aid>", "App ID to delete"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(Cmd, argtable, true); CLIExecWithReturn(Cmd, argtable, true);
int aidlength = 3; int aidlength = 3;
@ -812,9 +800,9 @@ static int CmdHF14ADesDeleteApp(const char *Cmd) {
return PM3_ESOFT; return PM3_ESOFT;
} }
uint8_t rootaid[3]={0x00,0x00,0x00}; uint8_t rootaid[3] = {0x00, 0x00, 0x00};
int res=get_desfire_select_application(rootaid); int res = get_desfire_select_application(rootaid);
if (res!=PM3_SUCCESS) return res; if (res != PM3_SUCCESS) return res;
return get_desfire_deleteapp(aid); return get_desfire_deleteapp(aid);
} }
@ -825,12 +813,12 @@ static int CmdHF14ADesFormatPICC(const char *Cmd) {
"Formats MIFARE DESFire PICC to factory state", "Formats MIFARE DESFire PICC to factory state",
"Usage:\n\t-k PICC key (8 bytes)\n\n" "Usage:\n\t-k PICC key (8 bytes)\n\n"
"Example:\n\thf mfdes formatpicc -k 0000000000000000\n" "Example:\n\thf mfdes formatpicc -k 0000000000000000\n"
); );
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
arg_str0("kK", "key", "<Key>", "Key for checking (HEX 16 bytes)"), arg_str0("kK", "key", "<Key>", "Key for checking (HEX 16 bytes)"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(Cmd, argtable, true); CLIExecWithReturn(Cmd, argtable, true);
@ -847,9 +835,9 @@ static int CmdHF14ADesFormatPICC(const char *Cmd) {
clearCommandBuffer(); clearCommandBuffer();
DropField(); DropField();
uint8_t aid[3]={0}; uint8_t aid[3] = {0};
int res=get_desfire_select_application(aid); int res = get_desfire_select_application(aid);
if (res!=PM3_SUCCESS) return res; if (res != PM3_SUCCESS) return res;
uint8_t data[25] = {keylen}; // max length: 1 + 24 (3k3DES) uint8_t data[25] = {keylen}; // max length: 1 + 24 (3k3DES)
memcpy(data + 1, key, keylen); memcpy(data + 1, key, keylen);
SendCommandOLD(CMD_HF_DESFIRE_AUTH1, 2, 1, 0, data, keylen + 1); SendCommandOLD(CMD_HF_DESFIRE_AUTH1, 2, 1, 0, data, keylen + 1);
@ -870,7 +858,7 @@ static int CmdHF14ADesFormatPICC(const char *Cmd) {
DropField(); DropField();
return PM3_ETIMEOUT; return PM3_ETIMEOUT;
} }
if (resp.oldarg[0]&0xFF){ if (resp.oldarg[0] & 0xFF) {
PrintAndLogEx(INFO, "Card successfully reset"); PrintAndLogEx(INFO, "Card successfully reset");
return PM3_SUCCESS; return PM3_SUCCESS;
} }
@ -973,7 +961,7 @@ static int CmdHF14ADesInfo(const char *Cmd) {
if (get_desfire_signature(signature, &signature_len) == PM3_SUCCESS) if (get_desfire_signature(signature, &signature_len) == PM3_SUCCESS)
desfire_print_signature(package->uid, signature, signature_len, cardtype); desfire_print_signature(package->uid, signature, signature_len, cardtype);
else{ else {
PrintAndLogEx(WARNING, "--- " _YELLOW_("Couldn't verify signature. Unknown public key ?")); PrintAndLogEx(WARNING, "--- " _YELLOW_("Couldn't verify signature. Unknown public key ?"));
} }
@ -1066,19 +1054,19 @@ char *getVersionStr(uint8_t major, uint8_t minor) {
} }
int getKeySettings(uint8_t *aid) { int getKeySettings(uint8_t *aid) {
if (aid==NULL) return PM3_EINVARG; if (aid == NULL) return PM3_EINVARG;
int res=0; int res = 0;
if (memcmp(aid, "\x00\x00\x00", 3) == 0) { if (memcmp(aid, "\x00\x00\x00", 3) == 0) {
// CARD MASTER KEY // CARD MASTER KEY
//PrintAndLogEx(INFO, "--- " _CYAN_("CMK - PICC, Card Master Key settings")); //PrintAndLogEx(INFO, "--- " _CYAN_("CMK - PICC, Card Master Key settings"));
res=get_desfire_select_application(aid); res = get_desfire_select_application(aid);
if (res!=PM3_SUCCESS) return res; if (res != PM3_SUCCESS) return res;
// KEY Settings - AMK // KEY Settings - AMK
uint8_t num_keys = 0; uint8_t num_keys = 0;
uint8_t key_setting = 0; uint8_t key_setting = 0;
res=get_desfire_keysettings(&key_setting, &num_keys); res = get_desfire_keysettings(&key_setting, &num_keys);
if (res == PM3_SUCCESS) { if (res == PM3_SUCCESS) {
// number of Master keys (0x01) // number of Master keys (0x01)
PrintAndLogEx(SUCCESS, " Number of Masterkeys : " _YELLOW_("%u"), (num_keys & 0x3F)); PrintAndLogEx(SUCCESS, " Number of Masterkeys : " _YELLOW_("%u"), (num_keys & 0x3F));
@ -1133,13 +1121,13 @@ int getKeySettings(uint8_t *aid) {
// AID - APPLICATION MASTER KEYS // AID - APPLICATION MASTER KEYS
//PrintAndLogEx(SUCCESS, "--- " _CYAN_("AMK - Application Master Key settings")); //PrintAndLogEx(SUCCESS, "--- " _CYAN_("AMK - Application Master Key settings"));
res=get_desfire_select_application(aid); res = get_desfire_select_application(aid);
if (res!=PM3_SUCCESS) return res; if (res != PM3_SUCCESS) return res;
// KEY Settings - AMK // KEY Settings - AMK
uint8_t num_keys = 0; uint8_t num_keys = 0;
uint8_t key_setting = 0; uint8_t key_setting = 0;
res=get_desfire_keysettings(&key_setting, &num_keys); res = get_desfire_keysettings(&key_setting, &num_keys);
if (res == PM3_SUCCESS) { if (res == PM3_SUCCESS) {
desfire_print_keysetting(key_setting, num_keys); desfire_print_keysetting(key_setting, num_keys);
} else { } else {
@ -1173,9 +1161,8 @@ int getKeySettings(uint8_t *aid) {
return PM3_SUCCESS; return PM3_SUCCESS;
} }
static void DecodeFileType(uint8_t filetype){ static void DecodeFileType(uint8_t filetype) {
switch (filetype) switch (filetype) {
{
case 0x00: case 0x00:
PrintAndLogEx(INFO, " File Type: 0x%02X -> Standard Data File", filetype); PrintAndLogEx(INFO, " File Type: 0x%02X -> Standard Data File", filetype);
break; break;
@ -1197,9 +1184,8 @@ static void DecodeFileType(uint8_t filetype){
} }
} }
static void DecodeComSet(uint8_t comset){ static void DecodeComSet(uint8_t comset) {
switch (comset) switch (comset) {
{
case 0x00: case 0x00:
PrintAndLogEx(INFO, " Com.Setting: 0x%02X -> Plain", comset); PrintAndLogEx(INFO, " Com.Setting: 0x%02X -> Plain", comset);
break; break;
@ -1215,11 +1201,10 @@ static void DecodeComSet(uint8_t comset){
} }
} }
static char* DecodeAccessValue(uint8_t value) static char *DecodeAccessValue(uint8_t value) {
{ char *car = (char *)malloc(255);
char* car=(char*)malloc(255); memset(car, 0x0, 255);
memset(car,0x0,255); switch (value) {
switch(value){
case 0xE: case 0xE:
strcat(car, "(Free Access)"); strcat(car, "(Free Access)");
break; break;
@ -1227,46 +1212,45 @@ static char* DecodeAccessValue(uint8_t value)
strcat(car, "(Denied Access)"); strcat(car, "(Denied Access)");
break; break;
default: default:
sprintf(car,"(Access Key: %d)",value); sprintf(car, "(Access Key: %d)", value);
break; break;
} }
return car; return car;
} }
static void DecodeAccessRights(uint16_t accrights){ static void DecodeAccessRights(uint16_t accrights) {
int change_access_rights=accrights&0xF; int change_access_rights = accrights & 0xF;
int read_write_access=(accrights>>4)&0xF; int read_write_access = (accrights >> 4) & 0xF;
int write_access=(accrights>>8)&0xF; int write_access = (accrights >> 8) & 0xF;
int read_access=(accrights>>12)&0xF; int read_access = (accrights >> 12) & 0xF;
char* car=DecodeAccessValue(change_access_rights); char *car = DecodeAccessValue(change_access_rights);
char* rwa=DecodeAccessValue(read_write_access); char *rwa = DecodeAccessValue(read_write_access);
char* wa=DecodeAccessValue(write_access); char *wa = DecodeAccessValue(write_access);
char* ra=DecodeAccessValue(read_access); char *ra = DecodeAccessValue(read_access);
PrintAndLogEx(INFO, " Access Rights: 0x%04X - Change %s - RW %s - W %s - R %s", accrights,car,rwa,wa,ra); PrintAndLogEx(INFO, " Access Rights: 0x%04X - Change %s - RW %s - W %s - R %s", accrights, car, rwa, wa, ra);
free(car); free(car);
free(rwa); free(rwa);
free(wa); free(wa);
free(ra); free(ra);
} }
static int DecodeFileSettings(uint8_t* filesettings, int fileset_len, int maclen){ static int DecodeFileSettings(uint8_t *filesettings, int fileset_len, int maclen) {
uint8_t filetype=filesettings[0]; uint8_t filetype = filesettings[0];
uint8_t comset=filesettings[1]; uint8_t comset = filesettings[1];
uint16_t accrights=(filesettings[4]<<8)+filesettings[3]; uint16_t accrights = (filesettings[4] << 8) + filesettings[3];
if (fileset_len==1+1+2+3+maclen) if (fileset_len == 1 + 1 + 2 + 3 + maclen) {
{ int filesize = (filesettings[7] << 16) + (filesettings[6] << 8) + filesettings[5];
int filesize=(filesettings[7]<<16)+(filesettings[6]<<8)+filesettings[5];
DecodeFileType(filetype); DecodeFileType(filetype);
DecodeComSet(comset); DecodeComSet(comset);
DecodeAccessRights(accrights); DecodeAccessRights(accrights);
PrintAndLogEx(INFO, " Filesize: %d", filesize); PrintAndLogEx(INFO, " Filesize: %d", filesize);
return PM3_SUCCESS; return PM3_SUCCESS;
} else if (fileset_len==1+1+2+4+4+4+1+maclen) { } else if (fileset_len == 1 + 1 + 2 + 4 + 4 + 4 + 1 + maclen) {
int lowerlimit=(filesettings[8]<<24)+(filesettings[7]<<16)+(filesettings[6]<<8)+filesettings[5]; int lowerlimit = (filesettings[8] << 24) + (filesettings[7] << 16) + (filesettings[6] << 8) + filesettings[5];
int upperlimit=(filesettings[12]<<24)+(filesettings[11]<<16)+(filesettings[10]<<8)+filesettings[9]; int upperlimit = (filesettings[12] << 24) + (filesettings[11] << 16) + (filesettings[10] << 8) + filesettings[9];
int limitcredvalue=(filesettings[16]<<24)+(filesettings[15]<<16)+(filesettings[14]<<8)+filesettings[13]; int limitcredvalue = (filesettings[16] << 24) + (filesettings[15] << 16) + (filesettings[14] << 8) + filesettings[13];
uint8_t limited_credit_enabled=filesettings[17]; uint8_t limited_credit_enabled = filesettings[17];
DecodeFileType(filetype); DecodeFileType(filetype);
DecodeComSet(comset); DecodeComSet(comset);
DecodeAccessRights(accrights); DecodeAccessRights(accrights);
@ -1287,10 +1271,10 @@ static int CmdHF14ADesEnumApplications(const char *Cmd) {
uint8_t file_ids[33] = {0}; uint8_t file_ids[33] = {0};
uint8_t file_ids_len = 0; uint8_t file_ids_len = 0;
dfname_t dfnames[255] = {0}; dfname_t dfnames[255];
uint8_t dfname_count = 0; uint8_t dfname_count = 0;
int res=0; int res = 0;
if (get_desfire_appids(app_ids, &app_ids_len) != PM3_SUCCESS) { if (get_desfire_appids(app_ids, &app_ids_len) != PM3_SUCCESS) {
PrintAndLogEx(ERR, "Can't get list of applications on tag"); PrintAndLogEx(ERR, "Can't get list of applications on tag");
@ -1331,10 +1315,10 @@ static int CmdHF14ADesEnumApplications(const char *Cmd) {
} }
} }
res=getKeySettings(aid); res = getKeySettings(aid);
if (res!=PM3_SUCCESS) return res; if (res != PM3_SUCCESS) return res;
res=get_desfire_select_application(aid); res = get_desfire_select_application(aid);
// Get File IDs // Get File IDs
@ -1346,9 +1330,9 @@ static int CmdHF14ADesEnumApplications(const char *Cmd) {
uint8_t filesettings[20] = {0}; uint8_t filesettings[20] = {0};
int fileset_len = 0; int fileset_len = 0;
int res = get_desfire_filesettings(j, filesettings, &fileset_len); int res = get_desfire_filesettings(j, filesettings, &fileset_len);
int maclen=0; // To be implemented int maclen = 0; // To be implemented
if (res == PM3_SUCCESS) { if (res == PM3_SUCCESS) {
if (DecodeFileSettings(filesettings,fileset_len,maclen)!=PM3_SUCCESS){ if (DecodeFileSettings(filesettings, fileset_len, maclen) != PM3_SUCCESS) {
PrintAndLogEx(INFO, " Settings [%u] %s", fileset_len, sprint_hex(filesettings, fileset_len)); PrintAndLogEx(INFO, " Settings [%u] %s", fileset_len, sprint_hex(filesettings, fileset_len));
} }
} }
@ -1387,7 +1371,7 @@ static int CmdHF14ADesEnumApplications(const char *Cmd) {
// //
#define BUFSIZE 256 #define BUFSIZE 256
static int CmdHF14ADesAuth(const char *Cmd) { static int CmdHF14ADesAuth(const char *Cmd) {
int res=0; int res = 0;
DropField(); DropField();
clearCommandBuffer(); clearCommandBuffer();
// NR DESC KEYLENGHT // NR DESC KEYLENGHT
@ -1498,10 +1482,10 @@ static int CmdHF14ADesAuth(const char *Cmd) {
} }
res=get_desfire_select_application(aid); res = get_desfire_select_application(aid);
if (res!=PM3_SUCCESS) return res; if (res != PM3_SUCCESS) return res;
if (memcmp(aid,"\x00\x00\x00",3)!=0){ if (memcmp(aid, "\x00\x00\x00", 3) != 0) {
uint8_t file_ids[33] = {0}; uint8_t file_ids[33] = {0};
uint8_t file_ids_len = 0; uint8_t file_ids_len = 0;
res = get_desfire_fileids(file_ids, &file_ids_len); res = get_desfire_fileids(file_ids, &file_ids_len);

View file

@ -91,14 +91,20 @@ CRC1 = crc8 over addr 0x00..0x03+0x07..0x0E (special 'gantner crc8')
CRC2 = MCD + MSB0..2+ addr 0x06 + addr 0x05 + addr 0x07 + Stamp (regular Master-Token-CRC) CRC2 = MCD + MSB0..2+ addr 0x06 + addr 0x05 + addr 0x07 + Stamp (regular Master-Token-CRC)
--]] --]]
--[[
Known issues; needs to be fixed:
* last byte in last segment is handled incorrectly when it is the last bytes on the card itself (MIM256: => byte 256)
--]]
example = "script run legic" example = "script run legic"
author = "Mosci" author = "Mosci, uhei"
version = "1.0.3" version = "1.0.4"
desc = desc =
[[ [[
This script helps you to read, create and modify Legic Prime Tags (MIM22, MIM256, MIM1024) This script helps you to read, create and modify Legic Prime Tags (MIM22, MIM256, MIM1024)
The virtual tag (and therefore the file to be saved) is always a MIM1024 tag.
it's kinda interactive with following commands in three categories: it's kinda interactive with following commands in three categories:
Data I/O Segment Manipulation Token-Data Data I/O Segment Manipulation Token-Data
@ -108,8 +114,8 @@ it's kinda interactive with following commands in three categories:
ed => edit Segment Data tk => toggle KGH-Flag ed => edit Segment Data tk => toggle KGH-Flag
File I/O rs => remove Segment File I/O rs => remove Segment
----------------- cc => check Segment-CRC ----------------- cc => check Segment-CRC
lf => load File ck => check KGH lf => load bin File ck => check KGH
sf => save File ds => dump Segments sf => save eml/bin File ds => dump Segments
xf => xor to File xf => xor to File
@ -128,8 +134,8 @@ it's kinda interactive with following commands in three categories:
without the need of changing anything - MCD,MSN,MCC will be read from the tag without the need of changing anything - MCD,MSN,MCC will be read from the tag
before and applied to the output. before and applied to the output.
lf: 'load file' - load a (xored) file from the local Filesystem into the 'virtual inTag' lf: 'load file' - load a (xored) binary file (*.bin) from the local Filesystem into the 'virtual inTag'
sf: 'save file' - saves the 'virtual inTag' to the local Filesystem (xored with Tag-MCC) sf: 'save file' - saves the 'virtual inTag' to the local Filesystem as eml and bin (xored with Tag-MCC)
xf: 'xor file' - saves the 'virtual inTag' to the local Filesystem (xored with choosen MCC - use '00' for plain values) xf: 'xor file' - saves the 'virtual inTag' to the local Filesystem (xored with choosen MCC - use '00' for plain values)
ct: 'copy tag' - copy the 'virtual Tag' to a second 'virtual TAG' - not usefull yet, but inernally needed ct: 'copy tag' - copy the 'virtual Tag' to a second 'virtual TAG' - not usefull yet, but inernally needed
@ -242,6 +248,16 @@ function istable(t)
return type(t) == 'table' return type(t) == 'table'
end end
---
-- To have two char string for a byte
local function padString(str)
if (#str == 1) then
return '0'..str
end
return str
end
--- ---
-- creates a 'deep copy' of a table (a=b only references) -- creates a 'deep copy' of a table (a=b only references)
function deepCopy(object) function deepCopy(object)
@ -387,15 +403,15 @@ end
function bytesToTag(bytes, tag) function bytesToTag(bytes, tag)
if istable(tag) == false then return oops("tag is no table in: bytesToTag ("..type(tag)..")") end if istable(tag) == false then return oops("tag is no table in: bytesToTag ("..type(tag)..")") end
tag.MCD =bytes[1]; tag.MCD =padString(bytes[1]);
tag.MSN0=bytes[2]; tag.MSN0=padString(bytes[2]);
tag.MSN1=bytes[3]; tag.MSN1=padString(bytes[3]);
tag.MSN2=bytes[4]; tag.MSN2=padString(bytes[4]);
tag.MCC =bytes[5]; tag.MCC =padString(bytes[5]);
tag.DCFl=bytes[6]; tag.DCFl=padString(bytes[6]);
tag.DCFh=bytes[7]; tag.DCFh=padString(bytes[7]);
tag.raw =bytes[8]; tag.raw =padString(bytes[8]);
tag.SSC =bytes[9]; tag.SSC =padString(bytes[9]);
tag.Type=getTokenType(tag.DCFl); tag.Type=getTokenType(tag.DCFl);
tag.OLE=bbit("0x"..tag.DCFl,7,1) tag.OLE=bbit("0x"..tag.DCFl,7,1)
tag.WRP=("%d"):format(bbit("0x"..bytes[8],0,4)) tag.WRP=("%d"):format(bbit("0x"..bytes[8],0,4))
@ -500,42 +516,26 @@ function tagToBytes(tag)
return bytes return bytes
end end
---
--- PM3 I/O --- --- PM3 I/O ---
---
-- read from pm3 into virtual-tag
function readFromPM3()
local tag, bytes, infile
infile="legic.temp"
-- core.console("hf legic reader")
-- core.console("hf legic esave "..infile)
core.console("hf legic dump o "..infile)
tag=readFile(infile..".bin")
return tag
end
local function padString(str)
if (#str == 1) then
return '0'..str
end
return str
end
---
-- write virtual Tag to real Tag -- write virtual Tag to real Tag
function writeToTag(tag) function writeToTag(tag)
local bytes local bytes
local filename = 'MylegicClone.hex'
local taglen = 22 local taglen = 22
if(utils.confirm(acred.."\nplace the (empty) Tag onto the PM3\nand confirm writing to this Tag: "..acoff) == false) then local writeDCF = false
if(utils.confirm(acred.."\nPlace the (empty) Tag onto the PM3\nand confirm writing to this Tag: "..acoff) == false) then
return return
end end
if(utils.confirm(acred.."\nShould the decremental field (DCF) be written?: "..acoff) == true) then
writeDCF = true
end
-- get used bytes / tag-len -- get used bytes / tag-len
if (istable(tag.SEG)) then if (istable(tag.SEG)) then
if (istable(tag.Bck)) then if (istable(tag.Bck)) then
for i=0, #tag.SEG do for i=0, #tag.SEG do
taglen = taglen + tag.SEG[i] . len + 5 taglen = taglen + tag.SEG[i] . len
end end
end end
local uid_old = tag.MCD..tag.MSN0..tag.MSN1..tag.MSN2 local uid_old = tag.MCD..tag.MSN0..tag.MSN1..tag.MSN2
@ -571,37 +571,32 @@ function writeToTag(tag)
bytes[22] = calcMtCrc(bytes) bytes[22] = calcMtCrc(bytes)
end end
if (bytes) then if (bytes) then
print("write temp-file '"..filename.."'") bytes = xorBytes(bytes,tag.MCC)
print(accyan)
writeFile(bytes, filename..".bin")
print(acoff)
end end
end end
-- write data to file -- write data to file
if (taglen > 0) then if (taglen > 0) then
WriteBytes = input(acyellow.."enter number of bytes to write?"..acoff, taglen) WriteBytes = input(acyellow.."enter number of bytes to write?"..acoff, taglen)
-- load file into pm3-buffer
if (type(filename) ~= "string") then
filename = input(acyellow.."filename to load to pm3-buffer?"..acoff, "legic.temp")
end
cmd = 'hf legic eload 2 '..filename
core.console(cmd)
-- write pm3-buffer to Tag -- write pm3-buffer to Tag
for i=0, WriteBytes do for i=1, WriteBytes do
if (i > 6) then if (i > 7) then
cmd = ("hf legic write o %x d %s "):format(i, padString(bytes[i])) cmd = ("hf legic wrbl o %02x d %s "):format(i-1, padString(bytes[i]))
print(acgreen..cmd..acoff) print(acgreen..cmd..acoff)
core.console(cmd) core.console(cmd)
core.clearCommandBuffer() core.clearCommandBuffer()
elseif (i == 7) then
if (writeDCF) then
-- write DCF in reverse order (requires 'mosci-patch')
cmd = ('hf legic wrbl o 05 d %s%s'):format(padString(bytes[i-1]), padString(bytes[i]))
print(acgreen..cmd..acoff)
core.console(cmd)
core.clearCommandBuffer()
else
print(acgreen.."skip byte 0x05-0x06 - DCF"..acoff)
end
elseif (i == 6) then elseif (i == 6) then
-- write DCF in reverse order (requires 'mosci-patch')
cmd = ('hf legic write o 05 d %s%s'):format(padString(bytes[i-1]), padString(bytes[i]))
print(acgreen..cmd..acoff)
core.console(cmd)
core.clearCommandBuffer()
elseif (i == 5) then
print(acgreen.."skip byte 0x05 - will be written next step"..acoff) print(acgreen.."skip byte 0x05 - will be written next step"..acoff)
else else
print(acgreen.."skip byte 0x00-0x04 - unwritable area"..acoff) print(acgreen.."skip byte 0x00-0x04 - unwritable area"..acoff)
@ -641,12 +636,12 @@ end
local function save_BIN(data, filename) local function save_BIN(data, filename)
local outfile local outfile
local counter = 1 local counter = 1
local ext = filename:match("^.+(%..+)$") or '' local ext = ".bin"
local fn = filename local fn = filename..ext
-- Make sure we don't overwrite a file -- Make sure we don't overwrite a file
while file_check(fn) do while file_check(fn) do
fn = filename:gsub(ext, tostring(counter)..ext) fn = filename..ext:gsub(ext, "-"..tostring(counter)..ext)
counter = counter + 1 counter = counter + 1
end end
@ -664,26 +659,27 @@ end
--- ---
-- write bytes to file -- write bytes to file
function writeFile(bytes, filename) function writeFile(bytes, filename)
if (filename ~= 'MylegicClone.hex') then local emlext = ".eml"
if (file_check(filename)) then if (filename ~= 'MyLegicClone') then
local answer = confirm("\nthe output-file "..filename.." already exists!\nthis will delete the previous content!\ncontinue?") if (file_check(filename..emlext)) then
local answer = confirm("\nthe output-file "..filename..emlext.." already exists!\nthis will delete the previous content!\ncontinue?")
if not answer then return print("user abort") end if not answer then return print("user abort") end
end end
end end
local line local line
local bcnt = 0 local bcnt = 0
local fho, err = io.open(filename, "w") local fho, err = io.open(filename..emlext, "w")
if err then if err then
return oops("OOps ... failed to open output-file ".. filename) return oops("OOps ... failed to open output-file ".. filename..emlext)
end end
bytes = xorBytes(bytes, bytes[5]) bytes = xorBytes(bytes, bytes[5])
for i = 1, #bytes do for i = 1, #bytes do
if (bcnt == 0) then if (bcnt == 0) then
line = bytes[i] line = padString(bytes[i])
elseif (bcnt <= 7) then elseif (bcnt <= 7) then
line = line.." "..bytes[i] line = line.." "..padString(bytes[i])
end end
if (bcnt == 7) then if (bcnt == 7) then
-- write line to new file -- write line to new file
@ -699,7 +695,7 @@ function writeFile(bytes, filename)
-- save binary -- save binary
local fn_bin, fn_bin_num = save_BIN(bytes, filename) local fn_bin, fn_bin_num = save_BIN(bytes, filename)
print("\nwrote "..acyellow..(#bytes * 3)..acoff.." bytes to " ..acyellow..filename..acoff) print("\nwrote "..acyellow..(#bytes * 3)..acoff.." bytes to " ..acyellow..filename..emlext..acoff)
if fn_bin and fn_bin_num then if fn_bin and fn_bin_num then
print("\nwrote "..acyellow..fn_bin_num..acoff.." bytes to BINARY file "..acyellow..fn_bin..acoff) print("\nwrote "..acyellow..fn_bin_num..acoff.." bytes to BINARY file "..acyellow..fn_bin..acoff)
@ -708,6 +704,21 @@ function writeFile(bytes, filename)
return true return true
end end
---
-- read from pm3 into virtual-tag
function readFromPM3()
local tag, bytes, infile
--infile="legic.temp"
infile=os.tmpname()
core.console("hf legic dump f "..infile)
tag=readFile(infile..".bin")
os.remove(infile)
os.remove(infile..".bin")
os.remove(infile..".eml")
os.remove(infile..".json")
return tag
end
--- Map related --- --- Map related ---
--- ---
-- make tagMap -- make tagMap
@ -2265,8 +2276,8 @@ function modifyHelp()
ed => edit Segment Data tk => toggle KGH-Flag ed => edit Segment Data tk => toggle KGH-Flag
File I/O rs => remove Segment File I/O rs => remove Segment
----------------- cc => check Segment-CRC ----------------- cc => check Segment-CRC
lf => load File ck => check KGH lf => load bin File ck => check KGH
sf => save File ds => dump Segments sf => save eml/bin File ds => dump Segments
xf => xor to File xf => xor to File
@ -2352,10 +2363,10 @@ function modifyMode()
-- save values of mainTAG to a file (xored with MCC of mainTAG) -- save values of mainTAG to a file (xored with MCC of mainTAG)
["sf"] = function(x) ["sf"] = function(x)
if istable(inTAG) then if istable(inTAG) then
outfile = input("enter filename:", "legic.temp") outfile = input("enter filename:", "hf-legic-"..inTAG.MCD..inTAG.MSN0..inTAG.MSN1..inTAG.MSN2)
bytes = tagToBytes(inTAG) bytes = tagToBytes(inTAG)
--bytes=xorBytes(bytes, inTAG.MCC) --bytes=xorBytes(bytes, inTAG.MCC)
if bytes then if (bytes) then
writeFile(bytes, outfile) writeFile(bytes, outfile)
end end
end end
@ -2364,7 +2375,7 @@ function modifyMode()
-- save values of mainTAG to a file (xored with 'specific' MCC) -- save values of mainTAG to a file (xored with 'specific' MCC)
["xf"] = function(x) ["xf"] = function(x)
if istable(inTAG) then if istable(inTAG) then
outfile = input("enter filename:", "legic.temp") outfile = input("enter filename:", "hf-legic-"..inTAG.MCD..inTAG.MSN0..inTAG.MSN1..inTAG.MSN2)
crc = input("enter new crc: ('00' for a plain dump)", inTAG.MCC) crc = input("enter new crc: ('00' for a plain dump)", inTAG.MCC)
print("obfuscate with: "..crc) print("obfuscate with: "..crc)
bytes=tagToBytes(inTAG) bytes=tagToBytes(inTAG)

1569
cmdhfmfdes.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -18,7 +18,7 @@ Always use the latest repository commits from *master* branch. There are always
* [File not found](#file-not-found) * [File not found](#file-not-found)
* [Pixmap / pixbuf warnings](#pixmap--pixbuf-warnings) * [Pixmap / pixbuf warnings](#pixmap--pixbuf-warnings)
* [Usb cable](#usb-cable) * [Usb cable](#usb-cable)
* [WSL 2 explorer.exe . doesnt work](WSL-2) * [WSL 2 explorer.exe . doesnt work](#WSL-2)
## `pm3` or `pm3-flash*` doesn't see my Proxmark ## `pm3` or `pm3-flash*` doesn't see my Proxmark