Add first 3K3 support. Improve algo error handling

This commit is contained in:
Bjoern Kerler 2020-04-11 02:32:55 +02:00
commit 4c2f98ac3d
2 changed files with 92 additions and 57 deletions

View file

@ -132,7 +132,7 @@ void MifareDesfireGetInformation() {
clear_trace(); clear_trace();
set_tracing(true); set_tracing(true);
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
// reset the pcb_blocknum, // reset the pcb_blocknum,
pcb_blocknum = 0; pcb_blocknum = 0;
@ -259,6 +259,7 @@ void MifareDES_Auth1(uint8_t *datain) {
// Default Keys // Default Keys
uint8_t PICC_MASTER_KEY8[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; uint8_t PICC_MASTER_KEY8[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t PICC_MASTER_KEY16[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; uint8_t PICC_MASTER_KEY16[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint8_t PICC_MASTER_KEY24[24] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
//uint8_t null_key_data16[16] = {0x00}; //uint8_t null_key_data16[16] = {0x00};
//uint8_t new_key_data8[8] = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77}; //uint8_t new_key_data8[8] = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77};
//uint8_t new_key_data16[16] = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF}; //uint8_t new_key_data16[16] = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF};
@ -272,10 +273,12 @@ void MifareDES_Auth1(uint8_t *datain) {
LED_C_OFF(); LED_C_OFF();
if (payload->key == NULL) { if (payload->key == NULL) {
if (payload->mode == MFDES_AUTH_DES || payload->mode == MFDES_AUTH_PICC) { if (payload->algo == MFDES_AUTH_DES) {
memcpy(keybytes, PICC_MASTER_KEY8, 8); memcpy(keybytes, PICC_MASTER_KEY8, 8);
} else if (payload->mode == MFDES_AUTH_AES) { } else if (payload->algo == MFDES_ALGO_AES || payload->algo == MFDES_ALGO_3DES) {
memcpy(keybytes, PICC_MASTER_KEY16, 16); memcpy(keybytes, PICC_MASTER_KEY16, 16);
} else if (payload->algo == MFDES_ALGO_3DES) {
memcpy(keybytes, PICC_MASTER_KEY24, 24);
} }
} else { } else {
memcpy(keybytes, payload->key, payload->keylen); memcpy(keybytes, payload->key, payload->keylen);
@ -334,6 +337,20 @@ void MifareDES_Auth1(uint8_t *datain) {
return; return;
} }
int expectedlen = 1 + 8 + 2 + 2;
if (payload->algo == MFDES_ALGO_AES || payload->algo == MFDES_ALGO_3K3DES) {
expectedlen = 1 + 16 + 2 + 2;
}
if (len != expectedlen) {
if (DBGLEVEL >= DBG_ERROR) {
DbpString("Authentication failed. Length of answer doesn't match algo.");
print_result("Res-Buffer: ", resp, len);
}
OnErrorNG(CMD_HF_DESFIRE_AUTH1, 3);
return;
}
// Part 2 // Part 2
if (payload->mode != MFDES_AUTH_PICC) { if (payload->mode != MFDES_AUTH_PICC) {
memcpy(encRndB, resp + 1, payload->keylen); memcpy(encRndB, resp + 1, payload->keylen);
@ -355,6 +372,8 @@ void MifareDES_Auth1(uint8_t *datain) {
tdes_dec(&RndB, &encRndB, key->data); tdes_dec(&RndB, &encRndB, key->data);
else if (payload->algo == MFDES_ALGO_DES) else if (payload->algo == MFDES_ALGO_DES)
des_dec(&RndB, &encRndB, key->data); des_dec(&RndB, &encRndB, key->data);
else if (payload->algo == MFDES_ALGO_3K3DES)
tdes_3key_dec(&RndB, &encRndB, 16, key->data, IV);
// - Rotate RndB by 8 bits // - Rotate RndB by 8 bits
memcpy(rotRndB, RndB, payload->keylen); memcpy(rotRndB, RndB, payload->keylen);
@ -363,25 +382,35 @@ void MifareDES_Auth1(uint8_t *datain) {
uint8_t encRndA[16] = {0x00}; uint8_t encRndA[16] = {0x00};
// - Encrypt our response // - Encrypt our response
if (payload->mode == MFDES_AUTH_DES || payload->mode == MFDES_AUTH_PICC) { if (payload->mode == MFDES_AUTH_DES || payload->mode == MFDES_AUTH_ISO || payload->mode == MFDES_AUTH_PICC) {
if (payload->algo == MFDES_ALGO_3DES) if (payload->algo == MFDES_ALGO_3DES) {
tdes_dec(&encRndA, &RndA, key->data); tdes_dec(&encRndA, &RndA, key->data);
else if (payload->algo == MFDES_ALGO_DES) memcpy(both, encRndA, 8);
} else if (payload->algo == MFDES_ALGO_DES) {
des_dec(&encRndA, &RndA, key->data); des_dec(&encRndA, &RndA, key->data);
memcpy(both, encRndA, 8);
} else if (payload->algo == MFDES_ALGO_3K3DES) {
tdes_3key_dec(&encRndA, &RndA, 16, key->data, IV);
memcpy(both, encRndA, 16);
}
memcpy(both, encRndA, 8);
for (int x = 0; x < 8; x++) { for (int x = 0; x < 8; x++) {
rotRndB[x] = rotRndB[x] ^ encRndA[x]; rotRndB[x] = rotRndB[x] ^ encRndA[x];
} }
if (payload->algo == MFDES_ALGO_3DES) if (payload->algo == MFDES_ALGO_3DES) {
tdes_dec(&encRndB, &rotRndB, key->data); tdes_dec(&encRndB, &rotRndB, key->data);
else if (payload->algo == MFDES_ALGO_DES) memcpy(both + 8, encRndB, 8);
} else if (payload->algo == MFDES_ALGO_DES) {
des_dec(&encRndB, &rotRndB, key->data); des_dec(&encRndB, &rotRndB, key->data);
memcpy(both + 8, encRndB, 8);
} else if (payload->algo == MFDES_ALGO_3K3DES) {
tdes_3key_dec(&encRndB, &rotRndB, 16, key->data, IV);
memcpy(both + 16, encRndB, 16);
}
memcpy(both + 8, encRndB, 8); } else if (payload->mode == MFDES_AUTH_AES) {
} else if (payload->mode == MFDES_AUTH_AES || payload->mode == MFDES_AUTH_ISO) {
uint8_t tmp[32] = {0x00}; uint8_t tmp[32] = {0x00};
memcpy(tmp, RndA, 16); memcpy(tmp, RndA, 16);
memcpy(tmp + 16, rotRndB, 16); memcpy(tmp + 16, rotRndB, 16);
@ -397,15 +426,19 @@ void MifareDES_Auth1(uint8_t *datain) {
} }
} }
int bothlen = 16;
if (payload->algo == MFDES_ALGO_AES || payload->algo == MFDES_ALGO_3K3DES) {
bothlen = 32;
}
if (payload->mode != MFDES_AUTH_PICC) { if (payload->mode != MFDES_AUTH_PICC) {
cmd[0] = 0x90; cmd[0] = 0x90;
cmd[1] = ADDITIONAL_FRAME; cmd[1] = ADDITIONAL_FRAME;
cmd[2] = 0x00; cmd[2] = 0x00;
cmd[3] = 0x00; cmd[3] = 0x00;
cmd[4] = (payload->keylen * 2); cmd[4] = bothlen;
memcpy(cmd + 5, both, payload->keylen * 2); memcpy(cmd + 5, both, bothlen);
cmd[(payload->keylen * 2) + 5] = 0x0; cmd[bothlen + 5] = 0x0;
len = DesfireAPDU(cmd, 5 + (payload->keylen * 2) + 1, resp); len = DesfireAPDU(cmd, 5 + bothlen + 1, resp);
} else { } else {
cmd[0] = ADDITIONAL_FRAME; cmd[0] = ADDITIONAL_FRAME;
memcpy(cmd + 1, both, 16); memcpy(cmd + 1, both, 16);
@ -452,6 +485,8 @@ void MifareDES_Auth1(uint8_t *datain) {
tdes_dec(&encRndA, &encRndA, key->data); tdes_dec(&encRndA, &encRndA, key->data);
else if (payload->algo == MFDES_ALGO_DES) else if (payload->algo == MFDES_ALGO_DES)
des_dec(&encRndA, &encRndA, key->data); des_dec(&encRndA, &encRndA, key->data);
else if (payload->algo == MFDES_ALGO_3K3DES)
tdes_3key_dec(&encRndA, &encRndA, 16, key->data, IV);
} else if (payload->mode == MFDES_AUTH_AES) { } else if (payload->mode == MFDES_AUTH_AES) {
if (mbedtls_aes_setkey_dec(&ctx, key->data, 128) != 0) { if (mbedtls_aes_setkey_dec(&ctx, key->data, 128) != 0) {
if (DBGLEVEL >= DBG_EXTENDED) { if (DBGLEVEL >= DBG_EXTENDED) {

View file

@ -92,13 +92,13 @@ static char *getCardSizeStr(uint8_t fsize) {
static char *getProtocolStr(uint8_t id, bool hw) { static char *getProtocolStr(uint8_t id, bool hw) {
static char buf[50] = {0x00}; static char buf[50] = {0x00};
char *retStr = buf; char *retStr = buf;
if (id == 0x04) { if (id == 0x04) {
sprintf(retStr, "0x%02X ( " _YELLOW_("ISO 14443-3 MIFARE, 14443-4") ")", id); sprintf(retStr, "0x%02X ( " _YELLOW_("ISO 14443-3 MIFARE, 14443-4") ")", id);
} else if (id == 0x05) { } else if (id == 0x05) {
if (hw) if (hw)
sprintf(retStr, "0x%02X ( " _YELLOW_("ISO 14443-2, 14443-3") ")", id); sprintf(retStr, "0x%02X ( " _YELLOW_("ISO 14443-2, 14443-3") ")", id);
else else
sprintf(retStr, "0x%02X ( " _YELLOW_("ISO 14443-3, 14443-4") ")", id); sprintf(retStr, "0x%02X ( " _YELLOW_("ISO 14443-3, 14443-4") ")", id);
@ -308,7 +308,7 @@ 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 (apdu == NULL) { if (apdu == NULL) {
PrintAndLogEx(DEBUG, "APDU=NULL"); PrintAndLogEx(DEBUG, "APDU=NULL");
return PM3_EINVARG; return PM3_EINVARG;
} }
/*if (dest == NULL) { /*if (dest == NULL) {
@ -362,7 +362,7 @@ static int send_desfire_cmd(sAPDU *apdu, bool select, uint8_t *dest, int *recv_l
PrintAndLogEx(DEBUG, "%s", GetErrorString(res, sw)); PrintAndLogEx(DEBUG, "%s", GetErrorString(res, sw));
return res; return res;
} }
if (dest != NULL) { if (dest != NULL) {
if (splitbysize) { if (splitbysize) {
memcpy(&dest[i * splitbysize], data, resplen); memcpy(&dest[i * splitbysize], data, resplen);
@ -376,7 +376,7 @@ static int send_desfire_cmd(sAPDU *apdu, bool select, uint8_t *dest, int *recv_l
if (*sw != status(MFDES_ADDITIONAL_FRAME)) break; if (*sw != status(MFDES_ADDITIONAL_FRAME)) break;
} }
*recv_len = (splitbysize) ? i : pos; *recv_len = (splitbysize) ? i : pos;
return PM3_SUCCESS; return PM3_SUCCESS;
} }
@ -392,7 +392,7 @@ static nxp_cardtype_t getCardType(uint8_t major, uint8_t minor) {
// return DESFIRE_EV3; // return DESFIRE_EV3;
if (major == 0x30 && minor == 0x00) if (major == 0x30 && minor == 0x00)
return DESFIRE_LIGHT; return DESFIRE_LIGHT;
if (major == 0x11 && minor == 0x00 ) if (major == 0x11 && minor == 0x00)
return PLUS_EV1; return PLUS_EV1;
return UNKNOWN; return UNKNOWN;
@ -442,12 +442,12 @@ static int get_desfire_freemem(uint32_t *free_mem) {
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)
return res; return res;
if (sw != status(MFDES_S_OPERATION_OK)) if (sw != status(MFDES_S_OPERATION_OK))
return PM3_ESOFT; return PM3_ESOFT;
*free_mem = le24toh(fmem); *free_mem = le24toh(fmem);
return res; return res;
} }
@ -587,7 +587,7 @@ static int get_desfire_keysettings(uint8_t *key_settings, uint8_t *num_keys) {
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 ) if (res != PM3_SUCCESS)
return res; return res;
if (sw != status(MFDES_S_OPERATION_OK)) if (sw != status(MFDES_S_OPERATION_OK))
return PM3_ESOFT; return PM3_ESOFT;
@ -612,8 +612,8 @@ static int get_desfire_keyversion(uint8_t curr_key, uint8_t *num_versions) {
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);
if (res != PM3_SUCCESS ) if (res != PM3_SUCCESS)
return res; return res;
if (sw != status(MFDES_S_OPERATION_OK)) if (sw != status(MFDES_S_OPERATION_OK))
@ -625,8 +625,8 @@ static int get_desfire_keyversion(uint8_t curr_key, uint8_t *num_versions) {
// --- GET APPIDS // --- GET APPIDS
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 (dest == NULL) { if (dest == NULL) {
PrintAndLogEx(DEBUG, "DEST=NULL"); PrintAndLogEx(DEBUG, "DEST=NULL");
return PM3_EINVARG; return PM3_EINVARG;
} }
if (app_ids_len == NULL) { if (app_ids_len == NULL) {
PrintAndLogEx(DEBUG, "APP_IDS_LEN=NULL"); PrintAndLogEx(DEBUG, "APP_IDS_LEN=NULL");
@ -637,8 +637,8 @@ static int get_desfire_appids(uint8_t *dest, uint8_t *app_ids_len) {
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 ) if (res != PM3_SUCCESS)
return res; return res;
if (sw != status(MFDES_S_OPERATION_OK)) if (sw != status(MFDES_S_OPERATION_OK))
@ -868,18 +868,18 @@ int getKeySettings(uint8_t *aid) {
return PM3_SUCCESS; return PM3_SUCCESS;
} }
static void swap24(uint8_t* data){ static void swap24(uint8_t *data) {
if (data==NULL) return; if (data == NULL) return;
uint8_t tmp=data[0]; uint8_t tmp = data[0];
data[0]=data[2]; data[0] = data[2];
data[2]=tmp; data[2] = tmp;
}; };
static void swap16(uint8_t* data){ static void swap16(uint8_t *data) {
if (data==NULL) return; if (data == NULL) return;
uint8_t tmp=data[0]; uint8_t tmp = data[0];
data[0]=data[1]; data[0] = data[1];
data[1]=tmp; data[1] = tmp;
}; };
@ -1151,7 +1151,7 @@ static int CmdHF14ADesInfo(const char *Cmd) {
} }
return PM3_ESOFT; return PM3_ESOFT;
} }
nxp_cardtype_t cardtype = getCardType(package->versionHW[3], package->versionHW[4]); nxp_cardtype_t cardtype = getCardType(package->versionHW[3], package->versionHW[4]);
if (cardtype == PLUS_EV1) { if (cardtype == PLUS_EV1) {
PrintAndLogEx(INFO, "Card seems to be MIFARE Plus EV1. Try " _YELLOW_("`hf mfp info`")); PrintAndLogEx(INFO, "Card seems to be MIFARE Plus EV1. Try " _YELLOW_("`hf mfp info`"));
@ -1209,7 +1209,7 @@ static int CmdHF14ADesInfo(const char *Cmd) {
size_t signature_len = 0; size_t signature_len = 0;
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "--- " _CYAN_("Tag Signature")); PrintAndLogEx(INFO, "--- " _CYAN_("Tag Signature"));
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 {
@ -1322,7 +1322,7 @@ static void DecodeAccessRights(uint16_t accrights) {
char *rwa = DecodeAccessValue(read_write_access); char *rwa = DecodeAccessValue(read_write_access);
if (rwa == NULL) return; if (rwa == NULL) return;
char *wa = DecodeAccessValue(write_access); char *wa = DecodeAccessValue(write_access);
if (wa == NULL) return; if (wa == NULL) return;
@ -1515,7 +1515,7 @@ static int CmdHF14ADesAuth(const char *Cmd) {
CLIParserFree(); CLIParserFree();
if ((keylen < 8) || (keylen > 24)) { if ((keylen < 8) || (keylen > 24)) {
PrintAndLogEx(ERR, "Specified key must have 16 bytes length."); PrintAndLogEx(ERR, "Specified key must have %d bytes length.", keylen);
return PM3_SNONCES; return PM3_SNONCES;
} }
@ -1621,7 +1621,7 @@ static int CmdHF14ADesAuth(const char *Cmd) {
PrintAndLogEx(SUCCESS, " SESSION : " _GREEN_("%s"), sprint_hex(session_key, keylength)); PrintAndLogEx(SUCCESS, " SESSION : " _GREEN_("%s"), sprint_hex(session_key, keylength));
PrintAndLogEx(INFO, "-------------------------------------------------------------"); PrintAndLogEx(INFO, "-------------------------------------------------------------");
} else { } else {
PrintAndLogEx(WARNING, _RED_("Client command failed, reason: %d."), resp.status); PrintAndLogEx(WARNING, _RED_("Auth command failed, reason: %d."), resp.status);
} }
PrintAndLogEx(INFO, "-------------------------------------------------------------"); PrintAndLogEx(INFO, "-------------------------------------------------------------");
return PM3_SUCCESS; return PM3_SUCCESS;
@ -1643,18 +1643,18 @@ static command_t CommandTable[] = {
{"formatpicc", CmdHF14ADesFormatPICC, IfPm3Iso14443a, "Format PICC"}, {"formatpicc", CmdHF14ADesFormatPICC, IfPm3Iso14443a, "Format PICC"},
// {"rdbl", CmdHF14ADesRb, IfPm3Iso14443a, "Read MIFARE DesFire block"}, // {"rdbl", CmdHF14ADesRb, IfPm3Iso14443a, "Read MIFARE DesFire block"},
// {"wrbl", CmdHF14ADesWb, IfPm3Iso14443a, "write MIFARE DesFire block"}, // {"wrbl", CmdHF14ADesWb, IfPm3Iso14443a, "write MIFARE DesFire block"},
/* /*
ISO/IEC 7816 Cmds ISO/IEC 7816 Cmds
'A4' Select 'A4' Select
'B0' Read Binary 'B0' Read Binary
'D6' Update Binary 'D6' Update Binary
'B2' Read Records 'B2' Read Records
'E2' Append Records 'E2' Append Records
'84' Get Challenge '84' Get Challenge
'88' Internal Authenticate '88' Internal Authenticate
'82' External Authenticate '82' External Authenticate
*/ */
{NULL, NULL, NULL, NULL} {NULL, NULL, NULL, NULL}
}; };