mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2024-11-10 09:32:41 +08:00
looping for smart card, inverted the silent to verbose, updated cardhelper stuff
This commit is contained in:
parent
26aeae1f3e
commit
d19da982f0
9 changed files with 316 additions and 107 deletions
15
armsrc/i2c.c
15
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();
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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"},
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue