diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 75d74c9da..75f85a7bd 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -1311,7 +1311,11 @@ static void PacketReceived(PacketCommandNG *packet) { break; } case CMD_HF_FELICALITE_SIMULATE: { - felica_sim_lite(packet->oldarg[0]); + struct p { + uint8_t uid[8]; + } PACKED; + struct p *payload = (struct p *) packet->data.asBytes; + felica_sim_lite(payload->uid); break; } case CMD_HF_FELICA_SNIFF: { diff --git a/armsrc/felica.c b/armsrc/felica.c index 7aa524e62..3783c802f 100644 --- a/armsrc/felica.c +++ b/armsrc/felica.c @@ -630,51 +630,74 @@ void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip) { #define R_READBLK_LEN 0x21 //simulate NFC Tag3 card - for now only poll response works // second half (4 bytes) of NDEF2 goes into nfcid2_0, first into nfcid2_1 -void felica_sim_lite(uint64_t uid) { +void felica_sim_lite(uint8_t *uid) { - int i, curlen = 0; - uint8_t *curresp = 0; - - uint8_t ndef[8]; - num_to_bytes(uid, 8, ndef); - - //prepare our 3 responses... + // prepare our 3 responses... uint8_t resp_poll0[R_POLL0_LEN] = { 0xb2, 0x4d, 0x12, FELICA_POLL_ACK, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf1, 0x00, 0x00, 0x00, 0x01, 0x43, 0x00, 0xb3, 0x7f}; uint8_t resp_poll1[R_POLL1_LEN] = { 0xb2, 0x4d, 0x14, FELICA_POLL_ACK, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf1, 0x00, 0x00, 0x00, 0x01, 0x43, 0x00, 0x88, 0xb4, 0xb3, 0x7f}; uint8_t resp_readblk[R_READBLK_LEN] = { 0xb2, 0x4d, 0x1d, FELICA_RDBLK_ACK, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x04, 0x01, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x23, 0xcb, 0x6e}; - //NFC tag 3/ ISo technically. Many overlapping standards - DbpString("Felica Lite-S sim start"); + // NFC tag 3/ ISo technically. Many overlapping standards + DbpString("Felica Lite-S simulation start"); Dbprintf("NDEF2 UID: %02x %02x %02x %02x %02x %02x %02x %02x", - ndef[0], ndef[1], ndef[2], ndef[3], ndef[4], ndef[5], ndef[6], ndef[7] + uid[0], uid[1], uid[2], uid[3], uid[4], uid[5], uid[6], uid[7] ); - //fill in blanks - for (i = 0; i < 8; i++) { - resp_poll0[i + 4] = ndef[i]; - resp_poll1[i + 4] = ndef[i]; - resp_readblk[i + 4] = ndef[i]; + // fill in blanks + for (uint8_t i = 0; i < 8; i++) { + resp_poll0[i + 4] = uid[i]; + resp_poll1[i + 4] = uid[i]; + resp_readblk[i + 4] = uid[i]; } - //calculate and set CRC + // calculate and set CRC AddCrc(resp_poll0, resp_poll0[2]); AddCrc(resp_poll1, resp_poll1[2]); AddCrc(resp_readblk, resp_readblk[2]); iso18092_setup(FPGA_HF_ISO18092_FLAG_NOMOD); + int retval = PM3_SUCCESS; + int curlen = 0; + uint8_t *curresp = NULL; bool listenmode = true; - //uint32_t frtm = GetCountSspClk(); + // uint32_t frtm = GetCountSspClk(); + + uint8_t flip = 0; + uint16_t checker = 0; for (;;) { - if (BUTTON_PRESS()) break; + + WDT_HIT(); + + // since simulation is a tight time critical loop, + // we only check for user request to end at iteration 3000, 9000. + if (flip == 3) { + if (data_available()) { + retval = PM3_EOPABORTED; + break; + } + flip = 0; + } + + if (checker >= 3000) { + + if (BUTTON_PRESS()) { + retval = PM3_EOPABORTED; + break; + } + flip++; + checker = 0; + } + ++checker; + WDT_HIT(); if (listenmode) { - //waiting for request... + // waiting for request... if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { uint8_t dist = (uint8_t)(AT91C_BASE_SSC->SSC_RHR); - //frtm = GetCountSspClk(); + // frtm = GetCountSspClk(); Process18092Byte(dist); if (FelicaFrame.state == STATE_FULL) { @@ -683,7 +706,7 @@ void felica_sim_lite(uint64_t uid) { if (FelicaFrame.framebytes[2] == 6 && FelicaFrame.framebytes[3] == 0) { - //polling... there are two types of polling we answer to + // polling... there are two types of polling we answer to if (FelicaFrame.framebytes[6] == 0) { curresp = resp_poll0; curlen = R_POLL0_LEN; @@ -697,28 +720,30 @@ void felica_sim_lite(uint64_t uid) { } if (FelicaFrame.framebytes[2] > 5 && FelicaFrame.framebytes[3] == 0x06) { - //we should rebuild it depending on page size, but... - //Let's see first + // we should rebuild it depending on page size, but... + // Let's see first curresp = resp_readblk; curlen = R_READBLK_LEN; listenmode = false; } - //clear frame + // clear frame FelicaFrameReset(); } else { - //frame invalid, clear it out to allow for the next one + // frame invalid, clear it out to allow for the next one FelicaFrameReset(); } } } } - if (!listenmode) { - //trying to answer... here to start answering immediately. - //this one is a bit finicky. Seems that being a bit late is better than earlier - //TransmitFor18092_AsReader(curresp, curlen, frtm+512, 0, 0); + + + if (listenmode == false) { + // trying to answer... here to start answering immediately. + // this one is a bit finicky. Seems that being a bit late is better than earlier + // TransmitFor18092_AsReader(curresp, curlen, frtm+512, 0, 0); TransmitFor18092_AsReader(curresp, curlen, NULL, 0, 0); - //switch back + // switch back FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO18092 | FPGA_HF_ISO18092_FLAG_NOMOD); FelicaFrameReset(); @@ -730,10 +755,11 @@ void felica_sim_lite(uint64_t uid) { switch_off(); - //reset framing + // reset framing AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0); - DbpString("Felica Lite-S sim end"); + Dbprintf("FeliCa Lite-S emulator stopped. Trace length: %d ", BigBuf_get_traceLen()); + reply_ng(CMD_HF_FELICALITE_SIMULATE, retval, NULL, 0); } #define RES_SVC_LEN 11 + 3 diff --git a/armsrc/felica.h b/armsrc/felica.h index 885815abb..f30de4b6f 100644 --- a/armsrc/felica.h +++ b/armsrc/felica.h @@ -6,7 +6,7 @@ // at your option, any later version. See the LICENSE.txt file for the text of // the license. //----------------------------------------------------------------------------- -// Definitions internal to the app source. +// Definitions internal to the FeliCa functionality //----------------------------------------------------------------------------- #ifndef __FELICA_H #define __FELICA_H @@ -16,7 +16,7 @@ void felica_sendraw(PacketCommandNG *c); void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip); -void felica_sim_lite(uint64_t uid); +void felica_sim_lite(uint8_t *uid); void felica_dump_lite_s(void); #endif diff --git a/client/src/cmdhffelica.c b/client/src/cmdhffelica.c index 2cf30a5ec..246d5bff3 100644 --- a/client/src/cmdhffelica.c +++ b/client/src/cmdhffelica.c @@ -8,22 +8,21 @@ // High frequency ISO18092 / FeliCa commands //----------------------------------------------------------------------------- #include "cmdhffelica.h" - #include #include #include #include #include - -#include "cmdparser.h" // command_t +#include "cmdparser.h" // command_t #include "comms.h" #include "cmdtrace.h" #include "crc16.h" #include "util.h" #include "ui.h" -#include "iso18.h" // felica_card_select_t struct +#include "iso18.h" // felica_card_select_t struct #include "des.h" -#include "cliparser.h" // cliparser +#include "cliparser.h" // cliparser +#include "util_posix.h" // msleep #define AddCrc(data, len) compute_crc(CRC_FELICA, (data), (len), (data)+(len)+1, (data)+(len)) @@ -136,28 +135,6 @@ static int usage_hf_felica_sniff(void) { return PM3_SUCCESS; } -static int usage_hf_felica_simlite(void) { - PrintAndLogEx(NORMAL, "\n Emulating ISO/18092 FeliCa Lite tag \n"); - PrintAndLogEx(NORMAL, "Usage: hf felica litesim [h] u "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h : This help"); - PrintAndLogEx(NORMAL, " uid : UID in hexsymbol"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf felica litesim 11223344556677"); - return PM3_SUCCESS; -} - -static int usage_hf_felica_dumplite(void) { - PrintAndLogEx(NORMAL, "\n Dump ISO/18092 FeliCa Lite tag \n"); - PrintAndLogEx(NORMAL, "press button to abort run, otherwise it will loop for 200sec."); - PrintAndLogEx(NORMAL, "Usage: hf felica litedump [h]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h : This help"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf felica litedump"); - return PM3_SUCCESS; -} - static int usage_hf_felica_request_service(void) { PrintAndLogEx(NORMAL, "\nInfo: Use this command to verify the existence of Area and Service, and to acquire Key Version:"); PrintAndLogEx(NORMAL, " - When the specified Area or Service exists, the card returns Key Version."); @@ -1455,13 +1432,48 @@ static int CmdHFFelicaSniff(const char *Cmd) { // uid hex static int CmdHFFelicaSimLite(const char *Cmd) { - uint64_t uid = param_get64ex(Cmd, 0, 0, 16); + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf felica litesim", + "Emulating ISO/18092 FeliCa Lite tag", + "hf felica litesim -u 1122334455667788" + ); + void *argtable[] = { + arg_param_begin, + arg_str1("u", "uid", "", "UID/NDEF2 8 hex bytes"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + int uid_len = 0; + struct p { + uint8_t uid[8]; + } PACKED payload; + CLIGetHexWithReturn(ctx, 1, payload.uid, &uid_len); + CLIParserFree(ctx); - if (!uid) - return usage_hf_felica_simlite(); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(INFO, "Press " _GREEN_("") " or pm3-button to abort simulation"); clearCommandBuffer(); - SendCommandMIX(CMD_HF_FELICALITE_SIMULATE, uid, 0, 0, NULL, 0); + SendCommandNG(CMD_HF_FELICALITE_SIMULATE, payload.uid, sizeof(payload)); + PacketResponseNG resp; + + for (;;) { + if (kbd_enter_pressed()) { + SendCommandNG(CMD_BREAK_LOOP, NULL, 0); + PrintAndLogEx(DEBUG, "User aborted"); + msleep(300); + break; + } + + if (WaitForResponseTimeout(CMD_HF_FELICALITE_SIMULATE, &resp, 1000)) { + if (resp.status == PM3_EOPABORTED) { + PrintAndLogEx(DEBUG, "Button pressed, user aborted"); + break; + } + } + } + + PrintAndLogEx(INFO, "Done"); return PM3_SUCCESS; } @@ -1618,19 +1630,46 @@ static uint16_t PrintFliteBlock(uint16_t tracepos, uint8_t *trace, uint16_t trac static int CmdHFFelicaDumpLite(const char *Cmd) { - char ctmp = tolower(param_getchar(Cmd, 0)); - if (ctmp == 'h') return usage_hf_felica_dumplite(); +/* +iceman 2021, +Why does this command say it dumps a FeliCa lite card +and then tries to print a trace?!? +Is this a trace list or a feclia dump cmd? +*/ + + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf felica litedump", + "Dump ISO/18092 FeliCa Lite tag. It will timeout after 200sec", + "hf felica litedump" + ); + void *argtable[] = { + arg_param_begin, + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + CLIParserFree(ctx); + PrintAndLogEx(SUCCESS, "FeliCa lite - dump started"); - PrintAndLogEx(SUCCESS, "press pm3-button to cancel"); + clearCommandBuffer(); SendCommandNG(CMD_HF_FELICALITE_DUMP, NULL, 0); PacketResponseNG resp; + PrintAndLogEx(INFO, "Press " _GREEN_("") " or pm3-button to abort dumping"); + uint8_t timeout = 0; - while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + while (WaitForResponseTimeout(CMD_ACK, &resp, 2000) == false) { + + if (kbd_enter_pressed()) { + SendCommandNG(CMD_BREAK_LOOP, NULL, 0); + PrintAndLogEx(DEBUG, "User aborted"); + return PM3_EOPABORTED; + } + timeout++; - PrintAndLogEx(NORMAL, "." NOLF); + PrintAndLogEx(INPLACE, "% 3i", timeout); + fflush(stdout); if (kbd_enter_pressed()) { PrintAndLogEx(WARNING, "\naborted via keyboard!\n"); @@ -1659,7 +1698,7 @@ static int CmdHFFelicaDumpLite(const char *Cmd) { uint8_t *trace = calloc(tracelen, sizeof(uint8_t)); if (trace == NULL) { - PrintAndLogEx(WARNING, "Cannot allocate memory for trace"); + PrintAndLogEx(WARNING, "failed to allocate memory "); return PM3_EMALLOC; } @@ -1669,8 +1708,8 @@ static int CmdHFFelicaDumpLite(const char *Cmd) { return PM3_ETIMEOUT; } - PrintAndLogEx(SUCCESS, "Recorded Activity (trace len = %"PRIu32" bytes)", tracelen); + PrintAndLogEx(SUCCESS, "Recorded Activity (trace len = %"PRIu32" bytes)", tracelen); print_hex_break(trace, tracelen, 32); printSep(); @@ -1791,7 +1830,7 @@ int readFelicaUid(bool verbose) { } case 0: { PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(SUCCESS, "FeliCa tag info"); + PrintAndLogEx(SUCCESS, "-------- " _CYAN_("FeliCa tag info") " -------------------"); PrintAndLogEx(SUCCESS, "IDm %s", sprint_hex(card.IDm, sizeof(card.IDm))); PrintAndLogEx(SUCCESS, " - CODE %s", sprint_hex(card.code, sizeof(card.code))); @@ -1839,7 +1878,7 @@ static command_t CommandTable[] = { //{"writev2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "write Block Data to authentication-required Service."}, //{"uprandomid", CmdHFFelicaNotImplementedYet, IfPm3Felica, "update Random ID (IDr)."}, {"-----------", CmdHelp, AlwaysAvailable, "----------------------- " _CYAN_("FeliCa Light") " -----------------------"}, - {"litesim", CmdHFFelicaSimLite, IfPm3Felica, " - only reply to poll request"}, + {"litesim", CmdHFFelicaSimLite, IfPm3Felica, "Emulating ISO/18092 FeliCa Lite tag"}, {"litedump", CmdHFFelicaDumpLite, IfPm3Felica, "Wait for and try dumping FelicaLite"}, // {"sim", CmdHFFelicaSim, IfPm3Felica, " -- Simulate ISO 18092/FeliCa tag"} {NULL, NULL, NULL, NULL}