Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cherry pick POC of emv simulation #2652

Merged
merged 2 commits into from
Jan 14, 2025
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Cherry pick POC of emv simulation
n-hutton committed Nov 21, 2024
commit 4a23fb05f0aa93a85f589d899f687a0dd71a45c6
4 changes: 2 additions & 2 deletions armsrc/Makefile
Original file line number Diff line number Diff line change
@@ -37,7 +37,7 @@ APP_CFLAGS = $(PLATFORM_DEFS) \
SRC_LF = lfops.c lfsampling.c pcf7931.c lfdemod.c lfadc.c
SRC_HF = hfops.c
SRC_ISO15693 = iso15693.c iso15693tools.c
SRC_ISO14443a = iso14443a.c mifareutil.c mifarecmd.c epa.c mifaresim.c sam_mfc.c sam_seos.c
SRC_ISO14443a = iso14443a.c mifareutil.c mifarecmd.c epa.c mifaresim.c sam_mfc.c sam_seos.c emvsim.c
#UNUSED: mifaresniff.c
SRC_ISO14443b = iso14443b.c
SRC_FELICA = felica.c
@@ -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
14 changes: 14 additions & 0 deletions armsrc/appmain.c
Original file line number Diff line number Diff line change
@@ -54,6 +54,7 @@
#include "mifarecmd.h"
#include "mifaredesfire.h"
#include "mifaresim.h"
#include "emvsim.h"
#include "pcf7931.h"
#include "Standalone/standalone.h"
#include "util.h"
@@ -1628,6 +1629,19 @@ static void PacketReceived(PacketCommandNG *packet) {
ReaderIso14443a(packet);
break;
}
case CMD_HF_ISO14443A_EMV_SIMULATE: {
struct p {
uint16_t flags;
uint8_t exitAfter;
uint8_t uid[7];
uint16_t atqa;
uint8_t sak;
} PACKED;
struct p *payload = (struct p *) packet->data.asBytes;

EMVsim(payload->flags, payload->exitAfter, payload->uid, payload->atqa, payload->sak);
break;
}
case CMD_HF_ISO14443A_SIMULATE: {
struct p {
uint8_t tagtype;
787 changes: 787 additions & 0 deletions armsrc/emvsim.c

Large diffs are not rendered by default.

29 changes: 29 additions & 0 deletions armsrc/emvsim.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//-----------------------------------------------------------------------------
// Copyright (C) Gerhard de Koning Gans - May 2008
// 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.
//-----------------------------------------------------------------------------
// Mifare Classic Card Simulation
//-----------------------------------------------------------------------------

#ifndef __EMVSIM_H
#define __EMVSIM_H

#include "common.h"

#define AUTHKEYNONE 0xff

void EMVsim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint16_t atqa, uint8_t sak);

#endif
371 changes: 371 additions & 0 deletions armsrc/i2c_direct.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,371 @@
// //-----------------------------------------------------------------------------
// 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 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); // special 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); // special print
//EmSendCmd14443aRaw(&resp[0], 5);
//EmSendCmd(&resp[0], 5);
memcpy(output, resp, 5);
*olen = 5;
FpgaDisableTracing();
}

if (len > 2) {
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); // special 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); // special print

AddCrc14A(&template[1], len-3);
Dbprintf("\nafter crc rearranged is: ");
Dbhexdump(len, &template[0], false); // special 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); // special print
AddCrc14A(&resp[1], len);
Dbhexdump(len+2, &resp[1], false); // special 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 changes: 22 additions & 0 deletions armsrc/i2c_direct.h
Original file line number Diff line number Diff line change
@@ -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
71 changes: 69 additions & 2 deletions client/src/emv/cmdemv.c
Original file line number Diff line number Diff line change
@@ -39,7 +39,6 @@
#include "crypto/libpcrypto.h"
#include "iso4217.h" // currency lookup


static int CmdHelp(const char *Cmd);

#define TLV_ADD(tag, value)( tlvdb_change_or_add_node(tlvRoot, tag, sizeof(value) - 1, (const unsigned char *)value) )
@@ -630,6 +629,73 @@ static int CmdEMVSelect(const char *Cmd) {
return PM3_SUCCESS;
}

static int CmdEMVSmartToNFC(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "emv smart2nfc",
"Executes ISO14443a payment, TX using ISO7816 interface for authentication",
"emv smart2nfc -t -> test that the attached card is working (must be VISA)\n");

void *argtable[] = {
arg_param_begin,
arg_lit0("t", "test", "test that the attached card is working (must be VISA)"),
arg_str0("u", "uid", "<hex>", "optional 7 hex bytes UID"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);

int uid_len = 0;
uint8_t uid[7] = {0};
CLIGetHexWithReturn(ctx, 2, uid, &uid_len);

if (uid_len == 0) {
PrintAndLogEx(SUCCESS, "No UID provided, using default.");
uint8_t default_uid[7] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
memcpy(uid, default_uid, sizeof(default_uid));
uid_len = sizeof(default_uid);
} else if (uid_len != 7) {
PrintAndLogEx(FAILED, "UID must be 7 bytes long.");
return PM3_EINVARG;
}

PrintAndLogEx(SUCCESS, "UID length is %d", uid_len);

bool testMode = arg_get_lit(ctx, 1);
bool show_apdu = true;

if (testMode) {
PrintAndLogEx(SUCCESS, "Test mode enabled.");
} else {
PrintAndLogEx(SUCCESS, "Test mode disabled.");
}

CLIParserFree(ctx);

// todo: check this is relevant for us.
SetAPDULogging(show_apdu);

struct {
uint16_t flags;
uint8_t exitAfter;
uint8_t uid[7];
uint16_t atqa;
uint8_t sak;
} PACKED payload;

memcpy(payload.uid, uid, uid_len);
payload.flags = 0x1204;
payload.exitAfter = 0x1;
payload.atqa = 0x0;
payload.sak = 0x20;

clearCommandBuffer();
SendCommandNG(0x0386, (uint8_t *)&payload, sizeof(payload));

PrintAndLogEx(INFO, "Press " _GREEN_("pm3 button") " to abort simulation");

SetAPDULogging(false);
return PM3_SUCCESS;
}

static int CmdEMVSearch(const char *Cmd) {

CLIParserContext *ctx;
@@ -2913,8 +2979,9 @@ static command_t CommandTable[] = {
{"scan", CmdEMVScan, IfPm3Iso14443, "Scan EMV card and save it contents to json file for emulator"},
{"search", CmdEMVSearch, IfPm3Iso14443, "Try to select all applets from applets list and print installed applets"},
{"select", CmdEMVSelect, IfPm3Iso14443, "Select applet"},
/*
{"-----------", CmdHelp, IfPm3Iso14443a, "---------------------- " _CYAN_("simulation") " ---------------------"},
{"smart2nfc", CmdEMVSmartToNFC, IfPm3Iso14443, "Complete transaction as a nfc smart card, using the ISO-7816 interface for auth"},
/*
{"getrng", CmdEMVGetrng, IfPm3Iso14443, "Get random number from terminal"},
{"eload", CmdEmvELoad, IfPm3Iso14443, "Load EMV tag into device"},
{"dump", CmdEmvDump, IfPm3Iso14443, "Dump EMV tag values"},
1 change: 1 addition & 0 deletions include/pm3_cmd.h
Original file line number Diff line number Diff line change
@@ -612,6 +612,7 @@ typedef struct {
#define CMD_HF_ISO14443A_SIM_AID 0x1420

#define CMD_HF_ISO14443A_READER 0x0385
#define CMD_HF_ISO14443A_EMV_SIMULATE 0x0386

#define CMD_HF_LEGIC_SIMULATE 0x0387
#define CMD_HF_LEGIC_READER 0x0388
3 changes: 2 additions & 1 deletion tools/deprecated-hid-flasher/flasher/usb_cmd.h
Original file line number Diff line number Diff line change
@@ -137,6 +137,7 @@ typedef struct {
#define CMD_HF_ISO14443A_SNIFF 0x0383
#define CMD_HF_ISO14443A_SIMULATE 0x0384
#define CMD_HF_ISO14443A_READER 0x0385
#define CMD_HF_ISO14443A_EMV_SIMULATE 0x0386

#define CMD_HF_LEGIC_SIMULATE 0x0387
#define CMD_HF_LEGIC_READER 0x0388
@@ -180,7 +181,7 @@ typedef struct {

#define CMD_HF_MIFARE_READER 0x0611
#define CMD_HF_MIFARE_NESTED 0x0612
#define CMD_HF_MIFARE_ACQ_ENCRYPTED_NONCES 0x0613
#define CMD_HF_MIFARE_ACQ_ENCRYPTED_NONCES 0x0613


#define CMD_HF_MIFARE_READBL 0x0620