From d19da982f044cfe18e17c0fc4a1e061d79829bd8 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 4 Apr 2021 17:01:43 +0200 Subject: [PATCH] looping for smart card, inverted the silent to verbose, updated cardhelper stuff --- armsrc/i2c.c | 15 ++-- client/src/cmdflashmem.c | 45 +----------- client/src/cmdhficlass.c | 144 ++++++++++++++++++++++++++++++++++++-- client/src/cmdhficlass.h | 6 ++ client/src/cmdsmartcard.c | 96 ++++++++++++++----------- client/src/cmdsmartcard.h | 4 +- client/src/emv/emvcore.c | 2 +- common/cardhelper.c | 105 ++++++++++++++++++++++++--- common/cardhelper.h | 6 +- 9 files changed, 316 insertions(+), 107 deletions(-) diff --git a/armsrc/i2c.c b/armsrc/i2c.c index 2b9bac13a..49136d364 100644 --- a/armsrc/i2c.c +++ b/armsrc/i2c.c @@ -32,7 +32,7 @@ #define I2C_ERROR "I2C_WaitAck Error" -static volatile uint32_t c; +//static // Direct use the loop to delay. 6 instructions loop, Masterclock 48MHz, // delay=1 is about 200kbps @@ -40,6 +40,7 @@ static volatile uint32_t c; // I2CSpinDelayClk(4) = 12.31us // I2CSpinDelayClk(1) = 3.07us static void __attribute__((optimize("O0"))) I2CSpinDelayClk(uint16_t delay) { + volatile uint32_t c; for (c = delay * 2; c; c--) {}; } @@ -160,7 +161,7 @@ static bool WaitSCL_H_delay(uint32_t delay) { // 5000 * 3.07us = 15350us. 15.35ms // 15000 * 3.07us = 46050us. 46.05ms static bool WaitSCL_H(void) { - return WaitSCL_H_delay(15000); + return WaitSCL_H_delay(10000); } static bool WaitSCL_L_delay(uint32_t delay) { @@ -174,7 +175,7 @@ static bool WaitSCL_L_delay(uint32_t delay) { } // 5000 * 3.07us = 15350us. 15.35ms static bool WaitSCL_L(void) { - return WaitSCL_L_delay(15000); + return WaitSCL_L_delay(10000); } // Wait max 1800ms or until SCL goes LOW. @@ -219,10 +220,7 @@ static bool I2C_WaitForSim(void) { // 8051 speaks with smart card. // 1000*50*3.07 = 153.5ms // 1byte transfer == 1ms with max frame being 256bytes - if (!WaitSCL_H_delay(10 * 1000 * 30)) - return false; - - return true; + return WaitSCL_H_delay(10 * 1000 * 50); } // send i2c STOP @@ -713,6 +711,9 @@ void SmartCardAtr(void) { I2C_Reset_EnterMainProgram(); smart_card_atr_t card; int res = GetATR(&card, true) ? PM3_SUCCESS : PM3_ETIMEOUT; + if (res == PM3_ETIMEOUT) { + I2C_Reset_EnterMainProgram(); + } reply_ng(CMD_SMART_ATR, res, (uint8_t *)&card, sizeof(smart_card_atr_t)); set_tracing(false); LEDsoff(); diff --git a/client/src/cmdflashmem.c b/client/src/cmdflashmem.c index c0a12cc39..bdc5dfd92 100644 --- a/client/src/cmdflashmem.c +++ b/client/src/cmdflashmem.c @@ -17,7 +17,7 @@ #include "cmdflashmemspiffs.h" // spiffs commands #include "rsa.h" #include "sha1.h" -#include "pk.h" // PEM key load functions +#include "pk.h" // PEM key load functions #define MCK 48000000 #define FLASH_MINFAST 24000000 //33000000 @@ -41,45 +41,6 @@ static int CmdHelp(const char *Cmd); "DB7FB5A3C8AC42EB635AE3C148C910750ABAA280CE82DC2F180F49F30A1393B5" //------------------------------------------------------------------------------------- -// Sample private RSA Key -// Following example RSA-1024 keypair, for test purposes (from common/polarssl/rsa.c) - -// private key - Exponent D -#define RSA_D "24BF6185468786FDD303083D25E64EFC" \ - "66CA472BC44D253102F8B4A9D3BFA750" \ - "91386C0077937FE33FA3252D28855837" \ - "AE1B484A8A9A45F7EE8C0C634F99E8CD" \ - "DF79C5CE07EE72C7F123142198164234" \ - "CABB724CF78B8173B9F880FC86322407" \ - "AF1FEDFDDE2BEB674CA15F3E81A1521E" \ - "071513A1E85B5DFA031F21ECAE91A34D" - -// prime P -#define RSA_P "C36D0EB7FCD285223CFB5AABA5BDA3D8" \ - "2C01CAD19EA484A87EA4377637E75500" \ - "FCB2005C5C7DD6EC4AC023CDA285D796" \ - "C3D9E75E1EFC42488BB4F1D13AC30A57" - -// prime Q -#define RSA_Q "C000DF51A7C77AE8D7C7370C1FF55B69" \ - "E211C2B9E5DB1ED0BF61D0D9899620F4" \ - "910E4168387E3C30AA1E00C339A79508" \ - "8452DD96A9A5EA5D9DCA68DA636032AF" - -#define RSA_DP "C1ACF567564274FB07A0BBAD5D26E298" \ - "3C94D22288ACD763FD8E5600ED4A702D" \ - "F84198A5F06C2E72236AE490C93F07F8" \ - "3CC559CD27BC2D1CA488811730BB5725" - -#define RSA_DQ "4959CBF6F8FEF750AEE6977C155579C7" \ - "D8AAEA56749EA28623272E4F7D0592AF" \ - "7C1F1313CAC9471B5C523BFE592F517B" \ - "407A1BD76C164B93DA2D32A383E58357" - -#define RSA_QP "9AE7FBC99546432DF71896FC239EADAE" \ - "F38D18D2B2F0E2DD275AA977E2BF4411" \ - "F5A3B2A5D33605AEBBCCBA7FEB9F2D2F" \ - "A74206CEC169D74BF5A8C50D6F48EA08" int rdv4_get_signature(rdv40_validation_t *out) { if (out == NULL) { @@ -107,7 +68,6 @@ int rdv4_get_signature(rdv40_validation_t *out) { // validate signature int rdv4_validate(rdv40_validation_t *mem) { - // Flash ID hash (sha1) uint8_t sha_hash[20] = {0}; mbedtls_sha1(mem->flashid, sizeof(mem->flashid), sha_hash); @@ -129,7 +89,6 @@ int rdv4_validate(rdv40_validation_t *mem) { return PM3_EFAILED; } - static int rdv4_sign_write(uint8_t *signature, uint8_t slen){ // save to mem clearCommandBuffer(); @@ -485,7 +444,6 @@ static int CmdFlashMemInfo(const char *Cmd) { return PM3_EINVARG; } - // set up PK key context now. mbedtls_pk_context pkctx; mbedtls_pk_init( &pkctx ); @@ -536,6 +494,7 @@ static int CmdFlashMemInfo(const char *Cmd) { if (res != PM3_SUCCESS) { return res; } + res = rdv4_validate(&mem); // Flash ID hash (sha1) diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index f4f9aa89a..6df780f06 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -35,6 +35,7 @@ #define ICLASS_KEYS_MAX 8 #define ICLASS_AUTH_RETRY 10 #define ICLASS_DECRYPTION_BIN "iclass_decryptionkey.bin" + static uint8_t empty[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; static int CmdHelp(const char *Cmd); @@ -127,6 +128,89 @@ uint8_t card_app2_limit[] = { 0xff, }; +iclass_config_card_item_t iclass_config_types[14]= { + {"", "", ""}, + {"", "", ""}, + {"", "", ""}, + {"", "", ""}, + {"", "", ""}, + {"", "", ""}, + {"", "", ""}, + {"", "", ""}, + {"", "", ""}, + {"", "", ""}, + {"", "", ""}, + {"", "", ""}, + {"", "", ""}, + // must be the last entry + {"no config card info available", "", ""} +}; + +static bool check_config_card(const iclass_config_card_item_t *o) { + if (o == NULL || strlen(o->desc) == 0) { + PrintAndLogEx(INFO, "No data available"); + PrintAndLogEx(HINT, "Try `" _YELLOW_("hf iclass config -l") "` to download from cardhelper"); + return false; + } + return true; +} + +static int load_config_cards(void) { + PrintAndLogEx(INFO, "Detecting cardhelper..."); + + if (IsCardHelperPresent(false) == false) + return PM3_ENODATA; + + for (int i = 0; i < ARRAYLEN(iclass_config_types); ++i) { + + PrintAndLogEx(INPLACE, "loading idx %i", i); + iclass_config_card_item_t *ret = &iclass_config_types[i]; + + uint8_t desc[70] = {0}; + if (GetConfigCardStrByIdx(i, desc) == PM3_SUCCESS) { + memcpy(ret->desc, desc, sizeof(desc)); + } + + uint8_t blocks[16] = {0}; + if (GetConfigCardByIdx(i, blocks) == PM3_SUCCESS) { + memcpy(ret->blk6, blocks, sizeof(ret->blk6)); + memcpy(ret->blk7, blocks + sizeof(ret->blk6), sizeof(ret->blk7)); + } + } + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(HINT, "Try `" _YELLOW_("hf iclass configcard -p") "` to list all"); + return PM3_SUCCESS; +} + +static const iclass_config_card_item_t *get_config_card_item(uint8_t idx) { + iclass_config_card_item_t *ret = &iclass_config_types[idx]; + return ret; +} + +static void print_config_cards(void) { + if (check_config_card(&iclass_config_types[0])) { + PrintAndLogEx(INFO, "---- " _CYAN_("Config cards available") " ------------"); + for (int i = 0; i < ARRAYLEN(iclass_config_types); ++i) { + PrintAndLogEx(INFO, "%2d, %s", i, iclass_config_types[i].desc); + } + PrintAndLogEx(NORMAL, ""); + } +} + +static void print_config_card(const iclass_config_card_item_t *o) { + if (check_config_card(o)) { + PrintAndLogEx(INFO, "description... %s", o->desc); + PrintAndLogEx(INFO, "block 6....... " _YELLOW_("%s"), sprint_hex_inrow(o->blk6, sizeof(o->blk6))); + PrintAndLogEx(INFO, "block 7....... " _YELLOW_("%s"), sprint_hex_inrow(o->blk7, sizeof(o->blk7))); + } +} + +static void generate_config_card(const iclass_config_card_item_t *o) { + if (check_config_card(o)) { + + } +} + static uint8_t isset(uint8_t val, uint8_t mask) { return (val & mask); } @@ -937,7 +1021,7 @@ static int CmdHFiClassDecrypt(const char *Cmd) { uint8_t dec_data[8] = {0}; bool use_sc = false; if (have_key == false) { - use_sc = IsCryptoHelperPresent(verbose); + use_sc = IsCardHelperPresent(verbose); if (use_sc == false) { size_t keylen = 0; int res = loadFile_safe(ICLASS_DECRYPTION_BIN, "", (void **)&keyptr, &keylen); @@ -1047,7 +1131,7 @@ static int CmdHFiClassDecrypt(const char *Cmd) { PrintAndLogEx(INFO, "Block 7 decoder"); - char hexstr[8 + 1] = {0}; + char hexstr[16 + 1] = {0}; hex_to_buffer((uint8_t *)hexstr, decrypted + (8 * 7), 8, sizeof(hexstr) - 1, 0, 0, true); char binstr[8 * 8 + 1] = {0}; @@ -1157,7 +1241,7 @@ static int CmdHFiClassEncryptBlk(const char *Cmd) { bool use_sc = false; if (have_key == false) { - use_sc = IsCryptoHelperPresent(verbose); + use_sc = IsCardHelperPresent(verbose); if (use_sc == false) { size_t keylen = 0; int res = loadFile_safe(ICLASS_DECRYPTION_BIN, "", (void **)&keyptr, &keylen); @@ -2008,7 +2092,7 @@ static int CmdHFiClass_ReadBlock(const char *Cmd) { if (memcmp(data, empty, 8) == 0) return PM3_SUCCESS; - bool use_sc = IsCryptoHelperPresent(verbose); + bool use_sc = IsCardHelperPresent(verbose); if (use_sc == false) return PM3_SUCCESS; @@ -3391,7 +3475,7 @@ static int CmdHFiClassEncode(const char *Cmd) { } if (have_enc_key == false) { - use_sc = IsCryptoHelperPresent(false); + use_sc = IsCardHelperPresent(false); if (use_sc == false) { size_t keylen = 0; int res = loadFile_safe(ICLASS_DECRYPTION_BIN, "", (void **)&enckeyptr, &keylen); @@ -3489,6 +3573,55 @@ static int CmdHFiClassAutopwn(const char *Cmd) { } */ +static int CmdHFiClassConfigCard(const char * Cmd) { + + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf iclass configcard", + "Manage reader configuration card via Cardhelper", + "hf iclass configcard -l --> download config cards " + "hf iclass configcard -p --> print config card" + "hf iclass configcard -g --ki 1 --> generate config dump file based on idx 1" + ); + + void *argtable[] = { + arg_param_begin, + arg_int0(NULL, "ki", "", "select index in list"), + arg_lit0("g", NULL, "generate card dump file"), + arg_lit0("l", NULL, "load available cards"), + arg_lit0("p", NULL, "print available cards"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + + int idx = arg_get_int_def(ctx, 1, -1); + bool generate = arg_get_lit(ctx, 2); + bool load = arg_get_lit(ctx, 3); + bool print = arg_get_lit(ctx, 4); + CLIParserFree(ctx); + + if (load) { + if (load_config_cards() != PM3_SUCCESS) { + PrintAndLogEx(INFO, "failed to load, check your cardhelper"); + } + } + + if (print) { + print_config_cards(); + } + + if (idx >= 0) { + const iclass_config_card_item_t *item = get_config_card_item(idx); + print_config_card(item); + } + + if (generate) { + const iclass_config_card_item_t *item = get_config_card_item(idx); + generate_config_card(item); + } + + return PM3_SUCCESS; +} + static command_t CommandTable[] = { {"-----------", CmdHelp, AlwaysAvailable, "--------------------- " _CYAN_("operations") " ---------------------"}, {"help", CmdHelp, AlwaysAvailable, "This help"}, @@ -3514,6 +3647,7 @@ static command_t CommandTable[] = { {"eview", CmdHFiClassEView, IfPm3Iclass, "View emulator memory"}, {"-----------", CmdHelp, AlwaysAvailable, "--------------------- " _CYAN_("utils") " ---------------------"}, + {"configcard", CmdHFiClassConfigCard, AlwaysAvailable, "Reader configuration card"}, {"calcnewkey", CmdHFiClassCalcNewKey, AlwaysAvailable, "Calc diversified keys (blocks 3 & 4) to write new keys"}, {"encode", CmdHFiClassEncode, AlwaysAvailable, "Encode binary wiegand to block 7"}, {"encrypt", CmdHFiClassEncryptBlk, AlwaysAvailable, "Encrypt given block data"}, diff --git a/client/src/cmdhficlass.h b/client/src/cmdhficlass.h index d060d1275..06a55122c 100644 --- a/client/src/cmdhficlass.h +++ b/client/src/cmdhficlass.h @@ -28,6 +28,12 @@ typedef struct iclass_prekey { uint8_t key[8]; } iclass_prekey_t; +typedef struct { + char desc[70]; + uint8_t blk6[8]; + uint8_t blk7[8]; +} iclass_config_card_item_t; + int CmdHFiClass(const char *Cmd); int info_iclass(void); diff --git a/client/src/cmdsmartcard.c b/client/src/cmdsmartcard.c index 2f099dfb1..c69404432 100644 --- a/client/src/cmdsmartcard.c +++ b/client/src/cmdsmartcard.c @@ -255,31 +255,43 @@ static void PrintATR(uint8_t *atr, size_t atrlen) { } } -static int smart_wait(uint8_t *data, bool silent) { - PacketResponseNG resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) { - if (!silent) PrintAndLogEx(WARNING, "smart card response timeout"); - return -1; - } +static int smart_wait(uint8_t *data, bool verbose) { + int i = 5; + uint32_t len = 0; + do { + clearCommandBuffer(); + PacketResponseNG resp; + if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { - uint32_t len = resp.oldarg[0]; - if (!len) { - if (!silent) PrintAndLogEx(WARNING, "smart card response failed"); - return -2; - } - memcpy(data, resp.data.asBytes, len); - if (len >= 2) { - if (!silent) PrintAndLogEx(SUCCESS, "%02X%02X | %s", data[len - 2], data[len - 1], GetAPDUCodeDescription(data[len - 2], data[len - 1])); - } else { - if (!silent) PrintAndLogEx(SUCCESS, " %d | %s", len, sprint_hex_inrow_ex(data, len, 8)); - } + len = resp.oldarg[0]; + if (len == 0) { + if (verbose) PrintAndLogEx(WARNING, "smart card response failed"); + return -2; + } - return len; + memcpy(data, resp.data.asBytes, len); + if (len >= 2) { + if (verbose) { + PrintAndLogEx(SUCCESS, "%02X%02X | %s", data[len - 2], data[len - 1], GetAPDUCodeDescription(data[len - 2], data[len - 1])); + } + } else { + if (verbose) { + PrintAndLogEx(SUCCESS, " %d | %s", len, sprint_hex_inrow_ex(data, len, 8)); + } + } + return len; + } + } while (i--); + + if (verbose) { + PrintAndLogEx(WARNING, "smart card response timeout"); + } + return -1; } -static int smart_responseEx(uint8_t *data, bool silent) { +static int smart_responseEx(uint8_t *data, bool verbose) { - int datalen = smart_wait(data, silent); + int datalen = smart_wait(data, verbose); bool needGetData = false; if (datalen < 2) { @@ -293,13 +305,13 @@ static int smart_responseEx(uint8_t *data, bool silent) { if (needGetData) { int len = data[datalen - 1]; - if (!silent) PrintAndLogEx(INFO, "Requesting 0x%02X bytes response", len); + if (verbose) PrintAndLogEx(INFO, "Requesting 0x%02X bytes response", len); uint8_t getstatus[] = {0x00, ISO7816_GET_RESPONSE, 0x00, 0x00, len}; clearCommandBuffer(); SendCommandMIX(CMD_SMART_RAW, SC_RAW, sizeof(getstatus), 0, getstatus, sizeof(getstatus)); - datalen = smart_wait(data, silent); + datalen = smart_wait(data, verbose); if (datalen < 2) { goto out; @@ -310,7 +322,7 @@ static int smart_responseEx(uint8_t *data, bool silent) { // data with ACK if (datalen == len + 2 + 1) { // 2 - response, 1 - ACK if (data[0] != ISO7816_GET_RESPONSE) { - if (!silent) { + if (verbose) { PrintAndLogEx(ERR, "GetResponse ACK error. len 0x%x | data[0] %02X", len, data[0]); } datalen = 0; @@ -321,7 +333,7 @@ static int smart_responseEx(uint8_t *data, bool silent) { memmove(data, &data[1], datalen); } else { // wrong length - if (!silent) { + if (verbose) { PrintAndLogEx(WARNING, "GetResponse wrong length. Must be 0x%02X got 0x%02X", len, datalen - 3); } } @@ -333,7 +345,7 @@ out: } static int smart_response(uint8_t *data) { - return smart_responseEx(data, false); + return smart_responseEx(data, true); } static int CmdSmartRaw(const char *Cmd) { @@ -358,7 +370,7 @@ static int CmdSmartRaw(const char *Cmd) { }; CLIExecWithReturn(ctx, Cmd, argtable, true); - bool reply = arg_get_lit(ctx, 1); + bool reply = (arg_get_lit(ctx, 1) == false); bool active = arg_get_lit(ctx, 2); bool active_select = arg_get_lit(ctx, 3); bool decode_tlv = arg_get_lit(ctx, 4); @@ -807,7 +819,7 @@ static void smart_brute_prim(void) { clearCommandBuffer(); SendCommandMIX(CMD_SMART_RAW, SC_RAW_T0, 5, 0, get_card_data + i, 5); - int len = smart_responseEx(buf, true); + int len = smart_responseEx(buf, false); if (len > 2) { // if ( decodeTLV ) { @@ -849,14 +861,14 @@ static int smart_brute_sfi(bool decodeTLV) { clearCommandBuffer(); SendCommandMIX(CMD_SMART_RAW, SC_RAW_T0, sizeof(READ_RECORD), 0, READ_RECORD, sizeof(READ_RECORD)); - len = smart_responseEx(buf, true); + len = smart_responseEx(buf, false); if (buf[0] == 0x6C) { READ_RECORD[4] = buf[1]; clearCommandBuffer(); SendCommandMIX(CMD_SMART_RAW, SC_RAW_T0, sizeof(READ_RECORD), 0, READ_RECORD, sizeof(READ_RECORD)); - len = smart_responseEx(buf, true); + len = smart_responseEx(buf, false); READ_RECORD[4] = 0; } @@ -892,7 +904,7 @@ static void smart_brute_options(bool decodeTLV) { clearCommandBuffer(); SendCommandMIX(CMD_SMART_RAW, SC_RAW_T0, sizeof(GET_PROCESSING_OPTIONS), 0, GET_PROCESSING_OPTIONS, sizeof(GET_PROCESSING_OPTIONS)); - int len = smart_responseEx(buf, true); + int len = smart_responseEx(buf, false); if (len > 4) { PrintAndLogEx(SUCCESS, "Got processing options"); if (decodeTLV) { @@ -988,7 +1000,7 @@ static int CmdSmartBruteforceSFI(const char *Cmd) { clearCommandBuffer(); SendCommandOLD(CMD_SMART_RAW, SC_RAW_T0, hexlen, 0, cmddata, hexlen); - int len = smart_responseEx(buf, true); + int len = smart_responseEx(buf, false); if (len < 3) continue; @@ -1056,12 +1068,16 @@ int CmdSmartcard(const char *Cmd) { return CmdsParse(CommandTable, Cmd); } -int ExchangeAPDUSC(bool silent, uint8_t *datain, int datainlen, bool activateCard, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen) { +int ExchangeAPDUSC(bool verbose, uint8_t *datain, int datainlen, bool activateCard, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen) { *dataoutlen = 0; - if (activateCard) - smart_select(true, NULL); + if (activateCard) { + if (smart_select(false, NULL) == false) { + PrintAndLogEx(DEBUG, "APDU SC - select card failed"); + return 1; + } + } PrintAndLogEx(DEBUG, "APDU SC"); @@ -1073,7 +1089,7 @@ int ExchangeAPDUSC(bool silent, uint8_t *datain, int datainlen, bool activateCar clearCommandBuffer(); SendCommandOLD(CMD_SMART_RAW, flags, datainlen, 0, datain, datainlen); - int len = smart_responseEx(dataout, silent); + int len = smart_responseEx(dataout, verbose); if (len < 0) { return 1; } @@ -1090,14 +1106,14 @@ int ExchangeAPDUSC(bool silent, uint8_t *datain, int datainlen, bool activateCar // something fishy: we have only 5 bytes but we put datainlen in arg1? SendCommandMIX(CMD_SMART_RAW, SC_RAW_T0, datainlen, 0, data, sizeof(data)); - len = smart_responseEx(dataout, silent); + len = smart_responseEx(dataout, verbose); } *dataoutlen = len; return 0; } -bool smart_select(bool silent, smart_card_atr_t *atr) { +bool smart_select(bool verbose, smart_card_atr_t *atr) { if (atr) memset(atr, 0, sizeof(smart_card_atr_t)); @@ -1106,12 +1122,12 @@ bool smart_select(bool silent, smart_card_atr_t *atr) { PacketResponseNG resp; if (!WaitForResponseTimeout(CMD_SMART_ATR, &resp, 2500)) { - if (!silent) PrintAndLogEx(WARNING, "smart card select failed"); + if (verbose) PrintAndLogEx(WARNING, "smart card select failed"); return false; } if (resp.status != PM3_SUCCESS) { - if (!silent) PrintAndLogEx(WARNING, "smart card select failed"); + if (verbose) PrintAndLogEx(WARNING, "smart card select failed"); return false; } @@ -1121,7 +1137,7 @@ bool smart_select(bool silent, smart_card_atr_t *atr) { if (atr) memcpy(atr, &card, sizeof(smart_card_atr_t)); - if (!silent) + if (verbose) PrintAndLogEx(INFO, "ISO7816-3 ATR : %s", sprint_hex(card.atr, card.atr_len)); return true; diff --git a/client/src/cmdsmartcard.h b/client/src/cmdsmartcard.h index 798ea4678..ca4733724 100644 --- a/client/src/cmdsmartcard.h +++ b/client/src/cmdsmartcard.h @@ -16,7 +16,7 @@ int CmdSmartcard(const char *Cmd); -bool smart_select(bool silent, smart_card_atr_t *atr); -int ExchangeAPDUSC(bool silent, uint8_t *datain, int datainlen, bool activateCard, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen); +bool smart_select(bool verbose, smart_card_atr_t *atr); +int ExchangeAPDUSC(bool verbose, uint8_t *datain, int datainlen, bool activateCard, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen); #endif diff --git a/client/src/emv/emvcore.c b/client/src/emv/emvcore.c index f9cbe4f82..8d2ce0f86 100644 --- a/client/src/emv/emvcore.c +++ b/client/src/emv/emvcore.c @@ -307,7 +307,7 @@ static int EMVExchangeEx(EMVCommandChannel channel, bool ActivateField, bool Lea case ECC_CONTACT: res = 1; if (IfPm3Smartcard()) - res = ExchangeAPDUSC(true, data, datalen, ActivateField, LeaveFieldON, Result, (int)MaxResultLen, (int *)ResultLen); + res = ExchangeAPDUSC(false, data, datalen, ActivateField, LeaveFieldON, Result, (int)MaxResultLen, (int *)ResultLen); if (res) { return res; diff --git a/common/cardhelper.c b/common/cardhelper.c index ce57f6051..c2206da20 100644 --- a/common/cardhelper.c +++ b/common/cardhelper.c @@ -17,19 +17,26 @@ #define CARD_INS_DECRYPT 0x01 #define CARD_INS_ENCRYPT 0x02 +#define CARD_INS_VEIRFY_RRG 0x05 #define CARD_INS_DECODE 0x06 #define CARD_INS_NUMBLOCKS 0x07 #define CARD_INS_PINSIZE 0x08 +#define CARD_INS_CC 0x81 +#define CARD_INS_CC_DESC 0x82 static uint8_t cmd[] = {0x96, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; -// look for CryptoHelper -bool IsCryptoHelperPresent(bool verbose) { +// look for CardHelper +bool IsCardHelperPresent(bool verbose) { if (IfPm3Smartcard()) { int resp_len = 0; uint8_t version[] = {0x96, 0x69, 0x00, 0x00, 0x00}; uint8_t resp[20] = {0}; - ExchangeAPDUSC(true, version, sizeof(version), true, true, resp, sizeof(resp), &resp_len); + ExchangeAPDUSC(verbose, version, sizeof(version), true, true, resp, sizeof(resp), &resp_len); + + if (resp_len < 8) { + return false; + } if (strstr("CryptoHelper", (char *)resp) == 0) { if (verbose) { @@ -48,7 +55,7 @@ static bool executeCrypto(uint8_t ins, uint8_t *src, uint8_t *dest) { cmd[1] = ins; memcpy(cmd + 5, src, 8); - ExchangeAPDUSC(true, cmd, sizeof(cmd), false, true, dec, sizeof(dec), &resp_len); + ExchangeAPDUSC(false, cmd, sizeof(cmd), false, false, dec, sizeof(dec), &resp_len); if (resp_len == 10) { memcpy(dest, dec, 8); @@ -74,12 +81,23 @@ void DecodeBlock6(uint8_t *src) { memcpy(c + 6, src, 8); // first part - ExchangeAPDUSC(true, c, sizeof(c), false, true, resp, sizeof(resp), &resp_len); + ExchangeAPDUSC(false, c, sizeof(c), false, true, resp, sizeof(resp), &resp_len); + + + if (resp_len < 11) { + return; + } + PrintAndLogEx(SUCCESS, "%.*s", resp_len - 11, resp + 9); // second part c[5] = 0x02; - ExchangeAPDUSC(true, c, sizeof(c), false, true, resp, sizeof(resp), &resp_len); + ExchangeAPDUSC(false, c, sizeof(c), false, false, resp, sizeof(resp), &resp_len); + + + if (resp_len < 11) { + return; + } PrintAndLogEx(SUCCESS, "%.*s", resp_len - 11, resp + 9); } @@ -89,7 +107,13 @@ uint8_t GetNumberBlocksForUserId(uint8_t *src) { uint8_t resp[254] = {0}; uint8_t c[] = {0x96, CARD_INS_NUMBLOCKS, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; memcpy(c + 5, src, 8); - ExchangeAPDUSC(true, c, sizeof(c), false, true, resp, sizeof(resp), &resp_len); + ExchangeAPDUSC(false, c, sizeof(c), false, false, resp, sizeof(resp), &resp_len); + + + if (resp_len < 8) { + return 0; + } + return resp[8]; } @@ -99,10 +123,75 @@ uint8_t GetPinSize(uint8_t *src) { uint8_t resp[254] = {0}; uint8_t c[] = {0x96, CARD_INS_PINSIZE, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; memcpy(c + 5, src, 8); - ExchangeAPDUSC(true, c, sizeof(c), false, true, resp, sizeof(resp), &resp_len); + ExchangeAPDUSC(false, c, sizeof(c), false, false, resp, sizeof(resp), &resp_len); + if (resp_len < 2) { + return 0; + } if (resp[resp_len - 2] == 0x90 && resp[resp_len - 1] == 0x00) { return resp[8]; } return 0; } + +int GetConfigCardByIdx(uint8_t typ, uint8_t *blocks) { + if (blocks == NULL) + return PM3_EINVARG; + + int resp_len = 0; + uint8_t resp[254] = {0}; + uint8_t c[] = {0x96, CARD_INS_CC, 0x00, 0x00, 17, typ, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + ExchangeAPDUSC(false, c, sizeof(c), false, true, resp, sizeof(resp), &resp_len); + + if (resp_len < 2) { + return PM3_ESOFT; + } + + if (resp[resp_len - 2] == 0x90 && resp[resp_len - 1] == 0x00) { + memcpy(blocks, resp + 1, 16); + return PM3_SUCCESS; + } + return PM3_ESOFT; +} + +int GetConfigCardStrByIdx(uint8_t typ, uint8_t *out) { + if (out == NULL) + return PM3_EINVARG; + + int resp_len = 0; + uint8_t resp[254] = {0}; + uint8_t c[] = {0x96, CARD_INS_CC_DESC, 0x00, 0x00, 1, typ}; + ExchangeAPDUSC(false, c, sizeof(c), false, true, resp, sizeof(resp), &resp_len); + + if (resp_len < 2) { + return PM3_ESOFT; + } + + if (resp[resp_len - 2] == 0x90 && resp[resp_len - 1] == 0x00) { + memcpy(out, resp + 1, resp_len - 2 - 1); + return PM3_SUCCESS; + } + return PM3_ESOFT; +} + +int VerifyRdv4Signature(uint8_t *memid, uint8_t *signature) { + if (memid == NULL || signature == NULL) + return PM3_EINVARG; + + int resp_len = 0; + uint8_t resp[254] = {0}; + uint8_t c[5 + 8 + 128] = {0x96, CARD_INS_VEIRFY_RRG, 0x00, 0x00, 8 + 128}; + + memcpy(c + 5, memid, 8); + memcpy(c + 5 + 8, signature, 128); + + ExchangeAPDUSC(false, c, sizeof(c), true, false, resp, sizeof(resp), &resp_len); + if (resp_len < 2) { + return PM3_ESOFT; + } + + if (memcmp(resp + resp_len - 4, "\x6f\x6b\x90\x00", 4) == 0) { + return PM3_SUCCESS; + } + return PM3_ESOFT; +} diff --git a/common/cardhelper.h b/common/cardhelper.h index d55ae6701..1ef5b646e 100644 --- a/common/cardhelper.h +++ b/common/cardhelper.h @@ -14,10 +14,14 @@ #include #include "common.h" -bool IsCryptoHelperPresent(bool verbose); +bool IsCardHelperPresent(bool verbose); bool Encrypt(uint8_t *src, uint8_t *dest); bool Decrypt(uint8_t *src, uint8_t *dest); void DecodeBlock6(uint8_t *src); uint8_t GetNumberBlocksForUserId(uint8_t *src); uint8_t GetPinSize(uint8_t *src); + +int GetConfigCardByIdx(uint8_t typ, uint8_t *blocks); +int GetConfigCardStrByIdx(uint8_t typ, uint8_t *out); +int VerifyRdv4Signature(uint8_t *memid, uint8_t *signature); #endif