looping for smart card, inverted the silent to verbose, updated cardhelper stuff

This commit is contained in:
iceman1001 2021-04-04 17:01:43 +02:00
parent 26aeae1f3e
commit d19da982f0
9 changed files with 316 additions and 107 deletions

View file

@ -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();

View file

@ -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)

View file

@ -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", "<dec>", "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"},

View file

@ -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);

View file

@ -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;

View file

@ -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

View file

@ -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;

View file

@ -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;
}

View file

@ -14,10 +14,14 @@
#include <ctype.h>
#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