still seems to work after big refactor

This commit is contained in:
n-hutton 2024-11-18 17:53:36 +00:00
commit 4bff031715
5 changed files with 408 additions and 407 deletions

View file

@ -59,7 +59,7 @@ else
endif
ifneq (,$(findstring WITH_SMARTCARD,$(APP_CFLAGS)))
SRC_SMARTCARD = i2c.c
SRC_SMARTCARD = i2c.c i2c_direct.c
else
SRC_SMARTCARD =
endif

View file

@ -47,6 +47,7 @@
#include "dbprint.h"
#include "ticks.h"
#include "i2c.h"
#include "i2c_direct.h"
#pragma GCC diagnostic ignored "-Wunused-variable"
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
@ -58,333 +59,9 @@ static uint8_t filenotfound[] = {0x02, 0x6a, 0x82, 0x93, 0x2f};
static uint8_t fci_query[] = {0x02, 0x00, 0xa4, 0x04, 0x00, 0x07, 0xa0, 0x00, 0x00, 0x00, 0x03, 0x10, 0x10, 0x00, 0x56, 0x3f};
static uint8_t fci_template[] = {0x02, 0x6f, 0x5e, 0x84, 0x07, 0xa0, 0x00, 0x00, 0x00, 0x03, 0x10, 0x10, 0xa5, 0x53, 0x50, 0x0a, 0x56, 0x69, 0x73, 0x61, 0x20, 0x44, 0x65, 0x62, 0x69, 0x74, 0x9f, 0x38, 0x18, 0x9f, 0x66, 0x04, 0x9f, 0x02, 0x06, 0x9f, 0x03, 0x06, 0x9f, 0x1a, 0x02, 0x95, 0x05, 0x5f, 0x2a, 0x02, 0x9a, 0x03, 0x9c, 0x01, 0x9f, 0x37, 0x04, 0x5f, 0x2d, 0x02, 0x65, 0x6e, 0x9f, 0x11, 0x01, 0x01, 0x9f, 0x12, 0x0a, 0x56, 0x69, 0x73, 0x61, 0x20, 0x44, 0x65, 0x62, 0x69, 0x74, 0xbf, 0x0c, 0x13, 0x9f, 0x5a, 0x05, 0x31, 0x08, 0x26, 0x08, 0x26, 0x9f, 0x0a, 0x08, 0x00, 0x01, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x90, 0x00, 0xd8, 0x15};
// this is a fci template with a modified PDOL (not including CDOL now)
//static uint8_t fci_template[] = { 0x02, 0x6f, 0x5b, 0x84, 0x07, 0xa0, 0x00, 0x00, 0x00, 0x03, 0x10, 0x10, 0xa5, 0x50, 0x50, 0x0a, 0x56, 0x69, 0x73, 0x61, 0x20, 0x44, 0x65, 0x62, 0x69, 0x74, 0x9f, 0x38, 0x15, 0x9F, 0x02, 0x06, 0x9F, 0x03, 0x06, 0x9F, 0x1A, 0x02, 0x95, 0x05, 0x5F, 0x2A, 0x02, 0x9A, 0x03, 0x9C, 0x01, 0x9F, 0x37, 0x04, 0x5f, 0x2d, 0x02, 0x65, 0x6e, 0x9f, 0x11, 0x01, 0x01, 0x9f, 0x12, 0x0a, 0x56, 0x69, 0x73, 0x61, 0x20, 0x44, 0x65, 0x62, 0x69, 0x74, 0xbf, 0x0c, 0x13, 0x9f, 0x5a, 0x05, 0x31, 0x08, 0x26, 0x08, 0x26, 0x9f, 0x0a, 0x08, 0x00, 0x01, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x90, 0x00, 0xfc, 0x9d};
//static uint8_t pay1_query[] = {0x03, 0x00, 0xa4, 0x04, 0x00, 0x0e, 0x31, 0x50, 0x41};
//static uint8_t pay2_query[] = {0x03, 0x00, 0xa4, 0x04, 0x00, 0x0e, 0x32, 0x50, 0x41};
static uint8_t pay1_response[] = { 0x6F, 0x1E, 0x84, 0x0E, 0x31, 0x50, 0x41, 0x59 };
static uint8_t pay2_response[] = { 0x03, 0x6f, 0x3e, 0x84, 0x0e, 0x32, 0x50, 0x41, 0x59, 0x2e, 0x53, 0x59, 0x53, 0x2e, 0x44, 0x44, 0x46, 0x30, 0x31, 0xa5, 0x2c, 0xbf, 0x0c, 0x29, 0x61, 0x27, 0x4f, 0x07, 0xa0, 0x00, 0x00, 0x00, 0x03, 0x10, 0x10, 0x50, 0x0a, 0x56, 0x69, 0x73, 0x61, 0x20, 0x44, 0x65, 0x62, 0x69, 0x74, 0x9f, 0x0a, 0x08, 0x00, 0x01, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x63, 0x04, 0xdf, 0x20, 0x01, 0x80, 0x90, 0x00, 0x07, 0x9d};
void SmartCardDirectSend(uint8_t prepend, const smart_card_raw_t *p);
void SmartCardDirectSend(uint8_t prepend, const smart_card_raw_t *p) {
LED_D_ON();
uint16_t len = 0;
uint8_t *resp = BigBuf_malloc(ISO7816_MAX_FRAME);
resp[0] = prepend;
// check if alloacted...
smartcard_command_t flags = p->flags;
//if ((flags & SC_CLEARLOG) == SC_CLEARLOG)
//clear_trace();
if ((flags & SC_LOG) == SC_LOG)
set_tracing(true);
else
set_tracing(false);
if ((flags & SC_CONNECT) == SC_CONNECT) {
I2C_Reset_EnterMainProgram();
if ((flags & SC_SELECT) == SC_SELECT) {
smart_card_atr_t card;
bool gotATR = GetATR(&card, true);
//reply_old(CMD_ACK, gotATR, sizeof(smart_card_atr_t), 0, &card, sizeof(smart_card_atr_t));
if (gotATR == false) {
Dbprintf("No ATR received...\n");
//reply_ng(CMD_SMART_RAW, PM3_ESOFT, NULL, 0);
goto OUT;
}
}
}
uint32_t wait = SIM_WAIT_DELAY;
if (((flags & SC_RAW) == SC_RAW) || ((flags & SC_RAW_T0) == SC_RAW_T0)) {
if ((flags & SC_WAIT) == SC_WAIT) {
wait = (uint32_t)((p->wait_delay * 1000) / 3.07);
}
LogTrace(p->data, p->len, 0, 0, NULL, true);
bool res = I2C_BufferWrite(
p->data,
p->len,
(((flags & SC_RAW_T0) == SC_RAW_T0) ? I2C_DEVICE_CMD_SEND_T0 : I2C_DEVICE_CMD_SEND),
I2C_DEVICE_ADDRESS_MAIN
);
if (res == false && g_dbglevel > 3) {
//DbpString(I2C_ERROR);
//reply_ng(CMD_SMART_RAW, PM3_ESOFT, NULL, 0);
Dbprintf("SmartCardDirectSend: I2C_BufferWrite failed\n");
goto OUT;
}
// read bytes from module
len = ISO7816_MAX_FRAME;
res = sc_rx_bytes(&resp[1], &len, wait);
if (res) {
LogTrace(&resp[1], len, 0, 0, NULL, false);
} else {
len = 0;
}
}
if (len == 2 && resp[1] == 0x61) {
//Dbprintf("Data to be read: len = %d\n", len);
//Dbprintf("\n");
uint8_t cmd_getresp[] = {0x00, ISO7816_GET_RESPONSE, 0x00, 0x00, resp[2]};
//smart_card_raw_t *payload = calloc(1, sizeof(smart_card_raw_t) + sizeof(cmd_getresp));
smart_card_raw_t *payload = (smart_card_raw_t *)BigBuf_calloc(sizeof(smart_card_raw_t) + sizeof(cmd_getresp));
payload->flags = SC_RAW | SC_LOG;
payload->len = sizeof(cmd_getresp);
payload->wait_delay = 0;
memcpy(payload->data, cmd_getresp, sizeof(cmd_getresp));
SmartCardDirectSend(prepend, payload);
} else if (len == 2) {
Dbprintf("***** BAD response from card (response unsupported)...");
Dbhexdump(3, &resp[0], false);
resp[0] = prepend;
resp[1] = 0x6a;
resp[2] =0x82;
AddCrc14A(resp, 3);
//Dbhexdump(5, &resp[0], false); // nathan print
//EmSendCmd14443aRaw(&resp[0], 5);
EmSendCmd(&resp[0], 5);
}
if (resp[1] == 0x6a && resp[2] == 0x82) {
Dbprintf("***** bad response from card (file not found)...");
resp[0] = prepend;
resp[1] = 0x6a;
resp[2] =0x82;
AddCrc14A(resp, 3);
//Dbhexdump(5, &resp[0], false); // nathan print
//EmSendCmd14443aRaw(&resp[0], 5);
EmSendCmd(&resp[0], 5);
FpgaDisableTracing();
}
if (len > 2) {
// print nathan
Dbprintf("***** sending it over the wire... len: %d =>\n", len);
resp[1] = prepend;
// if we have a generate AC request, lets extract the data and populate the template
if (resp[1] != 0xff && resp[2] == 0x77) {
Dbprintf("we have detected a generate ac response, lets repackage it!");
Dbhexdump(len, &resp[1], false); // nathan print
// 11 and 12 are trans counter.
// 16 to 24 are the cryptogram
// 27 to 34 is issuer application data
Dbprintf("atc: %d %d, cryptogram: %d ", resp[11], resp[12], resp[13]);
// then, on the template:
// 61 and 62 for counter
// 46 to 54 for cryptogram
// 36 to 43 for issuer application data
uint8_t template[] = { 0x00, 0x00, 0x77, 0x47, 0x82, 0x02, 0x39, 0x00, 0x57, 0x13, 0x47, 0x62, 0x28, 0x00, 0x05, 0x93, 0x38, 0x64, 0xd2, 0x70, 0x92, 0x01, 0x00, 0x00, 0x01, 0x42, 0x00, 0x00, 0x0f, 0x5f, 0x34, 0x01, 0x00, 0x9f, 0x10, 0x07, 0x06, 0x01, 0x12, 0x03, 0xa0, 0x20, 0x00, 0x9f, 0x26, 0x08, 0x56, 0xcb, 0x4e, 0xe1, 0xa4, 0xef, 0xac, 0x74, 0x9f, 0x27, 0x01, 0x80, 0x9f, 0x36, 0x02, 0x00, 0x07, 0x9f, 0x6c, 0x02, 0x3e, 0x00, 0x9f, 0x6e, 0x04, 0x20, 0x70, 0x00, 0x00, 0x90, 0x00, 0xff, 0xff};
// do the replacement
template[1] = resp[1]; // class bit
template[61] = resp[11];
template[62] = resp[12];
template[46] = resp[16];
template[47] = resp[17];
template[48] = resp[18];
template[49] = resp[19];
template[50] = resp[20];
template[51] = resp[21];
template[52] = resp[22];
template[53] = resp[23];
template[54] = resp[24];
template[36] = resp[27];
template[37] = resp[28];
template[38] = resp[29];
template[39] = resp[30];
template[40] = resp[31];
template[41] = resp[32];
template[42] = resp[33];
Dbprintf("\nrearranged is: ");
len = sizeof(template);
Dbhexdump(len, &template[0], false); // nathan print
AddCrc14A(&template[1], len-3);
Dbprintf("\nafter crc rearranged is: ");
Dbhexdump(len, &template[0], false); // nathan print
Dbprintf("\n");
EmSendCmd(&template[1], len-1);
BigBuf_free();
return;
}
//Dbhexdump(len, &resp[1], false); // nathan print
AddCrc14A(&resp[1], len);
Dbhexdump(len+2, &resp[1], false); // nathan print
// Check we don't want to modify the response (application profile response)
//uint8_t modifyme[] = {0x03, 0x77, 0x0e, 0x82, 0x02};
BigBuf_free();
if (prepend == 0xff) {
Dbprintf("pdol request, we can can the response...");
return;
}
if (memcmp(&resp[2], &pay1_response[0], sizeof(pay1_response)) == 0 && true) {
Dbprintf("Switching out the pay1 response for a pay2 response...");
EmSendCmd(&pay2_response[0], sizeof(pay2_response));
}
else if (memcmp(&resp[1], &fci_template[0], 2) == 0 && true) {
Dbprintf("***** modifying response to have full fci template...!");
EmSendCmd(&fci_template[0], sizeof(fci_template));
} else {
//Dbprintf("***** not modifying response...");
EmSendCmd(&resp[1], len + 2);
}
BigBuf_free();
//memcpy(saved_command, &resp[1], len+2);
//saved_command_len = len+2;
//EmSendCmd14443aRaw(&resp[1], len+2);
//FpgaDisableTracing();
//EmSend4bit(encrypted_data ? mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA) : CARD_NACK_NA);
}
//reply_ng(CMD_SMART_RAW, PM3_SUCCESS, resp, len);
OUT:
//BigBuf_free();
//set_tracing(false);
LEDsoff();
}
static int CmdSmartRaw(const uint8_t prepend, const uint8_t *data, int dlen, uint8_t *buffer) {
Dbprintf("sending command to smart card... %02x %02x %02x... =>", prepend, data[0], data[1]);
Dbhexdump(dlen, data, false);
if (data[4] + 5 != dlen) {
Dbprintf("invalid length of data. Received: %d, command specifies %d", dlen, data[4] + 5);
dlen = data[4] + 5;
}
//smart_card_raw_t *payload = calloc(1, sizeof(smart_card_raw_t) + dlen);
smart_card_raw_t *payload = (smart_card_raw_t *)BigBuf_calloc(sizeof(smart_card_raw_t) + dlen);
if (payload == NULL) {
Dbprintf("failed to allocate memory");
return PM3_EMALLOC;
}
payload->len = dlen;
memcpy(payload->data, data, dlen);
payload->flags = SC_LOG;
bool active = true;
bool active_select = false;
int timeout = 600;
bool use_t0 = true;
if (active || active_select) {
payload->flags |= (SC_CONNECT | SC_CLEARLOG);
if (active_select)
payload->flags |= SC_SELECT;
}
payload->wait_delay = 0;
if (timeout > -1) {
payload->flags |= SC_WAIT;
payload->wait_delay = timeout;
}
//Dbprintf("SIM Card timeout... %u ms", payload->wait_delay);
if (dlen > 0) {
if (use_t0)
payload->flags |= SC_RAW_T0;
else
payload->flags |= SC_RAW;
}
////uint8_t *buf = calloc(PM3_CMD_DATA_SIZE, sizeof(uint8_t));
//uint8_t *buf = BigBuf_calloc(PM3_CMD_DATA_SIZE, sizeof(uint8_t));
//if (buf == NULL) {
// Dbprintf("failed to allocate memory");
// free(payload);
// return PM3_EMALLOC;
//}
//clearCommandBuffer();
//SendCommandNG(CMD_SMART_RAW, (uint8_t *)payload, sizeof(smart_card_raw_t) + dlen);
//for (int i = 0; i < dlen; i++) {
// Dbprintf("%02x ", data[i]);
//}
SmartCardDirectSend(prepend, payload);
//if (reply == false) {
// Dbprintf("failed to talk to smart card!!!");
// goto out;
//}
//// reading response from smart card
//int len = smart_response(buf, PM3_CMD_DATA_SIZE);
//if (len < 0) {
// free(payload);
// free(buf);
// return PM3_ESOFT;
//}
//if (buf[0] == 0x6C) {
// // request more bytes to download
// data[4] = buf[1];
// memcpy(payload->data, data, dlen);
// clearCommandBuffer();
// SendCommandNG(CMD_SMART_RAW, (uint8_t *)payload, sizeof(smart_card_raw_t) + dlen);
// len = smart_response(buf, PM3_CMD_DATA_SIZE);
// data[4] = 0;
//}
//if (decode_tlv && len > 4) {
// TLVPrintFromBuffer(buf, len - 2);
//} else {
// if (len > 2) {
// Dbprintf("Response data:");
// Dbprintf(" # | bytes | ascii");
// Dbprintf("---+-------------------------------------------------+-----------------");
// print_hex_break(buf, len, 16);
// }
//}
//memcpy(buffer, buf, len);
//out:
//free(payload);
//free(buf);
return PM3_SUCCESS;
}
static bool MifareSimInit(uint16_t flags, uint8_t *datain, uint16_t atqa, uint8_t sak, tag_response_info_t **responses, uint32_t *cuid, uint8_t *uid_len, uint8_t **rats, uint8_t *rats_len) {
// SPEC: https://www.nxp.com/docs/en/application-note/AN10833.pdf
@ -687,6 +364,8 @@ void EMVsim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint16_t a
uint8_t receivedCmd_dec[MAX_FRAME_SIZE] = {0x00};
//uint8_t convenient_buffer[64] = {0x00};
uint8_t receivedCmd_par[MAX_MIFARE_PARITY_SIZE] = {0x00};
uint8_t responseToReader[MAX_FRAME_SIZE] = {0x00};
uint16_t responseToReader_len;
uint16_t receivedCmd_len;
uint16_t receivedCmd_len_copy = 0;
@ -1269,12 +948,14 @@ void EMVsim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint16_t a
Dbprintf("We are about to do a generate AC... we need to request PDOL first...");
uint8_t pdol_request[] = { 0x80, 0xa8, 0x00, 0x00, 0x02, 0x83, 0x00 };
CmdSmartRaw(0xff, &(pdol_request[0]), sizeof(pdol_request), (&receivedCmd_dec[1]));
CmdSmartRaw(0xff, &(pdol_request[0]), sizeof(pdol_request), (&responseToReader[0]), &responseToReader_len);
}
// This is minus 3 because we don't include the first byte (prepend), plus we don't want to send the
// last two bytes (CRC) to the card
CmdSmartRaw(receivedCmd_copy[0], &(receivedCmd_copy[1]), receivedCmd_len_copy-3, (&receivedCmd_dec[1]));
CmdSmartRaw(receivedCmd_copy[0], &(receivedCmd_copy[1]), receivedCmd_len_copy-3, (&responseToReader[0]), &responseToReader_len);
EmSendCmd(responseToReader, responseToReader_len);
Dbprintf("Sent delayed command to card...");
//EmSendCmd(thirdResponse, sizeof(thirdResponse));
continue;
@ -1297,41 +978,6 @@ void EMVsim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint16_t a
//return;
continue;
}
case MFEMUL_WRITEBL2: {
//emlGetMem(response, cardWRBL, 1);
// if (receivedCmd_len == MAX_MIFARE_FRAME_SIZE) {
// mf_crypto1_decryptEx(pcs, receivedCmd, receivedCmd_len, receivedCmd_dec);
// if (CheckCrc14A(receivedCmd_dec, receivedCmd_len)) {
// if (IsSectorTrailer(cardWRBL)) {
// emlGetMem(response, cardWRBL, 1);
// // if (!IsAccessAllowed(cardWRBL, cardAUTHKEY, AC_KEYA_WRITE)) {
// // memcpy(receivedCmd_dec, response, 6); // don't change KeyA
// // }
// // if (!IsAccessAllowed(cardWRBL, cardAUTHKEY, AC_KEYB_WRITE)) {
// // memcpy(receivedCmd_dec + 10, response + 10, 6); // don't change KeyA
// // }
// // if (!IsAccessAllowed(cardWRBL, cardAUTHKEY, AC_AC_WRITE)) {
// // memcpy(receivedCmd_dec + 6, response + 6, 4); // don't change AC bits
// // }
// // } else {
// // if (!IsAccessAllowed(cardWRBL, cardAUTHKEY, AC_DATA_WRITE)) {
// // memcpy(receivedCmd_dec, response, 16); // don't change anything
// // }
// }
// emlSetMem_xt(receivedCmd_dec, cardWRBL, 1, 16);
// EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK)); // always ACK?
// FpgaDisableTracing();
// cardSTATE = MFEMUL_WORK;
// if (999 >= DBG_EXTENDED) Dbprintf("[MFEMUL_WRITEBL2] cardSTATE = MFEMUL_WORK **********************************************");
// break;
// }
// }
// cardSTATE_TO_IDLE();
// if (999 >= DBG_EXTENDED) Dbprintf("[MFEMUL_WRITEBL2] cardSTATE = MFEMUL_IDLE");
// LogTrace(uart->output, uart->len, uart->startTime * 16 - DELAY_AIR2ARM_AS_TAG, uart->endTime * 16 - DELAY_AIR2ARM_AS_TAG, uart->parity, true);
// break;
}
} // End Switch Loop
button_pushed = BUTTON_PRESS();
@ -1341,48 +987,14 @@ void EMVsim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint16_t a
FpgaDisableTracing();
//// NR AR ATTACK
//// mfkey32
//if (((flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK) && (999 >= DBG_INFO)) {
// for (uint8_t i = 0; i < ATTACK_KEY_COUNT; i++) {
// if (ar_nr_collected[i] == 2) {
// Dbprintf("Collected two pairs of AR/NR which can be used to extract %s from reader for sector %d:", (i < ATTACK_KEY_COUNT / 2) ? "keyA" : "keyB", ar_nr_resp[i].sector);
// Dbprintf("../tools/mfkey/mfkey32 %08x %08x %08x %08x %08x %08x",
// ar_nr_resp[i].cuid, //UID
// ar_nr_resp[i].nonce, //NT
// ar_nr_resp[i].nr, //NR1
// ar_nr_resp[i].ar, //AR1
// ar_nr_resp[i].nr2, //NR2
// ar_nr_resp[i].ar2 //AR2
// );
// }
// }
//}
//// mfkey32 v2
//for (uint8_t i = ATTACK_KEY_COUNT; i < ATTACK_KEY_COUNT * 2; i++) {
// if (ar_nr_collected[i] == 2) {
// Dbprintf("Collected two pairs of AR/NR which can be used to extract %s from reader for sector %d:", (i < ATTACK_KEY_COUNT / 2) ? "keyA" : "keyB", ar_nr_resp[i].sector);
// Dbprintf("../tools/mfkey/mfkey32v2 %08x %08x %08x %08x %08x %08x %08x",
// ar_nr_resp[i].cuid, //UID
// ar_nr_resp[i].nonce, //NT
// ar_nr_resp[i].nr, //NR1
// ar_nr_resp[i].ar, //AR1
// ar_nr_resp[i].nonce2,//NT2
// ar_nr_resp[i].nr2, //NR2
// ar_nr_resp[i].ar2 //AR2
// );
// }
//}
if (999 >= DBG_ERROR) {
Dbprintf("Emulator stopped. Tracing: %d trace length: %d ", get_tracing(), BigBuf_get_traceLen());
}
if ((flags & FLAG_INTERACTIVE) == FLAG_INTERACTIVE) { // Interactive mode flag, means we need to send ACK
//Send the collected ar_nr in the response
reply_mix(CMD_ACK, CMD_HF_MIFARE_SIMULATE, button_pushed, 0, &ar_nr_resp, sizeof(ar_nr_resp));
}
//if ((flags & FLAG_INTERACTIVE) == FLAG_INTERACTIVE) { // Interactive mode flag, means we need to send ACK
// //Send the collected ar_nr in the response
// reply_mix(CMD_ACK, CMD_HF_MIFARE_SIMULATE, button_pushed, 0, &ar_nr_resp, sizeof(ar_nr_resp));
//}
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff();

View file

@ -41,13 +41,6 @@
#define AUTHKEYB 1
#define AUTHKEYNONE 0xff
//void EMVsim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint16_t atqa, uint8_t sak);
//void EMVsim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint16_t atqa, uint8_t sak) {
// Dbprintf("Evm sim init...");
//
//}
void EMVsim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint16_t atqa, uint8_t sak);
#endif

374
armsrc/i2c_direct.c Normal file
View file

@ -0,0 +1,374 @@
// //-----------------------------------------------------------------------------
// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// See LICENSE.txt for the text of the license.
//-----------------------------------------------------------------------------
// The main i2c code, for communications with smart card module
//-----------------------------------------------------------------------------
#include <inttypes.h>
#include "BigBuf.h"
#include "iso14443a.h"
#include "BigBuf.h"
#include "string.h"
#include "mifareutil.h"
#include "fpgaloader.h"
#include "proxmark3_arm.h"
#include "cmd.h"
#include "protocols.h"
#include "appmain.h"
#include "util.h"
#include "commonutil.h"
#include "crc16.h"
#include "dbprint.h"
#include "ticks.h"
#include "i2c.h"
#include "i2c_direct.h"
//void SmartCardDirectSend(uint8_t prepend, const smart_card_raw_t *p);
static uint8_t fci_template[] = {0x02, 0x6f, 0x5e, 0x84, 0x07, 0xa0, 0x00, 0x00, 0x00, 0x03, 0x10, 0x10, 0xa5, 0x53, 0x50, 0x0a, 0x56, 0x69, 0x73, 0x61, 0x20, 0x44, 0x65, 0x62, 0x69, 0x74, 0x9f, 0x38, 0x18, 0x9f, 0x66, 0x04, 0x9f, 0x02, 0x06, 0x9f, 0x03, 0x06, 0x9f, 0x1a, 0x02, 0x95, 0x05, 0x5f, 0x2a, 0x02, 0x9a, 0x03, 0x9c, 0x01, 0x9f, 0x37, 0x04, 0x5f, 0x2d, 0x02, 0x65, 0x6e, 0x9f, 0x11, 0x01, 0x01, 0x9f, 0x12, 0x0a, 0x56, 0x69, 0x73, 0x61, 0x20, 0x44, 0x65, 0x62, 0x69, 0x74, 0xbf, 0x0c, 0x13, 0x9f, 0x5a, 0x05, 0x31, 0x08, 0x26, 0x08, 0x26, 0x9f, 0x0a, 0x08, 0x00, 0x01, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x90, 0x00, 0xd8, 0x15};
static uint8_t pay1_response[] = { 0x6F, 0x1E, 0x84, 0x0E, 0x31, 0x50, 0x41, 0x59 };
static uint8_t pay2_response[] = { 0x03, 0x6f, 0x3e, 0x84, 0x0e, 0x32, 0x50, 0x41, 0x59, 0x2e, 0x53, 0x59, 0x53, 0x2e, 0x44, 0x44, 0x46, 0x30, 0x31, 0xa5, 0x2c, 0xbf, 0x0c, 0x29, 0x61, 0x27, 0x4f, 0x07, 0xa0, 0x00, 0x00, 0x00, 0x03, 0x10, 0x10, 0x50, 0x0a, 0x56, 0x69, 0x73, 0x61, 0x20, 0x44, 0x65, 0x62, 0x69, 0x74, 0x9f, 0x0a, 0x08, 0x00, 0x01, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x63, 0x04, 0xdf, 0x20, 0x01, 0x80, 0x90, 0x00, 0x07, 0x9d};
void SmartCardDirectSend(uint8_t prepend, const smart_card_raw_t *p, uint8_t *output, uint16_t *olen) {
LED_D_ON();
uint16_t len = 0;
uint8_t *resp = BigBuf_malloc(ISO7816_MAX_FRAME);
resp[0] = prepend;
// check if alloacted...
smartcard_command_t flags = p->flags;
//if ((flags & SC_CLEARLOG) == SC_CLEARLOG)
//clear_trace();
if ((flags & SC_LOG) == SC_LOG)
set_tracing(true);
else
set_tracing(false);
if ((flags & SC_CONNECT) == SC_CONNECT) {
I2C_Reset_EnterMainProgram();
if ((flags & SC_SELECT) == SC_SELECT) {
smart_card_atr_t card;
bool gotATR = GetATR(&card, true);
//reply_old(CMD_ACK, gotATR, sizeof(smart_card_atr_t), 0, &card, sizeof(smart_card_atr_t));
if (gotATR == false) {
Dbprintf("No ATR received...\n");
//reply_ng(CMD_SMART_RAW, PM3_ESOFT, NULL, 0);
goto OUT;
}
}
}
uint32_t wait = SIM_WAIT_DELAY;
if (((flags & SC_RAW) == SC_RAW) || ((flags & SC_RAW_T0) == SC_RAW_T0)) {
if ((flags & SC_WAIT) == SC_WAIT) {
wait = (uint32_t)((p->wait_delay * 1000) / 3.07);
}
LogTrace(p->data, p->len, 0, 0, NULL, true);
bool res = I2C_BufferWrite(
p->data,
p->len,
(((flags & SC_RAW_T0) == SC_RAW_T0) ? I2C_DEVICE_CMD_SEND_T0 : I2C_DEVICE_CMD_SEND),
I2C_DEVICE_ADDRESS_MAIN
);
if (res == false && g_dbglevel > 3) {
//DbpString(I2C_ERROR);
//reply_ng(CMD_SMART_RAW, PM3_ESOFT, NULL, 0);
Dbprintf("SmartCardDirectSend: I2C_BufferWrite failed\n");
goto OUT;
}
// read bytes from module
len = ISO7816_MAX_FRAME;
res = sc_rx_bytes(&resp[1], &len, wait);
if (res) {
LogTrace(&resp[1], len, 0, 0, NULL, false);
} else {
len = 0;
}
}
if (len == 2 && resp[1] == 0x61) {
//Dbprintf("Data to be read: len = %d\n", len);
//Dbprintf("\n");
uint8_t cmd_getresp[] = {0x00, ISO7816_GET_RESPONSE, 0x00, 0x00, resp[2]};
//smart_card_raw_t *payload = calloc(1, sizeof(smart_card_raw_t) + sizeof(cmd_getresp));
smart_card_raw_t *payload = (smart_card_raw_t *)BigBuf_calloc(sizeof(smart_card_raw_t) + sizeof(cmd_getresp));
payload->flags = SC_RAW | SC_LOG;
payload->len = sizeof(cmd_getresp);
payload->wait_delay = 0;
memcpy(payload->data, cmd_getresp, sizeof(cmd_getresp));
SmartCardDirectSend(prepend, payload, output, olen);
} else if (len == 2) {
Dbprintf("***** BAD response from card (response unsupported)...");
Dbhexdump(3, &resp[0], false);
resp[0] = prepend;
resp[1] = 0x6a;
resp[2] =0x82;
AddCrc14A(resp, 3);
//Dbhexdump(5, &resp[0], false); // nathan print
//EmSendCmd(&resp[0], 5);
memcpy(output, resp, 5);
*olen = 5;
}
if (resp[1] == 0x6a && resp[2] == 0x82) {
Dbprintf("***** bad response from card (file not found)...");
resp[0] = prepend;
resp[1] = 0x6a;
resp[2] =0x82;
AddCrc14A(resp, 3);
//Dbhexdump(5, &resp[0], false); // nathan print
//EmSendCmd14443aRaw(&resp[0], 5);
//EmSendCmd(&resp[0], 5);
memcpy(output, resp, 5);
*olen = 5;
FpgaDisableTracing();
}
if (len > 2) {
// print nathan
Dbprintf("***** sending it over the wire... len: %d =>\n", len);
resp[1] = prepend;
// if we have a generate AC request, lets extract the data and populate the template
if (resp[1] != 0xff && resp[2] == 0x77) {
Dbprintf("we have detected a generate ac response, lets repackage it!");
Dbhexdump(len, &resp[1], false); // nathan print
// 11 and 12 are trans counter.
// 16 to 24 are the cryptogram
// 27 to 34 is issuer application data
Dbprintf("atc: %d %d, cryptogram: %d ", resp[11], resp[12], resp[13]);
// then, on the template:
// 61 and 62 for counter
// 46 to 54 for cryptogram
// 36 to 43 for issuer application data
uint8_t template[] = { 0x00, 0x00, 0x77, 0x47, 0x82, 0x02, 0x39, 0x00, 0x57, 0x13, 0x47, 0x62, 0x28, 0x00, 0x05, 0x93, 0x38, 0x64, 0xd2, 0x70, 0x92, 0x01, 0x00, 0x00, 0x01, 0x42, 0x00, 0x00, 0x0f, 0x5f, 0x34, 0x01, 0x00, 0x9f, 0x10, 0x07, 0x06, 0x01, 0x12, 0x03, 0xa0, 0x20, 0x00, 0x9f, 0x26, 0x08, 0x56, 0xcb, 0x4e, 0xe1, 0xa4, 0xef, 0xac, 0x74, 0x9f, 0x27, 0x01, 0x80, 0x9f, 0x36, 0x02, 0x00, 0x07, 0x9f, 0x6c, 0x02, 0x3e, 0x00, 0x9f, 0x6e, 0x04, 0x20, 0x70, 0x00, 0x00, 0x90, 0x00, 0xff, 0xff};
// do the replacement
template[1] = resp[1]; // class bit
template[61] = resp[11];
template[62] = resp[12];
template[46] = resp[16];
template[47] = resp[17];
template[48] = resp[18];
template[49] = resp[19];
template[50] = resp[20];
template[51] = resp[21];
template[52] = resp[22];
template[53] = resp[23];
template[54] = resp[24];
template[36] = resp[27];
template[37] = resp[28];
template[38] = resp[29];
template[39] = resp[30];
template[40] = resp[31];
template[41] = resp[32];
template[42] = resp[33];
Dbprintf("\nrearranged is: ");
len = sizeof(template);
Dbhexdump(len, &template[0], false); // nathan print
AddCrc14A(&template[1], len-3);
Dbprintf("\nafter crc rearranged is: ");
Dbhexdump(len, &template[0], false); // nathan print
Dbprintf("\n");
//EmSendCmd(&template[1], len-1);
memcpy(output, &template[1], len-1);
*olen = len-1;
BigBuf_free();
return;
}
//Dbhexdump(len, &resp[1], false); // nathan print
AddCrc14A(&resp[1], len);
Dbhexdump(len+2, &resp[1], false); // nathan print
// Check we don't want to modify the response (application profile response)
//uint8_t modifyme[] = {0x03, 0x77, 0x0e, 0x82, 0x02};
BigBuf_free();
if (prepend == 0xff) {
Dbprintf("pdol request, we can can the response...");
return;
}
if (memcmp(&resp[2], &pay1_response[0], sizeof(pay1_response)) == 0 && true) {
Dbprintf("Switching out the pay1 response for a pay2 response...");
//EmSendCmd(&pay2_response[0], sizeof(pay2_response));
memcpy(output, &pay2_response[0], sizeof(pay2_response));
*olen = sizeof(pay2_response);
}
else if (memcmp(&resp[1], &fci_template[0], 2) == 0 && true) {
Dbprintf("***** modifying response to have full fci template...!");
//EmSendCmd(&fci_template[0], sizeof(fci_template));
memcpy(output, &fci_template[0], sizeof(fci_template));
*olen = sizeof(fci_template);
} else {
//Dbprintf("***** not modifying response...");
//EmSendCmd(&resp[1], len + 2);
memcpy(output, &resp[1], len + 2);
*olen = len + 2;
}
BigBuf_free();
//memcpy(saved_command, &resp[1], len+2);
//saved_command_len = len+2;
//EmSendCmd14443aRaw(&resp[1], len+2);
//FpgaDisableTracing();
//EmSend4bit(encrypted_data ? mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA) : CARD_NACK_NA);
}
//reply_ng(CMD_SMART_RAW, PM3_SUCCESS, resp, len);
OUT:
//BigBuf_free();
//set_tracing(false);
LEDsoff();
}
int CmdSmartRaw(const uint8_t prepend, const uint8_t *data, int dlen, uint8_t *output, uint16_t *olen) {
Dbprintf("sending command to smart card... %02x %02x %02x... =>", prepend, data[0], data[1]);
Dbhexdump(dlen, data, false);
if (data[4] + 5 != dlen) {
Dbprintf("invalid length of data. Received: %d, command specifies %d", dlen, data[4] + 5);
dlen = data[4] + 5;
}
//smart_card_raw_t *payload = calloc(1, sizeof(smart_card_raw_t) + dlen);
smart_card_raw_t *payload = (smart_card_raw_t *)BigBuf_calloc(sizeof(smart_card_raw_t) + dlen);
if (payload == NULL) {
Dbprintf("failed to allocate memory");
return PM3_EMALLOC;
}
payload->len = dlen;
memcpy(payload->data, data, dlen);
payload->flags = SC_LOG;
bool active = true;
bool active_select = false;
int timeout = 600;
bool use_t0 = true;
if (active || active_select) {
payload->flags |= (SC_CONNECT | SC_CLEARLOG);
if (active_select)
payload->flags |= SC_SELECT;
}
payload->wait_delay = 0;
if (timeout > -1) {
payload->flags |= SC_WAIT;
payload->wait_delay = timeout;
}
//Dbprintf("SIM Card timeout... %u ms", payload->wait_delay);
if (dlen > 0) {
if (use_t0)
payload->flags |= SC_RAW_T0;
else
payload->flags |= SC_RAW;
}
////uint8_t *buf = calloc(PM3_CMD_DATA_SIZE, sizeof(uint8_t));
//uint8_t *buf = BigBuf_calloc(PM3_CMD_DATA_SIZE, sizeof(uint8_t));
//if (buf == NULL) {
// Dbprintf("failed to allocate memory");
// free(payload);
// return PM3_EMALLOC;
//}
//clearCommandBuffer();
//SendCommandNG(CMD_SMART_RAW, (uint8_t *)payload, sizeof(smart_card_raw_t) + dlen);
//for (int i = 0; i < dlen; i++) {
// Dbprintf("%02x ", data[i]);
//}
SmartCardDirectSend(prepend, payload, output, olen);
//if (reply == false) {
// Dbprintf("failed to talk to smart card!!!");
// goto out;
//}
//// reading response from smart card
//int len = smart_response(buf, PM3_CMD_DATA_SIZE);
//if (len < 0) {
// free(payload);
// free(buf);
// return PM3_ESOFT;
//}
//if (buf[0] == 0x6C) {
// // request more bytes to download
// data[4] = buf[1];
// memcpy(payload->data, data, dlen);
// clearCommandBuffer();
// SendCommandNG(CMD_SMART_RAW, (uint8_t *)payload, sizeof(smart_card_raw_t) + dlen);
// len = smart_response(buf, PM3_CMD_DATA_SIZE);
// data[4] = 0;
//}
//if (decode_tlv && len > 4) {
// TLVPrintFromBuffer(buf, len - 2);
//} else {
// if (len > 2) {
// Dbprintf("Response data:");
// Dbprintf(" # | bytes | ascii");
// Dbprintf("---+-------------------------------------------------+-----------------");
// print_hex_break(buf, len, 16);
// }
//}
//memcpy(buffer, buf, len);
//out:
//free(payload);
//free(buf);
return PM3_SUCCESS;
}

22
armsrc/i2c_direct.h Normal file
View file

@ -0,0 +1,22 @@
//-----------------------------------------------------------------------------
// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// See LICENSE.txt for the text of the license.
//-----------------------------------------------------------------------------
#ifndef __I2C_DIRECT_H
#define __I2C_DIRECT_H
int CmdSmartRaw(const uint8_t prepend, const uint8_t *data, int dlen, uint8_t *output, uint16_t *olen);
#endif