From 75d0b0b06f11cb66581fb0c92f79bcca04cff952 Mon Sep 17 00:00:00 2001 From: Chris Date: Tue, 1 Jan 2019 10:53:41 +0100 Subject: [PATCH] CHG: 'emv roca' - added selftest and textual layouts' DEL: removed unused old emv files --- client/cmdhfemv.c | 351 ----------------------------------- client/cmdhfemv.h | 45 ----- client/emv/cmdemv.c | 9 +- client/emv/emv_roca.c | 30 +-- client/emv/emv_roca.h | 2 +- client/emv/test/cryptotest.c | 7 +- 6 files changed, 22 insertions(+), 422 deletions(-) delete mode 100644 client/cmdhfemv.c delete mode 100644 client/cmdhfemv.h diff --git a/client/cmdhfemv.c b/client/cmdhfemv.c deleted file mode 100644 index ab9396a14..000000000 --- a/client/cmdhfemv.c +++ /dev/null @@ -1,351 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (C) 2014 Peter Fillmore -// 2017 iceman -// -// This code is licensed to you under the terms of the GNU GPL, version 2 or, -// at your option, any later version. See the LICENSE.txt file for the text of -// the license. -//----------------------------------------------------------------------------- -// High frequency EMV commands -//----------------------------------------------------------------------------- -#include "cmdhfemv.h" - -static int CmdHelp(const char *Cmd); - -int usage_hf_emv_test(void){ - PrintAndLogEx(NORMAL, "EMV test "); - PrintAndLogEx(NORMAL, "Usage: hf emv test [h]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h : this help"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf emv test"); - return 0; -} -int usage_hf_emv_readrecord(void){ - PrintAndLogEx(NORMAL, "Read a EMV record "); - PrintAndLogEx(NORMAL, "Usage: hf emv readrecord [h] "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h : this help"); - PrintAndLogEx(NORMAL, " : number of records"); - PrintAndLogEx(NORMAL, " : number of SFI records"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf emv readrecord 1 1"); - return 0; -} -int usage_hf_emv_clone(void){ - PrintAndLogEx(NORMAL, "Usage: hf emv clone [h] "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h : this help"); - PrintAndLogEx(NORMAL, " : number of records"); - PrintAndLogEx(NORMAL, " : number of SFI records"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf emv clone 10 10"); - return 0; -} -int usage_hf_emv_transaction(void){ - PrintAndLogEx(NORMAL, "Performs EMV reader transaction"); - PrintAndLogEx(NORMAL, "Usage: hf emv trans [h]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h : this help"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf emv trans"); - return 0; -} -int usage_hf_emv_getrnd(void){ - PrintAndLogEx(NORMAL, "retrieve the UN number from a terminal"); - PrintAndLogEx(NORMAL, "Usage: hf emv getrnd [h]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h : this help"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf emv getrnd"); - return 0; -} -int usage_hf_emv_eload(void){ - PrintAndLogEx(NORMAL, "set EMV tags in the device to use in a transaction"); - PrintAndLogEx(NORMAL, "Usage: hf emv eload [h] o "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h : this help"); - PrintAndLogEx(NORMAL, " o : filename w/o '.bin'"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf emv eload o myfile"); - return 0; -} -int usage_hf_emv_dump(void){ - PrintAndLogEx(NORMAL, "Gets EMV contactless tag values."); - PrintAndLogEx(NORMAL, "and saves binary dump into the file `filename.bin` or `cardUID.bin`"); - PrintAndLogEx(NORMAL, "Usage: hf emv dump [h] o "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h : this help"); - PrintAndLogEx(NORMAL, " o : filename w/o '.bin' to dump bytes"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf emv dump"); - PrintAndLogEx(NORMAL, " hf emv dump o myfile"); - return 0; -} -int usage_hf_emv_sim(void){ - PrintAndLogEx(NORMAL, "Simulates a EMV contactless card"); - PrintAndLogEx(NORMAL, "Usage: hf emv sim [h]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h : this help"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf emv sim"); - return 0; -} - -int CmdHfEmvTest(const char *Cmd) { - char cmdp = param_getchar(Cmd, 0); - if ( cmdp == 'h' || cmdp == 'H') return usage_hf_emv_test(); - - UsbCommand c = {CMD_EMV_TEST, {0, 0, 0}}; - clearCommandBuffer(); - SendCommand(&c); - UsbCommand resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { - PrintAndLogEx(WARNING, "Command execute time-out"); - return 1; - } - uint8_t isOK = resp.arg[0] & 0xff; - PrintAndLogEx(NORMAL, "isOk: %02x", isOK); - return 0; -} - -int CmdHfEmvReadRecord(const char *Cmd) { - char cmdp = param_getchar(Cmd, 0); - if ((strlen(Cmd)<3) || cmdp == 'h' || cmdp == 'H') return usage_hf_emv_readrecord(); - - uint8_t record = param_get8(Cmd, 0); - uint8_t sfi = param_getchar(Cmd, 1); - if(record > 32){ - PrintAndLogEx(WARNING, "Record must be less than 32"); - return 1; - } - PrintAndLogEx(NORMAL, "--record no:%02x SFI:%02x ", record, sfi); - - UsbCommand c = {CMD_EMV_READ_RECORD, {record, sfi, 0}}; - clearCommandBuffer(); - SendCommand(&c); - UsbCommand resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { - PrintAndLogEx(WARNING, "Command execute timeout"); - return 1; - } - uint8_t isOK = resp.arg[0] & 0xff; - PrintAndLogEx(NORMAL, "isOk:%02x", isOK); - return 0; -} - -int CmdHfEmvClone(const char *Cmd) { - char cmdp = param_getchar(Cmd, 0); - if ((strlen(Cmd)<3) || cmdp == 'h' || cmdp == 'H') return usage_hf_emv_clone(); - - uint8_t record = param_get8(Cmd, 0); - uint8_t sfi = param_get8(Cmd, 1); - if(record > 32){ - PrintAndLogEx(WARNING, "Record must be less than 32"); - return 1; - } - UsbCommand c = {CMD_EMV_CLONE, {sfi, record, 0}}; - clearCommandBuffer(); - SendCommand(&c); - UsbCommand resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { - PrintAndLogEx(WARNING, "Command execute timeout"); - return 1; - } - uint8_t isOK = resp.arg[0] & 0xff; - PrintAndLogEx(NORMAL, "isOk:%02x", isOK); - return 0; -} - -int CmdHfEmvTrans(const char *Cmd) { - char cmdp = param_getchar(Cmd, 0); - if ( cmdp == 'h' || cmdp == 'H') return usage_hf_emv_transaction(); - - UsbCommand c = {CMD_EMV_TRANSACTION, {0, 0, 0}}; - clearCommandBuffer(); - SendCommand(&c); - UsbCommand resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, 5000)) { - PrintAndLogEx(WARNING, "Command execute time-out"); - return 1; - } - uint8_t isOK = resp.arg[0] & 0xff; - PrintAndLogEx(NORMAL, "isOk: %02x", isOK); - print_hex_break(resp.d.asBytes, 512, 32); - return 0; -} -//retrieve the UN number from a terminal -int CmdHfEmvGetrng(const char *Cmd) { - char cmdp = param_getchar(Cmd, 0); - if ( cmdp == 'h' || cmdp == 'H') return usage_hf_emv_getrnd(); - UsbCommand c = {CMD_EMV_GET_RANDOM_NUM, {0, 0, 0}}; - clearCommandBuffer(); - SendCommand(&c); - return 0; -} -//Load a dumped EMV tag on to emulator memory -int CmdHfEmvELoad(const char *Cmd) { - FILE * f; - char filename[FILE_PATH_SIZE]; - char *fnameptr = filename; - int len; - bool errors = false; - uint8_t cmdp = 0; - - while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch(param_getchar(Cmd, cmdp)) { - case 'h': - case 'H': - return usage_hf_emv_eload(); - case 'o': - case 'O': - len = param_getstr(Cmd, cmdp+1, filename, FILE_PATH_SIZE); - if (!len) - errors = true; - if (len > FILE_PATH_SIZE-5) - len = FILE_PATH_SIZE-5; - sprintf(fnameptr + len,".bin"); - cmdp += 2; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } - } - //Validations - if (errors || cmdp == 0) return usage_hf_emv_eload(); - - // open file - f = fopen(filename,"r"); - if (!f) { - PrintAndLogEx(WARNING, "File %s not found or locked", filename); - return 1; - } - - char line[512]; - char *token; - uint16_t tag; - - UsbCommand c = {CMD_EMV_LOAD_VALUE, {0,0,0}}; - - // transfer to device - while (fgets(line, sizeof (line), f)) { - PrintAndLogEx(NORMAL, "LINE = %s\n", line); - - token = strtok(line, ":"); - tag = (uint16_t)strtol(token, NULL, 0); - token = strtok(NULL,""); - - c.arg[0] = tag; - memcpy(c.d.asBytes, token, strlen(token)); - - clearCommandBuffer(); - SendCommand(&c); - - PrintAndLogEx(NORMAL, "Loaded TAG = %04x\n", tag); - PrintAndLogEx(NORMAL, "Loaded VALUE = %s\n", token); - } - - fclose(f); - PrintAndLogEx(NORMAL, "loaded %s", filename); - //PrintAndLogEx(NORMAL, "\nLoaded %d bytes from file: %s to emulator memory", numofbytes, filename); - return 0; -} - -int CmdHfEmvDump(const char *Cmd){ - - bool errors = false; - uint8_t cmdp = 0; - while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch(param_getchar(Cmd, cmdp)) { - case 'h': - case 'H': - return usage_hf_emv_dump(); - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } - } - //Validations - if (errors) return usage_hf_emv_dump(); - - UsbCommand c = {CMD_EMV_DUMP_CARD, {0, 0, 0}}; - clearCommandBuffer(); - SendCommand(&c); - UsbCommand resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, 3000)) { - PrintAndLogEx(WARNING, "Command execute time-out"); - return 1; - } - return 0; -} - -int CmdHfEmvSim(const char *Cmd) { - - bool errors = false; - uint8_t cmdp = 0; - while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch(param_getchar(Cmd, cmdp)) { - case 'h': - case 'H': - return usage_hf_emv_sim(); - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } - } - //Validations - if (errors) return usage_hf_emv_sim(); - - UsbCommand c = {CMD_EMV_SIM, {0,0,0}}; - clearCommandBuffer(); - SendCommand(&c); - UsbCommand resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { - PrintAndLogEx(WARNING, "Command execute time-out"); - return 1; - } - uint8_t isOK = resp.arg[0] & 0xff; - PrintAndLogEx(NORMAL, "isOk:%02x", isOK); - return 0; -} - -int CmdHfEmvList(const char *Cmd) { - return CmdTraceList("7816"); -} - -static command_t CommandTable[] = { - {"help", CmdHelp, 1, "This help"}, - {"readrecord", CmdHfEmvReadRecord, 0, "EMV Read Record"}, - {"transaction", CmdHfEmvTrans, 0, "Perform EMV Transaction"}, - {"getrng", CmdHfEmvGetrng, 0, "get random number from terminal"}, - {"eload", CmdHfEmvELoad, 0, "load EMV tag into device"}, - {"dump", CmdHfEmvDump, 0, "dump EMV tag values"}, - {"sim", CmdHfEmvSim, 0, "simulate EMV tag"}, - {"clone", CmdHfEmvClone, 0, "clone an EMV tag"}, - {"list", CmdHfEmvList, 0, "[Deprecated] List ISO7816 history"}, - {"test", CmdHfEmvTest, 0, "Test Function"}, - {NULL, NULL, 0, NULL} -}; - -int CmdHFEmv(const char *Cmd) { - clearCommandBuffer(); - CmdsParse(CommandTable, Cmd); - return 0; -} - -int CmdHelp(const char *Cmd) { - CmdsHelp(CommandTable); - return 0; -} \ No newline at end of file diff --git a/client/cmdhfemv.h b/client/cmdhfemv.h deleted file mode 100644 index 0b68a455c..000000000 --- a/client/cmdhfemv.h +++ /dev/null @@ -1,45 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (C) 2014 Peter Fillmore -// 2017 iceman -// -// This code is licensed to you under the terms of the GNU GPL, version 2 or, -// at your option, any later version. See the LICENSE.txt file for the text of -// the license. -//----------------------------------------------------------------------------- -// High frequency EMV commands -//----------------------------------------------------------------------------- - -#ifndef CMDHFEMV_H__ -#define CMDHFEMV_H__ - -#include -#include -#include "proxmark3.h" -#include "ui.h" -#include "cmdparser.h" -#include "cmdmain.h" -#include "util.h" -#include "cmdhf.h" // "hf list" - -int CmdHFEmv(const char *Cmd); - -int CmdHfEmvTest(const char *Cmd); -int CmdHfEmvReadRecord(const char *Cmd); -int CmdHfEmvClone(const char *Cmd); -int CmdHfEmvTrans(const char *Cmd); -int CmdHfEmvGetrng(const char *Cmd); -int CmdHfEmvELoad(const char *Cmd); -int CmdHfEmvDump(const char *Cmd); -int CmdHfEmvSim(const char *Cmd); -int CmdHfEmvList(const char *Cmd); - -int usage_hf_emv_test(void); -int usage_hf_emv_readrecord(void); -int usage_hf_emv_clone(void); -int usage_hf_emv_transaction(void); -int usage_hf_emv_getrnd(void); -int usage_hf_emv_eload(void); -int usage_hf_emv_dump(void); -int usage_hf_emv_sim(void); - -#endif diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index a443f6aad..396918d7e 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -1456,7 +1456,6 @@ int CmdEMVScan(const char *cmd) { return 0; } - int CmdEMVList(const char *Cmd) { return CmdTraceList("7816"); } @@ -1476,10 +1475,13 @@ int CmdEMVRoca(const char *cmd) { CLIParserInit("emv roca", "Tries to extract public keys and run the ROCA test against them.\n", "Usage:\n" - "\temv roca -w -> select CONTACT card and run test\n\temv roca -> select CONTACTLESS card and run test\n"); + "\temv roca -w -> select --CONTACT-- card and run test\n" + "\temv roca -> select --CONTACTLESS-- card and run test\n" + ); void* argtable[] = { arg_param_begin, + arg_lit0("tT", "selftest", "self test"), arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."), arg_param_end }; @@ -1487,6 +1489,9 @@ int CmdEMVRoca(const char *cmd) { EMVCommandChannel channel = ECC_CONTACTLESS; if (arg_get_lit(1)) + return roca_self_test(); + + if (arg_get_lit(2)) channel = ECC_CONTACT; // select card diff --git a/client/emv/emv_roca.c b/client/emv/emv_roca.c index a6738ae2f..6f90f11b5 100644 --- a/client/emv/emv_roca.c +++ b/client/emv/emv_roca.c @@ -138,11 +138,10 @@ cleanup: return ret; } -int roca_self_test( int verbose ) { +int roca_self_test(void) { int ret = 0; - if( verbose != 0 ) - printf( "\nROCA check vulnerability tests\n" ); + PrintAndLogEx(INFO, "ROCA check vulnerability tests" ); // positive uint8_t keyp[] = "\x94\x4e\x13\x20\x8a\x28\x0c\x37\xef\xc3\x1c\x31\x14\x48\x5e\x59"\ @@ -150,16 +149,13 @@ int roca_self_test( int verbose ) { "\x27\x83\x30\xd3\xf4\x71\xa2\x53\x8f\xa6\x67\x80\x2e\xd2\xa3\xc4"\ "\x4a\x8b\x7d\xea\x82\x6e\x88\x8d\x0a\xa3\x41\xfd\x66\x4f\x7f\xa7"; - if( verbose != 0 ) - printf( " ROCA positive test: " ); if (emv_rocacheck(keyp, 64, false)) { - if( verbose != 0 ) - printf( "passed\n" ); - } else { - ret = 1; - if( verbose != 0 ) - printf( "failed\n" ); + PrintAndLogEx(SUCCESS, "Weak modulus [ %s]", _GREEN_(PASS) ); + } + else { + ret++; + PrintAndLogEx(FAILED, "Weak modulus [ %s]", _RED_(FAIL) ); } // negative @@ -168,18 +164,12 @@ int roca_self_test( int verbose ) { "\x27\x83\x30\xd3\xf4\x71\xa2\x53\x8f\xa6\x67\x80\x2e\xd2\xa3\xc4"\ "\x4a\x8b\x7d\xea\x82\x6e\x88\x8d\x0a\xa3\x41\xfd\x66\x4f\x7f\xa7"; - if( verbose != 0 ) - printf( " ROCA negative test: " ); - if (emv_rocacheck(keyn, 64, false)) { - ret = 1; - if( verbose != 0 ) - printf( "failed\n" ); + ret++; + PrintAndLogEx(FAILED, "Strong modulus [ %s]", _RED_(FAIL) ); } else { - if( verbose != 0 ) - printf( "passed\n" ); + PrintAndLogEx(SUCCESS, "Strong modulus [ %s]", _GREEN_(PASS) ); } - return ret; } diff --git a/client/emv/emv_roca.h b/client/emv/emv_roca.h index 26d37d146..9e12e4256 100644 --- a/client/emv/emv_roca.h +++ b/client/emv/emv_roca.h @@ -32,7 +32,7 @@ #define ROCA_PRINTS_LENGTH 17 extern bool emv_rocacheck( const unsigned char *buf, size_t buflen, bool verbose ); -extern int roca_self_test( int verbose ); +extern int roca_self_test( void ); #endif diff --git a/client/emv/test/cryptotest.c b/client/emv/test/cryptotest.c index b0212a70b..4e8df1a25 100644 --- a/client/emv/test/cryptotest.c +++ b/client/emv/test/cryptotest.c @@ -91,14 +91,15 @@ int ExecuteCryptoTests(bool verbose) { res = exec_crypto_test(verbose); if (res) TestFail = true; - res = roca_self_test(verbose); + res = roca_self_test(); if (res) TestFail = true; PrintAndLog("\n--------------------------"); + if (TestFail) - PrintAndLog("Test(s) [ERROR]."); + PrintAndLogEx(FAILED, "\tTest(s) [ %s ]", _RED_(FAIL) ); else - PrintAndLog("Tests [OK]."); + PrintAndLogEx(SUCCESS, "\tTest(s) [ %s ]", _GREEN_(OK) ); return TestFail; }