mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-21 22:03:42 -07:00
Add first 3K3 support. Improve algo error handling
This commit is contained in:
parent
9b26fab1c2
commit
4c2f98ac3d
2 changed files with 92 additions and 57 deletions
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
|
@ -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,7 +442,7 @@ 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))
|
||||||
|
@ -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;
|
||||||
|
@ -613,7 +613,7 @@ static int get_desfire_keyversion(uint8_t curr_key, uint8_t *num_versions) {
|
||||||
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");
|
||||||
|
@ -638,7 +638,7 @@ static int get_desfire_appids(uint8_t *dest, uint8_t *app_ids_len) {
|
||||||
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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -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}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue