mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-22 22:33:48 -07:00
set config works auth lrp checks
This commit is contained in:
parent
b2022b1721
commit
e28b6cfe83
2 changed files with 149 additions and 15 deletions
|
@ -1960,8 +1960,8 @@ static int CmdHF14ADesAuth(const char *Cmd) {
|
||||||
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/lrp>", "Secure channel: d40/ev1/ev2/lrp"),
|
arg_str0("s", "schann", "<d40/ev1/ev2/lrp>", "Secure channel: d40/ev1/ev2/lrp"),
|
||||||
arg_str0(NULL, "aid", "<app id hex>", "Application ID of application for some parameters (3 hex bytes, big endian)"),
|
arg_str0(NULL, "aid", "<app id hex>", "Application ID of application for some parameters (3 hex bytes, big endian)"),
|
||||||
arg_lit0(NULL, "save", "saves channels parameters to defaults if authentication succeeds"),
|
|
||||||
arg_str0(NULL, "appisoid", "<isoid hex>", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian). Works only for ISO read commands."),
|
arg_str0(NULL, "appisoid", "<isoid hex>", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian). Works only for ISO read commands."),
|
||||||
|
arg_lit0(NULL, "save", "saves channels parameters to defaults if authentication succeeds"),
|
||||||
arg_param_end
|
arg_param_end
|
||||||
};
|
};
|
||||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||||
|
@ -1973,13 +1973,13 @@ static int CmdHF14ADesAuth(const char *Cmd) {
|
||||||
int securechann = defaultSecureChannel;
|
int securechann = defaultSecureChannel;
|
||||||
uint32_t id = 0x000000;
|
uint32_t id = 0x000000;
|
||||||
DesfireISOSelectWay selectway = ISW6bAID;
|
DesfireISOSelectWay selectway = ISW6bAID;
|
||||||
int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, &securechann, DCMPlain, &id, &selectway);
|
int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, &securechann, DCMPlain, &id, &selectway);
|
||||||
if (res) {
|
if (res) {
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool save = arg_get_lit(ctx, 12);
|
bool save = arg_get_lit(ctx, 13);
|
||||||
|
|
||||||
SetAPDULogging(APDULogging);
|
SetAPDULogging(APDULogging);
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
|
@ -2026,15 +2026,16 @@ static int CmdHF14ADesSetConfiguration(const char *Cmd) {
|
||||||
"02h ATS update.\n"
|
"02h ATS update.\n"
|
||||||
"03h SAK update\n"
|
"03h SAK update\n"
|
||||||
"04h Secure Messaging Configuration.\n"
|
"04h Secure Messaging Configuration.\n"
|
||||||
"05h Capability data. (here change for LRP in the Desfire Light)\n"
|
"05h Capability data. (here change for LRP in the Desfire Light [00000000010000000000])\n"
|
||||||
"06h DF Name renaming\n"
|
"06h DF Name renaming (one-time)\n"
|
||||||
"08h File renaming\n"
|
"08h File renaming (one-time)\n"
|
||||||
"09h Value file configuration\n"
|
"09h Value file configuration (one-time)\n"
|
||||||
"0Ah Failed authentication counter setting\n"
|
"0Ah Failed authentication counter setting\n"
|
||||||
"0Bh HW configuration\n"
|
"0Bh HW configuration\n"
|
||||||
"\n"
|
"\n"
|
||||||
"hf mfdes setconfig --param 03 --data 0428 -> set SAK\n"
|
"hf mfdes setconfig --param 03 --data 0428 -> set SAK\n"
|
||||||
"hf mfdes setconfig --param 02 --data 0875778102637264 -> set ATS (first byte - length)");
|
"hf mfdes setconfig --param 02 --data 0875778102637264 -> set ATS (first byte - length)\n"
|
||||||
|
"hf mfdes setconfig --appisoid 01df -t aes -s ev2 --param 05 --data 00000000020000000000 -> set LRP mode enable for Desfire Light");
|
||||||
|
|
||||||
void *argtable[] = {
|
void *argtable[] = {
|
||||||
arg_param_begin,
|
arg_param_begin,
|
||||||
|
@ -2049,6 +2050,7 @@ static int CmdHF14ADesSetConfiguration(const char *Cmd) {
|
||||||
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/lrp>", "Secure channel: d40/ev1/ev2/lrp"),
|
arg_str0("s", "schann", "<d40/ev1/ev2/lrp>", "Secure channel: d40/ev1/ev2/lrp"),
|
||||||
arg_str0(NULL, "aid", "<app id hex>", "Application ID of application for some parameters (3 hex bytes, big endian)"),
|
arg_str0(NULL, "aid", "<app id hex>", "Application ID of application for some parameters (3 hex bytes, big endian)"),
|
||||||
|
arg_str0(NULL, "appisoid", "<isoid hex>", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian). Works only for ISO read commands."),
|
||||||
arg_str0("p", "param", "<HEX 1 byte>", "Parameter id (HEX 1 byte)"),
|
arg_str0("p", "param", "<HEX 1 byte>", "Parameter id (HEX 1 byte)"),
|
||||||
arg_str0("d", "data", "<data HEX>", "Data for parameter (HEX 1..30 bytes)"),
|
arg_str0("d", "data", "<data HEX>", "Data for parameter (HEX 1..30 bytes)"),
|
||||||
arg_param_end
|
arg_param_end
|
||||||
|
@ -2060,22 +2062,23 @@ static int CmdHF14ADesSetConfiguration(const char *Cmd) {
|
||||||
|
|
||||||
DesfireContext dctx;
|
DesfireContext dctx;
|
||||||
int securechann = defaultSecureChannel;
|
int securechann = defaultSecureChannel;
|
||||||
uint32_t appid = 0x000000;
|
uint32_t id = 0x000000;
|
||||||
int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, &securechann, DCMEncrypted, &appid, NULL);
|
DesfireISOSelectWay selectway = ISW6bAID;
|
||||||
|
int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, &securechann, DCMEncrypted, &id, &selectway);
|
||||||
if (res) {
|
if (res) {
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t paramid = 0;
|
uint32_t paramid = 0;
|
||||||
if (CLIGetUint32Hex(ctx, 12, 0, ¶mid, NULL, 1, "Parameter ID must have 1 bytes length")) {
|
if (CLIGetUint32Hex(ctx, 13, 0, ¶mid, NULL, 1, "Parameter ID must have 1 bytes length")) {
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t param[250] = {0};
|
uint8_t param[250] = {0};
|
||||||
int paramlen = sizeof(param);
|
int paramlen = sizeof(param);
|
||||||
CLIGetHexWithReturn(ctx, 13, param, ¶mlen);
|
CLIGetHexWithReturn(ctx, 14, param, ¶mlen);
|
||||||
if (paramlen == 0) {
|
if (paramlen == 0) {
|
||||||
PrintAndLogEx(ERR, "Parameter must have a data.");
|
PrintAndLogEx(ERR, "Parameter must have a data.");
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
|
@ -2091,13 +2094,13 @@ static int CmdHF14ADesSetConfiguration(const char *Cmd) {
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
if (appid == 0x000000)
|
if (DesfireMFSelected(selectway, id))
|
||||||
PrintAndLogEx(INFO, _CYAN_("PICC") " param ID: 0x%02x param[%d]: %s", paramid, paramlen, sprint_hex(param, paramlen));
|
PrintAndLogEx(INFO, _CYAN_("PICC") " param ID: 0x%02x param[%d]: %s", paramid, paramlen, sprint_hex(param, paramlen));
|
||||||
else
|
else
|
||||||
PrintAndLogEx(INFO, _CYAN_("Application %06x") " param ID: 0x%02x param[%d]: %s", appid, paramid, paramlen, sprint_hex(param, paramlen));
|
PrintAndLogEx(INFO, _CYAN_("%s %06x") " param ID: 0x%02x param[%d]: %s", DesfireSelectWayToStr(selectway), id, paramid, paramlen, sprint_hex(param, paramlen));
|
||||||
}
|
}
|
||||||
|
|
||||||
res = DesfireSelectAndAuthenticate(&dctx, securechann, appid, verbose);
|
res = DesfireSelectAndAuthenticateW(&dctx, securechann, selectway, id, false, 0, false, verbose);
|
||||||
if (res != PM3_SUCCESS) {
|
if (res != PM3_SUCCESS) {
|
||||||
DropField();
|
DropField();
|
||||||
return res;
|
return res;
|
||||||
|
|
|
@ -1373,6 +1373,134 @@ static int DesfireAuthenticateISO(DesfireContext *dctx, DesfireSecureChannel sec
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int DesfireAuthenticateLRP(DesfireContext *dctx, DesfireSecureChannel secureChannel, bool firstauth, bool verbose) {
|
||||||
|
// Crypt constants
|
||||||
|
uint8_t IV[16] = {0};
|
||||||
|
uint8_t RndA[CRYPTO_AES_BLOCK_SIZE] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16};
|
||||||
|
uint8_t RndB[CRYPTO_AES_BLOCK_SIZE] = {0};
|
||||||
|
uint8_t encRndB[CRYPTO_AES_BLOCK_SIZE] = {0};
|
||||||
|
uint8_t rotRndA[CRYPTO_AES_BLOCK_SIZE] = {0}; //RndA'
|
||||||
|
uint8_t rotRndB[CRYPTO_AES_BLOCK_SIZE] = {0}; //RndB'
|
||||||
|
uint8_t both[CRYPTO_AES_BLOCK_SIZE * 2 + 1] = {0}; // ek/dk_keyNo(RndA+RndB')
|
||||||
|
|
||||||
|
uint8_t subcommand = firstauth ? MFDES_AUTHENTICATE_EV2F : MFDES_AUTHENTICATE_EV2NF;
|
||||||
|
uint8_t *key = dctx->key;
|
||||||
|
|
||||||
|
size_t recv_len = 0;
|
||||||
|
uint8_t respcode = 0;
|
||||||
|
uint8_t recv_data[256] = {0};
|
||||||
|
|
||||||
|
if (verbose)
|
||||||
|
PrintAndLogEx(INFO, _CYAN_("Auth %s:") " cmd: 0x%02x keynum: 0x%02x key: %s", (firstauth) ? "first" : "non-first", subcommand, dctx->keyNum, sprint_hex(key, 16));
|
||||||
|
|
||||||
|
// Let's send our auth command
|
||||||
|
uint8_t cdata[] = {dctx->keyNum, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02};
|
||||||
|
int res = DesfireExchangeEx(false, dctx, subcommand, cdata, (firstauth) ? sizeof(cdata) : 1, &respcode, recv_data, &recv_len, false, 0);
|
||||||
|
if (res != PM3_SUCCESS) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!recv_len) {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (respcode != MFDES_ADDITIONAL_FRAME) {
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (recv_len != CRYPTO_AES_BLOCK_SIZE) {
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Part 2
|
||||||
|
memcpy(encRndB, recv_data, 16);
|
||||||
|
|
||||||
|
// Part 3
|
||||||
|
if (aes_decode(IV, key, encRndB, RndB, CRYPTO_AES_BLOCK_SIZE))
|
||||||
|
return 5;
|
||||||
|
|
||||||
|
if (g_debugMode > 1) {
|
||||||
|
PrintAndLogEx(DEBUG, "encRndB: %s", sprint_hex(encRndB, CRYPTO_AES_BLOCK_SIZE));
|
||||||
|
PrintAndLogEx(DEBUG, "RndB: %s", sprint_hex(RndB, CRYPTO_AES_BLOCK_SIZE));
|
||||||
|
}
|
||||||
|
|
||||||
|
// - Rotate RndB by 8 bits
|
||||||
|
memcpy(rotRndB, RndB, CRYPTO_AES_BLOCK_SIZE);
|
||||||
|
rol(rotRndB, CRYPTO_AES_BLOCK_SIZE);
|
||||||
|
|
||||||
|
// - Encrypt our response
|
||||||
|
uint8_t tmp[32] = {0x00};
|
||||||
|
memcpy(tmp, RndA, CRYPTO_AES_BLOCK_SIZE);
|
||||||
|
memcpy(tmp + CRYPTO_AES_BLOCK_SIZE, rotRndB, CRYPTO_AES_BLOCK_SIZE);
|
||||||
|
if (g_debugMode > 1) {
|
||||||
|
PrintAndLogEx(DEBUG, "rotRndB: %s", sprint_hex(rotRndB, CRYPTO_AES_BLOCK_SIZE));
|
||||||
|
PrintAndLogEx(DEBUG, "Both: %s", sprint_hex(tmp, CRYPTO_AES_BLOCK_SIZE * 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aes_encode(IV, key, tmp, both, CRYPTO_AES_BLOCK_SIZE * 2))
|
||||||
|
return 6;
|
||||||
|
if (g_debugMode > 1) {
|
||||||
|
PrintAndLogEx(DEBUG, "EncBoth: %s", sprint_hex(both, CRYPTO_AES_BLOCK_SIZE * 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
res = DesfireExchangeEx(false, dctx, MFDES_ADDITIONAL_FRAME, both, CRYPTO_AES_BLOCK_SIZE * 2, &respcode, recv_data, &recv_len, false, 0);
|
||||||
|
if (res != PM3_SUCCESS) {
|
||||||
|
return 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!recv_len) {
|
||||||
|
return 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (respcode != MFDES_S_OPERATION_OK) {
|
||||||
|
return 9;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Part 4
|
||||||
|
uint8_t data[32] = {0};
|
||||||
|
|
||||||
|
if (aes_decode(IV, key, recv_data, data, recv_len))
|
||||||
|
return 10;
|
||||||
|
|
||||||
|
// rotate rndA to check
|
||||||
|
memcpy(rotRndA, RndA, CRYPTO_AES_BLOCK_SIZE);
|
||||||
|
rol(rotRndA, CRYPTO_AES_BLOCK_SIZE);
|
||||||
|
|
||||||
|
uint8_t *recRndA = (firstauth) ? &data[4] : data;
|
||||||
|
|
||||||
|
if (memcmp(rotRndA, recRndA, CRYPTO_AES_BLOCK_SIZE) != 0) {
|
||||||
|
if (g_debugMode > 1) {
|
||||||
|
PrintAndLogEx(DEBUG, "Expected_RndA' : %s", sprint_hex(rotRndA, CRYPTO_AES_BLOCK_SIZE));
|
||||||
|
PrintAndLogEx(DEBUG, "Generated_RndA' : %s", sprint_hex(recRndA, CRYPTO_AES_BLOCK_SIZE));
|
||||||
|
}
|
||||||
|
return 11;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (firstauth) {
|
||||||
|
dctx->cmdCntr = 0;
|
||||||
|
memcpy(dctx->TI, data, 4);
|
||||||
|
}
|
||||||
|
DesfireClearIV(dctx);
|
||||||
|
DesfireGenSessionKeyEV2(dctx->key, RndA, RndB, true, dctx->sessionKeyEnc);
|
||||||
|
DesfireGenSessionKeyEV2(dctx->key, RndA, RndB, false, dctx->sessionKeyMAC);
|
||||||
|
dctx->secureChannel = secureChannel;
|
||||||
|
|
||||||
|
if (verbose) {
|
||||||
|
if (firstauth) {
|
||||||
|
PrintAndLogEx(INFO, "TI : %s", sprint_hex(data, 4));
|
||||||
|
PrintAndLogEx(INFO, "pic : %s", sprint_hex(&data[20], 6));
|
||||||
|
PrintAndLogEx(INFO, "pcd : %s", sprint_hex(&data[26], 6));
|
||||||
|
} else {
|
||||||
|
PrintAndLogEx(INFO, "TI : %s", sprint_hex(dctx->TI, 4));
|
||||||
|
}
|
||||||
|
PrintAndLogEx(INFO, "session key ENC: %s", sprint_hex(dctx->sessionKeyEnc, 16));
|
||||||
|
PrintAndLogEx(INFO, "session key MAC: %s", sprint_hex(dctx->sessionKeyMAC, 16));
|
||||||
|
}
|
||||||
|
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int DesfireAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel, bool verbose) {
|
int DesfireAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel, bool verbose) {
|
||||||
if (dctx->kdfAlgo == MFDES_KDF_ALGO_AN10922) {
|
if (dctx->kdfAlgo == MFDES_KDF_ALGO_AN10922) {
|
||||||
MifareKdfAn10922(dctx, DCOMasterKey, dctx->kdfInput, dctx->kdfInputLen);
|
MifareKdfAn10922(dctx, DCOMasterKey, dctx->kdfInput, dctx->kdfInputLen);
|
||||||
|
@ -1399,6 +1527,9 @@ int DesfireAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel
|
||||||
if (secureChannel == DACEV2)
|
if (secureChannel == DACEV2)
|
||||||
return DesfireAuthenticateEV2(dctx, secureChannel, (DesfireIsAuthenticated(dctx) == false), verbose); // non first auth if there is a working secure channel
|
return DesfireAuthenticateEV2(dctx, secureChannel, (DesfireIsAuthenticated(dctx) == false), verbose); // non first auth if there is a working secure channel
|
||||||
|
|
||||||
|
if (secureChannel == DACLRP)
|
||||||
|
return DesfireAuthenticateLRP(dctx, secureChannel, (DesfireIsAuthenticated(dctx) == false), verbose);
|
||||||
|
|
||||||
return 100;
|
return 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue