detect lrp authentication

This commit is contained in:
merlokk 2021-08-22 23:12:16 +03:00
commit d716971430
3 changed files with 50 additions and 53 deletions

View file

@ -1294,7 +1294,7 @@ static int CmdHF14ADesList(const char *Cmd) {
return CmdTraceListAlias(Cmd, "hf mfdes", "des");
}
static int DesfireAuthCheck(DesfireContext_t *dctx, uint32_t appid, DesfireSecureChannel secureChannel, uint8_t *key) {
static int DesfireAuthCheck(DesfireContext_t *dctx, DesfireISOSelectWay way, uint32_t appID, DesfireSecureChannel secureChannel, uint8_t *key) {
DesfireSetKeyNoClear(dctx, dctx->keyNum, dctx->keyType, key);
int res = DesfireAuthenticate(dctx, secureChannel, false);
@ -1303,7 +1303,7 @@ static int DesfireAuthCheck(DesfireContext_t *dctx, uint32_t appid, DesfireSecur
return PM3_SUCCESS;
} else if (res < 7) {
DropField();
res = DesfireSelectAIDHex(dctx, appid, false, 0);
res = DesfireSelect(dctx, way, appID, NULL);
if (res != PM3_SUCCESS) {
return -10;
}
@ -1335,6 +1335,7 @@ static int CmdHF14aDesDetect(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 (3 hex bytes, big endian)"),
arg_str0(NULL, "appisoid", "<isoid hex>", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian)."),
arg_str0(NULL, "dict", "<file>", "File with keys dictionary"),
arg_lit0(NULL, "save", "save found key and parameters to defaults"),
arg_param_end
@ -1346,8 +1347,9 @@ static int CmdHF14aDesDetect(const char *Cmd) {
DesfireContext_t dctx;
int securechann = defaultSecureChannel;
uint32_t appid = 0x000000;
int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, &securechann, DCMMACed, &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, DCMMACed, &id, &selectway);
if (res) {
CLIParserFree(ctx);
return res;
@ -1355,22 +1357,22 @@ static int CmdHF14aDesDetect(const char *Cmd) {
uint8_t dict_filename[FILE_PATH_SIZE + 2] = {0};
int dict_filenamelen = 0;
if (CLIParamStrToBuf(arg_get_str(ctx, 12), dict_filename, FILE_PATH_SIZE, &dict_filenamelen)) {
if (CLIParamStrToBuf(arg_get_str(ctx, 13), dict_filename, FILE_PATH_SIZE, &dict_filenamelen)) {
PrintAndLogEx(FAILED, "File name too long or invalid.");
CLIParserFree(ctx);
return PM3_EINVARG;
}
bool save = arg_get_lit(ctx, 13);
bool save = arg_get_lit(ctx, 14);
SetAPDULogging(APDULogging);
CLIParserFree(ctx);
// no auth and fill KDF if needs
res = DesfireSelectAndAuthenticateEx(&dctx, securechann, appid, true, verbose);
res = DesfireSelectAndAuthenticateAppW(&dctx, securechann, selectway, id, true, verbose);
if (res != PM3_SUCCESS) {
DropField();
PrintAndLogEx(FAILED, "Select AID 0x%06x " _RED_("failed") ". Result: %d", appid, res);
PrintAndLogEx(FAILED, "Select or authentication %s " _RED_("failed") ". Result [%d] %s", DesfireWayIDStr(selectway, id), res, DesfireAuthErrorToStr(res));
return res;
}
@ -1398,7 +1400,7 @@ static int CmdHF14aDesDetect(const char *Cmd) {
} else {
// if fail - check auth commands
AuthCommandsChk_t authCmdCheck = {0};
DesfireCheckAuthCommands(appid, NULL, 0, &authCmdCheck);
DesfireCheckAuthCommands(selectway, id, NULL, 0, &authCmdCheck);
if (authCmdCheck.checked) {
if (authCmdCheck.auth) {
keytypes[T_DES] = true;
@ -1416,18 +1418,19 @@ static int CmdHF14aDesDetect(const char *Cmd) {
keytypes[T_DES] = true;
}
res = DesfireSelectAIDHex(&dctx, appid, false, 0);
res = DesfireSelectAndAuthenticateAppW(&dctx, securechann, selectway, id, true, verbose);
if (res != PM3_SUCCESS) {
PrintAndLogEx(ERR, "Desfire select " _RED_("error") ".");
DropField();
PrintAndLogEx(FAILED, "Select or authentication %s " _RED_("failed") ". Result [%d] %s", DesfireWayIDStr(selectway, id), res, DesfireAuthErrorToStr(res));
return res;
}
}
if (verbose) {
if (appid == 0)
if (DesfireMFSelected(selectway, id))
PrintAndLogEx(INFO, "Check PICC key num: %d (0x%02x)", dctx.keyNum, dctx.keyNum);
else
PrintAndLogEx(INFO, "Check app: %06x key num: %d (0x%02x)", appid, dctx.keyNum, dctx.keyNum);
PrintAndLogEx(INFO, "Check: %s key num: %d (0x%02x)", DesfireWayIDStr(selectway, id), dctx.keyNum, dctx.keyNum);
PrintAndLogEx(INFO, "keys: DES: %s 2TDEA: %s 3TDEA: %s AES: %s",
keytypes[T_DES] ? _GREEN_("YES") : _RED_("NO"),
keytypes[T_3DES] ? _GREEN_("YES") : _RED_("NO"),
@ -1455,7 +1458,7 @@ static int CmdHF14aDesDetect(const char *Cmd) {
if (ktype == T_3K3DES)
memcpy(&key[16], key, 8);
res = DesfireAuthCheck(&dctx, appid, securechann, key);
res = DesfireAuthCheck(&dctx, selectway, id, securechann, key);
if (res == PM3_SUCCESS) {
found = true;
break; // all the params already in the dctx
@ -1490,7 +1493,7 @@ static int CmdHF14aDesDetect(const char *Cmd) {
break;
for (int i = 0; i < keyListLen; i++) {
res = DesfireAuthCheck(&dctx, appid, securechann, &keyList[i * keylen]);
res = DesfireAuthCheck(&dctx, selectway, id, securechann, &keyList[i * keylen]);
if (res == PM3_SUCCESS) {
found = true;
break; // all the params already in the dctx
@ -1523,10 +1526,10 @@ static int CmdHF14aDesDetect(const char *Cmd) {
}
if (found) {
if (appid == 0)
if (DesfireMFSelected(selectway, id))
PrintAndLogEx(INFO, _GREEN_("Found") " key num: %d (0x%02x)", dctx.keyNum, dctx.keyNum);
else
PrintAndLogEx(INFO, "Found key for app: %06x key num: %d (0x%02x)", appid, dctx.keyNum, dctx.keyNum);
PrintAndLogEx(INFO, "Found key for: %s key num: %d (0x%02x)", DesfireWayIDStr(selectway, id), dctx.keyNum, dctx.keyNum);
PrintAndLogEx(INFO, "key " _GREEN_("%s") " [%d]: " _GREEN_("%s"),
CLIGetOptionListStr(DesfireAlgoOpts, dctx.keyType),

View file

@ -1571,7 +1571,7 @@ int DesfireAuthenticate(DesfireContext_t *dctx, DesfireSecureChannel secureChann
return 100;
}
static bool DesfireCheckAuthCmd(uint32_t appAID, uint8_t keyNum, uint8_t authcmd) {
static bool DesfireCheckAuthCmd(DesfireISOSelectWay way, uint32_t appID, uint8_t keyNum, uint8_t authcmd, bool checklrp) {
size_t recv_len = 0;
uint8_t respcode = 0;
uint8_t recv_data[256] = {0};
@ -1579,44 +1579,35 @@ static bool DesfireCheckAuthCmd(uint32_t appAID, uint8_t keyNum, uint8_t authcmd
DesfireContext_t dctx = {0};
dctx.keyNum = keyNum;
dctx.commMode = DCMPlain;
dctx.cmdSet = DCCNative;
dctx.cmdSet = (checklrp) ? DCCNativeISO : DCCNative;
// if cant select - return false
int res = DesfireSelectAIDHex(&dctx, appAID, false, 0);
int res = DesfireSelect(&dctx, way, appID, NULL);
if (res != PM3_SUCCESS)
return false;
uint8_t data[] = {keyNum, 0x00};
res = DesfireExchangeEx(false, &dctx, authcmd, data, (authcmd == MFDES_AUTHENTICATE_EV2F) ? 2 : 1, &respcode, recv_data, &recv_len, false, 0);
uint8_t data[] = {keyNum, (checklrp) ? 0x01 : 0x00, 0x02};
uint8_t datalen = (authcmd == MFDES_AUTHENTICATE_EV2F) ? 2 : 1;
if (checklrp)
datalen = 3;
res = DesfireExchangeEx(false, &dctx, authcmd, data, datalen, &respcode, recv_data, &recv_len, false, 0);
DropField();
return (res == PM3_SUCCESS && respcode == 0xaf);
if (checklrp)
return (res == PM3_SUCCESS && respcode == 0xaf && recv_len == 17 && recv_data[0] == 0x01);
else
return (res == PM3_SUCCESS && respcode == 0xaf);
}
static bool DesfireCheckISOAuthCmd(uint32_t appAID, char *dfname, uint8_t keyNum, DesfireCryptoAlgorithm keytype) {
static bool DesfireCheckISOAuthCmd(DesfireISOSelectWay way, uint32_t appID, char *dfname, uint8_t keyNum, DesfireCryptoAlgorithm keytype) {
DesfireContext_t dctx = {0};
dctx.keyNum = keyNum;
dctx.commMode = DCMPlain;
dctx.cmdSet = DCCISO;
bool app_level = (appAID != 0x000000);
int res = 0;
if (dfname == NULL || strnlen(dfname, 16) == 0) {
if (appAID == 0x000000) {
res = DesfireISOSelect(&dctx, ISSMFDFEF, NULL, 0, NULL, NULL);
if (res != PM3_SUCCESS)
return false;
} else {
res = DesfireSelectAIDHex(&dctx, appAID, false, 0);
if (res != PM3_SUCCESS)
return false;
}
} else {
res = DesfireISOSelectDF(&dctx, dfname, NULL, NULL);
if (res != PM3_SUCCESS)
return false;
app_level = true;
}
bool app_level = DesfireMFSelected(way, appID);
int res = DesfireSelect(&dctx, way, appID, dfname);
uint8_t rndlen = DesfireGetRndLenForKey(keytype);
@ -1637,24 +1628,26 @@ static bool DesfireCheckISOAuthCmd(uint32_t appAID, char *dfname, uint8_t keyNum
return (sw == 0x9000 || sw == 0x6982);
}
void DesfireCheckAuthCommands(uint32_t appAID, char *dfname, uint8_t keyNum, AuthCommandsChk_t *authCmdCheck) {
void DesfireCheckAuthCommands(DesfireISOSelectWay way, uint32_t appID, char *dfname, uint8_t keyNum, AuthCommandsChk_t *authCmdCheck) {
memset(authCmdCheck, 0, sizeof(AuthCommandsChk_t));
authCmdCheck->auth = DesfireCheckAuthCmd(appAID, keyNum, MFDES_AUTHENTICATE);
authCmdCheck->authISO = DesfireCheckAuthCmd(appAID, keyNum, MFDES_AUTHENTICATE_ISO);
authCmdCheck->authAES = DesfireCheckAuthCmd(appAID, keyNum, MFDES_AUTHENTICATE_AES);
authCmdCheck->authEV2 = DesfireCheckAuthCmd(appAID, keyNum, MFDES_AUTHENTICATE_EV2F);
authCmdCheck->authISONative = DesfireCheckISOAuthCmd(appAID, dfname, keyNum, T_DES);
authCmdCheck->auth = DesfireCheckAuthCmd(way, appID, keyNum, MFDES_AUTHENTICATE, false);
authCmdCheck->authISO = DesfireCheckAuthCmd(way, appID, keyNum, MFDES_AUTHENTICATE_ISO, false);
authCmdCheck->authAES = DesfireCheckAuthCmd(way, appID, keyNum, MFDES_AUTHENTICATE_AES, false);
authCmdCheck->authEV2 = DesfireCheckAuthCmd(way, appID, keyNum, MFDES_AUTHENTICATE_EV2F, false);
authCmdCheck->authISONative = DesfireCheckISOAuthCmd(way, appID, dfname, keyNum, T_DES);
authCmdCheck->authLRP = DesfireCheckAuthCmd(way, appID, keyNum, MFDES_AUTHENTICATE_EV2F, true);
authCmdCheck->checked = true;
}
void DesfireCheckAuthCommandsPrint(AuthCommandsChk_t *authCmdCheck) {
PrintAndLogEx(NORMAL, "auth: %s auth iso: %s auth aes: %s auth ev2: %s auth iso native: %s",
PrintAndLogEx(NORMAL, "auth: %s auth iso: %s auth aes: %s auth ev2: %s auth iso native: %s auth lrp: %s",
authCmdCheck->auth ? _GREEN_("YES") : _RED_("NO"),
authCmdCheck->authISO ? _GREEN_("YES") : _RED_("NO"),
authCmdCheck->authAES ? _GREEN_("YES") : _RED_("NO"),
authCmdCheck->authEV2 ? _GREEN_("YES") : _RED_("NO"),
authCmdCheck->authISONative ? _GREEN_("YES") : _RED_("NO")
authCmdCheck->authISONative ? _GREEN_("YES") : _RED_("NO"),
authCmdCheck->authLRP ? _GREEN_("YES") : _RED_("NO")
);
}
@ -1688,7 +1681,7 @@ int DesfireFillPICCInfo(DesfireContext_t *dctx, PICCInfo_t *PICCInfo, bool deepm
// field on-off zone
if (deepmode)
DesfireCheckAuthCommands(0x000000, NULL, 0, &PICCInfo->authCmdCheck);
DesfireCheckAuthCommands(ISW6bAID, 0x000000, NULL, 0, &PICCInfo->authCmdCheck);
return PM3_SUCCESS;
}
@ -1770,7 +1763,7 @@ int DesfireFillAppList(DesfireContext_t *dctx, PICCInfo_t *PICCInfo, AppListS ap
// field on-off zone
if (fillAppSettings && PICCInfo->appCount > 0 && deepmode) {
for (int i = 0; i < PICCInfo->appCount; i++) {
DesfireCheckAuthCommands(appList[i].appNum, appList[i].appDFName, 0, &appList[i].authCmdCheck);
DesfireCheckAuthCommands(ISW6bAID, appList[i].appNum, appList[i].appDFName, 0, &appList[i].authCmdCheck);
}
}

View file

@ -98,6 +98,7 @@ typedef struct {
bool authAES;
bool authEV2;
bool authISONative;
bool authLRP;
} AuthCommandsChk_t;
typedef struct {
@ -183,7 +184,7 @@ int DesfireSelectAndAuthenticateW(DesfireContext_t *dctx, DesfireSecureChannel s
int DesfireSelectAndAuthenticateAppW(DesfireContext_t *dctx, DesfireSecureChannel secureChannel, DesfireISOSelectWay way, uint32_t id, bool noauth, bool verbose);
int DesfireSelectAndAuthenticateISO(DesfireContext_t *dctx, DesfireSecureChannel secureChannel, bool useaid, uint32_t aid, uint16_t isoappid, bool selectfile, uint16_t isofileid, bool noauth, bool verbose);
int DesfireAuthenticate(DesfireContext_t *dctx, DesfireSecureChannel secureChannel, bool verbose);
void DesfireCheckAuthCommands(uint32_t appAID, char *dfname, uint8_t keyNum, AuthCommandsChk_t *authCmdCheck);
void DesfireCheckAuthCommands(DesfireISOSelectWay way, uint32_t appID, char *dfname, uint8_t keyNum, AuthCommandsChk_t *authCmdCheck);
void DesfireCheckAuthCommandsPrint(AuthCommandsChk_t *authCmdCheck);
int DesfireFormatPICC(DesfireContext_t *dctx);