mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-07-05 20:41:34 -07:00
205 lines
5.8 KiB
C
205 lines
5.8 KiB
C
// //-----------------------------------------------------------------------------
|
|
// 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"
|
|
|
|
static 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_calloc(ISO7816_MAX_FRAME);
|
|
resp[0] = prepend;
|
|
// check if alloacted...
|
|
smartcard_command_t flags = p->flags;
|
|
|
|
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);
|
|
|
|
if (gotATR == false) {
|
|
Dbprintf("No ATR received...\n");
|
|
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) {
|
|
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) {
|
|
uint8_t cmd_getresp[] = {0x00, ISO7816_GET_RESPONSE, 0x00, 0x00, resp[2]};
|
|
|
|
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);
|
|
|
|
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);
|
|
|
|
memcpy(output, resp, 5);
|
|
*olen = 5;
|
|
FpgaDisableTracing();
|
|
}
|
|
|
|
if (len > 2) {
|
|
Dbprintf("***** sending it over the wire... len: %d =>\n", len);
|
|
resp[1] = prepend;
|
|
|
|
AddCrc14A(&resp[1], len);
|
|
Dbhexdump(len + 2, &resp[1], false);
|
|
|
|
BigBuf_free();
|
|
|
|
if (prepend == 0xff) {
|
|
Dbprintf("pdol request, we can ignore the response...");
|
|
return;
|
|
}
|
|
|
|
memcpy(output, &resp[1], len + 2);
|
|
*olen = len + 2;
|
|
|
|
BigBuf_free();
|
|
}
|
|
|
|
OUT:
|
|
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 = (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;
|
|
}
|
|
|
|
if (dlen > 0) {
|
|
if (use_t0)
|
|
payload->flags |= SC_RAW_T0;
|
|
else
|
|
payload->flags |= SC_RAW;
|
|
}
|
|
|
|
SmartCardDirectSend(prepend, payload, output, olen);
|
|
|
|
return PM3_SUCCESS;
|
|
}
|