set config works auth lrp checks

This commit is contained in:
merlokk 2021-08-17 23:31:42 +03:00
commit e28b6cfe83
2 changed files with 149 additions and 15 deletions

View file

@ -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("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_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_lit0(NULL, "save", "saves channels parameters to defaults if authentication succeeds"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
@ -1973,13 +1973,13 @@ static int CmdHF14ADesAuth(const char *Cmd) {
int securechann = defaultSecureChannel;
uint32_t id = 0x000000;
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) {
CLIParserFree(ctx);
return res;
}
bool save = arg_get_lit(ctx, 12);
bool save = arg_get_lit(ctx, 13);
SetAPDULogging(APDULogging);
CLIParserFree(ctx);
@ -2026,15 +2026,16 @@ static int CmdHF14ADesSetConfiguration(const char *Cmd) {
"02h ATS update.\n"
"03h SAK update\n"
"04h Secure Messaging Configuration.\n"
"05h Capability data. (here change for LRP in the Desfire Light)\n"
"06h DF Name renaming\n"
"08h File renaming\n"
"09h Value file configuration\n"
"05h Capability data. (here change for LRP in the Desfire Light [00000000010000000000])\n"
"06h DF Name renaming (one-time)\n"
"08h File renaming (one-time)\n"
"09h Value file configuration (one-time)\n"
"0Ah Failed authentication counter setting\n"
"0Bh HW configuration\n"
"\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[] = {
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("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, "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("d", "data", "<data HEX>", "Data for parameter (HEX 1..30 bytes)"),
arg_param_end
@ -2060,22 +2062,23 @@ static int CmdHF14ADesSetConfiguration(const char *Cmd) {
DesfireContext dctx;
int securechann = defaultSecureChannel;
uint32_t appid = 0x000000;
int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, &securechann, DCMEncrypted, &appid, NULL);
uint32_t id = 0x000000;
DesfireISOSelectWay selectway = ISW6bAID;
int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, &securechann, DCMEncrypted, &id, &selectway);
if (res) {
CLIParserFree(ctx);
return res;
}
uint32_t paramid = 0;
if (CLIGetUint32Hex(ctx, 12, 0, &paramid, NULL, 1, "Parameter ID must have 1 bytes length")) {
if (CLIGetUint32Hex(ctx, 13, 0, &paramid, NULL, 1, "Parameter ID must have 1 bytes length")) {
CLIParserFree(ctx);
return PM3_EINVARG;
}
uint8_t param[250] = {0};
int paramlen = sizeof(param);
CLIGetHexWithReturn(ctx, 13, param, &paramlen);
CLIGetHexWithReturn(ctx, 14, param, &paramlen);
if (paramlen == 0) {
PrintAndLogEx(ERR, "Parameter must have a data.");
CLIParserFree(ctx);
@ -2091,13 +2094,13 @@ static int CmdHF14ADesSetConfiguration(const char *Cmd) {
CLIParserFree(ctx);
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));
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) {
DropField();
return res;

View file

@ -1373,6 +1373,134 @@ static int DesfireAuthenticateISO(DesfireContext *dctx, DesfireSecureChannel sec
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) {
if (dctx->kdfAlgo == MFDES_KDF_ALGO_AN10922) {
MifareKdfAn10922(dctx, DCOMasterKey, dctx->kdfInput, dctx->kdfInputLen);
@ -1399,6 +1527,9 @@ int DesfireAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel
if (secureChannel == DACEV2)
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;
}