diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 96ba18729..73ef066af 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -1464,6 +1464,7 @@ static void PacketReceived(PacketCommandNG *packet) { iso14443a_antifuzz(payload->flag); break; } + // EPA related case CMD_HF_EPA_COLLECT_NONCE: { EPA_PACE_Collect_Nonce(packet); break; @@ -1472,6 +1473,11 @@ static void PacketReceived(PacketCommandNG *packet) { EPA_PACE_Replay(packet); break; } + case CMD_HF_EPA_PACE_SIMULATE: { + EPA_PACE_Simulate(packet); + break; + } + case CMD_HF_MIFARE_READER: { struct p { uint8_t first_run; diff --git a/armsrc/epa.c b/armsrc/epa.c index 7206e5fd2..9ec396031 100644 --- a/armsrc/epa.c +++ b/armsrc/epa.c @@ -592,3 +592,44 @@ int EPA_Setup(void) { Dbprintf("No card found"); return 1; } + +void EPA_PACE_Simulate(PacketCommandNG *c) { + + //---------Initializing--------- + + // Get password from arguments + unsigned char pwd[6]; + memcpy(pwd, c->data.asBytes, 6); + + // Set up communication with the card + int res = EPA_Setup(); + if (res != 0){ + EPA_PACE_Collect_Nonce_Abort(CMD_HF_EPA_PACE_SIMULATE, 1, res); + return; + } + + // Read EF.CardAccess + uint8_t card_access[210] = {0}; + int card_access_length = EPA_Read_CardAccess(card_access, 210); + + // The response has to be at least this big to hold the OID + if (card_access_length < 18) { + EPA_PACE_Collect_Nonce_Abort(CMD_HF_EPA_PACE_SIMULATE, 2, card_access_length); + return; + } + + // PACEInfo of the card + pace_version_info_t pace_version_info; + + // Search for the PACE OID + res = EPA_Parse_CardAccess(card_access, card_access_length, &pace_version_info); + + if (res != 0 || pace_version_info.version == 0) { + EPA_PACE_Collect_Nonce_Abort(CMD_HF_EPA_PACE_SIMULATE, 3, res); + return; + } + + Dbprintf("Standardized Domain Parameter: %i", pace_version_info.parameter_id); + DbpString(""); + DbpString("finished"); +} \ No newline at end of file diff --git a/armsrc/epa.h b/armsrc/epa.h index d3ed7b75e..72524f836 100644 --- a/armsrc/epa.h +++ b/armsrc/epa.h @@ -32,9 +32,7 @@ typedef struct { // general functions void EPA_Finish(void); -size_t EPA_Parse_CardAccess(uint8_t *data, - size_t length, - pace_version_info_t *pace_info); +size_t EPA_Parse_CardAccess(uint8_t *data, size_t length, pace_version_info_t *pace_info); int EPA_Read_CardAccess(uint8_t *buffer, size_t max_length); int EPA_Setup(void); @@ -44,5 +42,6 @@ int EPA_PACE_Get_Nonce(uint8_t requested_length, uint8_t *nonce); void EPA_PACE_Collect_Nonce(PacketCommandNG *c); void EPA_PACE_Replay(PacketCommandNG *c); +void EPA_PACE_Simulate(PacketCommandNG *c); #endif /* __EPA_H */ diff --git a/client/src/cmdhfepa.c b/client/src/cmdhfepa.c index c676cc2f5..c79bc5ae1 100644 --- a/client/src/cmdhfepa.c +++ b/client/src/cmdhfepa.c @@ -103,9 +103,10 @@ static int CmdHFEPACollectPACENonces(const char *Cmd) { // perform the PACE protocol by replaying APDUs static int CmdHFEPAPACEReplay(const char *Cmd) { CLIParserContext *ctx; - CLIParserInit(&ctx, "hf epa preplay", + CLIParserInit(&ctx, "hf epa replay", "Perform PACE protocol by replaying given APDUs", - "hf epa preplay --mse 0022C1A4 --get 1068000000 --map 1086000002 --pka 1234ABCDEF --ma 1A2B3C4D"); + "hf epa replay --mse 0022C1A4 --get 1068000000 --map 1086000002 --pka 1234ABCDEF --ma 1A2B3C4D" + ); void *argtable[] = { arg_param_begin, @@ -207,10 +208,72 @@ static int CmdHFEPAPACEReplay(const char *Cmd) { return PM3_SUCCESS; } +// perform the PACE protocol by replaying APDUs +static int CmdHFEPAPACESimulate(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf epa sim", + "Simulate PACE protocol with given password pwd of type pty.\n" + "The crypto is performed on pc or proxmark", + "hf epa sim --pwd 112233445566\n" + "hf epa sim --pc --pty 1 --pwd 112233445566" + ); + + void *argtable[] = { + arg_param_begin, + arg_lit1(NULL, "pc", "perform crypto on PC"), + arg_str1(NULL, "pty", "", "type of password"), + arg_str1("p", "pwd", "", "password"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + +// bool use_pc = arg_get_lit(ctx, 1); +// uint8_t pwd_type = 0; + + int plen = 0; + uint8_t pwd[6] = {0}; + CLIGetHexWithReturn(ctx, 3, pwd, &plen); + + CLIParserFree(ctx); + + PrintAndLogEx(INFO, "Starting PACE simulation..."); + + + clearCommandBuffer(); + SendCommandMIX(CMD_HF_EPA_PACE_SIMULATE, 0, 0, 0, pwd, plen); + + PacketResponseNG resp; + WaitForResponse(CMD_ACK, &resp); + + uint32_t *data = resp.data.asDwords; + + if (resp.oldarg[0] != 0) { + PrintAndLogEx(INFO, "\nPACE failed in step %u!", (uint32_t)resp.oldarg[0]); + PrintAndLogEx(INFO, "MSE Set AT: %u us", data[0]); + PrintAndLogEx(INFO, "GA Get Nonce: %u us", data[1]); + PrintAndLogEx(INFO, "GA Map Nonce: %u us", data[2]); + PrintAndLogEx(INFO, "GA Perform Key Agreement: %u us", data[3]); + PrintAndLogEx(INFO, "GA Mutual Authenticate: %u us", data[4]); + PrintAndLogEx(INFO, "----------------"); + } else { + PrintAndLogEx(INFO, "PACE successful!"); + PrintAndLogEx(INFO, "MSE Set AT: %u us", data[0]); + PrintAndLogEx(INFO, "GA Get Nonce: %u us", data[1]); + PrintAndLogEx(INFO, "GA Map Nonce: %u us", data[2]); + PrintAndLogEx(INFO, "GA Perform Key Agreement: %u us", data[3]); + PrintAndLogEx(INFO, "GA Mutual Authenticate: %u us", data[4]); + PrintAndLogEx(INFO, "----------------"); + } + + return PM3_SUCCESS; +} + + static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "This help"}, {"cnonces", CmdHFEPACollectPACENonces, IfPm3Iso14443, "Acquire encrypted PACE nonces of specific size"}, - {"preplay", CmdHFEPAPACEReplay, IfPm3Iso14443, "Perform PACE protocol by replaying given APDUs"}, + {"replay", CmdHFEPAPACEReplay, IfPm3Iso14443, "Perform PACE protocol by replaying given APDUs"}, + {"sim", CmdHFEPAPACESimulate, IfPm3Iso14443, "Simulate PACE protocol"}, {NULL, NULL, NULL, NULL} }; diff --git a/include/pm3_cmd.h b/include/pm3_cmd.h index 7c7eb6ed6..5a49871e1 100644 --- a/include/pm3_cmd.h +++ b/include/pm3_cmd.h @@ -556,6 +556,7 @@ typedef struct { #define CMD_HF_EPA_COLLECT_NONCE 0x038A #define CMD_HF_EPA_REPLAY 0x038B +#define CMD_HF_EPA_PACE_SIMULATE 0x039C #define CMD_HF_LEGIC_INFO 0x03BC #define CMD_HF_LEGIC_ESET 0x03BD