From f7d4f2e9f3a0a069f916b406519104095bf1e9db Mon Sep 17 00:00:00 2001 From: Thomas Sutter Date: Sun, 20 Oct 2019 18:28:07 +0200 Subject: [PATCH 01/24] Unfinished request service commands. --- armsrc/felica.c | 14 ++-- client/cmdhffelica.c | 149 +++++++++++++++++++++++++++++++++++++++---- client/cmdhffelica.h | 3 +- 3 files changed, 144 insertions(+), 22 deletions(-) diff --git a/armsrc/felica.c b/armsrc/felica.c index ab22bc778..023f4d719 100644 --- a/armsrc/felica.c +++ b/armsrc/felica.c @@ -14,17 +14,17 @@ // FeliCa timings // minimum time between the start bits of consecutive transfers from reader to tag: 6800 carrier (13.56MHz) cycles #ifndef FELICA_REQUEST_GUARD_TIME -# define FELICA_REQUEST_GUARD_TIME (6800/16 + 1) +# define FELICA_REQUEST_GUARD_TIME (6800/16 + 1) // 426 #endif // FRAME DELAY TIME 2672 carrier cycles #ifndef FELICA_FRAME_DELAY_TIME -# define FELICA_FRAME_DELAY_TIME (2672/16 + 1) +# define FELICA_FRAME_DELAY_TIME (2672/16 + 1) // 168 #endif #ifndef DELAY_AIR2ARM_AS_READER -#define DELAY_AIR2ARM_AS_READER (3 + 16 + 8 + 8*16 + 4*16 - 8*16) +#define DELAY_AIR2ARM_AS_READER (3 + 16 + 8 + 8*16 + 4*16 - 8*16) // 91 #endif #ifndef DELAY_ARM2AIR_AS_READER -#define DELAY_ARM2AIR_AS_READER (4*16 + 8*16 + 8 + 8 + 1) +#define DELAY_ARM2AIR_AS_READER (4*16 + 8*16 + 8 + 8 + 1) // 209 #endif // CRC skips two first sync bits in data buffer @@ -357,7 +357,6 @@ static void TransmitFor18092_AsReader(uint8_t *frame, int len, uint32_t *timing, // sending 0x00 0x00 0x00 0x00 0x00 0x00 uint16_t c = 0; while (c < 6) { - // keep tx buffer in a defined state anyway. if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { AT91C_BASE_SSC->SSC_THR = 0x00; @@ -416,8 +415,6 @@ bool WaitForFelicaReply(uint16_t maxbytes) { uint32_t timeout = iso18092_get_timeout(); if (DBGLEVEL > 3) Dbprintf("timeout set: %i", timeout); - //TODO FIX THIS METHOD - Race Condition or something: TIMING/MEMORY ISSUES - // If you add content here (dbprintf), timing problems appear?! Last Bytes (CRC) of frame will be cutoff. for (;;) { WDT_HIT(); if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { @@ -527,7 +524,7 @@ void felica_sendraw(PacketCommandNG *c) { arg0 = felica_select_card(&card); reply_mix(CMD_ACK, arg0, sizeof(card.uid), 0, &card, sizeof(felica_card_select_t)); if (arg0 > 0) { - Dbprintf("Error: Failed selecting card! "); + Dbprintf("Error: Failed selecting card!"); felica_reset_frame_mode(); return; } @@ -565,6 +562,7 @@ void felica_sendraw(PacketCommandNG *c) { Dbprintf("Received Frame Code: %d", arg0); Dbhexdump(FelicaFrame.len, FelicaFrame.framebytes, 0); }; + uint32_t result = reply_mix(CMD_ACK, FelicaFrame.len, arg0, 0, FelicaFrame.framebytes, FelicaFrame.len); if (result) { Dbprintf("Reply to Client Error Code: %i", result); diff --git a/client/cmdhffelica.c b/client/cmdhffelica.c index 22acf6344..288ef409e 100644 --- a/client/cmdhffelica.c +++ b/client/cmdhffelica.c @@ -43,7 +43,7 @@ static int usage_hf_felica_sim(void) { static int usage_hf_felica_sniff(void) { PrintAndLogEx(NORMAL, "It get data from the field and saves it into command buffer."); PrintAndLogEx(NORMAL, "Buffer accessible from command 'hf list felica'"); - PrintAndLogEx(NORMAL, "Usage: hf felica sniff "); + PrintAndLogEx(NORMAL, "Usage: hf felica sniff "); PrintAndLogEx(NORMAL, " s samples to skip (decimal)"); PrintAndLogEx(NORMAL, " t triggers to skip (decimal)"); PrintAndLogEx(NORMAL, "Examples:"); @@ -81,6 +81,17 @@ static int usage_hf_felica_raw(void) { return 0; } +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."); + PrintAndLogEx(NORMAL, " - When the specified Area or Service does not exist, the card returns FFFFh as Key Version."); + PrintAndLogEx(NORMAL, "\nUsage: hf felica rqservice [-h] <0A 0B 0C ... IDm hex> <01 Number of Node hex> <0A 0B Node Code List hex (Little Endian)> <0A 0B CRC hex>"); + PrintAndLogEx(NORMAL, " -h this help"); + PrintAndLogEx(NORMAL, " -c calculate and append CRC"); + PrintAndLogEx(NORMAL, "Example: rqservice 01100910c11bc407 01 FFFF 2837"); + return 0; +} + static int usage_hf_felica_dump(void) { PrintAndLogEx(NORMAL, "Usage: hf felica dump [-h] "); PrintAndLogEx(NORMAL, " -h this help"); @@ -102,7 +113,95 @@ static int CmdHFFelicaReader(const char *Cmd) { static int CmdHFFelicaDump(const char *Cmd) { if (strlen(Cmd) < 1) return usage_hf_felica_dump(); - dump(*Cmd); + clearCommandBuffer(); + char ctmp = tolower(param_getchar(Cmd, 0)); + if (ctmp == 'h') return usage_hf_felica_dumplite(); + dump(); + return 0; +} + +static int CmdHFFelicaRequestService(const char *Cmd) { + if (strlen(Cmd) < 2) return usage_hf_felica_request_service(); + char buf[5] = ""; + int i = 0; + uint8_t data[PM3_CMD_DATA_SIZE]; + uint16_t datalen = 0; + set_number_of_cmds(); + while (Cmd[i] != '\0') { + PrintAndLogEx(NORMAL, "String %s: ", Cmd[i]); + if (Cmd[i] == '-') { + switch (Cmd[i + 1]) { + case 'H': + case 'h': + return usage_hf_felica_raw(); + case 'c': + crc = true; + break; + default: + return usage_hf_felica_raw(); + } + i += 2; + } + i = i + parse_cmd_parameter(i); + if(is_hex_input()){ + buf[strlen(buf) + 1] = 0; + buf[strlen(buf)] = Cmd[i]; + i++; + i = i + get_cmd_data(i); + }else{ + i++; + } + } + request_service(); + clearCommandBuffer(); + return 0; +} + +/* + * Parses line spacing and tabs. + * Returns 1 if the given char is a space or tab + */ +static int parse_cmd_parameter_separator(const char *Cmd, int i){ + PrintAndLogEx(NORMAL, "parse_cmd_parameter_separator String %s: ", Cmd[i]); + return Cmd[i] == ' ' || Cmd[i] == '\t' ? 1 : 0; +} + +/* + * Counts and sets the number of commands. + */ +static void set_number_of_cmds(const char *Cmd){ + while (*Cmd == ' ' || *Cmd == '\t'){ + Cmd++; + } +} + +/** + * Checks if a char is a hex value. + * @param Cmd + * @return one if it is a valid hex char. Zero if not a valid hex char. + */ +static bool is_hex_input(const char *Cmd, int i){ + PrintAndLogEx(NORMAL, "is_hex_input String %s: ", Cmd[i]); + return (Cmd[i] >= '0' && Cmd[i] <= '9') || (Cmd[i] >= 'a' && Cmd[i] <= 'f') || (Cmd[i] >= 'A' && Cmd[i] <= 'F') ? 1 : 0; +} + +/** + * + * @param Cmd the chars from which the data will be extracted. + * @return a buffer with the data from the command + */ +static int get_cmd_data(const char *Cmd, int i){ + int char_counter = 0; + if (strlen(buf) >= 2) { + sscanf(buf, "%x", &temp); + data[datalen] = (uint8_t)(temp & 0xff); + *buf = 0; + } + return 0; +} + +static int CmdHFFelicaNotImplementedYet(const char *Cmd) { + PrintAndLogEx(NORMAL, "Feature not implemented Yet!"); return 0; } @@ -174,7 +273,6 @@ static int CmdHFFelicaSim(const char *Cmd) { */ static int CmdHFFelicaSniff(const char *Cmd) { - uint8_t cmdp = 0; uint64_t samples2skip = 0; uint64_t triggers2skip = 0; @@ -211,7 +309,6 @@ static int CmdHFFelicaSniff(const char *Cmd) { // uid hex static int CmdHFFelicaSimLite(const char *Cmd) { - uint64_t uid = param_get64ex(Cmd, 0, 0, 16); if (!uid) @@ -446,6 +543,9 @@ static void waitCmdFelica(uint8_t iSelect) { if (!len) return; PrintAndLogEx(NORMAL, "%s", sprint_hex(resp.data.asBytes, len)); + if(!check_crc(CRC_FELICA, resp.data.asBytes + 2, len - 2)){ + PrintAndLogEx(ERR, "Error: CRC of received bytes are incorrect!"); + } } else { PrintAndLogEx(WARNING, "Timeout while waiting for reply."); } @@ -530,7 +630,6 @@ static int CmdHFFelicaCmdRaw(const char *Cmd) { if (crc && datalen > 0 && datalen < sizeof(data) - 2) { uint8_t b1, b2; compute_crc(CRC_FELICA, data, datalen, &b1, &b2); - // TODO FIND OUT IF FeliCa Light has another CRC order - Order changed for FeliCa Standard cards data[datalen++] = b2; data[datalen++] = b1; } @@ -617,27 +716,53 @@ int readFelicaUid(bool verbose) { return status; } +int dump() { -int dump(const char *Cmd) { - clearCommandBuffer(); - char ctmp = tolower(param_getchar(Cmd, 0)); - if (ctmp == 'h') return usage_hf_felica_dumplite(); // TODO FINISH THIS METHOD PrintAndLogEx(SUCCESS, "NOT IMPLEMENTED YET!"); + return 0; +} + +int request_service() { + + + return 0; } static command_t CommandTable[] = { + {"----------- General -----------", CmdHelp, IfPm3Iso14443a, ""}, {"help", CmdHelp, AlwaysAvailable, "This help"}, {"list", CmdHFFelicaList, AlwaysAvailable, "List ISO 18092/FeliCa history"}, {"reader", CmdHFFelicaReader, IfPm3Felica, "Act like an ISO18092/FeliCa reader"}, -// {"sim", CmdHFFelicaSim, IfPm3Felica, " -- Simulate ISO 18092/FeliCa tag"}, - {"sniff", CmdHFFelicaSniff, IfPm3Felica, "sniff ISO 18092/Felica traffic"}, + {"sniff", CmdHFFelicaSniff, IfPm3Felica, "Sniff ISO 18092/FeliCa traffic"}, {"raw", CmdHFFelicaCmdRaw, IfPm3Felica, "Send raw hex data to tag"}, - {"dump", CmdHFFelicaDump, IfPm3Felica, "Wait for and try dumping Felica"}, + {"----------- FeliCa Standard (support in progress) -----------", CmdHelp, IfPm3Iso14443a, ""}, + {"dump", CmdHFFelicaDump, IfPm3Felica, "Wait for and try dumping FeliCa"}, + {"rqservice", CmdHFFelicaRequestService, IfPm3Felica, "verify the existence of Area and Service, and to acquire Key Version."}, + {"rqresponse", CmdHFFelicaNotImplementedYet, IfPm3Felica, "verify the existence of a card and its Mode."}, + //{"rdNoEncryption", CmdHFFelicaNotImplementedYet, IfPm3Felica, "read Block Data from authentication-not-required Service."}, + //{"wrNoEncryption", CmdHFFelicaNotImplementedYet, IfPm3Felica, "write Block Data to an authentication-required Service."}, + //{"searchSvCode", CmdHFFelicaNotImplementedYet, IfPm3Felica, "acquire Area Code and Service Code."}, + //{"rqSysCode", CmdHFFelicaNotImplementedYet, IfPm3Felica, "acquire System Code registered to the card."}, + //{"auth1", CmdHFFelicaNotImplementedYet, IfPm3Felica, "authenticate a card."}, + //{"auth2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "allow a card to authenticate a Reader/Writer."}, + //{"read", CmdHFFelicaNotImplementedYet, IfPm3Felica, "read Block Data from authentication-required Service."}, + //{"write", CmdHFFelicaNotImplementedYet, IfPm3Felica, "write Block Data to an authentication-required Service."}, + //{"searchSvCodeV2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "verify the existence of Area or Service, and to acquire Key Version."}, + //{"getSysStatus", CmdHFFelicaNotImplementedYet, IfPm3Felica, "acquire the setup information in System."}, + //{"rqSpecVer", CmdHFFelicaNotImplementedYet, IfPm3Felica, "acquire the version of card OS."}, + //{"resetMode", CmdHFFelicaNotImplementedYet, IfPm3Felica, "reset Mode to Mode 0."}, + //{"auth1V2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "authenticate a card."}, + //{"auth2V2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "allow a card to authenticate a Reader/Writer."}, + //{"readV2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "read Block Data from authentication-required Service."}, + //{"writeV2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "write Block Data to authentication-required Service."}, + //{"upRandomID", CmdHFFelicaNotImplementedYet, IfPm3Felica, "update Random ID (IDr)."}, + {"----------- FeliCa Light -----------", CmdHelp, IfPm3Iso14443a, ""}, {"litesim", CmdHFFelicaSimLite, IfPm3Felica, " - only reply to poll request"}, {"litedump", CmdHFFelicaDumpLite, IfPm3Felica, "Wait for and try dumping FelicaLite"}, + // {"sim", CmdHFFelicaSim, IfPm3Felica, " -- Simulate ISO 18092/FeliCa tag"} {NULL, NULL, NULL, NULL} }; diff --git a/client/cmdhffelica.h b/client/cmdhffelica.h index abbbd42a4..88a1a0080 100644 --- a/client/cmdhffelica.h +++ b/client/cmdhffelica.h @@ -14,8 +14,7 @@ #include "common.h" int CmdHFFelica(const char *Cmd); - int readFelicaUid(bool verbose); - int dump(); +int request_service(); #endif From a3f8d635ca6f33550fc4cb494b7003b6580c3ac2 Mon Sep 17 00:00:00 2001 From: Thomas Sutter Date: Sun, 20 Oct 2019 20:26:00 +0200 Subject: [PATCH 02/24] Add new cmd parser functions. --- client/cmdhffelica.c | 134 ++++++++++++++++++++++--------------------- client/cmdhffelica.h | 2 - 2 files changed, 69 insertions(+), 67 deletions(-) diff --git a/client/cmdhffelica.c b/client/cmdhffelica.c index 04580b239..5f963b947 100644 --- a/client/cmdhffelica.c +++ b/client/cmdhffelica.c @@ -88,10 +88,52 @@ static int usage_hf_felica_request_service(void) { PrintAndLogEx(NORMAL, "\nUsage: hf felica rqservice [-h] <0A 0B 0C ... IDm hex> <01 Number of Node hex> <0A 0B Node Code List hex (Little Endian)> <0A 0B CRC hex>"); PrintAndLogEx(NORMAL, " -h this help"); PrintAndLogEx(NORMAL, " -c calculate and append CRC"); - PrintAndLogEx(NORMAL, "Example: rqservice 01100910c11bc407 01 FFFF 2837"); + PrintAndLogEx(NORMAL, "\nExample: hf felica rqservice 01100910c11bc407 01 FFFF 2837\n\n"); return PM3_SUCCESS; } +/* + * Parses line spacing and tabs. + * Returns 1 if the given char is a space or tab + */ +static int parse_cmd_parameter_separator(const char *Cmd, int i){ + return Cmd[i] == ' ' || Cmd[i] == '\t' ? 1 : 0; +} + +/* + * Counts and sets the number of commands. + */ +static void strip_cmds(const char *Cmd){ + PrintAndLogEx(NORMAL, "CMD count: %i", strlen(Cmd)); + while (*Cmd == ' ' || *Cmd == '\t'){ + PrintAndLogEx(NORMAL, "CMD: %s", Cmd); + Cmd++; + } + PrintAndLogEx(NORMAL, "CMD string: %s", Cmd); +} + +/** + * Checks if a char is a hex value. + * @param Cmd + * @return one if it is a valid hex char. Zero if not a valid hex char. + */ +static bool is_hex_input(const char *Cmd, int i){ + return (Cmd[i] >= '0' && Cmd[i] <= '9') || (Cmd[i] >= 'a' && Cmd[i] <= 'f') || (Cmd[i] >= 'A' && Cmd[i] <= 'F') ? 1 : 0; +} + +/** + * + * @param Extracts the data from the cmd and puts it into the data array. + */ +static void get_cmd_data(const char *Cmd, int i, uint16_t datalen, uint8_t *data, char buf[]){ + uint32_t temp; + if (strlen(buf) >= 2) { + sscanf(buf, "%x", &temp); + data[datalen] = (uint8_t)(temp & 0xff); + *buf = 0; + } +} + static int usage_hf_felica_dump(void) { PrintAndLogEx(NORMAL, "Usage: hf felica dump [-h] "); PrintAndLogEx(NORMAL, " -h this help"); @@ -120,15 +162,24 @@ static int CmdHFFelicaDump(const char *Cmd) { return 0; } +/** + * Command parser for rqservice. + * @param Cmd input data of the user. + * @return client result code. + */ static int CmdHFFelicaRequestService(const char *Cmd) { if (strlen(Cmd) < 2) return usage_hf_felica_request_service(); - char buf[5] = ""; int i = 0; uint8_t data[PM3_CMD_DATA_SIZE]; + bool crc = false; + bool length = false; uint16_t datalen = 0; - set_number_of_cmds(); + char buf[5] = ""; + + strip_cmds(Cmd); while (Cmd[i] != '\0') { - PrintAndLogEx(NORMAL, "String %s: ", Cmd[i]); + PrintAndLogEx(NORMAL, "Parse String %s: ", Cmd); + PrintAndLogEx(NORMAL, "i = %i: ", i); if (Cmd[i] == '-') { switch (Cmd[i + 1]) { case 'H': @@ -137,72 +188,36 @@ static int CmdHFFelicaRequestService(const char *Cmd) { case 'c': crc = true; break; + case 'l': + length = true; + break; default: return usage_hf_felica_raw(); } i += 2; } - i = i + parse_cmd_parameter(i); - if(is_hex_input()){ + PrintAndLogEx(NORMAL, "i after single params = %i: ", i); + i = i + parse_cmd_parameter_separator(Cmd, i); + PrintAndLogEx(NORMAL, "i after cnd separator: %i", i); + if (is_hex_input(Cmd, i)){ buf[strlen(buf) + 1] = 0; buf[strlen(buf)] = Cmd[i]; i++; - i = i + get_cmd_data(i); - }else{ + PrintAndLogEx(NORMAL, "i after is hex input: %i", i); + get_cmd_data(Cmd, i, datalen, data, buf); + + }else { i++; } } request_service(); clearCommandBuffer(); - return 0; -} - -/* - * Parses line spacing and tabs. - * Returns 1 if the given char is a space or tab - */ -static int parse_cmd_parameter_separator(const char *Cmd, int i){ - PrintAndLogEx(NORMAL, "parse_cmd_parameter_separator String %s: ", Cmd[i]); - return Cmd[i] == ' ' || Cmd[i] == '\t' ? 1 : 0; -} - -/* - * Counts and sets the number of commands. - */ -static void set_number_of_cmds(const char *Cmd){ - while (*Cmd == ' ' || *Cmd == '\t'){ - Cmd++; - } -} - -/** - * Checks if a char is a hex value. - * @param Cmd - * @return one if it is a valid hex char. Zero if not a valid hex char. - */ -static bool is_hex_input(const char *Cmd, int i){ - PrintAndLogEx(NORMAL, "is_hex_input String %s: ", Cmd[i]); - return (Cmd[i] >= '0' && Cmd[i] <= '9') || (Cmd[i] >= 'a' && Cmd[i] <= 'f') || (Cmd[i] >= 'A' && Cmd[i] <= 'F') ? 1 : 0; -} - -/** - * - * @param Cmd the chars from which the data will be extracted. - * @return a buffer with the data from the command - */ -static int get_cmd_data(const char *Cmd, int i){ - int char_counter = 0; - if (strlen(buf) >= 2) { - sscanf(buf, "%x", &temp); - data[datalen] = (uint8_t)(temp & 0xff); - *buf = 0; - } - return 0; + return PM3_SUCCESS; } static int CmdHFFelicaNotImplementedYet(const char *Cmd) { PrintAndLogEx(NORMAL, "Feature not implemented Yet!"); - return 0; + return PM3_SUCCESS; } // simulate iso18092 / FeliCa tag @@ -717,21 +732,10 @@ int readFelicaUid(bool verbose) { return PM3_SUCCESS; } -int dump(const char *Cmd) { - clearCommandBuffer(); - char ctmp = tolower(param_getchar(Cmd, 0)); - if (ctmp == 'h') return usage_hf_felica_dumplite(); - - // TODO FINISH THIS METHOD - PrintAndLogEx(SUCCESS, "NOT IMPLEMENTED YET!"); - return PM3_SUCCESS; -} - int request_service() { return PM3_SUCCESS; } - static command_t CommandTable[] = { {"----------- General -----------", CmdHelp, IfPm3Iso14443a, ""}, {"help", CmdHelp, AlwaysAvailable, "This help"}, @@ -740,7 +744,7 @@ static command_t CommandTable[] = { {"sniff", CmdHFFelicaSniff, IfPm3Felica, "Sniff ISO 18092/FeliCa traffic"}, {"raw", CmdHFFelicaCmdRaw, IfPm3Felica, "Send raw hex data to tag"}, {"----------- FeliCa Standard (support in progress) -----------", CmdHelp, IfPm3Iso14443a, ""}, - {"dump", CmdHFFelicaDump, IfPm3Felica, "Wait for and try dumping FeliCa"}, + //{"dump", CmdHFFelicaDump, IfPm3Felica, "Wait for and try dumping FeliCa"}, {"rqservice", CmdHFFelicaRequestService, IfPm3Felica, "verify the existence of Area and Service, and to acquire Key Version."}, {"rqresponse", CmdHFFelicaNotImplementedYet, IfPm3Felica, "verify the existence of a card and its Mode."}, //{"rdNoEncryption", CmdHFFelicaNotImplementedYet, IfPm3Felica, "read Block Data from authentication-not-required Service."}, diff --git a/client/cmdhffelica.h b/client/cmdhffelica.h index 88a1a0080..59032ee31 100644 --- a/client/cmdhffelica.h +++ b/client/cmdhffelica.h @@ -15,6 +15,4 @@ int CmdHFFelica(const char *Cmd); int readFelicaUid(bool verbose); -int dump(); -int request_service(); #endif From 3a3b66d0798472e82fe22cc667704bb4d7a15c5a Mon Sep 17 00:00:00 2001 From: Thomas Sutter Date: Sun, 20 Oct 2019 20:28:57 +0200 Subject: [PATCH 03/24] Fix build --- client/cmdhffelica.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/client/cmdhffelica.c b/client/cmdhffelica.c index 5f963b947..caeb4cb9f 100644 --- a/client/cmdhffelica.c +++ b/client/cmdhffelica.c @@ -134,11 +134,13 @@ static void get_cmd_data(const char *Cmd, int i, uint16_t datalen, uint8_t *data } } +/* static int usage_hf_felica_dump(void) { + // TODO IMPLEMENT PrintAndLogEx(NORMAL, "Usage: hf felica dump [-h] "); PrintAndLogEx(NORMAL, " -h this help"); return PM3_SUCCESS; -} +}*/ static int CmdHFFelicaList(const char *Cmd) { (void)Cmd; // Cmd is not used so far @@ -152,14 +154,19 @@ static int CmdHFFelicaReader(const char *Cmd) { return readFelicaUid(verbose); } +/* static int CmdHFFelicaDump(const char *Cmd) { if (strlen(Cmd) < 1) return usage_hf_felica_dump(); - return dump(*Cmd); - clearCommandBuffer(); - char ctmp = tolower(param_getchar(Cmd, 0)); - if (ctmp == 'h') return usage_hf_felica_dumplite(); - dump(); - return 0; + // TODO IMPLEMENT + return PM3_SUCCESS; +}*/ + +/** + * Sends a request service frame + * @return + */ +static int request_service() { + return PM3_SUCCESS; } /** @@ -732,10 +739,6 @@ int readFelicaUid(bool verbose) { return PM3_SUCCESS; } -int request_service() { - return PM3_SUCCESS; -} - static command_t CommandTable[] = { {"----------- General -----------", CmdHelp, IfPm3Iso14443a, ""}, {"help", CmdHelp, AlwaysAvailable, "This help"}, From e7f7810d2260bd5fa5f27a954af908160400e353 Mon Sep 17 00:00:00 2001 From: Thomas Sutter Date: Mon, 21 Oct 2019 09:59:15 +0200 Subject: [PATCH 04/24] Make style. Change DBG_DEBUG. Refactor CRC calculation --- armsrc/felica.c | 34 ++++++------ client/cmdhf.c | 2 +- client/cmdhffelica.c | 128 ++++++++++++++++++++++++++----------------- 3 files changed, 96 insertions(+), 68 deletions(-) diff --git a/armsrc/felica.c b/armsrc/felica.c index 6a0e8c190..3b4de9d5f 100644 --- a/armsrc/felica.c +++ b/armsrc/felica.c @@ -229,21 +229,21 @@ static uint8_t felica_select_card(felica_card_select_t *card) { // timed-out if (len == 0) { - if (DBGLEVEL > 3) + if (DBGLEVEL >= DBG_DEBUG) Dbprintf("Error: Time out card selection!"); return 1; } // wrong answer if (FelicaFrame.framebytes[3] != FELICA_POLL_ACK) { - if (DBGLEVEL > 3) + if (DBGLEVEL >= DBG_DEBUG) Dbprintf("Error: Wrong answer selecting card!"); return 2; } // VALIDATE CRC residue is 0, hence if crc is a value it failed. if (!check_crc(CRC_FELICA, FelicaFrame.framebytes + 2, FelicaFrame.len - 2)) { - if (DBGLEVEL > 3) { + if (DBGLEVEL >= DBG_DEBUG) { Dbprintf("Error: CRC check failed!"); Dbprintf("CRC check was done on Frame: "); Dbhexdump(FelicaFrame.len - 2, FelicaFrame.framebytes + 2, 0); @@ -251,7 +251,7 @@ static uint8_t felica_select_card(felica_card_select_t *card) { return 3; } - if (DBGLEVEL > 3) + if (DBGLEVEL >= DBG_DEBUG) Dbprintf("Card selection successful!"); // copy UID // idm 8 @@ -263,7 +263,7 @@ static uint8_t felica_select_card(felica_card_select_t *card) { memcpy(card->uid, card->IDm + 2, 6); memcpy(card->iccode, card->PMm, 2); memcpy(card->mrt, card->PMm + 2, 6); - if (DBGLEVEL > 3) { + if (DBGLEVEL >= DBG_DEBUG) { Dbprintf("Received Frame: "); Dbhexdump(FelicaFrame.len, FelicaFrame.framebytes, 0); } @@ -365,7 +365,7 @@ static void TransmitFor18092_AsReader(uint8_t *frame, int len, uint32_t *timing, } // sending data with sync bytes c = 0; - if (DBGLEVEL > 3) { + if (DBGLEVEL >= DBG_DEBUG) { Dbprintf("Sending frame:"); Dbhexdump(len, frame, 0); } @@ -403,7 +403,7 @@ static void TransmitFor18092_AsReader(uint8_t *frame, int len, uint32_t *timing, // stop when button is pressed // or return TRUE when command is captured bool WaitForFelicaReply(uint16_t maxbytes) { - if (DBGLEVEL > 3) + if (DBGLEVEL >= DBG_DEBUG) Dbprintf("WaitForFelicaReply Start"); uint32_t c = 0; // power, no modulation @@ -413,7 +413,7 @@ bool WaitForFelicaReply(uint16_t maxbytes) { // clear RXRDY: uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; uint32_t timeout = iso18092_get_timeout(); - if (DBGLEVEL > 3) + if (DBGLEVEL >= DBG_DEBUG) Dbprintf("timeout set: %i", timeout); for (;;) { WDT_HIT(); @@ -435,10 +435,10 @@ bool WaitForFelicaReply(uint16_t maxbytes) { NULL, false ); - if (DBGLEVEL > 3) Dbprintf("All bytes received! STATE_FULL"); + if (DBGLEVEL >= DBG_DEBUG) Dbprintf("All bytes received! STATE_FULL"); return true; } else if (c++ > timeout && FelicaFrame.state == STATE_UNSYNCD) { - if (DBGLEVEL > 3) Dbprintf("Error: Timeout! STATE_UNSYNCD"); + if (DBGLEVEL >= DBG_DEBUG) Dbprintf("Error: Timeout! STATE_UNSYNCD"); return false; } } @@ -448,7 +448,7 @@ bool WaitForFelicaReply(uint16_t maxbytes) { // Set up FeliCa communication (similar to iso14443a_setup) // field is setup for "Sending as Reader" static void iso18092_setup(uint8_t fpga_minor_mode) { - if (DBGLEVEL > 3) Dbprintf("Start iso18092_setup"); + if (DBGLEVEL >= DBG_DEBUG) Dbprintf("Start iso18092_setup"); LEDsoff(); FpgaDownloadAndGo(FPGA_BITSTREAM_HF); @@ -501,7 +501,7 @@ void felica_reset_frame_mode() { // arg1 len of commandbytes // d.asBytes command bytes to send void felica_sendraw(PacketCommandNG *c) { - if (DBGLEVEL > 3) Dbprintf("FeliCa_sendraw Enter"); + if (DBGLEVEL >= DBG_DEBUG) Dbprintf("FeliCa_sendraw Enter"); felica_command_t param = c->oldarg[0]; size_t len = c->oldarg[1] & 0xffff; @@ -511,7 +511,7 @@ void felica_sendraw(PacketCommandNG *c) { felica_card_select_t card; if ((param & FELICA_CONNECT)) - if (DBGLEVEL > 3) Dbprintf("Clear trace"); + if (DBGLEVEL >= DBG_DEBUG) Dbprintf("Clear trace"); clear_trace(); set_tracing(true); @@ -530,7 +530,7 @@ void felica_sendraw(PacketCommandNG *c) { } } } else { - if (DBGLEVEL > 3) Dbprintf("No card selection"); + if (DBGLEVEL >= DBG_DEBUG) Dbprintf("No card selection"); } if ((param & FELICA_RAW)) { @@ -551,14 +551,14 @@ void felica_sendraw(PacketCommandNG *c) { AddCrc(buf, len); } } - if (DBGLEVEL > 3) { + if (DBGLEVEL >= DBG_DEBUG) { Dbprintf("Transmit Frame (no CRC shown):"); Dbhexdump(len, buf, 0); Dbprintf("Buffer Length: %i", buf[2] + 4); }; TransmitFor18092_AsReader(buf, buf[2] + 4, NULL, 1, 0); arg0 = WaitForFelicaReply(1024); - if (DBGLEVEL > 3) { + if (DBGLEVEL >= DBG_DEBUG) { Dbprintf("Received Frame Code: %d", arg0); Dbhexdump(FelicaFrame.len, FelicaFrame.framebytes, 0); }; @@ -571,7 +571,7 @@ void felica_sendraw(PacketCommandNG *c) { if ((param & FELICA_NO_DISCONNECT)) { Dbprintf("Disconnect"); } - if (DBGLEVEL > 3) + if (DBGLEVEL >= DBG_DEBUG) Dbprintf("FeliCa_sendraw Exit"); felica_reset_frame_mode(); return; diff --git a/client/cmdhf.c b/client/cmdhf.c index bf8a9dceb..9166b01ca 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -96,7 +96,7 @@ int CmdHFSearch(const char *Cmd) { return PM3_SUCCESS; } } - + PROMPT_CLEARLINE; PrintAndLogEx(INPLACE, "Searching for ISO15693 tag..."); if (IfPm3Iso15693()) { diff --git a/client/cmdhffelica.c b/client/cmdhffelica.c index caeb4cb9f..c50382758 100644 --- a/client/cmdhffelica.c +++ b/client/cmdhffelica.c @@ -85,27 +85,47 @@ 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."); PrintAndLogEx(NORMAL, " - When the specified Area or Service does not exist, the card returns FFFFh as Key Version."); - PrintAndLogEx(NORMAL, "\nUsage: hf felica rqservice [-h] <0A 0B 0C ... IDm hex> <01 Number of Node hex> <0A 0B Node Code List hex (Little Endian)> <0A 0B CRC hex>"); + PrintAndLogEx(NORMAL, "\nUsage: hf felica rqservice [-h] [-i] <01 Number of Node hex> <0A 0B Node Code List hex (Little Endian)>"); PrintAndLogEx(NORMAL, " -h this help"); - PrintAndLogEx(NORMAL, " -c calculate and append CRC"); + PrintAndLogEx(NORMAL, " -i <0A 0B 0C ... hex> set IDm"); PrintAndLogEx(NORMAL, "\nExample: hf felica rqservice 01100910c11bc407 01 FFFF 2837\n\n"); return PM3_SUCCESS; } +/** + * Wait for response from pm3 or timeout. + * Checks if receveid bytes have a valid CRC. + */ +static void waitCmdFelica(uint8_t iSelect) { + PacketResponseNG resp; + if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + uint16_t len = iSelect ? (resp.oldarg[1] & 0xffff) : (resp.oldarg[0] & 0xffff); + PrintAndLogEx(NORMAL, "Client Received %i octets", len); + if (!len) + return; + PrintAndLogEx(NORMAL, "%s", sprint_hex(resp.data.asBytes, len)); + if (!check_crc(CRC_FELICA, resp.data.asBytes + 2, len - 2)) { + PrintAndLogEx(ERR, "Error: CRC of received bytes are incorrect!"); + } + } else { + PrintAndLogEx(WARNING, "Timeout while waiting for reply."); + } +} + /* * Parses line spacing and tabs. * Returns 1 if the given char is a space or tab */ -static int parse_cmd_parameter_separator(const char *Cmd, int i){ +static int parse_cmd_parameter_separator(const char *Cmd, int i) { return Cmd[i] == ' ' || Cmd[i] == '\t' ? 1 : 0; } /* * Counts and sets the number of commands. */ -static void strip_cmds(const char *Cmd){ +static void strip_cmds(const char *Cmd) { PrintAndLogEx(NORMAL, "CMD count: %i", strlen(Cmd)); - while (*Cmd == ' ' || *Cmd == '\t'){ + while (*Cmd == ' ' || *Cmd == '\t') { PrintAndLogEx(NORMAL, "CMD: %s", Cmd); Cmd++; } @@ -117,15 +137,36 @@ static void strip_cmds(const char *Cmd){ * @param Cmd * @return one if it is a valid hex char. Zero if not a valid hex char. */ -static bool is_hex_input(const char *Cmd, int i){ +static bool is_hex_input(const char *Cmd, int i) { return (Cmd[i] >= '0' && Cmd[i] <= '9') || (Cmd[i] >= 'a' && Cmd[i] <= 'f') || (Cmd[i] >= 'A' && Cmd[i] <= 'F') ? 1 : 0; } /** - * - * @param Extracts the data from the cmd and puts it into the data array. + * Add crc bytes to the end of the given data. + * @param datalen length of the data frame. + * @param data frame on which the crc is calculated. + * @param size of the data. + * @return true if the crc was added. */ -static void get_cmd_data(const char *Cmd, int i, uint16_t datalen, uint8_t *data, char buf[]){ +static bool add_crc_bytes(uint16_t *datalen, uint8_t *data, size_t dataSize) { + if (*datalen > 0 && *datalen < dataSize - 2) { + uint8_t b1, b2; + compute_crc(CRC_FELICA, data, *datalen, &b1, &b2); + data[(*datalen)++] = b2; + data[(*datalen)++] = b1; + return 1; + } + return 0; +} + +/** + * Extracts the data from the cmd and puts it into the data array. + * @param Cmd input string of the user with the data + * @param datalen length of the data frame. + * @param data the array in which the data gets stored. + * @param buf temporary buffer. + */ +static void get_cmd_data(const char *Cmd, uint16_t datalen, uint8_t *data, char buf[]) { uint32_t temp; if (strlen(buf) >= 2) { sscanf(buf, "%x", &temp); @@ -161,14 +202,6 @@ static int CmdHFFelicaDump(const char *Cmd) { return PM3_SUCCESS; }*/ -/** - * Sends a request service frame - * @return - */ -static int request_service() { - return PM3_SUCCESS; -} - /** * Command parser for rqservice. * @param Cmd input data of the user. @@ -178,9 +211,10 @@ static int CmdHFFelicaRequestService(const char *Cmd) { if (strlen(Cmd) < 2) return usage_hf_felica_request_service(); int i = 0; uint8_t data[PM3_CMD_DATA_SIZE]; - bool crc = false; - bool length = false; + bool custom_IDm = false; uint16_t datalen = 0; + uint16_t numbits = 0; + uint8_t flags = 0; char buf[5] = ""; strip_cmds(Cmd); @@ -192,11 +226,8 @@ static int CmdHFFelicaRequestService(const char *Cmd) { case 'H': case 'h': return usage_hf_felica_raw(); - case 'c': - crc = true; - break; - case 'l': - length = true; + case 'i': + custom_IDm = true; break; default: return usage_hf_felica_raw(); @@ -206,19 +237,33 @@ static int CmdHFFelicaRequestService(const char *Cmd) { PrintAndLogEx(NORMAL, "i after single params = %i: ", i); i = i + parse_cmd_parameter_separator(Cmd, i); PrintAndLogEx(NORMAL, "i after cnd separator: %i", i); - if (is_hex_input(Cmd, i)){ + if (is_hex_input(Cmd, i)) { buf[strlen(buf) + 1] = 0; buf[strlen(buf)] = Cmd[i]; i++; PrintAndLogEx(NORMAL, "i after is hex input: %i", i); - get_cmd_data(Cmd, i, datalen, data, buf); - - }else { - i++; + get_cmd_data(Cmd, datalen, data, buf); + } else { + i++; } } - request_service(); + flags |= FELICA_APPEND_CRC; + if (custom_IDm) { + flags |= FELICA_NO_SELECT; + } + if (datalen > 0) { + flags |= FELICA_RAW; + } + datalen = (datalen > PM3_CMD_DATA_SIZE) ? PM3_CMD_DATA_SIZE : datalen; clearCommandBuffer(); + PrintAndLogEx(NORMAL, "Data: %s", data); + SendCommandMIX(CMD_HF_FELICA_COMMAND, flags, (datalen & 0xFFFF) | (uint32_t)(numbits << 16), 0, data, datalen); + if (custom_IDm) { + waitCmdFelica(1); + } + if (datalen > 0) { + waitCmdFelica(0); + } return PM3_SUCCESS; } @@ -557,21 +602,7 @@ static int CmdHFFelicaDumpLite(const char *Cmd) { return PM3_SUCCESS; } -static void waitCmdFelica(uint8_t iSelect) { - PacketResponseNG resp; - if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { - uint16_t len = iSelect ? (resp.oldarg[1] & 0xffff) : (resp.oldarg[0] & 0xffff); - PrintAndLogEx(NORMAL, "Client Received %i octets", len); - if (!len) - return; - PrintAndLogEx(NORMAL, "%s", sprint_hex(resp.data.asBytes, len)); - if(!check_crc(CRC_FELICA, resp.data.asBytes + 2, len - 2)){ - PrintAndLogEx(ERR, "Error: CRC of received bytes are incorrect!"); - } - } else { - PrintAndLogEx(WARNING, "Timeout while waiting for reply."); - } -} + static int CmdHFFelicaCmdRaw(const char *Cmd) { bool reply = 1; @@ -649,11 +680,8 @@ static int CmdHFFelicaCmdRaw(const char *Cmd) { return PM3_EINVARG; } - if (crc && datalen > 0 && datalen < sizeof(data) - 2) { - uint8_t b1, b2; - compute_crc(CRC_FELICA, data, datalen, &b1, &b2); - data[datalen++] = b2; - data[datalen++] = b1; + if (crc) { + add_crc_bytes(&datalen, data, sizeof(data)); } uint8_t flags = 0; From 6144e2d09bab56b29f746db53bac5e82495107af Mon Sep 17 00:00:00 2001 From: Thomas Sutter Date: Tue, 22 Oct 2019 15:56:05 +0200 Subject: [PATCH 05/24] Add felica request service command. Add cmd parser functions. --- armsrc/felica.c | 84 +-------------------------- client/cmdhffelica.c | 131 +++++++++++++++++++++++++++++++------------ include/mifare.h | 9 +++ 3 files changed, 107 insertions(+), 117 deletions(-) diff --git a/armsrc/felica.c b/armsrc/felica.c index 3b4de9d5f..83ff2bea3 100644 --- a/armsrc/felica.c +++ b/armsrc/felica.c @@ -337,9 +337,7 @@ static void BuildFliteRdblk(uint8_t *idm, int blocknum, uint16_t *blocks) { } static void TransmitFor18092_AsReader(uint8_t *frame, int len, uint32_t *timing, uint8_t power, uint8_t highspeed) { - uint8_t flags = FPGA_MAJOR_MODE_ISO18092; - if (power) flags |= FPGA_HF_ISO18092_FLAG_READER; if (highspeed) @@ -371,7 +369,6 @@ static void TransmitFor18092_AsReader(uint8_t *frame, int len, uint32_t *timing, } while (c < len) { - // Put byte into tx holding register as soon as it is ready if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { AT91C_BASE_SSC->SSC_THR = frame[c++]; @@ -415,18 +412,16 @@ bool WaitForFelicaReply(uint16_t maxbytes) { uint32_t timeout = iso18092_get_timeout(); if (DBGLEVEL >= DBG_DEBUG) Dbprintf("timeout set: %i", timeout); + for (;;) { WDT_HIT(); if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { b = (uint8_t)(AT91C_BASE_SSC->SSC_RHR); Process18092Byte(b); if (FelicaFrame.state == STATE_FULL) { - felica_nexttransfertime = - MAX( - felica_nexttransfertime, + felica_nexttransfertime = MAX(felica_nexttransfertime, (GetCountSspClk() & 0xfffffff8) - (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER) / 16 + FELICA_FRAME_DELAY_TIME - ); - + ); LogTrace( FelicaFrame.framebytes, FelicaFrame.len, @@ -774,79 +769,6 @@ void felica_dump() { } } -} - -void felica_send_request_service(uint8_t *request_service) { - Dbprintf("Send Service Request - len: d%", RES_SVC_LEN); - TransmitFor18092_AsReader(request_service, RES_SVC_LEN, NULL, 1, 0); - if (WaitForFelicaReply(512) && FelicaFrame.framebytes[3] == FELICA_REQSRV_ACK) { - Dbprintf("Got Service Response!"); - } -} - -/* Create Request Service Frame -// Use this command to verify the existence of Area and Service, and to acquire Key Version. -// When the specified Area or Service exists, the card returns Key Version. -// When the specified Area or Service does not exist, the card returns FFFFh as Key Version. -*/ -uint8_t *felica_create_request_service_frame(uint8_t nodeNumber, uint8_t *idm) { - if (nodeNumber < 1 && nodeNumber > 32) { - Dbprintf("Node number out of range: 1 <= %d <= 32 - set node number to 1"); - nodeNumber = 1; - } - // Sync 2-Byte, Length 1-Byte, CMD 1-Byte, IDm 8-Byte, nodeNumber 1 <= n <= 32 1-Byte, Node Code List - uint8_t *request_service = BigBuf_malloc(sizeof(uint8_t) * RES_SVC_LEN); - //{ 0xb2, 0x4d, 0x06, FELICA_REQSRV_REQ, 0xff, 0xff, 0x00, 0x00, 0x09, 0x21}; - request_service[0] = 0xb2; //Sync - request_service[1] = 0x4d; //Sync - request_service[2] = 0x0B; // Length - request_service[3] = FELICA_REQSRV_REQ; // CMD - request_service[4] = idm[0]; - request_service[5] = idm[1]; - request_service[6] = idm[2]; - request_service[7] = idm[3]; - request_service[8] = idm[4]; - request_service[9] = idm[5]; - request_service[10] = idm[6]; - request_service[11] = idm[7]; - request_service[12] = nodeNumber; // Node we like to ask for services - request_service[13] = 0x00; // Node Code List // TODO FIND OUT WHAT NEEDS TO BE IN HERE - return request_service; -} - -// Create Frame for authentication1 CMD -void felica_create_authentication1_frame() { - -} - -// Create Frame for authentication2 CMD -void felica_create_authentication2_frame() { - -} - -// Create a Frame for Read without encryption CMD as Payload -void felica_create_read_block_frame(uint16_t blockNr) { - if (blockNr < 1 || blockNr > 567) { - Dbprintf("Block number out of range!"); - return; - } - uint8_t c = 0; - // First Byte of SYNC - frameSpace[c++] = 0xb2; - frameSpace[c++] = 0x4d; - // skip Length of Frame - c++; - // Payload - frameSpace[c++] = FELICA_RDBLK_REQ; //command number - - // Set frame length - - // CRC -} - -void felica_read_block(uint8_t *idm, uint16_t blockNr) { - - } void felica_dump_lite_s() { diff --git a/client/cmdhffelica.c b/client/cmdhffelica.c index c50382758..81fb3e67d 100644 --- a/client/cmdhffelica.c +++ b/client/cmdhffelica.c @@ -24,6 +24,11 @@ #include "mifare.h" // felica_card_select_t struct static int CmdHelp(const char *Cmd); +static felica_card_select_t last_known_card; + +static void set_last_known_card(felica_card_select_t card){ + last_known_card = card; +} /* static int usage_hf_felica_sim(void) { @@ -85,10 +90,14 @@ 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."); PrintAndLogEx(NORMAL, " - When the specified Area or Service does not exist, the card returns FFFFh as Key Version."); + PrintAndLogEx(NORMAL, "For Node Code List of a command packet, Area Code or Service Code of the target " + "of acquisition of Key Version shall be enumerated in Little Endian format." + "If Key Version of System is the target of acquisition, FFFFh shall be specified " + "in the command packet."); PrintAndLogEx(NORMAL, "\nUsage: hf felica rqservice [-h] [-i] <01 Number of Node hex> <0A 0B Node Code List hex (Little Endian)>"); PrintAndLogEx(NORMAL, " -h this help"); - PrintAndLogEx(NORMAL, " -i <0A 0B 0C ... hex> set IDm"); - PrintAndLogEx(NORMAL, "\nExample: hf felica rqservice 01100910c11bc407 01 FFFF 2837\n\n"); + PrintAndLogEx(NORMAL, " -i <0A 0B 0C ... hex> set custom IDm to use"); + PrintAndLogEx(NORMAL, "\nExample: hf felica rqservice 01 FFFF \n\n"); return PM3_SUCCESS; } @@ -96,20 +105,22 @@ static int usage_hf_felica_request_service(void) { * Wait for response from pm3 or timeout. * Checks if receveid bytes have a valid CRC. */ -static void waitCmdFelica(uint8_t iSelect) { - PacketResponseNG resp; - if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { - uint16_t len = iSelect ? (resp.oldarg[1] & 0xffff) : (resp.oldarg[0] & 0xffff); +static bool waitCmdFelica(uint8_t iSelect, PacketResponseNG *resp) { + if (WaitForResponseTimeout(CMD_ACK, resp, 2000)) { + uint16_t len = iSelect ? (resp->oldarg[1] & 0xffff) : (resp->oldarg[0] & 0xffff); PrintAndLogEx(NORMAL, "Client Received %i octets", len); - if (!len) - return; - PrintAndLogEx(NORMAL, "%s", sprint_hex(resp.data.asBytes, len)); - if (!check_crc(CRC_FELICA, resp.data.asBytes + 2, len - 2)) { - PrintAndLogEx(ERR, "Error: CRC of received bytes are incorrect!"); + if (!len || len < 2){ + PrintAndLogEx(ERR, "Could not receive data correctly!"); } + PrintAndLogEx(NORMAL, "%s", sprint_hex(resp->data.asBytes, len)); + if (!check_crc(CRC_FELICA, resp->data.asBytes + 2, len - 2)) { + PrintAndLogEx(WARNING, "Wrong or no CRC bytes"); + } + return true; } else { PrintAndLogEx(WARNING, "Timeout while waiting for reply."); } + return false; } /* @@ -124,12 +135,9 @@ static int parse_cmd_parameter_separator(const char *Cmd, int i) { * Counts and sets the number of commands. */ static void strip_cmds(const char *Cmd) { - PrintAndLogEx(NORMAL, "CMD count: %i", strlen(Cmd)); while (*Cmd == ' ' || *Cmd == '\t') { - PrintAndLogEx(NORMAL, "CMD: %s", Cmd); Cmd++; } - PrintAndLogEx(NORMAL, "CMD string: %s", Cmd); } /** @@ -160,21 +168,53 @@ static bool add_crc_bytes(uint16_t *datalen, uint8_t *data, size_t dataSize) { } /** - * Extracts the data from the cmd and puts it into the data array. + * Extracts the hex data from the cmd and puts it into the data array. * @param Cmd input string of the user with the data * @param datalen length of the data frame. * @param data the array in which the data gets stored. - * @param buf temporary buffer. + * @param buf buffer with hex data. */ -static void get_cmd_data(const char *Cmd, uint16_t datalen, uint8_t *data, char buf[]) { - uint32_t temp; +static void get_cmd_data(const char *Cmd, uint16_t *datalen, uint8_t *data, char buf[]) { + uint32_t hex; if (strlen(buf) >= 2) { - sscanf(buf, "%x", &temp); - data[datalen] = (uint8_t)(temp & 0xff); + sscanf(buf, "%x", &hex); + data[*datalen] = (uint8_t)(hex & 0xff); + (*datalen)++; *buf = 0; } } +/** + * Converts integer value to equivalent hex value. + * @param number number of hex bytes. + * @return number as hex value. + */ +static uint8_t int_to_hex(uint16_t *number){ + uint32_t hex; + char dataLengthChar[5]; + sprintf(dataLengthChar, "%x", *number); + sscanf(dataLengthChar, "%x", &hex); + return (uint8_t)(hex & 0xff); +} + +/** + * Adds the last known IDm (8-Byte) to the data frame. + * @param position start of where the IDm is added within the frame. + * @param data frame in where the IDM is added. + * @return true if IDm was added; + */ +static bool add_last_IDm(uint8_t position, uint8_t *data){ + if(last_known_card.IDm[0] != 0 && last_known_card.IDm[1] != 0){ + for(int i = 0; i < 8; i++){ + uint16_t number = (uint16_t)last_known_card.IDm[i]; + data[position+i] = int_to_hex(&number); + } + return true; + }else{ + return false; + } +} + /* static int usage_hf_felica_dump(void) { // TODO IMPLEMENT @@ -213,14 +253,12 @@ static int CmdHFFelicaRequestService(const char *Cmd) { uint8_t data[PM3_CMD_DATA_SIZE]; bool custom_IDm = false; uint16_t datalen = 0; - uint16_t numbits = 0; uint8_t flags = 0; + uint16_t numbits = 0; char buf[5] = ""; - + datalen += 10; // length (1) + CMD (1) + IDm (8) strip_cmds(Cmd); while (Cmd[i] != '\0') { - PrintAndLogEx(NORMAL, "Parse String %s: ", Cmd); - PrintAndLogEx(NORMAL, "i = %i: ", i); if (Cmd[i] == '-') { switch (Cmd[i + 1]) { case 'H': @@ -234,15 +272,12 @@ static int CmdHFFelicaRequestService(const char *Cmd) { } i += 2; } - PrintAndLogEx(NORMAL, "i after single params = %i: ", i); i = i + parse_cmd_parameter_separator(Cmd, i); - PrintAndLogEx(NORMAL, "i after cnd separator: %i", i); if (is_hex_input(Cmd, i)) { buf[strlen(buf) + 1] = 0; buf[strlen(buf)] = Cmd[i]; i++; - PrintAndLogEx(NORMAL, "i after is hex input: %i", i); - get_cmd_data(Cmd, datalen, data, buf); + get_cmd_data(Cmd, &datalen, data, buf); } else { i++; } @@ -255,14 +290,37 @@ static int CmdHFFelicaRequestService(const char *Cmd) { flags |= FELICA_RAW; } datalen = (datalen > PM3_CMD_DATA_SIZE) ? PM3_CMD_DATA_SIZE : datalen; + if(!custom_IDm){ + if(!add_last_IDm(2, data)){ + PrintAndLogEx(ERR, "No last known card! Use reader first or set a custom IDm!"); + return PM3_EINVARG; + }else{ + PrintAndLogEx(INFO, "Used last known IDm.", sprint_hex(data, datalen)); + } + } + data[0] = int_to_hex(&datalen); + data[1] = 0x02; // Request Command ID + add_crc_bytes(&datalen, data, sizeof(data)); + PrintAndLogEx(NORMAL, "Send Service Request Frame: %s", sprint_hex(data, datalen)); clearCommandBuffer(); - PrintAndLogEx(NORMAL, "Data: %s", data); SendCommandMIX(CMD_HF_FELICA_COMMAND, flags, (datalen & 0xFFFF) | (uint32_t)(numbits << 16), 0, data, datalen); + PacketResponseNG resp; if (custom_IDm) { - waitCmdFelica(1); + waitCmdFelica(1, &resp); } if (datalen > 0) { - waitCmdFelica(0); + if(!waitCmdFelica(0, &resp)){ + return PM3_ESOFT; + } + felica_request_service_response_t rqs_response; + memcpy(&rqs_response, (felica_request_service_response_t *)resp.data.asBytes, sizeof(felica_request_service_response_t)); + + PrintAndLogEx(SUCCESS, "\nGot Service Response:"); + PrintAndLogEx(NORMAL, "IDm: %s", sprint_hex(rqs_response.IDm, sizeof(rqs_response.IDm))); + PrintAndLogEx(NORMAL, " -Node Number: %s", sprint_hex(rqs_response.node_number, sizeof(rqs_response.node_number))); + PrintAndLogEx(NORMAL, " -Node Key Version List: %s\n", sprint_hex(rqs_response.node_key_versions, sizeof(rqs_response.node_key_versions))); + }else{ + return PM3_ESOFT; } return PM3_SUCCESS; } @@ -602,8 +660,6 @@ static int CmdHFFelicaDumpLite(const char *Cmd) { return PM3_SUCCESS; } - - static int CmdHFFelicaCmdRaw(const char *Cmd) { bool reply = 1; bool crc = false; @@ -703,15 +759,18 @@ static int CmdHFFelicaCmdRaw(const char *Cmd) { datalen = (datalen > PM3_CMD_DATA_SIZE) ? PM3_CMD_DATA_SIZE : datalen; clearCommandBuffer(); + PrintAndLogEx(NORMAL, "Data: %s", sprint_hex(data, datalen)); SendCommandMIX(CMD_HF_FELICA_COMMAND, flags, (datalen & 0xFFFF) | (uint32_t)(numbits << 16), 0, data, datalen); if (reply) { if (active_select) { PrintAndLogEx(NORMAL, "Active select wait for FeliCa."); - waitCmdFelica(1); + PacketResponseNG resp_IDm; + waitCmdFelica(1, &resp_IDm); } if (datalen > 0) { - waitCmdFelica(0); + PacketResponseNG resp_frame; + waitCmdFelica(0, &resp_frame); } } return PM3_SUCCESS; @@ -724,7 +783,6 @@ int readFelicaUid(bool verbose) { PacketResponseNG resp; if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) { if (verbose) PrintAndLogEx(WARNING, "FeliCa card select failed"); - //SendCommandMIX(CMD_HF_FELICA_COMMAND, 0, 0, 0, NULL, 0); return PM3_ESOFT; } @@ -761,6 +819,7 @@ int readFelicaUid(bool verbose) { PrintAndLogEx(NORMAL, " - MRT %s", sprint_hex(card.mrt, sizeof(card.mrt))); PrintAndLogEx(NORMAL, "SERVICE CODE %s", sprint_hex(card.servicecode, sizeof(card.servicecode))); + set_last_known_card(card); break; } } diff --git a/include/mifare.h b/include/mifare.h index 23dbceb68..32427309d 100644 --- a/include/mifare.h +++ b/include/mifare.h @@ -169,6 +169,15 @@ typedef struct { uint8_t servicecode[2]; } PACKED felica_card_select_t; +typedef struct { + uint8_t sync[4]; + uint8_t length[1]; + uint8_t cmd_code[1]; + uint8_t IDm[8]; + uint8_t node_number[1]; + uint8_t node_key_versions[2]; +} PACKED felica_request_service_response_t; + typedef enum FELICA_COMMAND { FELICA_CONNECT = (1 << 0), FELICA_NO_DISCONNECT = (1 << 1), From 3f56116615bf3da583e4ce81dda63ea835e28306 Mon Sep 17 00:00:00 2001 From: Thomas Sutter Date: Tue, 22 Oct 2019 17:03:54 +0200 Subject: [PATCH 06/24] Add felica request service all nodes command. Make style. --- armsrc/felica.c | 4 +- client/cmdhffelica.c | 107 ++++++++++++++++++++------------ client/cmdhffelica.h | 1 + client/luascripts/init_rdv4.lua | 2 +- include/mifare.h | 2 +- 5 files changed, 71 insertions(+), 45 deletions(-) diff --git a/armsrc/felica.c b/armsrc/felica.c index 83ff2bea3..cc9c2c9ed 100644 --- a/armsrc/felica.c +++ b/armsrc/felica.c @@ -420,8 +420,8 @@ bool WaitForFelicaReply(uint16_t maxbytes) { Process18092Byte(b); if (FelicaFrame.state == STATE_FULL) { felica_nexttransfertime = MAX(felica_nexttransfertime, - (GetCountSspClk() & 0xfffffff8) - (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER) / 16 + FELICA_FRAME_DELAY_TIME - ); + (GetCountSspClk() & 0xfffffff8) - (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER) / 16 + FELICA_FRAME_DELAY_TIME + ); LogTrace( FelicaFrame.framebytes, FelicaFrame.len, diff --git a/client/cmdhffelica.c b/client/cmdhffelica.c index 81fb3e67d..bcca6f63a 100644 --- a/client/cmdhffelica.c +++ b/client/cmdhffelica.c @@ -26,7 +26,7 @@ static int CmdHelp(const char *Cmd); static felica_card_select_t last_known_card; -static void set_last_known_card(felica_card_select_t card){ +static void set_last_known_card(felica_card_select_t card) { last_known_card = card; } @@ -91,13 +91,16 @@ static int usage_hf_felica_request_service(void) { PrintAndLogEx(NORMAL, " - When the specified Area or Service exists, the card returns Key Version."); PrintAndLogEx(NORMAL, " - When the specified Area or Service does not exist, the card returns FFFFh as Key Version."); PrintAndLogEx(NORMAL, "For Node Code List of a command packet, Area Code or Service Code of the target " - "of acquisition of Key Version shall be enumerated in Little Endian format." - "If Key Version of System is the target of acquisition, FFFFh shall be specified " - "in the command packet."); + "of acquisition of Key Version shall be enumerated in Little Endian format." + "If Key Version of System is the target of acquisition, FFFFh shall be specified " + "in the command packet."); PrintAndLogEx(NORMAL, "\nUsage: hf felica rqservice [-h] [-i] <01 Number of Node hex> <0A 0B Node Code List hex (Little Endian)>"); PrintAndLogEx(NORMAL, " -h this help"); PrintAndLogEx(NORMAL, " -i <0A 0B 0C ... hex> set custom IDm to use"); - PrintAndLogEx(NORMAL, "\nExample: hf felica rqservice 01 FFFF \n\n"); + PrintAndLogEx(NORMAL, "\nExamples: hf felica rqservice 01 FF FF"); + PrintAndLogEx(NORMAL, " hf felica rqservice 01 FF FF"); + PrintAndLogEx(NORMAL, " hf felica rqs -a FF FF"); + PrintAndLogEx(NORMAL, " hf felica rqs -i 01 10 09 10 c1 1b c4 07 01 FF FF \n\n"); return PM3_SUCCESS; } @@ -109,7 +112,7 @@ static bool waitCmdFelica(uint8_t iSelect, PacketResponseNG *resp) { if (WaitForResponseTimeout(CMD_ACK, resp, 2000)) { uint16_t len = iSelect ? (resp->oldarg[1] & 0xffff) : (resp->oldarg[0] & 0xffff); PrintAndLogEx(NORMAL, "Client Received %i octets", len); - if (!len || len < 2){ + if (!len || len < 2) { PrintAndLogEx(ERR, "Could not receive data correctly!"); } PrintAndLogEx(NORMAL, "%s", sprint_hex(resp->data.asBytes, len)); @@ -120,7 +123,7 @@ static bool waitCmdFelica(uint8_t iSelect, PacketResponseNG *resp) { } else { PrintAndLogEx(WARNING, "Timeout while waiting for reply."); } - return false; + return false; } /* @@ -150,7 +153,7 @@ static bool is_hex_input(const char *Cmd, int i) { } /** - * Add crc bytes to the end of the given data. + * Add crc bytes to the end of the given data and increments datalen. * @param datalen length of the data frame. * @param data frame on which the crc is calculated. * @param size of the data. @@ -189,7 +192,7 @@ static void get_cmd_data(const char *Cmd, uint16_t *datalen, uint8_t *data, char * @param number number of hex bytes. * @return number as hex value. */ -static uint8_t int_to_hex(uint16_t *number){ +static uint8_t int_to_hex(uint16_t *number) { uint32_t hex; char dataLengthChar[5]; sprintf(dataLengthChar, "%x", *number); @@ -203,14 +206,14 @@ static uint8_t int_to_hex(uint16_t *number){ * @param data frame in where the IDM is added. * @return true if IDm was added; */ -static bool add_last_IDm(uint8_t position, uint8_t *data){ - if(last_known_card.IDm[0] != 0 && last_known_card.IDm[1] != 0){ - for(int i = 0; i < 8; i++){ +static bool add_last_IDm(uint8_t position, uint8_t *data) { + if (last_known_card.IDm[0] != 0 && last_known_card.IDm[1] != 0) { + for (int i = 0; i < 8; i++) { uint16_t number = (uint16_t)last_known_card.IDm[i]; - data[position+i] = int_to_hex(&number); + data[position + i] = int_to_hex(&number); } return true; - }else{ + } else { return false; } } @@ -242,6 +245,32 @@ static int CmdHFFelicaDump(const char *Cmd) { return PM3_SUCCESS; }*/ +/** + * Sends a request service frame to the pm3. + */ +void send_request_service(uint8_t flags, uint16_t datalen, uint8_t *data) { + uint16_t numbits = 0; + clearCommandBuffer(); + PrintAndLogEx(NORMAL, "Send Service Request Frame: %s", sprint_hex(data, datalen)); + SendCommandMIX(CMD_HF_FELICA_COMMAND, flags, (datalen & 0xFFFF) | (uint32_t)(numbits << 16), 0, data, datalen); + PacketResponseNG resp; + if (datalen > 0) { + if (!waitCmdFelica(0, &resp)) { + PrintAndLogEx(ERR, "\nGot no Response from card"); + return; + } + felica_request_service_response_t rqs_response; + memcpy(&rqs_response, (felica_request_service_response_t *)resp.data.asBytes, sizeof(felica_request_service_response_t)); + + if (rqs_response.IDm[0] != 0) { + PrintAndLogEx(SUCCESS, "\nGot Service Response:"); + PrintAndLogEx(NORMAL, "IDm: %s", sprint_hex(rqs_response.IDm, sizeof(rqs_response.IDm))); + PrintAndLogEx(NORMAL, " -Node Number: %s", sprint_hex(rqs_response.node_number, sizeof(rqs_response.node_number))); + PrintAndLogEx(NORMAL, " -Node Key Version List: %s\n", sprint_hex(rqs_response.node_key_versions, sizeof(rqs_response.node_key_versions))); + } + } +} + /** * Command parser for rqservice. * @param Cmd input data of the user. @@ -252,23 +281,29 @@ static int CmdHFFelicaRequestService(const char *Cmd) { int i = 0; uint8_t data[PM3_CMD_DATA_SIZE]; bool custom_IDm = false; + bool all_nodes = false; uint16_t datalen = 0; uint8_t flags = 0; - uint16_t numbits = 0; + char buf[5] = ""; - datalen += 10; // length (1) + CMD (1) + IDm (8) + datalen += 10; // length (1) + CMD (1) + IDm(8) strip_cmds(Cmd); while (Cmd[i] != '\0') { if (Cmd[i] == '-') { switch (Cmd[i + 1]) { case 'H': case 'h': - return usage_hf_felica_raw(); + return usage_hf_felica_request_service(); case 'i': custom_IDm = true; + datalen -= 8; + break; + case 'a': + all_nodes = true; + datalen += 1; break; default: - return usage_hf_felica_raw(); + return usage_hf_felica_request_service(); } i += 2; } @@ -290,38 +325,28 @@ static int CmdHFFelicaRequestService(const char *Cmd) { flags |= FELICA_RAW; } datalen = (datalen > PM3_CMD_DATA_SIZE) ? PM3_CMD_DATA_SIZE : datalen; - if(!custom_IDm){ - if(!add_last_IDm(2, data)){ + if (!custom_IDm) { + if (!add_last_IDm(2, data)) { PrintAndLogEx(ERR, "No last known card! Use reader first or set a custom IDm!"); return PM3_EINVARG; - }else{ + } else { PrintAndLogEx(INFO, "Used last known IDm.", sprint_hex(data, datalen)); } } data[0] = int_to_hex(&datalen); data[1] = 0x02; // Request Command ID - add_crc_bytes(&datalen, data, sizeof(data)); - PrintAndLogEx(NORMAL, "Send Service Request Frame: %s", sprint_hex(data, datalen)); - clearCommandBuffer(); - SendCommandMIX(CMD_HF_FELICA_COMMAND, flags, (datalen & 0xFFFF) | (uint32_t)(numbits << 16), 0, data, datalen); - PacketResponseNG resp; - if (custom_IDm) { - waitCmdFelica(1, &resp); - } - if (datalen > 0) { - if(!waitCmdFelica(0, &resp)){ - return PM3_ESOFT; + if (all_nodes) { + for (uint16_t y = 1; y < 32; y++) { + data[10] = int_to_hex(&y); + add_crc_bytes(&datalen, data, sizeof(data)); + send_request_service(flags, datalen, data); + datalen -= 2; // Remove CRC bytes before adding new ones } - felica_request_service_response_t rqs_response; - memcpy(&rqs_response, (felica_request_service_response_t *)resp.data.asBytes, sizeof(felica_request_service_response_t)); - - PrintAndLogEx(SUCCESS, "\nGot Service Response:"); - PrintAndLogEx(NORMAL, "IDm: %s", sprint_hex(rqs_response.IDm, sizeof(rqs_response.IDm))); - PrintAndLogEx(NORMAL, " -Node Number: %s", sprint_hex(rqs_response.node_number, sizeof(rqs_response.node_number))); - PrintAndLogEx(NORMAL, " -Node Key Version List: %s\n", sprint_hex(rqs_response.node_key_versions, sizeof(rqs_response.node_key_versions))); - }else{ - return PM3_ESOFT; + } else { + add_crc_bytes(&datalen, data, sizeof(data)); + send_request_service(flags, datalen, data); } + return PM3_SUCCESS; } diff --git a/client/cmdhffelica.h b/client/cmdhffelica.h index 59032ee31..dd127cfaf 100644 --- a/client/cmdhffelica.h +++ b/client/cmdhffelica.h @@ -15,4 +15,5 @@ int CmdHFFelica(const char *Cmd); int readFelicaUid(bool verbose); +void send_request_service(uint8_t flags, uint16_t datalen, uint8_t *data); #endif diff --git a/client/luascripts/init_rdv4.lua b/client/luascripts/init_rdv4.lua index 4836cda77..d2dd03e24 100644 --- a/client/luascripts/init_rdv4.lua +++ b/client/luascripts/init_rdv4.lua @@ -88,7 +88,7 @@ function main(args) print('') core.console('hw status') print(dash) - + print('all done!') end diff --git a/include/mifare.h b/include/mifare.h index 32427309d..5461bd19f 100644 --- a/include/mifare.h +++ b/include/mifare.h @@ -170,7 +170,7 @@ typedef struct { } PACKED felica_card_select_t; typedef struct { - uint8_t sync[4]; + uint8_t sync[2]; uint8_t length[1]; uint8_t cmd_code[1]; uint8_t IDm[8]; From b6117e499695b9fe05cb1743c904b1184054a37d Mon Sep 17 00:00:00 2001 From: Thomas Sutter Date: Tue, 22 Oct 2019 17:10:32 +0200 Subject: [PATCH 07/24] Add parameter a to usage text. --- client/cmdhffelica.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/client/cmdhffelica.c b/client/cmdhffelica.c index bcca6f63a..1c276c629 100644 --- a/client/cmdhffelica.c +++ b/client/cmdhffelica.c @@ -91,13 +91,14 @@ static int usage_hf_felica_request_service(void) { PrintAndLogEx(NORMAL, " - When the specified Area or Service exists, the card returns Key Version."); PrintAndLogEx(NORMAL, " - When the specified Area or Service does not exist, the card returns FFFFh as Key Version."); PrintAndLogEx(NORMAL, "For Node Code List of a command packet, Area Code or Service Code of the target " - "of acquisition of Key Version shall be enumerated in Little Endian format." + "of acquisition of Key Version shall be enumerated in Little Endian format. " "If Key Version of System is the target of acquisition, FFFFh shall be specified " "in the command packet."); PrintAndLogEx(NORMAL, "\nUsage: hf felica rqservice [-h] [-i] <01 Number of Node hex> <0A 0B Node Code List hex (Little Endian)>"); PrintAndLogEx(NORMAL, " -h this help"); PrintAndLogEx(NORMAL, " -i <0A 0B 0C ... hex> set custom IDm to use"); - PrintAndLogEx(NORMAL, "\nExamples: hf felica rqservice 01 FF FF"); + PrintAndLogEx(NORMAL, " -a auto node number mode - iterates through all possible node 1 < n < 32"); + PrintAndLogEx(NORMAL, "\nExamples: "); PrintAndLogEx(NORMAL, " hf felica rqservice 01 FF FF"); PrintAndLogEx(NORMAL, " hf felica rqs -a FF FF"); PrintAndLogEx(NORMAL, " hf felica rqs -i 01 10 09 10 c1 1b c4 07 01 FF FF \n\n"); From 22743831297b29eee59916a1ba8949210c33de6b Mon Sep 17 00:00:00 2001 From: Thomas Sutter Date: Wed, 23 Oct 2019 09:21:43 +0200 Subject: [PATCH 08/24] Remove crc methode. Add CRC macro. Change help text for request service. --- armsrc/felica.c | 2 +- client/cmdhffelica.c | 52 ++++++++++---------------------------------- 2 files changed, 12 insertions(+), 42 deletions(-) diff --git a/armsrc/felica.c b/armsrc/felica.c index cc9c2c9ed..09e2b582f 100644 --- a/armsrc/felica.c +++ b/armsrc/felica.c @@ -3,7 +3,7 @@ #include "BigBuf.h" #include "util.h" #include "protocols.h" -#include "crc16.h" // crc16 ccitt +#include "crc16.h" #include "fpgaloader.h" #include "string.h" #include "commonutil.h" diff --git a/client/cmdhffelica.c b/client/cmdhffelica.c index 1c276c629..dfdbfe887 100644 --- a/client/cmdhffelica.c +++ b/client/cmdhffelica.c @@ -22,6 +22,7 @@ #include "ui.h" #include "mifare.h" // felica_card_select_t struct +#define AddCrc(data, len) compute_crc(CRC_FELICA, (data), (len), (data)+(len)+1, (data)+(len)) static int CmdHelp(const char *Cmd); static felica_card_select_t last_known_card; @@ -100,8 +101,8 @@ static int usage_hf_felica_request_service(void) { PrintAndLogEx(NORMAL, " -a auto node number mode - iterates through all possible node 1 < n < 32"); PrintAndLogEx(NORMAL, "\nExamples: "); PrintAndLogEx(NORMAL, " hf felica rqservice 01 FF FF"); - PrintAndLogEx(NORMAL, " hf felica rqs -a FF FF"); - PrintAndLogEx(NORMAL, " hf felica rqs -i 01 10 09 10 c1 1b c4 07 01 FF FF \n\n"); + PrintAndLogEx(NORMAL, " hf felica rqservice -a FF FF"); + PrintAndLogEx(NORMAL, " hf felica rqservice -i 01 10 09 10 c1 1b c4 07 01 FF FF \n\n"); return PM3_SUCCESS; } @@ -153,24 +154,6 @@ static bool is_hex_input(const char *Cmd, int i) { return (Cmd[i] >= '0' && Cmd[i] <= '9') || (Cmd[i] >= 'a' && Cmd[i] <= 'f') || (Cmd[i] >= 'A' && Cmd[i] <= 'F') ? 1 : 0; } -/** - * Add crc bytes to the end of the given data and increments datalen. - * @param datalen length of the data frame. - * @param data frame on which the crc is calculated. - * @param size of the data. - * @return true if the crc was added. - */ -static bool add_crc_bytes(uint16_t *datalen, uint8_t *data, size_t dataSize) { - if (*datalen > 0 && *datalen < dataSize - 2) { - uint8_t b1, b2; - compute_crc(CRC_FELICA, data, *datalen, &b1, &b2); - data[(*datalen)++] = b2; - data[(*datalen)++] = b1; - return 1; - } - return 0; -} - /** * Extracts the hex data from the cmd and puts it into the data array. * @param Cmd input string of the user with the data @@ -219,17 +202,8 @@ static bool add_last_IDm(uint8_t position, uint8_t *data) { } } -/* -static int usage_hf_felica_dump(void) { - // TODO IMPLEMENT - PrintAndLogEx(NORMAL, "Usage: hf felica dump [-h] "); - PrintAndLogEx(NORMAL, " -h this help"); - return PM3_SUCCESS; -}*/ - static int CmdHFFelicaList(const char *Cmd) { - (void)Cmd; // Cmd is not used so far - //PrintAndLogEx(NORMAL, "Deprecated command, use 'hf list felica' instead"); + (void)Cmd; CmdTraceList("felica"); return PM3_SUCCESS; } @@ -239,13 +213,6 @@ static int CmdHFFelicaReader(const char *Cmd) { return readFelicaUid(verbose); } -/* -static int CmdHFFelicaDump(const char *Cmd) { - if (strlen(Cmd) < 1) return usage_hf_felica_dump(); - // TODO IMPLEMENT - return PM3_SUCCESS; -}*/ - /** * Sends a request service frame to the pm3. */ @@ -314,7 +281,7 @@ static int CmdHFFelicaRequestService(const char *Cmd) { buf[strlen(buf)] = Cmd[i]; i++; get_cmd_data(Cmd, &datalen, data, buf); - } else { + } else { i++; } } @@ -339,12 +306,14 @@ static int CmdHFFelicaRequestService(const char *Cmd) { if (all_nodes) { for (uint16_t y = 1; y < 32; y++) { data[10] = int_to_hex(&y); - add_crc_bytes(&datalen, data, sizeof(data)); + AddCrc(data, datalen); send_request_service(flags, datalen, data); datalen -= 2; // Remove CRC bytes before adding new ones } } else { - add_crc_bytes(&datalen, data, sizeof(data)); + PrintAndLogEx(INFO, "Datalen %i", datalen); + AddCrc(data, datalen); + datalen += 2; send_request_service(flags, datalen, data); } @@ -763,7 +732,8 @@ static int CmdHFFelicaCmdRaw(const char *Cmd) { } if (crc) { - add_crc_bytes(&datalen, data, sizeof(data)); + AddCrc(data, datalen); + datalen += 2; } uint8_t flags = 0; From 21f0095029b80e9150cd6d9b6033e66298196075 Mon Sep 17 00:00:00 2001 From: Thomas Sutter Date: Wed, 23 Oct 2019 09:42:45 +0200 Subject: [PATCH 09/24] Make Style. --- client/cmdhffelica.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdhffelica.c b/client/cmdhffelica.c index dfdbfe887..e7e410d4b 100644 --- a/client/cmdhffelica.c +++ b/client/cmdhffelica.c @@ -281,7 +281,7 @@ static int CmdHFFelicaRequestService(const char *Cmd) { buf[strlen(buf)] = Cmd[i]; i++; get_cmd_data(Cmd, &datalen, data, buf); - } else { + } else { i++; } } From bdbb4cb5c940fd0bf72775e0a41a03ded56fb32f Mon Sep 17 00:00:00 2001 From: Thomas Sutter Date: Wed, 23 Oct 2019 13:25:52 +0200 Subject: [PATCH 10/24] Refactor request service parsing. Change Examples. --- client/cmdhffelica.c | 92 ++++++++++++++++++-------------------------- 1 file changed, 37 insertions(+), 55 deletions(-) diff --git a/client/cmdhffelica.c b/client/cmdhffelica.c index e7e410d4b..bad416212 100644 --- a/client/cmdhffelica.c +++ b/client/cmdhffelica.c @@ -19,7 +19,7 @@ #include "comms.h" #include "cmdtrace.h" #include "crc16.h" - +#include "util.h" #include "ui.h" #include "mifare.h" // felica_card_select_t struct #define AddCrc(data, len) compute_crc(CRC_FELICA, (data), (len), (data)+(len)+1, (data)+(len)) @@ -98,11 +98,11 @@ static int usage_hf_felica_request_service(void) { PrintAndLogEx(NORMAL, "\nUsage: hf felica rqservice [-h] [-i] <01 Number of Node hex> <0A 0B Node Code List hex (Little Endian)>"); PrintAndLogEx(NORMAL, " -h this help"); PrintAndLogEx(NORMAL, " -i <0A 0B 0C ... hex> set custom IDm to use"); - PrintAndLogEx(NORMAL, " -a auto node number mode - iterates through all possible node 1 < n < 32"); + PrintAndLogEx(NORMAL, " -a auto node number mode - iterates through all possible nodes 1 < n < 32"); PrintAndLogEx(NORMAL, "\nExamples: "); - PrintAndLogEx(NORMAL, " hf felica rqservice 01 FF FF"); - PrintAndLogEx(NORMAL, " hf felica rqservice -a FF FF"); - PrintAndLogEx(NORMAL, " hf felica rqservice -i 01 10 09 10 c1 1b c4 07 01 FF FF \n\n"); + PrintAndLogEx(NORMAL, " hf felica rqservice 01 FFFF"); + PrintAndLogEx(NORMAL, " hf felica rqservice -a FFFF"); + PrintAndLogEx(NORMAL, " hf felica rqservice -i 01100910c11bc407 01 FFFF \n\n"); return PM3_SUCCESS; } @@ -129,15 +129,7 @@ static bool waitCmdFelica(uint8_t iSelect, PacketResponseNG *resp) { } /* - * Parses line spacing and tabs. - * Returns 1 if the given char is a space or tab - */ -static int parse_cmd_parameter_separator(const char *Cmd, int i) { - return Cmd[i] == ' ' || Cmd[i] == '\t' ? 1 : 0; -} - -/* - * Counts and sets the number of commands. + * Counts and sets the number of parameters. */ static void strip_cmds(const char *Cmd) { while (*Cmd == ' ' || *Cmd == '\t') { @@ -145,34 +137,9 @@ static void strip_cmds(const char *Cmd) { } } -/** - * Checks if a char is a hex value. - * @param Cmd - * @return one if it is a valid hex char. Zero if not a valid hex char. - */ -static bool is_hex_input(const char *Cmd, int i) { - return (Cmd[i] >= '0' && Cmd[i] <= '9') || (Cmd[i] >= 'a' && Cmd[i] <= 'f') || (Cmd[i] >= 'A' && Cmd[i] <= 'F') ? 1 : 0; -} - -/** - * Extracts the hex data from the cmd and puts it into the data array. - * @param Cmd input string of the user with the data - * @param datalen length of the data frame. - * @param data the array in which the data gets stored. - * @param buf buffer with hex data. - */ -static void get_cmd_data(const char *Cmd, uint16_t *datalen, uint8_t *data, char buf[]) { - uint32_t hex; - if (strlen(buf) >= 2) { - sscanf(buf, "%x", &hex); - data[*datalen] = (uint8_t)(hex & 0xff); - (*datalen)++; - *buf = 0; - } -} - /** * Converts integer value to equivalent hex value. + * Examples: 1 = 1, 11 = B * @param number number of hex bytes. * @return number as hex value. */ @@ -250,11 +217,9 @@ static int CmdHFFelicaRequestService(const char *Cmd) { uint8_t data[PM3_CMD_DATA_SIZE]; bool custom_IDm = false; bool all_nodes = false; - uint16_t datalen = 0; + uint16_t datalen = 13; // length (1) + CMD (1) + IDm(8) + Node Number (1) + Node Code List (2) uint8_t flags = 0; - - char buf[5] = ""; - datalen += 10; // length (1) + CMD (1) + IDm(8) + uint8_t paramCount = 0; strip_cmds(Cmd); while (Cmd[i] != '\0') { if (Cmd[i] == '-') { @@ -263,28 +228,45 @@ static int CmdHFFelicaRequestService(const char *Cmd) { case 'h': return usage_hf_felica_request_service(); case 'i': + paramCount++; custom_IDm = true; - datalen -= 8; + if (param_getlength(Cmd, paramCount) == 16) { + param_gethex(Cmd, paramCount++, data + 2, 16); + } else { + PrintAndLogEx(ERR, "Incorrect IDm length! IDm must be 8-Byte."); + return PM3_EINVARG; + } + i += 8; break; case 'a': + paramCount++; all_nodes = true; - datalen += 1; break; default: return usage_hf_felica_request_service(); } i += 2; } - i = i + parse_cmd_parameter_separator(Cmd, i); - if (is_hex_input(Cmd, i)) { - buf[strlen(buf) + 1] = 0; - buf[strlen(buf)] = Cmd[i]; - i++; - get_cmd_data(Cmd, &datalen, data, buf); + i++; + } + if (!all_nodes) { + // Node Number + if (param_getlength(Cmd, paramCount) == 2) { + param_gethex(Cmd, paramCount++, data + 10, 2); } else { - i++; + PrintAndLogEx(ERR, "Incorrect Node number length!"); + return PM3_EINVARG; } } + + // Node Code List + if (param_getlength(Cmd, paramCount) == 4) { + param_gethex(Cmd, paramCount++, data + 11, 4); + } else { + PrintAndLogEx(ERR, "Incorrect Node Code List length!"); + return PM3_EINVARG; + } + flags |= FELICA_APPEND_CRC; if (custom_IDm) { flags |= FELICA_NO_SELECT; @@ -302,16 +284,16 @@ static int CmdHFFelicaRequestService(const char *Cmd) { } } data[0] = int_to_hex(&datalen); - data[1] = 0x02; // Request Command ID + data[1] = 0x02; // Service Request Command ID if (all_nodes) { for (uint16_t y = 1; y < 32; y++) { data[10] = int_to_hex(&y); AddCrc(data, datalen); + datalen += 2; send_request_service(flags, datalen, data); datalen -= 2; // Remove CRC bytes before adding new ones } } else { - PrintAndLogEx(INFO, "Datalen %i", datalen); AddCrc(data, datalen); datalen += 2; send_request_service(flags, datalen, data); From 1f7dd3e2a7e9f290bc24bb58688d4e3db1841053 Mon Sep 17 00:00:00 2001 From: Thomas Sutter Date: Wed, 23 Oct 2019 14:48:23 +0200 Subject: [PATCH 11/24] Add request response command for felica Mode. --- CHANGELOG.md | 3 + client/cmdhffelica.c | 142 ++++++++++++++++++++++++++++++++++--------- include/mifare.h | 8 +++ 3 files changed, 123 insertions(+), 30 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cc6237f6a..168199c2b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,9 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Added hf felica rqresponse (@7homasSutter) + - Added hf felica rqservice (@7homasSutter) + - Added polling for felica standard (@7homasSutter) - Added lf t55xx dump save and lf t55xx restore for .bin and .eml files (@mwalker33) - Added lf t55xx detected to try without password first (@mwalker33) - Chg `lf indala read` - added indala 26bit decoding (@martinbeier) diff --git a/client/cmdhffelica.c b/client/cmdhffelica.c index bad416212..1b46f68e5 100644 --- a/client/cmdhffelica.c +++ b/client/cmdhffelica.c @@ -95,9 +95,9 @@ static int usage_hf_felica_request_service(void) { "of acquisition of Key Version shall be enumerated in Little Endian format. " "If Key Version of System is the target of acquisition, FFFFh shall be specified " "in the command packet."); - PrintAndLogEx(NORMAL, "\nUsage: hf felica rqservice [-h] [-i] <01 Number of Node hex> <0A 0B Node Code List hex (Little Endian)>"); + PrintAndLogEx(NORMAL, "\nUsage: hf felica rqservice [-h] [-i] <01 Number of Node hex> <0A0B Node Code List hex (Little Endian)>"); PrintAndLogEx(NORMAL, " -h this help"); - PrintAndLogEx(NORMAL, " -i <0A 0B 0C ... hex> set custom IDm to use"); + PrintAndLogEx(NORMAL, " -i <0A0B0C ... hex> set custom IDm to use"); PrintAndLogEx(NORMAL, " -a auto node number mode - iterates through all possible nodes 1 < n < 32"); PrintAndLogEx(NORMAL, "\nExamples: "); PrintAndLogEx(NORMAL, " hf felica rqservice 01 FFFF"); @@ -106,6 +106,16 @@ static int usage_hf_felica_request_service(void) { return PM3_SUCCESS; } +static int usage_hf_felica_request_response(void) { + PrintAndLogEx(NORMAL, "\nInfo: Use this command to verify the existence of a card and its Mode."); + PrintAndLogEx(NORMAL, " - Current Mode of the card is returned."); + PrintAndLogEx(NORMAL, "\nUsage: hf felica rqresponse [-h]"); + PrintAndLogEx(NORMAL, " -h this help"); + PrintAndLogEx(NORMAL, " -i <0A0B0C ... hex> set custom IDm to use"); + + return PM3_SUCCESS; +} + /** * Wait for response from pm3 or timeout. * Checks if receveid bytes have a valid CRC. @@ -181,13 +191,20 @@ static int CmdHFFelicaReader(const char *Cmd) { } /** - * Sends a request service frame to the pm3. + * Clears command buffer and sends the given data to pm3 with mix mode. */ -void send_request_service(uint8_t flags, uint16_t datalen, uint8_t *data) { +static void clear_and_send_command(uint8_t flags, uint16_t datalen, uint8_t *data) { uint16_t numbits = 0; clearCommandBuffer(); PrintAndLogEx(NORMAL, "Send Service Request Frame: %s", sprint_hex(data, datalen)); SendCommandMIX(CMD_HF_FELICA_COMMAND, flags, (datalen & 0xFFFF) | (uint32_t)(numbits << 16), 0, data, datalen); +} + +/** + * Sends a request service frame to the pm3. + */ +void send_request_service(uint8_t flags, uint16_t datalen, uint8_t *data) { + clear_and_send_command(flags, datalen, data); PacketResponseNG resp; if (datalen > 0) { if (!waitCmdFelica(0, &resp)) { @@ -206,6 +223,71 @@ void send_request_service(uint8_t flags, uint16_t datalen, uint8_t *data) { } } +/** + * Command parser for rqresponse + * @param Cmd input data of the user. + * @return client result code. + */ +static int CmdHFFelicaRequestResponse(const char *Cmd) { + uint8_t data[PM3_CMD_DATA_SIZE]; + bool custom_IDm = false; + strip_cmds(Cmd); + uint16_t datalen = 10; // Length (1), Command ID (1), IDm (8) + uint8_t paramCount = 0; + uint8_t flags = 0; + int i = 0; + while (Cmd[i] != '\0') { + if (Cmd[i] == '-') { + switch (Cmd[i + 1]) { + case 'H': + case 'h': + return usage_hf_felica_request_response(); + case 'i': + paramCount++; + custom_IDm = true; + if (param_getlength(Cmd, paramCount) == 16) { + param_gethex(Cmd, paramCount++, data + 2, 16); + } else { + PrintAndLogEx(ERR, "Incorrect IDm length! IDm must be 8-Byte."); + return PM3_EINVARG; + } + break; + } + } + i++; + } + data[0] = 0x0A; // Static length + data[1] = 0x04; // Command ID + if (!custom_IDm) { + if (!add_last_IDm(2, data)) { + PrintAndLogEx(ERR, "No last known card! Use reader first or set a custom IDm!"); + return PM3_EINVARG; + } else { + PrintAndLogEx(INFO, "Used last known IDm.", sprint_hex(data, datalen)); + } + } + AddCrc(data, datalen); + datalen += 2; + flags |= FELICA_APPEND_CRC; + flags |= FELICA_RAW; + clear_and_send_command(flags, datalen, data); + PacketResponseNG resp; + if (!waitCmdFelica(0, &resp)) { + PrintAndLogEx(ERR, "\nGot no Response from card"); + return PM3_ERFTRANS; + } else { + felica_request_request_response_t rq_response; + memcpy(&rq_response, (felica_request_request_response_t *)resp.data.asBytes, sizeof(felica_request_request_response_t)); + if (rq_response.IDm[0] != 0) { + PrintAndLogEx(SUCCESS, "\nGot Request Response:"); + PrintAndLogEx(NORMAL, "IDm: %s", sprint_hex(rq_response.IDm, sizeof(rq_response.IDm))); + PrintAndLogEx(NORMAL, " -Mode: %s\n\n", sprint_hex(rq_response.mode, sizeof(rq_response.mode))); + } + } + return PM3_SUCCESS; +} + + /** * Command parser for rqservice. * @param Cmd input data of the user. @@ -806,36 +888,36 @@ int readFelicaUid(bool verbose) { static command_t CommandTable[] = { {"----------- General -----------", CmdHelp, IfPm3Iso14443a, ""}, - {"help", CmdHelp, AlwaysAvailable, "This help"}, - {"list", CmdHFFelicaList, AlwaysAvailable, "List ISO 18092/FeliCa history"}, - {"reader", CmdHFFelicaReader, IfPm3Felica, "Act like an ISO18092/FeliCa reader"}, - {"sniff", CmdHFFelicaSniff, IfPm3Felica, "Sniff ISO 18092/FeliCa traffic"}, - {"raw", CmdHFFelicaCmdRaw, IfPm3Felica, "Send raw hex data to tag"}, + {"help", CmdHelp, AlwaysAvailable, "This help"}, + {"list", CmdHFFelicaList, AlwaysAvailable, "List ISO 18092/FeliCa history"}, + {"reader", CmdHFFelicaReader, IfPm3Felica, "Act like an ISO18092/FeliCa reader"}, + {"sniff", CmdHFFelicaSniff, IfPm3Felica, "Sniff ISO 18092/FeliCa traffic"}, + {"raw", CmdHFFelicaCmdRaw, IfPm3Felica, "Send raw hex data to tag"}, {"----------- FeliCa Standard (support in progress) -----------", CmdHelp, IfPm3Iso14443a, ""}, - //{"dump", CmdHFFelicaDump, IfPm3Felica, "Wait for and try dumping FeliCa"}, - {"rqservice", CmdHFFelicaRequestService, IfPm3Felica, "verify the existence of Area and Service, and to acquire Key Version."}, - {"rqresponse", CmdHFFelicaNotImplementedYet, IfPm3Felica, "verify the existence of a card and its Mode."}, - //{"rdNoEncryption", CmdHFFelicaNotImplementedYet, IfPm3Felica, "read Block Data from authentication-not-required Service."}, + //{"dump", CmdHFFelicaDump, IfPm3Felica, "Wait for and try dumping FeliCa"}, + {"rqservice", CmdHFFelicaRequestService, IfPm3Felica, "verify the existence of Area and Service, and to acquire Key Version."}, + {"rqresponse", CmdHFFelicaRequestResponse, IfPm3Felica, "verify the existence of a card and its Mode."}, + {"rdNoEncryption", CmdHFFelicaNotImplementedYet, IfPm3Felica, "read Block Data from authentication-not-required Service."}, //{"wrNoEncryption", CmdHFFelicaNotImplementedYet, IfPm3Felica, "write Block Data to an authentication-required Service."}, - //{"searchSvCode", CmdHFFelicaNotImplementedYet, IfPm3Felica, "acquire Area Code and Service Code."}, - //{"rqSysCode", CmdHFFelicaNotImplementedYet, IfPm3Felica, "acquire System Code registered to the card."}, - //{"auth1", CmdHFFelicaNotImplementedYet, IfPm3Felica, "authenticate a card."}, - //{"auth2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "allow a card to authenticate a Reader/Writer."}, - //{"read", CmdHFFelicaNotImplementedYet, IfPm3Felica, "read Block Data from authentication-required Service."}, - //{"write", CmdHFFelicaNotImplementedYet, IfPm3Felica, "write Block Data to an authentication-required Service."}, + //{"searchSvCode", CmdHFFelicaNotImplementedYet, IfPm3Felica, "acquire Area Code and Service Code."}, + //{"rqSysCode", CmdHFFelicaNotImplementedYet, IfPm3Felica, "acquire System Code registered to the card."}, + //{"auth1", CmdHFFelicaNotImplementedYet, IfPm3Felica, "authenticate a card."}, + //{"auth2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "allow a card to authenticate a Reader/Writer."}, + //{"read", CmdHFFelicaNotImplementedYet, IfPm3Felica, "read Block Data from authentication-required Service."}, + //{"write", CmdHFFelicaNotImplementedYet, IfPm3Felica, "write Block Data to an authentication-required Service."}, //{"searchSvCodeV2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "verify the existence of Area or Service, and to acquire Key Version."}, - //{"getSysStatus", CmdHFFelicaNotImplementedYet, IfPm3Felica, "acquire the setup information in System."}, - //{"rqSpecVer", CmdHFFelicaNotImplementedYet, IfPm3Felica, "acquire the version of card OS."}, - //{"resetMode", CmdHFFelicaNotImplementedYet, IfPm3Felica, "reset Mode to Mode 0."}, - //{"auth1V2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "authenticate a card."}, - //{"auth2V2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "allow a card to authenticate a Reader/Writer."}, - //{"readV2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "read Block Data from authentication-required Service."}, - //{"writeV2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "write Block Data to authentication-required Service."}, - //{"upRandomID", CmdHFFelicaNotImplementedYet, IfPm3Felica, "update Random ID (IDr)."}, + //{"getSysStatus", CmdHFFelicaNotImplementedYet, IfPm3Felica, "acquire the setup information in System."}, + //{"rqSpecVer", CmdHFFelicaNotImplementedYet, IfPm3Felica, "acquire the version of card OS."}, + //{"resetMode", CmdHFFelicaNotImplementedYet, IfPm3Felica, "reset Mode to Mode 0."}, + //{"auth1V2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "authenticate a card."}, + //{"auth2V2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "allow a card to authenticate a Reader/Writer."}, + //{"readV2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "read Block Data from authentication-required Service."}, + //{"writeV2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "write Block Data to authentication-required Service."}, + //{"upRandomID", CmdHFFelicaNotImplementedYet, IfPm3Felica, "update Random ID (IDr)."}, {"----------- FeliCa Light -----------", CmdHelp, IfPm3Iso14443a, ""}, - {"litesim", CmdHFFelicaSimLite, IfPm3Felica, " - only reply to poll request"}, - {"litedump", CmdHFFelicaDumpLite, IfPm3Felica, "Wait for and try dumping FelicaLite"}, - // {"sim", CmdHFFelicaSim, IfPm3Felica, " -- Simulate ISO 18092/FeliCa tag"} + {"litesim", CmdHFFelicaSimLite, IfPm3Felica, " - only reply to poll request"}, + {"litedump", CmdHFFelicaDumpLite, IfPm3Felica, "Wait for and try dumping FelicaLite"}, + // {"sim", CmdHFFelicaSim, IfPm3Felica, " -- Simulate ISO 18092/FeliCa tag"} {NULL, NULL, NULL, NULL} }; diff --git a/include/mifare.h b/include/mifare.h index 5461bd19f..754a0c82f 100644 --- a/include/mifare.h +++ b/include/mifare.h @@ -178,6 +178,14 @@ typedef struct { uint8_t node_key_versions[2]; } PACKED felica_request_service_response_t; +typedef struct { + uint8_t sync[2]; + uint8_t length[1]; + uint8_t cmd_code[1]; + uint8_t IDm[8]; + uint8_t mode[1]; +} PACKED felica_request_request_response_t; + typedef enum FELICA_COMMAND { FELICA_CONNECT = (1 << 0), FELICA_NO_DISCONNECT = (1 << 1), From e872ac58f747dadb318ffaf23d3073fedc80f3fd Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Thu, 24 Oct 2019 01:30:54 +0200 Subject: [PATCH 12/24] coverity 263770 fix dead code --- armsrc/felica.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/armsrc/felica.c b/armsrc/felica.c index 4d9712a0d..1374927d8 100644 --- a/armsrc/felica.c +++ b/armsrc/felica.c @@ -792,7 +792,7 @@ void felica_send_request_service(uint8_t *request_service) { // When the specified Area or Service does not exist, the card returns FFFFh as Key Version. */ uint8_t *felica_create_request_service_frame(uint8_t nodeNumber, uint8_t *idm) { - if (nodeNumber < 1 && nodeNumber > 32) { + if (nodeNumber < 1 || nodeNumber > 32) { Dbprintf("Node number out of range: 1 <= %d <= 32 - set node number to 1"); nodeNumber = 1; } From 30da3cfd429d3e2019e1d1b2de69daf3df11bc5d Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Thu, 24 Oct 2019 01:32:44 +0200 Subject: [PATCH 13/24] coverity 263769 dereference before null check --- common/crapto1/crypto1.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/common/crapto1/crypto1.c b/common/crapto1/crypto1.c index bb501cd58..dd5541b29 100644 --- a/common/crapto1/crypto1.c +++ b/common/crapto1/crypto1.c @@ -26,12 +26,11 @@ (x = (x >> 8 & 0xff00ff) | (x & 0xff00ff) << 8, x = x >> 16 | x << 16) void crypto1_init(struct Crypto1State *state, uint64_t key) { + if (state == NULL) + return; state->odd = 0; state->even = 0; - - int i; - - for (i = 47; state && i > 0; i -= 2) { + for (int i = 47; i > 0; i -= 2) { state->odd = state->odd << 1 | BIT(key, (i - 1) ^ 7); state->even = state->even << 1 | BIT(key, i ^ 7); } From ff9eabdab50ade1d2440199290df950f3789e4a7 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Thu, 24 Oct 2019 01:35:58 +0200 Subject: [PATCH 14/24] coverity 226329 invalid type for printf --- client/cmdhffelica.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdhffelica.c b/client/cmdhffelica.c index 1fa5b035d..bdb9cc57f 100644 --- a/client/cmdhffelica.c +++ b/client/cmdhffelica.c @@ -421,7 +421,7 @@ static int CmdHFFelicaDumpLite(const char *Cmd) { return PM3_ETIMEOUT; } - PrintAndLogEx(SUCCESS, "Recorded Activity (trace len = %"PRIu64" bytes)", tracelen); + PrintAndLogEx(SUCCESS, "Recorded Activity (trace len = %"PRIu32" bytes)", tracelen); print_hex_break(trace, tracelen, 32); printSep(); From 3b0447fbb3ccf06799b45df298631058f5db738c Mon Sep 17 00:00:00 2001 From: Thomas Sutter Date: Thu, 24 Oct 2019 08:44:20 +0200 Subject: [PATCH 15/24] Draft read without encryption --- client/cmdhffelica.c | 54 ++++++++++++++++++++++++++++++++++++++++++-- include/mifare.h | 11 +++++++++ 2 files changed, 63 insertions(+), 2 deletions(-) diff --git a/client/cmdhffelica.c b/client/cmdhffelica.c index 1b46f68e5..f0c699b9b 100644 --- a/client/cmdhffelica.c +++ b/client/cmdhffelica.c @@ -116,6 +116,16 @@ static int usage_hf_felica_request_response(void) { return PM3_SUCCESS; } +static int usage_hf_felica_read_without_encryption(void) { + PrintAndLogEx(NORMAL, "\nInfo: Use this command to read Block Data from authentication-not-required Service."); + PrintAndLogEx(NORMAL, " - Mode shall be Mode0."); + PrintAndLogEx(NORMAL, "\nUsage: hf felica rdNoEncryption [-h]"); + PrintAndLogEx(NORMAL, " -h this help"); + PrintAndLogEx(NORMAL, " -i <0A0B0C ... hex> set custom IDm to use"); + + return PM3_SUCCESS; +} + /** * Wait for response from pm3 or timeout. * Checks if receveid bytes have a valid CRC. @@ -223,6 +233,46 @@ void send_request_service(uint8_t flags, uint16_t datalen, uint8_t *data) { } } +/** + * Command parser for rdNoEncryption. + * @param Cmd input data of the user. + * @return client result code. + */ +static int CmdHFFelicaReadWithoutEncryption(const char *Cmd) { + if (strlen(Cmd) < 4) + return usage_hf_felica_read_without_encryption; + uint8_t data[PM3_CMD_DATA_SIZE]; + bool custom_IDm = false; + strip_cmds(Cmd); + uint16_t datalen = 17; // Length (1), Command ID (1), IDm (8), Number of Service (1), Service Code List(2), Number of Block(1), Block List(3) + uint8_t paramCount = 0; + uint8_t flags = 0; + int i = 0; + while (Cmd[i] != '\0') { + if (Cmd[i] == '-') { + switch (Cmd[i + 1]) { + case 'H': + case 'h': + return usage_hf_felica_request_response(); + case 'i': + paramCount++; + custom_IDm = true; + if (param_getlength(Cmd, paramCount) == 16) { + param_gethex(Cmd, paramCount++, data + 2, 16); + } else { + PrintAndLogEx(ERR, "Incorrect IDm length! IDm must be 8-Byte."); + return PM3_EINVARG; + } + break; + } + } + i++; + } + + + return PM3_SUCCESS; +} + /** * Command parser for rqresponse * @param Cmd input data of the user. @@ -897,8 +947,8 @@ static command_t CommandTable[] = { //{"dump", CmdHFFelicaDump, IfPm3Felica, "Wait for and try dumping FeliCa"}, {"rqservice", CmdHFFelicaRequestService, IfPm3Felica, "verify the existence of Area and Service, and to acquire Key Version."}, {"rqresponse", CmdHFFelicaRequestResponse, IfPm3Felica, "verify the existence of a card and its Mode."}, - {"rdNoEncryption", CmdHFFelicaNotImplementedYet, IfPm3Felica, "read Block Data from authentication-not-required Service."}, - //{"wrNoEncryption", CmdHFFelicaNotImplementedYet, IfPm3Felica, "write Block Data to an authentication-required Service."}, + {"rdNoEncryption", CmdHFFelicaReadWithoutEncryption, IfPm3Felica, "read Block Data from authentication-not-required Service."}, + {"wrNoEncryption", CmdHFFelicaNotImplementedYet, IfPm3Felica, "write Block Data to an authentication-required Service."}, //{"searchSvCode", CmdHFFelicaNotImplementedYet, IfPm3Felica, "acquire Area Code and Service Code."}, //{"rqSysCode", CmdHFFelicaNotImplementedYet, IfPm3Felica, "acquire System Code registered to the card."}, //{"auth1", CmdHFFelicaNotImplementedYet, IfPm3Felica, "authenticate a card."}, diff --git a/include/mifare.h b/include/mifare.h index 754a0c82f..e472d5c59 100644 --- a/include/mifare.h +++ b/include/mifare.h @@ -186,6 +186,17 @@ typedef struct { uint8_t mode[1]; } PACKED felica_request_request_response_t; +typedef struct { + uint8_t sync[2]; + uint8_t length[1]; + uint8_t cmd_code[1]; + uint8_t IDm[8]; + uint8_t status_flag1[1]; + uint8_t status_flag2[1]; + uint8_t number_of_block[1]; + uint8_t block_data[16]; +} PACKED felica_read_without_encryption_response_t; + typedef enum FELICA_COMMAND { FELICA_CONNECT = (1 << 0), FELICA_NO_DISCONNECT = (1 << 1), From fc800d97b52fa356eb84b904d4b6431981736f5f Mon Sep 17 00:00:00 2001 From: mwalker33 Date: Thu, 24 Oct 2019 19:06:59 +1100 Subject: [PATCH 16/24] Update appmain.c --- armsrc/appmain.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 84589ff00..dcb7d63a0 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -1589,9 +1589,14 @@ static void PacketReceived(PacketCommandNG *packet) { BigBuf_free(); } uint16_t offset = MIN(BIGBUF_SIZE - PM3_CMD_DATA_SIZE - 3, payload->offset); + + // need to copy len bytes of data, not PM3_CMD_DATA_SIZE - 3 - offset + // ensure len bytes copied wont go past end of bigbuf + uint16_t len = MIN(BIGBUF_SIZE - offset,PM3_CMD_DATA_SIZE - 3); uint8_t *mem = BigBuf_get_addr(); - memcpy(mem + offset, &payload->data, PM3_CMD_DATA_SIZE - 3 - offset); + memcpy(mem + offset, &payload->data, len); + // memcpy(mem + offset, &payload->data, PM3_CMD_DATA_SIZE - 3 - offset); reply_ng(CMD_LF_UPLOAD_SIM_SAMPLES, PM3_SUCCESS, NULL, 0); break; } From 003aada18f7727cef11ec082c86843d93d6a3711 Mon Sep 17 00:00:00 2001 From: Thomas Sutter Date: Thu, 24 Oct 2019 11:30:52 +0200 Subject: [PATCH 17/24] Add basic read_without_encryption command. --- client/cmdhffelica.c | 113 +++++++++++++++++++++++++++++++++---------- 1 file changed, 88 insertions(+), 25 deletions(-) diff --git a/client/cmdhffelica.c b/client/cmdhffelica.c index f0c699b9b..ea52e5112 100644 --- a/client/cmdhffelica.c +++ b/client/cmdhffelica.c @@ -112,17 +112,19 @@ static int usage_hf_felica_request_response(void) { PrintAndLogEx(NORMAL, "\nUsage: hf felica rqresponse [-h]"); PrintAndLogEx(NORMAL, " -h this help"); PrintAndLogEx(NORMAL, " -i <0A0B0C ... hex> set custom IDm to use"); - return PM3_SUCCESS; } static int usage_hf_felica_read_without_encryption(void) { PrintAndLogEx(NORMAL, "\nInfo: Use this command to read Block Data from authentication-not-required Service."); PrintAndLogEx(NORMAL, " - Mode shall be Mode0."); - PrintAndLogEx(NORMAL, "\nUsage: hf felica rdNoEncryption [-h]"); + + PrintAndLogEx(NORMAL, "\nUsage: hf felica rdunencrypted [-h] <01 Number of Service hex> <0A0B Service Code List hex> <01 Number of Block hex> <0A0B or 0A0B0C Block List Element hex>"); PrintAndLogEx(NORMAL, " -h this help"); PrintAndLogEx(NORMAL, " -i <0A0B0C ... hex> set custom IDm to use"); - + PrintAndLogEx(NORMAL, "\nExamples: "); + PrintAndLogEx(NORMAL, " hf felica rdunencrypted 01 8B00 01 8000"); + PrintAndLogEx(NORMAL, " hf felica rdunencrypted -i 01100910c11bc407 01 8B00 01 8000\n\n"); return PM3_SUCCESS; } @@ -211,7 +213,35 @@ static void clear_and_send_command(uint8_t flags, uint16_t datalen, uint8_t *dat } /** - * Sends a request service frame to the pm3. + * Prints the given block data. + */ +static void print_block_data(uint8_t *number_of_block, uint8_t *block_data, size_t block_size){ + PrintAndLogEx(NORMAL, "Block Nr.: %i", *number_of_block); + PrintAndLogEx(NORMAL, "Data: %s", sprint_hex(block_data, block_size)); +}; + + +/** + * Adds a parameter to the frame and checks if the parameter has the specific length. + * @param Cmd User input with the parameter. + * @param paramCount number of the parameter within the user input. + * @param data frame in which the data is stored. + * @param dataPosition position within frame where the data will be stored. + * @param length which the parameter should have and will be tested against. + * @return + */ +static bool add_param(const char *Cmd, uint8_t paramCount, uint8_t *data, uint8_t dataPosition, uint8_t length){ + if (param_getlength(Cmd, paramCount) == length) { + param_gethex(Cmd, paramCount, data + dataPosition, length); + return true; + } else { + PrintAndLogEx(ERR, "Incorrect Parameter length! Param %i", paramCount); + return false; + } +} + +/** + * Sends a request service frame to the pm3 and prints response. */ void send_request_service(uint8_t flags, uint16_t datalen, uint8_t *data) { clear_and_send_command(flags, datalen, data); @@ -234,17 +264,17 @@ void send_request_service(uint8_t flags, uint16_t datalen, uint8_t *data) { } /** - * Command parser for rdNoEncryption. + * Command parser for rdunencrypted. * @param Cmd input data of the user. * @return client result code. */ static int CmdHFFelicaReadWithoutEncryption(const char *Cmd) { if (strlen(Cmd) < 4) - return usage_hf_felica_read_without_encryption; + return usage_hf_felica_read_without_encryption(); uint8_t data[PM3_CMD_DATA_SIZE]; bool custom_IDm = false; strip_cmds(Cmd); - uint16_t datalen = 17; // Length (1), Command ID (1), IDm (8), Number of Service (1), Service Code List(2), Number of Block(1), Block List(3) + uint16_t datalen = 16; // Length (1), Command ID (1), IDm (8), Number of Service (1), Service Code List(2), Number of Block(1), Block List(3) uint8_t paramCount = 0; uint8_t flags = 0; int i = 0; @@ -257,10 +287,7 @@ static int CmdHFFelicaReadWithoutEncryption(const char *Cmd) { case 'i': paramCount++; custom_IDm = true; - if (param_getlength(Cmd, paramCount) == 16) { - param_gethex(Cmd, paramCount++, data + 2, 16); - } else { - PrintAndLogEx(ERR, "Incorrect IDm length! IDm must be 8-Byte."); + if(!add_param(Cmd, paramCount, data, 3, 8)){ return PM3_EINVARG; } break; @@ -268,8 +295,44 @@ static int CmdHFFelicaReadWithoutEncryption(const char *Cmd) { } i++; } + data[0] = 0x10; // Static length + data[1] = 0x06; // Command ID + if (!custom_IDm) { + if (!add_last_IDm(2, data)) { + PrintAndLogEx(ERR, "No last known card! Use reader first or set a custom IDm!"); + return PM3_EINVARG; + } else { + PrintAndLogEx(INFO, "Used last known IDm.", sprint_hex(data, datalen)); + } + } + // Number of Service 2, Service Code List 4, Number of Block 2, Block List Element 4 + uint8_t lengths[] = {2, 4, 2, 4}; + uint8_t dataPositions[] = {10, 11, 13, 14}; + for(int i=0; i < 4; i++){ + if(add_param(Cmd, paramCount, data, dataPositions[i], lengths[i])){ + paramCount++; + }else{ + return PM3_EINVARG; + } + } + AddCrc(data, datalen); + datalen += 2; + flags |= FELICA_APPEND_CRC; + flags |= FELICA_RAW; + clear_and_send_command(flags, datalen, data); + PacketResponseNG resp; + if (!waitCmdFelica(0, &resp)) { + PrintAndLogEx(ERR, "\nGot no Response from card"); + return PM3_ERFTRANS; + } else { + PrintAndLogEx(SUCCESS, "\nGot Response from card"); + felica_read_without_encryption_response_t rd_noCry_resp; + memcpy(&rd_noCry_resp, (felica_read_without_encryption_response_t *)resp.data.asBytes, sizeof(felica_read_without_encryption_response_t)); - + if (rd_noCry_resp.IDm[0] != 0) { + print_block_data(rd_noCry_resp.number_of_block, rd_noCry_resp.block_data, sizeof(rd_noCry_resp.block_data)); + } + } return PM3_SUCCESS; } @@ -947,23 +1010,23 @@ static command_t CommandTable[] = { //{"dump", CmdHFFelicaDump, IfPm3Felica, "Wait for and try dumping FeliCa"}, {"rqservice", CmdHFFelicaRequestService, IfPm3Felica, "verify the existence of Area and Service, and to acquire Key Version."}, {"rqresponse", CmdHFFelicaRequestResponse, IfPm3Felica, "verify the existence of a card and its Mode."}, - {"rdNoEncryption", CmdHFFelicaReadWithoutEncryption, IfPm3Felica, "read Block Data from authentication-not-required Service."}, - {"wrNoEncryption", CmdHFFelicaNotImplementedYet, IfPm3Felica, "write Block Data to an authentication-required Service."}, - //{"searchSvCode", CmdHFFelicaNotImplementedYet, IfPm3Felica, "acquire Area Code and Service Code."}, - //{"rqSysCode", CmdHFFelicaNotImplementedYet, IfPm3Felica, "acquire System Code registered to the card."}, + {"rdunencrypted", CmdHFFelicaReadWithoutEncryption, IfPm3Felica, "read Block Data from authentication-not-required Service."}, + {"wrunencrypted", CmdHFFelicaNotImplementedYet, IfPm3Felica, "write Block Data to an authentication-not-required Service."}, + //{"scsvcode", CmdHFFelicaNotImplementedYet, IfPm3Felica, "acquire Area Code and Service Code."}, + //{"rqsyscode", CmdHFFelicaNotImplementedYet, IfPm3Felica, "acquire System Code registered to the card."}, //{"auth1", CmdHFFelicaNotImplementedYet, IfPm3Felica, "authenticate a card."}, //{"auth2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "allow a card to authenticate a Reader/Writer."}, //{"read", CmdHFFelicaNotImplementedYet, IfPm3Felica, "read Block Data from authentication-required Service."}, //{"write", CmdHFFelicaNotImplementedYet, IfPm3Felica, "write Block Data to an authentication-required Service."}, - //{"searchSvCodeV2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "verify the existence of Area or Service, and to acquire Key Version."}, - //{"getSysStatus", CmdHFFelicaNotImplementedYet, IfPm3Felica, "acquire the setup information in System."}, - //{"rqSpecVer", CmdHFFelicaNotImplementedYet, IfPm3Felica, "acquire the version of card OS."}, - //{"resetMode", CmdHFFelicaNotImplementedYet, IfPm3Felica, "reset Mode to Mode 0."}, - //{"auth1V2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "authenticate a card."}, - //{"auth2V2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "allow a card to authenticate a Reader/Writer."}, - //{"readV2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "read Block Data from authentication-required Service."}, - //{"writeV2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "write Block Data to authentication-required Service."}, - //{"upRandomID", CmdHFFelicaNotImplementedYet, IfPm3Felica, "update Random ID (IDr)."}, + //{"scsvcodev2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "verify the existence of Area or Service, and to acquire Key Version."}, + //{"getsysstatus", CmdHFFelicaNotImplementedYet, IfPm3Felica, "acquire the setup information in System."}, + //{"rqspecver", CmdHFFelicaNotImplementedYet, IfPm3Felica, "acquire the version of card OS."}, + //{"resetmode", CmdHFFelicaNotImplementedYet, IfPm3Felica, "reset Mode to Mode 0."}, + //{"auth1v2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "authenticate a card."}, + //{"auth2v2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "allow a card to authenticate a Reader/Writer."}, + //{"readv2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "read Block Data from authentication-required Service."}, + //{"writev2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "write Block Data to authentication-required Service."}, + //{"uprandomid", CmdHFFelicaNotImplementedYet, IfPm3Felica, "update Random ID (IDr)."}, {"----------- FeliCa Light -----------", CmdHelp, IfPm3Iso14443a, ""}, {"litesim", CmdHFFelicaSimLite, IfPm3Felica, " - only reply to poll request"}, {"litedump", CmdHFFelicaDumpLite, IfPm3Felica, "Wait for and try dumping FelicaLite"}, From 94ec36de2007bf277f9fff0925c26be03db9094e Mon Sep 17 00:00:00 2001 From: Thomas Sutter Date: Thu, 24 Oct 2019 11:59:58 +0200 Subject: [PATCH 18/24] Add status flag interpretation. --- client/cmdhffelica.c | 60 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 57 insertions(+), 3 deletions(-) diff --git a/client/cmdhffelica.c b/client/cmdhffelica.c index ea52e5112..176031d3f 100644 --- a/client/cmdhffelica.c +++ b/client/cmdhffelica.c @@ -115,11 +115,58 @@ static int usage_hf_felica_request_response(void) { return PM3_SUCCESS; } +static void print_status_flag1_interpretation(){ + PrintAndLogEx(NORMAL, "Status Flag1:"); + PrintAndLogEx(NORMAL, " - 00h : Indicates the successful completion of a command."); + PrintAndLogEx(NORMAL, " - FFh : If an error occurs during the processing of a command that includes no list in the command packet, or if " + "an error occurs independently of any list, the card returns a response by setting FFh to Status Flag1."); + PrintAndLogEx(NORMAL, " - XXh : If an error occurs while processing a command that includes Service Code List or Block List " + "in the command packet, the card returns a response by setting a number in the list to Status Flag1, " + "indicating the location of the error. Have a look at the FeliCa User Manual for more information."); +} + +static void print_status_flag2_interpration(){ + PrintAndLogEx(NORMAL, "Status Flag2:"); + PrintAndLogEx(NORMAL, " - 00h : Indicates the successful completion of a command."); + PrintAndLogEx(NORMAL, " - 01h : The calculated result is either less than zero when the purse data is decremented, or exceeds 4" + "Bytes when the purse data is incremented."); + PrintAndLogEx(NORMAL, " - 02h : The specified data exceeds the value of cashback data at cashback of purse."); + PrintAndLogEx(NORMAL, " - 70h : Memory error (fatal error)."); + PrintAndLogEx(NORMAL, " - 71h : The number of memory rewrites exceeds the upper limit (this is only a warning; data writing is " + "performed as normal). The maximum number of rewrites can differ, depending on the product being used." + " In addition, Status Flag1 is either 00h or FFh depending on the product being used."); + PrintAndLogEx(NORMAL, " - A1h : Illegal Number of Service: Number of Service or Number of Node specified by the command falls outside the range of the prescribed value."); + PrintAndLogEx(NORMAL, " - A2h : Illegal command packet (specified Number of Block): Number of Block specified by the command falls outside the range of the prescribed values for the product."); + PrintAndLogEx(NORMAL, " - A3h : Illegal Block List (specified order of Service): Service Code List Order specified by Block List Element falls outside the Number of Service specified by the " + "command (or the Number of Service specified at the times of mutual authentication)."); + PrintAndLogEx(NORMAL, " - A4h : Illegal Service type: Area Attribute specified by the command or Service Attribute of Service Code is incorrect."); + PrintAndLogEx(NORMAL, " - A5h : Access is not allowed: Area or Service specified by the command cannot be accessed. " + "The parameter specified by the command does not satisfy the conditions for success."); + PrintAndLogEx(NORMAL, " - A6h : Illegal Service Code List: Target to be accessed, identified by Service Code List Order, specified by Block " + "List Element does not exist. Or, Node specified by Node Code List does not exist."); + PrintAndLogEx(NORMAL, " - A7h : Illegal Block List (Access Mode): Access Mode specified by Block List Element is incorrect."); + PrintAndLogEx(NORMAL, " - A8h : Illegal Block Number Block Number (access to the specified data is inhibited): specified by Block List Element exceeds the number of Blocks assigned to Service."); + PrintAndLogEx(NORMAL, " - A9h : Data write failure: This is the error that occurs in issuance commands."); + PrintAndLogEx(NORMAL, " - AAh : Key-change failure: Key change failed."); + PrintAndLogEx(NORMAL, " - ABh : Illegal Package Parity or illegal Package MAC: This is the error that occurs in issuance commands."); + PrintAndLogEx(NORMAL, " - ACh : Illegal parameter: This is the error that occurs in issuance commands."); + PrintAndLogEx(NORMAL, " - ADh : Service exists already: This is the error that occurs in issuance commands."); + PrintAndLogEx(NORMAL, " - AEh : Illegal System Code: This is the error that occurs in issuance commands."); + PrintAndLogEx(NORMAL, " - AFh : Too many simultaneous cyclic write operations: Number of simultaneous write Blocks specified by the command to Cyclic Service " + "exceeds the number of Blocks assigned to Service."); + PrintAndLogEx(NORMAL, " - C0h : Illegal Package Identifier: This is the error that occurs in issuance commands."); + PrintAndLogEx(NORMAL, " - C1h : Discrepancy of parameters inside and outside Package: This is the error that occurs in issuance commands."); + PrintAndLogEx(NORMAL, " - C2h : Command is disabled already: This is the error that occurs in issuance commands."); +} + static int usage_hf_felica_read_without_encryption(void) { PrintAndLogEx(NORMAL, "\nInfo: Use this command to read Block Data from authentication-not-required Service."); PrintAndLogEx(NORMAL, " - Mode shall be Mode0."); - - PrintAndLogEx(NORMAL, "\nUsage: hf felica rdunencrypted [-h] <01 Number of Service hex> <0A0B Service Code List hex> <01 Number of Block hex> <0A0B or 0A0B0C Block List Element hex>"); + PrintAndLogEx(NORMAL, " - Successful read: Card responses the block data"); + PrintAndLogEx(NORMAL, " - Unsuccessful read: Card responses with Status Flag1 and Flag2"); + print_status_flag1_interpretation(); + print_status_flag2_interpration(); + PrintAndLogEx(NORMAL, "\nUsage: hf felica rdunencrypted [-h] <01 Number of Service hex> <0A0B Service Code List (Little Endian) hex> <01 Number of Block hex> <0A0B Block List Element hex>"); PrintAndLogEx(NORMAL, " -h this help"); PrintAndLogEx(NORMAL, " -i <0A0B0C ... hex> set custom IDm to use"); PrintAndLogEx(NORMAL, "\nExamples: "); @@ -330,7 +377,14 @@ static int CmdHFFelicaReadWithoutEncryption(const char *Cmd) { memcpy(&rd_noCry_resp, (felica_read_without_encryption_response_t *)resp.data.asBytes, sizeof(felica_read_without_encryption_response_t)); if (rd_noCry_resp.IDm[0] != 0) { - print_block_data(rd_noCry_resp.number_of_block, rd_noCry_resp.block_data, sizeof(rd_noCry_resp.block_data)); + PrintAndLogEx(NORMAL, "IDm: %s", sprint_hex(rd_noCry_resp.IDm, sizeof(rd_noCry_resp.IDm))); + PrintAndLogEx(NORMAL, " -Status Flag1: %s", sprint_hex(rd_noCry_resp.status_flag1, sizeof(rd_noCry_resp.status_flag1))); + PrintAndLogEx(NORMAL, " -Status Flag2: %s", sprint_hex(rd_noCry_resp.status_flag2, sizeof(rd_noCry_resp.status_flag2))); + if(rd_noCry_resp.status_flag1[0] == 00 && rd_noCry_resp.status_flag2[0] == 00){ + print_block_data(rd_noCry_resp.number_of_block, rd_noCry_resp.block_data, sizeof(rd_noCry_resp.block_data)); + }else{ + PrintAndLogEx(ERR, "Could not read data! See -h for more information about the status flags."); + } } } return PM3_SUCCESS; From bfd5214cd5ab5ddfae2e2293b059f9216d6c1700 Mon Sep 17 00:00:00 2001 From: Thomas Sutter Date: Thu, 24 Oct 2019 16:08:44 +0200 Subject: [PATCH 19/24] Add read_without_encryption command. --- armsrc/felica.c | 20 ----- armsrc/felica.h | 5 -- client/cmdhffelica.c | 181 ++++++++++++++++++++++++++++++------------- client/cmdhffelica.h | 4 +- include/mifare.h | 1 + 5 files changed, 133 insertions(+), 78 deletions(-) diff --git a/armsrc/felica.c b/armsrc/felica.c index 09e2b582f..7ec40efcf 100644 --- a/armsrc/felica.c +++ b/armsrc/felica.c @@ -751,26 +751,6 @@ void felica_sim_lite(uint64_t uid) { #define RES_SVC_LEN 11 + 3 -void felica_dump() { - uint8_t ndef[8]; - uint8_t poll[10] = { 0xb2, 0x4d, 0x06, FELICA_POLL_REQ, 0xff, 0xff, 0x00, 0x00, 0x09, 0x21}; // B24D0600FFFF00000921 - iso18092_setup(FPGA_HF_ISO18092_FLAG_READER | FPGA_HF_ISO18092_FLAG_NOMOD); - - TransmitFor18092_AsReader(poll, 10, NULL, 1, 0); - - // iceman, no exit path in this loop - while (!BUTTON_PRESS() && !data_available()) { - WDT_HIT(); - TransmitFor18092_AsReader(poll, 10, NULL, 1, 0); - if (WaitForFelicaReply(512) && FelicaFrame.framebytes[3] == FELICA_POLL_ACK) { - memcpy(ndef, FelicaFrame.framebytes + 4, 8); - uint8_t *request_service = felica_create_request_service_frame(0x01, ndef); - felica_send_request_service(request_service); - } - } - -} - void felica_dump_lite_s() { uint8_t ndef[8]; uint8_t poll[10] = { 0xb2, 0x4d, 0x06, FELICA_POLL_REQ, 0xff, 0xff, 0x00, 0x00, 0x09, 0x21}; diff --git a/armsrc/felica.h b/armsrc/felica.h index 7bbc48614..95e13a588 100644 --- a/armsrc/felica.h +++ b/armsrc/felica.h @@ -18,12 +18,7 @@ void felica_sendraw(PacketCommandNG *c); void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip); void felica_sim_lite(uint64_t uid); void felica_dump_lite_s(); -void felica_dump(); void felica_create_read_block_frame(uint16_t blockNr); -void felica_create_authentication1_frame(); -void felica_create_authentication2_frame(); void felica_send_request_service(uint8_t *request_service); -void felica_reset_frame_mode(); -uint8_t *felica_create_request_service_frame(uint8_t nodeNumber, uint8_t *idm); #endif diff --git a/client/cmdhffelica.c b/client/cmdhffelica.c index 176031d3f..8a1926276 100644 --- a/client/cmdhffelica.c +++ b/client/cmdhffelica.c @@ -159,9 +159,19 @@ static void print_status_flag2_interpration(){ PrintAndLogEx(NORMAL, " - C2h : Command is disabled already: This is the error that occurs in issuance commands."); } -static int usage_hf_felica_read_without_encryption(void) { +static int usage_hf_felica_read_without_encryption() { PrintAndLogEx(NORMAL, "\nInfo: Use this command to read Block Data from authentication-not-required Service."); PrintAndLogEx(NORMAL, " - Mode shall be Mode0."); + PrintAndLogEx(NORMAL, " - Number of Service shall be a positive integer in the range of 1 to 16, inclusive."); + PrintAndLogEx(NORMAL, " - Number of Block shall be less than or equal to the maximum number of Blocks that can be read simultaneously. " + "The maximum number of Blocks that can be read simultaneously can differ, depending on the product being used."); + PrintAndLogEx(NORMAL, " - Each Block List Element shall satisfy the following conditions:"); + PrintAndLogEx(NORMAL, " - The value of Service Code List Order shall not exceed Number of Service."); + PrintAndLogEx(NORMAL, " - Access Mode shall be 000b."); + PrintAndLogEx(NORMAL, " - The target specified by Service Code shall not be Area or System."); + PrintAndLogEx(NORMAL, " - Service specified in Service Code List shall exist in System."); + PrintAndLogEx(NORMAL, " - Service Attribute of Service specified in Service Code List shall be authentication-not-required Service."); + PrintAndLogEx(NORMAL, " - Block Number shall be in the range of the number of Blocks assigned to the specified Service."); PrintAndLogEx(NORMAL, " - Successful read: Card responses the block data"); PrintAndLogEx(NORMAL, " - Unsuccessful read: Card responses with Status Flag1 and Flag2"); print_status_flag1_interpretation(); @@ -169,6 +179,7 @@ static int usage_hf_felica_read_without_encryption(void) { PrintAndLogEx(NORMAL, "\nUsage: hf felica rdunencrypted [-h] <01 Number of Service hex> <0A0B Service Code List (Little Endian) hex> <01 Number of Block hex> <0A0B Block List Element hex>"); PrintAndLogEx(NORMAL, " -h this help"); PrintAndLogEx(NORMAL, " -i <0A0B0C ... hex> set custom IDm to use"); + PrintAndLogEx(NORMAL, " -b get all Block List Elements of service"); PrintAndLogEx(NORMAL, "\nExamples: "); PrintAndLogEx(NORMAL, " hf felica rdunencrypted 01 8B00 01 8000"); PrintAndLogEx(NORMAL, " hf felica rdunencrypted -i 01100910c11bc407 01 8B00 01 8000\n\n"); @@ -178,17 +189,20 @@ static int usage_hf_felica_read_without_encryption(void) { /** * Wait for response from pm3 or timeout. * Checks if receveid bytes have a valid CRC. + * @param verbose prints out the response received. */ -static bool waitCmdFelica(uint8_t iSelect, PacketResponseNG *resp) { +static bool waitCmdFelica(uint8_t iSelect, PacketResponseNG *resp, bool verbose) { if (WaitForResponseTimeout(CMD_ACK, resp, 2000)) { uint16_t len = iSelect ? (resp->oldarg[1] & 0xffff) : (resp->oldarg[0] & 0xffff); - PrintAndLogEx(NORMAL, "Client Received %i octets", len); - if (!len || len < 2) { - PrintAndLogEx(ERR, "Could not receive data correctly!"); - } - PrintAndLogEx(NORMAL, "%s", sprint_hex(resp->data.asBytes, len)); - if (!check_crc(CRC_FELICA, resp->data.asBytes + 2, len - 2)) { - PrintAndLogEx(WARNING, "Wrong or no CRC bytes"); + if(verbose){ + PrintAndLogEx(NORMAL, "Client Received %i octets", len); + if (!len || len < 2) { + PrintAndLogEx(ERR, "Could not receive data correctly!"); + } + PrintAndLogEx(NORMAL, "%s", sprint_hex(resp->data.asBytes, len)); + if (!check_crc(CRC_FELICA, resp->data.asBytes + 2, len - 2)) { + PrintAndLogEx(WARNING, "Wrong or no CRC bytes"); + } } return true; } else { @@ -252,22 +266,15 @@ static int CmdHFFelicaReader(const char *Cmd) { /** * Clears command buffer and sends the given data to pm3 with mix mode. */ -static void clear_and_send_command(uint8_t flags, uint16_t datalen, uint8_t *data) { +static void clear_and_send_command(uint8_t flags, uint16_t datalen, uint8_t *data, bool verbose) { uint16_t numbits = 0; clearCommandBuffer(); - PrintAndLogEx(NORMAL, "Send Service Request Frame: %s", sprint_hex(data, datalen)); + if(verbose){ + PrintAndLogEx(NORMAL, "Send Service Request Frame: %s", sprint_hex(data, datalen)); + } SendCommandMIX(CMD_HF_FELICA_COMMAND, flags, (datalen & 0xFFFF) | (uint32_t)(numbits << 16), 0, data, datalen); } -/** - * Prints the given block data. - */ -static void print_block_data(uint8_t *number_of_block, uint8_t *block_data, size_t block_size){ - PrintAndLogEx(NORMAL, "Block Nr.: %i", *number_of_block); - PrintAndLogEx(NORMAL, "Data: %s", sprint_hex(block_data, block_size)); -}; - - /** * Adds a parameter to the frame and checks if the parameter has the specific length. * @param Cmd User input with the parameter. @@ -275,7 +282,7 @@ static void print_block_data(uint8_t *number_of_block, uint8_t *block_data, size * @param data frame in which the data is stored. * @param dataPosition position within frame where the data will be stored. * @param length which the parameter should have and will be tested against. - * @return + * @return true if parameters was added. */ static bool add_param(const char *Cmd, uint8_t paramCount, uint8_t *data, uint8_t dataPosition, uint8_t length){ if (param_getlength(Cmd, paramCount) == length) { @@ -287,16 +294,42 @@ static bool add_param(const char *Cmd, uint8_t paramCount, uint8_t *data, uint8_ } } +/** + * Prints read-without-encryption response. + * @param rd_noCry_resp Response frame. + */ +static void print_rd_noEncrpytion_response(felica_read_without_encryption_response_t *rd_noCry_resp){ + if(rd_noCry_resp->status_flag1[0] == 00 && rd_noCry_resp->status_flag2[0] == 00){ + char bl_number[4]; + char *temp = sprint_hex(rd_noCry_resp->number_of_block, sizeof(rd_noCry_resp->number_of_block)); + strcpy(bl_number, temp); + + temp = sprint_hex(rd_noCry_resp->block_data, sizeof(rd_noCry_resp->block_data)); + char bl_data[256]; + strcpy(bl_data, temp); + + char bl_element_number[4]; + temp = sprint_hex(rd_noCry_resp->block_element_number, sizeof(rd_noCry_resp->block_element_number)); + strcpy(bl_element_number, temp); + + PrintAndLogEx(NORMAL, "%s: %s: %s", bl_number, bl_element_number, bl_data); + }else{ + PrintAndLogEx(NORMAL, "IDm: %s", sprint_hex(rd_noCry_resp->IDm, sizeof(rd_noCry_resp->IDm))); + PrintAndLogEx(NORMAL, "Status Flag1: %s", sprint_hex(rd_noCry_resp->status_flag1, sizeof(rd_noCry_resp->status_flag1))); + PrintAndLogEx(NORMAL, "Status Flag2: %s", sprint_hex(rd_noCry_resp->status_flag1, sizeof(rd_noCry_resp->status_flag1))); + } +} + /** * Sends a request service frame to the pm3 and prints response. */ -void send_request_service(uint8_t flags, uint16_t datalen, uint8_t *data) { - clear_and_send_command(flags, datalen, data); +int send_request_service(uint8_t flags, uint16_t datalen, uint8_t *data, bool verbose) { + clear_and_send_command(flags, datalen, data, verbose); PacketResponseNG resp; if (datalen > 0) { - if (!waitCmdFelica(0, &resp)) { + if (!waitCmdFelica(0, &resp, 1)) { PrintAndLogEx(ERR, "\nGot no Response from card"); - return; + return PM3_ERFTRANS; } felica_request_service_response_t rqs_response; memcpy(&rqs_response, (felica_request_service_response_t *)resp.data.asBytes, sizeof(felica_request_service_response_t)); @@ -307,6 +340,30 @@ void send_request_service(uint8_t flags, uint16_t datalen, uint8_t *data) { PrintAndLogEx(NORMAL, " -Node Number: %s", sprint_hex(rqs_response.node_number, sizeof(rqs_response.node_number))); PrintAndLogEx(NORMAL, " -Node Key Version List: %s\n", sprint_hex(rqs_response.node_key_versions, sizeof(rqs_response.node_key_versions))); } + return PM3_SUCCESS; + } + return PM3_ERFTRANS; +} + +/** + * Sends a read_without_encryption frame to the pm3 and prints response. + * @param flags to use for pm3 communication. + * @param datalen frame length. + * @param data frame to be send. + * @param verbose display additional output. + * @param rd_noCry_resp frame in which the response will be saved + * @return success if response was received. + */ +int send_rd_unencrypted(uint8_t flags, uint16_t datalen, uint8_t *data, bool verbose, felica_read_without_encryption_response_t *rd_noCry_resp){ + clear_and_send_command(flags, datalen, data, verbose); + PacketResponseNG resp; + if (!waitCmdFelica(0, &resp, verbose)) { + PrintAndLogEx(ERR, "\nGot no Response from card"); + return PM3_ERFTRANS; + } else { + memcpy(rd_noCry_resp, (felica_read_without_encryption_response_t *)resp.data.asBytes, sizeof(felica_read_without_encryption_response_t)); + rd_noCry_resp->block_element_number[0] = data[15]; + return PM3_SUCCESS; } } @@ -324,6 +381,8 @@ static int CmdHFFelicaReadWithoutEncryption(const char *Cmd) { uint16_t datalen = 16; // Length (1), Command ID (1), IDm (8), Number of Service (1), Service Code List(2), Number of Block(1), Block List(3) uint8_t paramCount = 0; uint8_t flags = 0; + uint8_t all_block_list_elements = false; + uint8_t long_block_numbers = false; int i = 0; while (Cmd[i] != '\0') { if (Cmd[i] == '-') { @@ -338,6 +397,14 @@ static int CmdHFFelicaReadWithoutEncryption(const char *Cmd) { return PM3_EINVARG; } break; + case 'b': + paramCount++; + all_block_list_elements = true; + break; + case 'l': + paramCount++; + long_block_numbers = true; + break; } } i++; @@ -355,6 +422,10 @@ static int CmdHFFelicaReadWithoutEncryption(const char *Cmd) { // Number of Service 2, Service Code List 4, Number of Block 2, Block List Element 4 uint8_t lengths[] = {2, 4, 2, 4}; uint8_t dataPositions[] = {10, 11, 13, 14}; + if(long_block_numbers){ + datalen += 1; + lengths[3] = 6; + } for(int i=0; i < 4; i++){ if(add_param(Cmd, paramCount, data, dataPositions[i], lengths[i])){ paramCount++; @@ -362,30 +433,36 @@ static int CmdHFFelicaReadWithoutEncryption(const char *Cmd) { return PM3_EINVARG; } } - AddCrc(data, datalen); - datalen += 2; + flags |= FELICA_APPEND_CRC; flags |= FELICA_RAW; - clear_and_send_command(flags, datalen, data); - PacketResponseNG resp; - if (!waitCmdFelica(0, &resp)) { - PrintAndLogEx(ERR, "\nGot no Response from card"); - return PM3_ERFTRANS; - } else { - PrintAndLogEx(SUCCESS, "\nGot Response from card"); - felica_read_without_encryption_response_t rd_noCry_resp; - memcpy(&rd_noCry_resp, (felica_read_without_encryption_response_t *)resp.data.asBytes, sizeof(felica_read_without_encryption_response_t)); - - if (rd_noCry_resp.IDm[0] != 0) { - PrintAndLogEx(NORMAL, "IDm: %s", sprint_hex(rd_noCry_resp.IDm, sizeof(rd_noCry_resp.IDm))); - PrintAndLogEx(NORMAL, " -Status Flag1: %s", sprint_hex(rd_noCry_resp.status_flag1, sizeof(rd_noCry_resp.status_flag1))); - PrintAndLogEx(NORMAL, " -Status Flag2: %s", sprint_hex(rd_noCry_resp.status_flag2, sizeof(rd_noCry_resp.status_flag2))); - if(rd_noCry_resp.status_flag1[0] == 00 && rd_noCry_resp.status_flag2[0] == 00){ - print_block_data(rd_noCry_resp.number_of_block, rd_noCry_resp.block_data, sizeof(rd_noCry_resp.block_data)); - }else{ - PrintAndLogEx(ERR, "Could not read data! See -h for more information about the status flags."); - } + if(all_block_list_elements){ + uint16_t last_block_number = 0xFF; + if(long_block_numbers){ + last_block_number = 0xFFFF; } + for(int i=0x00; i < last_block_number; i++){ + data[15] = i; + AddCrc(data, datalen); + datalen += 2; + felica_read_without_encryption_response_t rd_noCry_resp; + if((send_rd_unencrypted(flags, datalen, data, 0, &rd_noCry_resp) == PM3_SUCCESS)){ + if(rd_noCry_resp.status_flag1[0] == 00 && rd_noCry_resp.status_flag2[0] == 00){ + print_rd_noEncrpytion_response(&rd_noCry_resp); + }else{ + break; + } + }else{ + break; + } + datalen -= 2; + } + }else{ + AddCrc(data, datalen); + datalen += 2; + felica_read_without_encryption_response_t rd_noCry_resp; + send_rd_unencrypted(flags, datalen, data, 1, &rd_noCry_resp); + print_rd_noEncrpytion_response(&rd_noCry_resp); } return PM3_SUCCESS; } @@ -437,9 +514,9 @@ static int CmdHFFelicaRequestResponse(const char *Cmd) { datalen += 2; flags |= FELICA_APPEND_CRC; flags |= FELICA_RAW; - clear_and_send_command(flags, datalen, data); + clear_and_send_command(flags, datalen, data, 0); PacketResponseNG resp; - if (!waitCmdFelica(0, &resp)) { + if (!waitCmdFelica(0, &resp, 1)) { PrintAndLogEx(ERR, "\nGot no Response from card"); return PM3_ERFTRANS; } else { @@ -539,13 +616,13 @@ static int CmdHFFelicaRequestService(const char *Cmd) { data[10] = int_to_hex(&y); AddCrc(data, datalen); datalen += 2; - send_request_service(flags, datalen, data); + send_request_service(flags, datalen, data, 1); datalen -= 2; // Remove CRC bytes before adding new ones } } else { AddCrc(data, datalen); datalen += 2; - send_request_service(flags, datalen, data); + send_request_service(flags, datalen, data, 1); } return PM3_SUCCESS; @@ -993,11 +1070,11 @@ static int CmdHFFelicaCmdRaw(const char *Cmd) { if (active_select) { PrintAndLogEx(NORMAL, "Active select wait for FeliCa."); PacketResponseNG resp_IDm; - waitCmdFelica(1, &resp_IDm); + waitCmdFelica(1, &resp_IDm, 1); } if (datalen > 0) { PacketResponseNG resp_frame; - waitCmdFelica(0, &resp_frame); + waitCmdFelica(0, &resp_frame, 1); } } return PM3_SUCCESS; diff --git a/client/cmdhffelica.h b/client/cmdhffelica.h index dd127cfaf..7626d002b 100644 --- a/client/cmdhffelica.h +++ b/client/cmdhffelica.h @@ -12,8 +12,10 @@ #define CMDHFFELICA_H__ #include "common.h" +#include "mifare.h" int CmdHFFelica(const char *Cmd); int readFelicaUid(bool verbose); -void send_request_service(uint8_t flags, uint16_t datalen, uint8_t *data); +int send_request_service(uint8_t flags, uint16_t datalen, uint8_t *data, bool verbose); +int send_rd_unencrypted(uint8_t flags, uint16_t datalen, uint8_t *data, bool verbose, felica_read_without_encryption_response_t *rd_noCry_resp); #endif diff --git a/include/mifare.h b/include/mifare.h index e472d5c59..7a40a26e4 100644 --- a/include/mifare.h +++ b/include/mifare.h @@ -195,6 +195,7 @@ typedef struct { uint8_t status_flag2[1]; uint8_t number_of_block[1]; uint8_t block_data[16]; + uint8_t block_element_number[1]; } PACKED felica_read_without_encryption_response_t; typedef enum FELICA_COMMAND { From 12cd208253b61bef7fdd4565b8eabfbfd16b696f Mon Sep 17 00:00:00 2001 From: Thomas Sutter Date: Thu, 24 Oct 2019 17:07:27 +0200 Subject: [PATCH 20/24] Make style. Format help text. --- client/cmdhffelica.c | 94 ++++++++++++++++++++++---------------------- 1 file changed, 48 insertions(+), 46 deletions(-) diff --git a/client/cmdhffelica.c b/client/cmdhffelica.c index 8a1926276..bd0099923 100644 --- a/client/cmdhffelica.c +++ b/client/cmdhffelica.c @@ -115,35 +115,35 @@ static int usage_hf_felica_request_response(void) { return PM3_SUCCESS; } -static void print_status_flag1_interpretation(){ - PrintAndLogEx(NORMAL, "Status Flag1:"); +static void print_status_flag1_interpretation() { + PrintAndLogEx(NORMAL, "\nStatus Flag1:"); PrintAndLogEx(NORMAL, " - 00h : Indicates the successful completion of a command."); PrintAndLogEx(NORMAL, " - FFh : If an error occurs during the processing of a command that includes no list in the command packet, or if " - "an error occurs independently of any list, the card returns a response by setting FFh to Status Flag1."); + "an error occurs independently of any list, the card returns a response by setting FFh to Status Flag1."); PrintAndLogEx(NORMAL, " - XXh : If an error occurs while processing a command that includes Service Code List or Block List " - "in the command packet, the card returns a response by setting a number in the list to Status Flag1, " - "indicating the location of the error. Have a look at the FeliCa User Manual for more information."); + "in the command packet, the card returns a response by setting a number in the list to Status Flag1, " + "indicating the location of the error."); } -static void print_status_flag2_interpration(){ - PrintAndLogEx(NORMAL, "Status Flag2:"); +static void print_status_flag2_interpration() { + PrintAndLogEx(NORMAL, "\nStatus Flag2:"); PrintAndLogEx(NORMAL, " - 00h : Indicates the successful completion of a command."); PrintAndLogEx(NORMAL, " - 01h : The calculated result is either less than zero when the purse data is decremented, or exceeds 4" - "Bytes when the purse data is incremented."); + "Bytes when the purse data is incremented."); PrintAndLogEx(NORMAL, " - 02h : The specified data exceeds the value of cashback data at cashback of purse."); PrintAndLogEx(NORMAL, " - 70h : Memory error (fatal error)."); PrintAndLogEx(NORMAL, " - 71h : The number of memory rewrites exceeds the upper limit (this is only a warning; data writing is " - "performed as normal). The maximum number of rewrites can differ, depending on the product being used." - " In addition, Status Flag1 is either 00h or FFh depending on the product being used."); + "performed as normal). The maximum number of rewrites can differ, depending on the product being used."); + PrintAndLogEx(NORMAL, " In addition, Status Flag1 is either 00h or FFh depending on the product being used."); PrintAndLogEx(NORMAL, " - A1h : Illegal Number of Service: Number of Service or Number of Node specified by the command falls outside the range of the prescribed value."); PrintAndLogEx(NORMAL, " - A2h : Illegal command packet (specified Number of Block): Number of Block specified by the command falls outside the range of the prescribed values for the product."); PrintAndLogEx(NORMAL, " - A3h : Illegal Block List (specified order of Service): Service Code List Order specified by Block List Element falls outside the Number of Service specified by the " - "command (or the Number of Service specified at the times of mutual authentication)."); + "command (or the Number of Service specified at the times of mutual authentication)."); PrintAndLogEx(NORMAL, " - A4h : Illegal Service type: Area Attribute specified by the command or Service Attribute of Service Code is incorrect."); PrintAndLogEx(NORMAL, " - A5h : Access is not allowed: Area or Service specified by the command cannot be accessed. " - "The parameter specified by the command does not satisfy the conditions for success."); + "The parameter specified by the command does not satisfy the conditions for success."); PrintAndLogEx(NORMAL, " - A6h : Illegal Service Code List: Target to be accessed, identified by Service Code List Order, specified by Block " - "List Element does not exist. Or, Node specified by Node Code List does not exist."); + "List Element does not exist. Or, Node specified by Node Code List does not exist."); PrintAndLogEx(NORMAL, " - A7h : Illegal Block List (Access Mode): Access Mode specified by Block List Element is incorrect."); PrintAndLogEx(NORMAL, " - A8h : Illegal Block Number Block Number (access to the specified data is inhibited): specified by Block List Element exceeds the number of Blocks assigned to Service."); PrintAndLogEx(NORMAL, " - A9h : Data write failure: This is the error that occurs in issuance commands."); @@ -153,7 +153,7 @@ static void print_status_flag2_interpration(){ PrintAndLogEx(NORMAL, " - ADh : Service exists already: This is the error that occurs in issuance commands."); PrintAndLogEx(NORMAL, " - AEh : Illegal System Code: This is the error that occurs in issuance commands."); PrintAndLogEx(NORMAL, " - AFh : Too many simultaneous cyclic write operations: Number of simultaneous write Blocks specified by the command to Cyclic Service " - "exceeds the number of Blocks assigned to Service."); + "exceeds the number of Blocks assigned to Service."); PrintAndLogEx(NORMAL, " - C0h : Illegal Package Identifier: This is the error that occurs in issuance commands."); PrintAndLogEx(NORMAL, " - C1h : Discrepancy of parameters inside and outside Package: This is the error that occurs in issuance commands."); PrintAndLogEx(NORMAL, " - C2h : Command is disabled already: This is the error that occurs in issuance commands."); @@ -162,9 +162,12 @@ static void print_status_flag2_interpration(){ static int usage_hf_felica_read_without_encryption() { PrintAndLogEx(NORMAL, "\nInfo: Use this command to read Block Data from authentication-not-required Service."); PrintAndLogEx(NORMAL, " - Mode shall be Mode0."); - PrintAndLogEx(NORMAL, " - Number of Service shall be a positive integer in the range of 1 to 16, inclusive."); - PrintAndLogEx(NORMAL, " - Number of Block shall be less than or equal to the maximum number of Blocks that can be read simultaneously. " - "The maximum number of Blocks that can be read simultaneously can differ, depending on the product being used."); + PrintAndLogEx(NORMAL, " - Number of Service: shall be a positive integer in the range of 1 to 16, inclusive."); + PrintAndLogEx(NORMAL, " - Number of Block: shall be less than or equal to the maximum number of Blocks that can be read simultaneously. " + "The maximum number of Blocks that can be read simultaneously can differ, depending on the product being used. Use as default 01"); + PrintAndLogEx(NORMAL, " - Service Code List: For Service Code List, only Service Code existing in the product shall be specified:"); + PrintAndLogEx(NORMAL, " - Even when Service Code exists in the product, Service Code not referenced from Block List shall not be specified to Service Code List."); + PrintAndLogEx(NORMAL, " - For existence or nonexistence of Service in a product, please check using the Request Service (or Request Service v2) command."); PrintAndLogEx(NORMAL, " - Each Block List Element shall satisfy the following conditions:"); PrintAndLogEx(NORMAL, " - The value of Service Code List Order shall not exceed Number of Service."); PrintAndLogEx(NORMAL, " - Access Mode shall be 000b."); @@ -179,10 +182,12 @@ static int usage_hf_felica_read_without_encryption() { PrintAndLogEx(NORMAL, "\nUsage: hf felica rdunencrypted [-h] <01 Number of Service hex> <0A0B Service Code List (Little Endian) hex> <01 Number of Block hex> <0A0B Block List Element hex>"); PrintAndLogEx(NORMAL, " -h this help"); PrintAndLogEx(NORMAL, " -i <0A0B0C ... hex> set custom IDm to use"); - PrintAndLogEx(NORMAL, " -b get all Block List Elements of service"); + PrintAndLogEx(NORMAL, " -b get all Block List Elements starting from 00 to FF - stops when a block return an error status flags"); + PrintAndLogEx(NORMAL, " -l use 3-byte block list element block number"); PrintAndLogEx(NORMAL, "\nExamples: "); PrintAndLogEx(NORMAL, " hf felica rdunencrypted 01 8B00 01 8000"); - PrintAndLogEx(NORMAL, " hf felica rdunencrypted -i 01100910c11bc407 01 8B00 01 8000\n\n"); + PrintAndLogEx(NORMAL, " hf felica rdunencrypted -i 01100910c11bc407 01 8B00 01 8000"); + PrintAndLogEx(NORMAL, " hf felica rdunencrypted -b 01 8B00 01 8000\n\n"); return PM3_SUCCESS; } @@ -194,7 +199,7 @@ static int usage_hf_felica_read_without_encryption() { static bool waitCmdFelica(uint8_t iSelect, PacketResponseNG *resp, bool verbose) { if (WaitForResponseTimeout(CMD_ACK, resp, 2000)) { uint16_t len = iSelect ? (resp->oldarg[1] & 0xffff) : (resp->oldarg[0] & 0xffff); - if(verbose){ + if (verbose) { PrintAndLogEx(NORMAL, "Client Received %i octets", len); if (!len || len < 2) { PrintAndLogEx(ERR, "Could not receive data correctly!"); @@ -269,7 +274,7 @@ static int CmdHFFelicaReader(const char *Cmd) { static void clear_and_send_command(uint8_t flags, uint16_t datalen, uint8_t *data, bool verbose) { uint16_t numbits = 0; clearCommandBuffer(); - if(verbose){ + if (verbose) { PrintAndLogEx(NORMAL, "Send Service Request Frame: %s", sprint_hex(data, datalen)); } SendCommandMIX(CMD_HF_FELICA_COMMAND, flags, (datalen & 0xFFFF) | (uint32_t)(numbits << 16), 0, data, datalen); @@ -284,7 +289,7 @@ static void clear_and_send_command(uint8_t flags, uint16_t datalen, uint8_t *dat * @param length which the parameter should have and will be tested against. * @return true if parameters was added. */ -static bool add_param(const char *Cmd, uint8_t paramCount, uint8_t *data, uint8_t dataPosition, uint8_t length){ +static bool add_param(const char *Cmd, uint8_t paramCount, uint8_t *data, uint8_t dataPosition, uint8_t length) { if (param_getlength(Cmd, paramCount) == length) { param_gethex(Cmd, paramCount, data + dataPosition, length); return true; @@ -298,22 +303,17 @@ static bool add_param(const char *Cmd, uint8_t paramCount, uint8_t *data, uint8_ * Prints read-without-encryption response. * @param rd_noCry_resp Response frame. */ -static void print_rd_noEncrpytion_response(felica_read_without_encryption_response_t *rd_noCry_resp){ - if(rd_noCry_resp->status_flag1[0] == 00 && rd_noCry_resp->status_flag2[0] == 00){ - char bl_number[4]; - char *temp = sprint_hex(rd_noCry_resp->number_of_block, sizeof(rd_noCry_resp->number_of_block)); - strcpy(bl_number, temp); - - temp = sprint_hex(rd_noCry_resp->block_data, sizeof(rd_noCry_resp->block_data)); +static void print_rd_noEncrpytion_response(felica_read_without_encryption_response_t *rd_noCry_resp) { + if (rd_noCry_resp->status_flag1[0] == 00 && rd_noCry_resp->status_flag2[0] == 00) { + char *temp = sprint_hex(rd_noCry_resp->block_data, sizeof(rd_noCry_resp->block_data)); char bl_data[256]; strcpy(bl_data, temp); char bl_element_number[4]; temp = sprint_hex(rd_noCry_resp->block_element_number, sizeof(rd_noCry_resp->block_element_number)); strcpy(bl_element_number, temp); - - PrintAndLogEx(NORMAL, "%s: %s: %s", bl_number, bl_element_number, bl_data); - }else{ + PrintAndLogEx(NORMAL, "\t%s\t| %s ", bl_element_number, bl_data); + } else { PrintAndLogEx(NORMAL, "IDm: %s", sprint_hex(rd_noCry_resp->IDm, sizeof(rd_noCry_resp->IDm))); PrintAndLogEx(NORMAL, "Status Flag1: %s", sprint_hex(rd_noCry_resp->status_flag1, sizeof(rd_noCry_resp->status_flag1))); PrintAndLogEx(NORMAL, "Status Flag2: %s", sprint_hex(rd_noCry_resp->status_flag1, sizeof(rd_noCry_resp->status_flag1))); @@ -354,7 +354,7 @@ int send_request_service(uint8_t flags, uint16_t datalen, uint8_t *data, bool ve * @param rd_noCry_resp frame in which the response will be saved * @return success if response was received. */ -int send_rd_unencrypted(uint8_t flags, uint16_t datalen, uint8_t *data, bool verbose, felica_read_without_encryption_response_t *rd_noCry_resp){ +int send_rd_unencrypted(uint8_t flags, uint16_t datalen, uint8_t *data, bool verbose, felica_read_without_encryption_response_t *rd_noCry_resp) { clear_and_send_command(flags, datalen, data, verbose); PacketResponseNG resp; if (!waitCmdFelica(0, &resp, verbose)) { @@ -393,7 +393,7 @@ static int CmdHFFelicaReadWithoutEncryption(const char *Cmd) { case 'i': paramCount++; custom_IDm = true; - if(!add_param(Cmd, paramCount, data, 3, 8)){ + if (!add_param(Cmd, paramCount, data, 3, 8)) { return PM3_EINVARG; } break; @@ -422,46 +422,48 @@ static int CmdHFFelicaReadWithoutEncryption(const char *Cmd) { // Number of Service 2, Service Code List 4, Number of Block 2, Block List Element 4 uint8_t lengths[] = {2, 4, 2, 4}; uint8_t dataPositions[] = {10, 11, 13, 14}; - if(long_block_numbers){ + if (long_block_numbers) { datalen += 1; lengths[3] = 6; } - for(int i=0; i < 4; i++){ - if(add_param(Cmd, paramCount, data, dataPositions[i], lengths[i])){ + for (int i = 0; i < 4; i++) { + if (add_param(Cmd, paramCount, data, dataPositions[i], lengths[i])) { paramCount++; - }else{ + } else { return PM3_EINVARG; } } flags |= FELICA_APPEND_CRC; flags |= FELICA_RAW; - if(all_block_list_elements){ + if (all_block_list_elements) { uint16_t last_block_number = 0xFF; - if(long_block_numbers){ + if (long_block_numbers) { last_block_number = 0xFFFF; } - for(int i=0x00; i < last_block_number; i++){ + PrintAndLogEx(NORMAL, "Block Element\t| Data "); + for (int i = 0x00; i < last_block_number; i++) { data[15] = i; AddCrc(data, datalen); datalen += 2; felica_read_without_encryption_response_t rd_noCry_resp; - if((send_rd_unencrypted(flags, datalen, data, 0, &rd_noCry_resp) == PM3_SUCCESS)){ - if(rd_noCry_resp.status_flag1[0] == 00 && rd_noCry_resp.status_flag2[0] == 00){ + if ((send_rd_unencrypted(flags, datalen, data, 0, &rd_noCry_resp) == PM3_SUCCESS)) { + if (rd_noCry_resp.status_flag1[0] == 00 && rd_noCry_resp.status_flag2[0] == 00) { print_rd_noEncrpytion_response(&rd_noCry_resp); - }else{ + } else { break; } - }else{ + } else { break; } datalen -= 2; } - }else{ + } else { AddCrc(data, datalen); datalen += 2; felica_read_without_encryption_response_t rd_noCry_resp; send_rd_unencrypted(flags, datalen, data, 1, &rd_noCry_resp); + PrintAndLogEx(NORMAL, "Block Element\t| Data "); print_rd_noEncrpytion_response(&rd_noCry_resp); } return PM3_SUCCESS; From b4bcec581cbc9a4e05fcdf42ec41ec167d74c8eb Mon Sep 17 00:00:00 2001 From: Thomas Sutter Date: Thu, 24 Oct 2019 17:10:56 +0200 Subject: [PATCH 21/24] Add changelong text --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 168199c2b..c0ef300cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Added hf felica rdunencrypted (@7homasSutter) - Added hf felica rqresponse (@7homasSutter) - Added hf felica rqservice (@7homasSutter) - Added polling for felica standard (@7homasSutter) From eb7268cd98ecf991b3fe61242dea8ce6bbe3fb63 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 25 Oct 2019 00:42:47 +0200 Subject: [PATCH 22/24] lf: change macros to allow float freq, change 134 -> 134.2 --- armsrc/lfops.c | 4 ++-- client/cmddata.c | 10 +++++----- client/cmdlf.c | 6 +++--- client/cmdlfmotorola.c | 2 +- include/pm3_cmd.h | 7 ++++--- 5 files changed, 15 insertions(+), 14 deletions(-) diff --git a/armsrc/lfops.c b/armsrc/lfops.c index a298af4a9..f4f3a9e7b 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -2418,7 +2418,7 @@ because of this, we can "sample" the data signal but we interpreate it to Manche This behavior looks very similar to old ancient Motorola Flexpass ----------------------------------------------------------------------- -According to patent: +According to patent EP0040544B1: Operating freq reader 132 kHz tag 66 kHz @@ -2453,7 +2453,7 @@ void Cotag(uint32_t arg0) { LED_A_ON(); - LFSetupFPGAForADC(LF_DIVISOR(132), true); + LFSetupFPGAForADC(LF_FREQ2DIV(132), true); //clear buffer now so it does not interfere with timing later BigBuf_Clear_ext(false); diff --git a/client/cmddata.c b/client/cmddata.c index 80c3bf076..5962d6ca6 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -1676,16 +1676,16 @@ int CmdTuneSamples(const char *Cmd) { struct p *package = (struct p *)resp.data.asBytes; if (package->v_lf125 > NON_VOLTAGE) - PrintAndLogEx(SUCCESS, "LF antenna: %5.2f V - %.2f kHz", (package->v_lf125 * ANTENNA_ERROR) / 1000.0, 12000.0 / (LF_DIVISOR_125 + 1)); + PrintAndLogEx(SUCCESS, "LF antenna: %5.2f V - %.2f kHz", (package->v_lf125 * ANTENNA_ERROR) / 1000.0, LF_DIV2FREQ(LF_DIVISOR_125)); if (package->v_lf134 > NON_VOLTAGE) - PrintAndLogEx(SUCCESS, "LF antenna: %5.2f V - %.2f kHz", (package->v_lf134 * ANTENNA_ERROR) / 1000.0, 12000.0 / (LF_DIVISOR_134 + 1)); + PrintAndLogEx(SUCCESS, "LF antenna: %5.2f V - %.2f kHz", (package->v_lf134 * ANTENNA_ERROR) / 1000.0, LF_DIV2FREQ(LF_DIVISOR_134)); if (package->v_lfconf > NON_VOLTAGE && package->divisor > 0 && package->divisor != LF_DIVISOR_125 && package->divisor != LF_DIVISOR_134) - PrintAndLogEx(SUCCESS, "LF antenna: %5.2f V - %.2f kHz", (package->v_lfconf * ANTENNA_ERROR) / 1000.0, 12000.0 / (package->divisor + 1)); + PrintAndLogEx(SUCCESS, "LF antenna: %5.2f V - %.2f kHz", (package->v_lfconf * ANTENNA_ERROR) / 1000.0, LF_DIV2FREQ(package->divisor)); if (package->peak_v > NON_VOLTAGE && package->peak_f > 0) - PrintAndLogEx(SUCCESS, "LF optimal: %5.2f V - %6.2f kHz", (package->peak_v * ANTENNA_ERROR) / 1000.0, 12000.0 / (package->peak_f + 1)); + PrintAndLogEx(SUCCESS, "LF optimal: %5.2f V - %6.2f kHz", (package->peak_v * ANTENNA_ERROR) / 1000.0, LF_DIV2FREQ(package->peak_f)); char judgement[20]; memset(judgement, 0, sizeof(judgement)); @@ -1730,7 +1730,7 @@ int CmdTuneSamples(const char *Cmd) { if (test1 > 0) { PrintAndLogEx(SUCCESS, "\nDisplaying LF tuning graph. Divisor %d is %.2f kHz, %d is %.2f kHz.\n\n", - LF_DIVISOR_134, 12000.0 / (LF_DIVISOR_134 + 1), LF_DIVISOR_125, 12000.0 / (LF_DIVISOR_125 + 1)); + LF_DIVISOR_134, LF_DIV2FREQ(LF_DIVISOR_134), LF_DIVISOR_125, LF_DIV2FREQ(LF_DIVISOR_125)); GraphTraceLen = 256; ShowGraphWindow(); RepaintGraphWindow(); diff --git a/client/cmdlf.c b/client/cmdlf.c index 4d7c72acc..8f5a88923 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -232,7 +232,7 @@ int CmdLFTune(const char *Cmd) { break; case 'f': { int freq = param_get32ex(Cmd, cmdp + 1, 125, 10); - divisor = LF_DIVISOR(freq); + divisor = LF_FREQ2DIV(freq); if (divisor < 19) { PrintAndLogEx(ERR, "freq must be between 47 and 600"); return PM3_EINVARG; @@ -254,7 +254,7 @@ int CmdLFTune(const char *Cmd) { //Validations if (errors) return usage_lf_tune(); - PrintAndLogEx(SUCCESS, "Measuring LF antenna at %.2f kHz, click button or press Enter to exit", 12000.0 / (divisor + 1)); + PrintAndLogEx(SUCCESS, "Measuring LF antenna at %.2f kHz, click button or press Enter to exit", LF_DIV2FREQ(divisor)); uint8_t params[] = {1, 0}; params[1] = divisor; @@ -498,7 +498,7 @@ int CmdLFConfig(const char *Cmd) { break; case 'f': { int freq = param_get32ex(Cmd, cmdp + 1, 125, 10); - divisor = LF_DIVISOR(freq); + divisor = LF_FREQ2DIV(freq); if (divisor < 19) { PrintAndLogEx(ERR, "freq must be between 47 and 600"); return PM3_EINVARG; diff --git a/client/cmdlfmotorola.c b/client/cmdlfmotorola.c index 87ea53a3b..dbcf28e40 100644 --- a/client/cmdlfmotorola.c +++ b/client/cmdlfmotorola.c @@ -127,7 +127,7 @@ static int CmdMotorolaRead(const char *Cmd) { .decimation = 0, .bits_per_sample = 0, .averaging = false, - .divisor = LF_DIVISOR(74), + .divisor = LF_FREQ2DIV(74), .trigger_threshold = -1, .samples_to_skip = 4500, .verbose = false diff --git a/include/pm3_cmd.h b/include/pm3_cmd.h index 19ef27afb..544d5e5c2 100644 --- a/include/pm3_cmd.h +++ b/include/pm3_cmd.h @@ -590,9 +590,10 @@ typedef struct { #define PM3_EFATAL -99 // LF -#define LF_DIVISOR(f) (((12000 + (f)/2)/(f))-1) -#define LF_DIVISOR_125 LF_DIVISOR(125) -#define LF_DIVISOR_134 LF_DIVISOR(134) +#define LF_FREQ2DIV(f) ((int)(((12000.0 + (f)/2.0)/(f))-1)) +#define LF_DIVISOR_125 LF_FREQ2DIV(125) +#define LF_DIVISOR_134 LF_FREQ2DIV(134.2) +#define LF_DIV2FREQ(d) (12000.0/((d)+1)) // Receiving from USART need more than 30ms as we used on USB // else we get errors about partial packet reception From 390d0ab52527b0410b7b52afb81c44a360c420f4 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 25 Oct 2019 00:53:56 +0200 Subject: [PATCH 23/24] lf tune: allow float, added parse_getfloat to utils --- client/cmdlf.c | 6 +++--- client/util.c | 8 ++++++++ client/util.h | 1 + 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/client/cmdlf.c b/client/cmdlf.c index 8f5a88923..328af5e29 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -231,12 +231,12 @@ int CmdLFTune(const char *Cmd) { } break; case 'f': { - int freq = param_get32ex(Cmd, cmdp + 1, 125, 10); - divisor = LF_FREQ2DIV(freq); - if (divisor < 19) { + float freq = param_getfloat(Cmd, cmdp + 1, 125); + if ((freq < 47) || (freq > 600)) { PrintAndLogEx(ERR, "freq must be between 47 and 600"); return PM3_EINVARG; } + divisor = LF_FREQ2DIV(freq); cmdp += 2; break; } diff --git a/client/util.c b/client/util.c index da1b5d0e2..58dce8eca 100644 --- a/client/util.c +++ b/client/util.c @@ -551,6 +551,14 @@ uint64_t param_get64ex(const char *line, int paramnum, int deflt, int base) { return deflt; } +float param_getfloat(const char *line, int paramnum, float deflt) { + int bg, en; + if (!param_getptr(line, &bg, &en, paramnum)) + return strtof(&line[bg], NULL); + else + return deflt; +} + int param_gethex(const char *line, int paramnum, uint8_t *data, int hexcnt) { int bg, en, i; uint32_t temp; diff --git a/client/util.h b/client/util.h index 7d6c6460e..d549458c4 100644 --- a/client/util.h +++ b/client/util.h @@ -68,6 +68,7 @@ uint8_t param_get8(const char *line, int paramnum); uint8_t param_get8ex(const char *line, int paramnum, int deflt, int base); uint32_t param_get32ex(const char *line, int paramnum, int deflt, int base); uint64_t param_get64ex(const char *line, int paramnum, int deflt, int base); +float param_getfloat(const char *line, int paramnum, float deflt); uint8_t param_getdec(const char *line, int paramnum, uint8_t *destination); uint8_t param_isdec(const char *line, int paramnum); int param_gethex(const char *line, int paramnum, uint8_t *data, int hexcnt); From 07cf3fd32bf7319241941a014c38c59747834030 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 25 Oct 2019 00:55:16 +0200 Subject: [PATCH 24/24] fix few missing declarations -> static or add include file --- client/cmddata.c | 2 +- client/cmdhf.c | 2 +- client/cmdhw.c | 2 +- client/cmdlf.c | 2 +- client/cmdlfhitag.c | 2 ++ client/cmdlfnedap.c | 2 +- client/fileutils.c | 7 +++++-- client/loclass/ikeys.c | 2 ++ client/loclass/ikeys.h | 1 + client/proxmark3.c | 4 ++-- client/wiegand_formats.c | 2 +- client/wiegand_formatutils.c | 2 +- 12 files changed, 19 insertions(+), 11 deletions(-) diff --git a/client/cmddata.c b/client/cmddata.c index 5962d6ca6..499db7128 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -508,7 +508,7 @@ int CmdGetBitStream(const char *Cmd) { RepaintGraphWindow(); return PM3_SUCCESS; } -int CmdConvertBitStream(const char *Cmd) { +static int CmdConvertBitStream(const char *Cmd) { if (isGraphBitstream()) { convertGraphFromBitstream(); diff --git a/client/cmdhf.c b/client/cmdhf.c index 9166b01ca..1960de2ee 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -8,7 +8,7 @@ //----------------------------------------------------------------------------- // High frequency commands //----------------------------------------------------------------------------- -//#include "cmdhf.h" +#include "cmdhf.h" #include // tolower diff --git a/client/cmdhw.c b/client/cmdhw.c index ec53ad2cf..619e73abe 100644 --- a/client/cmdhw.c +++ b/client/cmdhw.c @@ -366,7 +366,7 @@ static void lookupChipID(uint32_t iChipID, uint32_t mem_used) { PrintAndLogEx(NORMAL, " --= Nonvolatile Program Memory Type: %s", asBuff); } -int CmdDbg(const char *Cmd) { +static int CmdDbg(const char *Cmd) { char ctmp = tolower(param_getchar(Cmd, 0)); if (strlen(Cmd) < 1 || ctmp == 'h') return usage_dbg(); diff --git a/client/cmdlf.c b/client/cmdlf.c index 328af5e29..e0238b0d6 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -213,7 +213,7 @@ static int usage_lf_tune(void) { return PM3_SUCCESS; } -int CmdLFTune(const char *Cmd) { +static int CmdLFTune(const char *Cmd) { int iter = 0; uint8_t divisor = LF_DIVISOR_125;//Frequency divisor bool errors = false; diff --git a/client/cmdlfhitag.c b/client/cmdlfhitag.c index a54b96a68..40e909024 100644 --- a/client/cmdlfhitag.c +++ b/client/cmdlfhitag.c @@ -8,6 +8,8 @@ // Low frequency Hitag support //----------------------------------------------------------------------------- +#include "cmdlfhitag.h" + #include #include "cmdparser.h" // command_t diff --git a/client/cmdlfnedap.c b/client/cmdlfnedap.c index 66d093800..84b433a0c 100644 --- a/client/cmdlfnedap.c +++ b/client/cmdlfnedap.c @@ -426,7 +426,7 @@ static int CmdLfNedapGen(const char *Cmd) { return PM3_SUCCESS; } -int CmdLFNedapClone(const char *Cmd) { +static int CmdLFNedapClone(const char *Cmd) { uint8_t max; uint32_t blocks[5] = {0}; diff --git a/client/fileutils.c b/client/fileutils.c index 8b537d423..ebdb662ca 100644 --- a/client/fileutils.c +++ b/client/fileutils.c @@ -74,7 +74,8 @@ int fileExists(const char *filename) { * @param filename * @return */ -bool is_regular_file(const char *filename) { +/* +static bool is_regular_file(const char *filename) { #ifdef _WIN32 struct _stat st; if (_stat(filename, &st) == -1) @@ -87,12 +88,14 @@ bool is_regular_file(const char *filename) { #endif return S_ISREG(st.st_mode) != 0; } +*/ + /** * @brief checks if path is directory. * @param filename * @return */ -bool is_directory(const char *filename) { +static bool is_directory(const char *filename) { #ifdef _WIN32 struct _stat st; if (_stat(filename, &st) == -1) diff --git a/client/loclass/ikeys.c b/client/loclass/ikeys.c index 1bff33f37..2f3a6c067 100644 --- a/client/loclass/ikeys.c +++ b/client/loclass/ikeys.c @@ -58,6 +58,8 @@ From "Dismantling iclass": output of hash0 is the diversified card key k = k [0] , . . . , k [7] ∈ (F 82 ) 8 . **/ +#include "ikeys.h" + #include #include #include diff --git a/client/loclass/ikeys.h b/client/loclass/ikeys.h index 29d285639..ccbc5539b 100644 --- a/client/loclass/ikeys.h +++ b/client/loclass/ikeys.h @@ -38,6 +38,7 @@ #ifndef IKEYS_H #define IKEYS_H +#include /** * @brief diff --git a/client/proxmark3.c b/client/proxmark3.c index fb02396bd..fde2af91e 100644 --- a/client/proxmark3.c +++ b/client/proxmark3.c @@ -56,7 +56,7 @@ static void showBanner(void) { g_printAndLog = PRINTANDLOG_PRINT | PRINTANDLOG_LOG; } -int check_comm(void) { +static int check_comm(void) { // If communications thread goes down. Device disconnected then this should hook up PM3 again. if (IsCommunicationThreadDead() && session.pm3_present) { rl_set_prompt(PROXPROMPT_OFFLINE); @@ -86,7 +86,7 @@ int push_cmdscriptfile(char *path, bool stayafter) { return PM3_SUCCESS; } -FILE *current_cmdscriptfile() { +static FILE *current_cmdscriptfile() { return cmdscriptfile[cmdscriptfile_idx]; } diff --git a/client/wiegand_formats.c b/client/wiegand_formats.c index 983e0f432..613f68e20 100644 --- a/client/wiegand_formats.c +++ b/client/wiegand_formats.c @@ -650,7 +650,7 @@ bool HIDPack(int format_idx, wiegand_card_t *card, wiegand_message_t *packed) { return FormatTable[format_idx].Pack(card, packed); } -void HIDDisplayUnpackedCard(wiegand_card_t *card, const cardformat_t format) { +static void HIDDisplayUnpackedCard(wiegand_card_t *card, const cardformat_t format) { /* PrintAndLogEx(SUCCESS, " Format: %s (%s)", format.Name, format.Descrp); diff --git a/client/wiegand_formatutils.c b/client/wiegand_formatutils.c index 80a9c9268..ba446957a 100644 --- a/client/wiegand_formatutils.c +++ b/client/wiegand_formatutils.c @@ -120,7 +120,7 @@ bool set_nonlinear_field(wiegand_message_t *data, uint64_t value, uint8_t numBit return result; } -uint8_t get_length_from_header(wiegand_message_t *data) { +static uint8_t get_length_from_header(wiegand_message_t *data) { uint8_t len = 0; uint32_t hfmt = 0; // for calculating card length