From 83c54bb174c981a48c5da952f5ec6beb487604be Mon Sep 17 00:00:00 2001 From: zinongli <131403964+zinongli@users.noreply.github.com> Date: Fri, 25 Jul 2025 23:47:00 -0400 Subject: [PATCH 1/6] initial working for single node --- client/src/cmdhffelica.c | 74 ++++++++++++++++++++++++++++++++++++++-- client/src/cmdhffelica.h | 1 + include/iso18.h | 5 +++ 3 files changed, 77 insertions(+), 3 deletions(-) diff --git a/client/src/cmdhffelica.c b/client/src/cmdhffelica.c index 619f09da2..a498d492c 100644 --- a/client/src/cmdhffelica.c +++ b/client/src/cmdhffelica.c @@ -531,6 +531,28 @@ int send_rd_plain(uint8_t flags, uint16_t datalen, uint8_t *data, bool verbose, } } +/** + * Sends a dump_service 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 dump_sv_resp frame in which the response will be saved. + * @param is_area true if the service is an area, false if it is a service. + * @return success if response was received. + */ +int send_dump_sv_plain(uint8_t flags, uint16_t datalen, uint8_t *data, bool verbose, felica_service_dump_response_t *dump_sv_resp, bool is_area) { + clear_and_send_command(flags, datalen, data, verbose); + PacketResponseNG resp; + if (waitCmdFelica(false, &resp, verbose) == false) { + PrintAndLogEx(ERR, "No response from card"); + return PM3_ERFTRANS; + } else { + memcpy(dump_sv_resp, (felica_service_dump_response_t *)resp.data.asBytes, sizeof(felica_service_dump_response_t)); + return PM3_SUCCESS; + } +} + /** * Checks if last known card can be added to data and adds it if possible. * @param custom_IDm @@ -1743,18 +1765,64 @@ static int CmdHFFelicaRequestService(const char *Cmd) { return PM3_SUCCESS; } -static int CmdHFFelicaNotImplementedYet(const char *Cmd) { +static int CmdHFFelicaDumpServiceArea(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf felica scsvcode", - "Feature not implemented yet. Feel free to contribute!", + "Dump all existing Area Code and Service Code.\n", "hf felica scsvcode" ); void *argtable[] = { arg_param_begin, arg_param_end }; - CLIExecWithReturn(ctx, Cmd, argtable, false); + + CLIExecWithReturn(ctx, Cmd, argtable, true); CLIParserFree(ctx); + + + uint8_t data[PM3_CMD_DATA_SIZE]; + memset(data, 0, sizeof(data)); + data[0] = 0x0C; // Static length + data[1] = 0x0A; // Command ID + + uint16_t datalen = 12; // Length (1), Command ID (1), IDm (8), Cursor Node (2) + if (check_last_idm(data, datalen) == false) { + return PM3_EINVARG; + } + + uint8_t flags = (FELICA_APPEND_CRC | FELICA_RAW); + + // for each cursor stuff RFU + data[10] = 0x00; // Cursor Node + data[11] = 0x00; // Cursor Node + + AddCrc(data, datalen); + + felica_service_dump_response_t dump_sv_resp; + bool is_area = false; + + if ((send_dump_sv_plain(flags, datalen + 2, data, 0, &dump_sv_resp, is_area) == PM3_SUCCESS)) { + if (dump_sv_resp.frame_response.cmd_code[0] != 0x0B) { + PrintAndLogEx(ERR, "Return command wrong. \nExpected 0x0B, got 0x%02X", dump_sv_resp.frame_response.cmd_code[0]); + return PM3_ERFTRANS; + } else { + if (dump_sv_resp.frame_response.length[0] == 0x0C) { + // service code read + PrintAndLogEx(SUCCESS, "Service Code Read 0x%02X%02X", dump_sv_resp.payload[0], dump_sv_resp.payload[1]); + } else if (dump_sv_resp.frame_response.length[0] == 0x0E) { + // service code read with area (this current parsing is wrong.) + PrintAndLogEx(SUCCESS, "Service Code Read 0x%02X%02X Area 0x%02X%02X", dump_sv_resp.payload[0], dump_sv_resp.payload[1], dump_sv_resp.payload[2], dump_sv_resp.payload[3]); + } else { + PrintAndLogEx(ERR, "Something went wrong, check your card"); + return PM3_ERFTRANS; + + } + } + } else { + PrintAndLogEx(ERR, "Something went wrong, check your card"); + return PM3_ERFTRANS; + } + return PM3_SUCCESS; } diff --git a/client/src/cmdhffelica.h b/client/src/cmdhffelica.h index 9cb524814..6ab42aa36 100644 --- a/client/src/cmdhffelica.h +++ b/client/src/cmdhffelica.h @@ -26,5 +26,6 @@ int CmdHFFelica(const char *Cmd); int read_felica_uid(bool loop, bool verbose); int send_request_service(uint8_t flags, uint16_t datalen, uint8_t *data, bool verbose); int send_rd_plain(uint8_t flags, uint16_t datalen, uint8_t *data, bool verbose, felica_read_without_encryption_response_t *rd_noCry_resp); +int send_dump_sv_plain(uint8_t flags, uint16_t datalen, uint8_t *data, bool verbose, felica_service_dump_response_t *dump_sv_resp, bool is_area); #endif diff --git a/include/iso18.h b/include/iso18.h index 377f864d0..5446c74eb 100644 --- a/include/iso18.h +++ b/include/iso18.h @@ -124,4 +124,9 @@ typedef struct { uint8_t PMi[8]; } PACKED felica_auth2_response_t; +typedef struct { + felica_frame_response_t frame_response; + uint8_t payload[4]; +} PACKED felica_service_dump_response_t; + #endif // _ISO18_H_ From c74d04bfe79f4d908c909267187e322b8d3c2fef Mon Sep 17 00:00:00 2001 From: zinongli <131403964+zinongli@users.noreply.github.com> Date: Sat, 26 Jul 2025 00:10:37 -0400 Subject: [PATCH 2/6] enumerate nodes --- client/src/cmdhffelica.c | 132 +++++++++++++++++++++++++-------------- 1 file changed, 84 insertions(+), 48 deletions(-) diff --git a/client/src/cmdhffelica.c b/client/src/cmdhffelica.c index a498d492c..4b6811813 100644 --- a/client/src/cmdhffelica.c +++ b/client/src/cmdhffelica.c @@ -1765,64 +1765,100 @@ static int CmdHFFelicaRequestService(const char *Cmd) { return PM3_SUCCESS; } +/** + * Command parser for rqservice. + * @param Cmd input data of the user. + * @return client result code. + */ static int CmdHFFelicaDumpServiceArea(const char *Cmd) { + /* ── CLI boilerplate (unchanged) ─────────────────────────────── */ CLIParserContext *ctx; CLIParserInit(&ctx, "hf felica scsvcode", "Dump all existing Area Code and Service Code.\n", - "hf felica scsvcode" - ); - void *argtable[] = { - arg_param_begin, - arg_param_end - }; - + "hf felica scsvcode"); + void *argtable[] = { arg_param_begin, arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); CLIParserFree(ctx); + /* ── build static part of Search-Service frame ──────────────── */ + uint8_t data[PM3_CMD_DATA_SIZE] = {0}; + data[0] = 0x0C; /* LEN */ + data[1] = 0x0A; /* CMD = 0x0A */ + uint16_t datalen = 12; /* LEN + CMD + IDm + cursor */ - uint8_t data[PM3_CMD_DATA_SIZE]; - memset(data, 0, sizeof(data)); - data[0] = 0x0C; // Static length - data[1] = 0x0A; // Command ID - - uint16_t datalen = 12; // Length (1), Command ID (1), IDm (8), Cursor Node (2) - if (check_last_idm(data, datalen) == false) { + if(!check_last_idm(data, datalen)) return PM3_EINVARG; + + PrintAndLogEx(INFO, "Dumping Service Code and Area Code...\n"); + + uint8_t flags = FELICA_APPEND_CRC | FELICA_RAW; + + /* ── traversal state ────────────────────────────────────────── */ + uint16_t cursor = 0x0000; + uint16_t area_end_stack[8] = {0xFFFF}; /* root “end” = 0xFFFF */ + int depth = 0; /* current stack depth */ + + felica_service_dump_response_t resp; + + while(true){ + + /* insert cursor LE */ + data[10] = cursor & 0xFF; + data[11] = cursor >> 8; + AddCrc(data, datalen); + + if(send_dump_sv_plain(flags, datalen + 2, data, 0, + &resp, false) != PM3_SUCCESS){ + PrintAndLogEx(ERR, "No response at cursor 0x%04X", cursor); + return PM3_ERFTRANS; + } + if(resp.frame_response.cmd_code[0] != 0x0B){ + PrintAndLogEx(ERR, "Bad response cmd 0x%02X @ 0x%04X", + resp.frame_response.cmd_code[0], cursor); + return PM3_ERFTRANS; + } + + uint8_t len = resp.frame_response.length[0]; + uint16_t node_code = resp.payload[0] | (resp.payload[1] << 8); + + if(node_code == 0xFFFF) break; /* end-marker */ + + /* pop finished areas */ + while(depth && node_code > area_end_stack[depth]) depth--; + + /* ---------- build pretty prefix & print node -------------- */ + /* 1. Is this the last child in its parent? */ + bool last_in_parent = (node_code == area_end_stack[depth]); + + /* 2. Compose prefix string */ + char prefix[64] = ""; + for(int i = 1; i < depth; i++) { + bool more_siblings = (cursor < area_end_stack[i]); + strcat(prefix, more_siblings ? "│ " : " "); + } + strcat(prefix, last_in_parent ? "└── " : "├── "); + + /* 3. Print the line */ + if(len == 0x0E) { /* AREA */ + uint16_t end_code = resp.payload[2] | (resp.payload[3] << 8); + PrintAndLogEx(INFO, "%sAREA_%04X", prefix, node_code >> 6); + + if(depth < 7) { /* push end */ + depth++; + area_end_stack[depth] = end_code; + } + } else if (len == 0x0C) { /* SERVICE */ + PrintAndLogEx(INFO, "%ssvc_%04X", prefix, node_code); + } else{ + PrintAndLogEx(ERR, "Unexpected length 0x%02X @ 0x%04X", + len, cursor); + return PM3_ERFTRANS; + } + cursor++; + if(cursor == 0) break; /* overflow safety */ } - uint8_t flags = (FELICA_APPEND_CRC | FELICA_RAW); - - // for each cursor stuff RFU - data[10] = 0x00; // Cursor Node - data[11] = 0x00; // Cursor Node - - AddCrc(data, datalen); - - felica_service_dump_response_t dump_sv_resp; - bool is_area = false; - - if ((send_dump_sv_plain(flags, datalen + 2, data, 0, &dump_sv_resp, is_area) == PM3_SUCCESS)) { - if (dump_sv_resp.frame_response.cmd_code[0] != 0x0B) { - PrintAndLogEx(ERR, "Return command wrong. \nExpected 0x0B, got 0x%02X", dump_sv_resp.frame_response.cmd_code[0]); - return PM3_ERFTRANS; - } else { - if (dump_sv_resp.frame_response.length[0] == 0x0C) { - // service code read - PrintAndLogEx(SUCCESS, "Service Code Read 0x%02X%02X", dump_sv_resp.payload[0], dump_sv_resp.payload[1]); - } else if (dump_sv_resp.frame_response.length[0] == 0x0E) { - // service code read with area (this current parsing is wrong.) - PrintAndLogEx(SUCCESS, "Service Code Read 0x%02X%02X Area 0x%02X%02X", dump_sv_resp.payload[0], dump_sv_resp.payload[1], dump_sv_resp.payload[2], dump_sv_resp.payload[3]); - } else { - PrintAndLogEx(ERR, "Something went wrong, check your card"); - return PM3_ERFTRANS; - - } - } - } else { - PrintAndLogEx(ERR, "Something went wrong, check your card"); - return PM3_ERFTRANS; - } - + PrintAndLogEx(SUCCESS, "Service code and area dump complete."); return PM3_SUCCESS; } @@ -2292,7 +2328,7 @@ 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."}, - {"scsvcode", CmdHFFelicaNotImplementedYet, IfPm3Felica, "acquire Area Code and Service Code."}, + {"scsvcode", CmdHFFelicaDumpServiceArea, IfPm3Felica, "acquire Area Code and Service Code."}, {"rqsyscode", CmdHFFelicaRequestSystemCode, IfPm3Felica, "acquire System Code registered to the card."}, {"auth1", CmdHFFelicaAuthentication1, IfPm3Felica, "authenticate a card. Start mutual authentication with Auth1"}, {"auth2", CmdHFFelicaAuthentication2, IfPm3Felica, "allow a card to authenticate a Reader/Writer. Complete mutual authentication"}, From 3b88dd45a34e39eb94dbe97b76eb446f140d0ca6 Mon Sep 17 00:00:00 2001 From: zinongli <131403964+zinongli@users.noreply.github.com> Date: Sat, 26 Jul 2025 00:49:57 -0400 Subject: [PATCH 3/6] beautify output format --- client/src/cmdhffelica.c | 51 ++++++++++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/client/src/cmdhffelica.c b/client/src/cmdhffelica.c index 4b6811813..3ae1ce4fa 100644 --- a/client/src/cmdhffelica.c +++ b/client/src/cmdhffelica.c @@ -1789,8 +1789,8 @@ static int CmdHFFelicaDumpServiceArea(const char *Cmd) { if(!check_last_idm(data, datalen)) return PM3_EINVARG; - PrintAndLogEx(INFO, "Dumping Service Code and Area Code...\n"); - + PrintAndLogEx(INFO, "┌───────────────────────────────────────────────"); + uint8_t flags = FELICA_APPEND_CRC | FELICA_RAW; /* ── traversal state ────────────────────────────────────────── */ @@ -1809,12 +1809,14 @@ static int CmdHFFelicaDumpServiceArea(const char *Cmd) { if(send_dump_sv_plain(flags, datalen + 2, data, 0, &resp, false) != PM3_SUCCESS){ - PrintAndLogEx(ERR, "No response at cursor 0x%04X", cursor); + PrintAndLogEx(FAILED, "No response at cursor 0x%04X", cursor); return PM3_ERFTRANS; } if(resp.frame_response.cmd_code[0] != 0x0B){ - PrintAndLogEx(ERR, "Bad response cmd 0x%02X @ 0x%04X", + PrintAndLogEx(FAILED, "Bad response cmd 0x%02X @ 0x%04X.", resp.frame_response.cmd_code[0], cursor); + PrintAndLogEx(INFO, "This is a normal signal issue. Please try again."); + PrintAndLogEx(INFO, "If the issue persists, move the card around and check signal strength. FeliCa can be hard to keep in field."); return PM3_ERFTRANS; } @@ -1826,31 +1828,29 @@ static int CmdHFFelicaDumpServiceArea(const char *Cmd) { /* pop finished areas */ while(depth && node_code > area_end_stack[depth]) depth--; - /* ---------- build pretty prefix & print node -------------- */ - /* 1. Is this the last child in its parent? */ - bool last_in_parent = (node_code == area_end_stack[depth]); - - /* 2. Compose prefix string */ + + /* ----- compose nice prefix ------------------------------------ */ char prefix[64] = ""; - for(int i = 1; i < depth; i++) { + for (int i = 1; i < depth; i++) { bool more_siblings = (cursor < area_end_stack[i]); strcat(prefix, more_siblings ? "│ " : " "); } - strcat(prefix, last_in_parent ? "└── " : "├── "); + /* decide glyph for this line (areas always use └──) */ + const char *line_glyph = "├── "; + strcat(prefix, line_glyph); - /* 3. Print the line */ - if(len == 0x0E) { /* AREA */ + /* ----- print --------------------------------------------------- */ + if (len == 0x0E) { /* AREA node */ uint16_t end_code = resp.payload[2] | (resp.payload[3] << 8); PrintAndLogEx(INFO, "%sAREA_%04X", prefix, node_code >> 6); - if(depth < 7) { /* push end */ - depth++; - area_end_stack[depth] = end_code; + if (depth < 7) { + area_end_stack[++depth] = end_code; } } else if (len == 0x0C) { /* SERVICE */ PrintAndLogEx(INFO, "%ssvc_%04X", prefix, node_code); } else{ - PrintAndLogEx(ERR, "Unexpected length 0x%02X @ 0x%04X", + PrintAndLogEx(FAILED, "Unexpected length 0x%02X @ 0x%04X", len, cursor); return PM3_ERFTRANS; } @@ -1858,6 +1858,23 @@ static int CmdHFFelicaDumpServiceArea(const char *Cmd) { if(cursor == 0) break; /* overflow safety */ } + /* draw closing bar └─┴─... based on final depth */ + char bar[128]; /* large enough for depth≤7 */ + size_t pos = 0; + + /* leading corner */ + pos += snprintf(bar + pos, sizeof(bar) - pos, "└"); + + /* one segment per level-1 */ + for(int i = 0; i < depth - 1 && pos < sizeof(bar); i++) + pos += snprintf(bar + pos, sizeof(bar) - pos, "───┴"); + + /* tail */ + snprintf(bar + pos, sizeof(bar) - pos, "───────────────────────"); + + PrintAndLogEx(INFO, "%s", bar); + + PrintAndLogEx(SUCCESS, "Service code and area dump complete."); return PM3_SUCCESS; } From 4090828ebcb12ced172bb0fe1cf7f707cc537920 Mon Sep 17 00:00:00 2001 From: zinongli <131403964+zinongli@users.noreply.github.com> Date: Sat, 26 Jul 2025 00:59:37 -0400 Subject: [PATCH 4/6] hints for endian issue --- client/src/cmdhffelica.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/src/cmdhffelica.c b/client/src/cmdhffelica.c index 3ae1ce4fa..b06ea860c 100644 --- a/client/src/cmdhffelica.c +++ b/client/src/cmdhffelica.c @@ -1789,6 +1789,8 @@ static int CmdHFFelicaDumpServiceArea(const char *Cmd) { if(!check_last_idm(data, datalen)) return PM3_EINVARG; + PrintAndLogEx(HINT, "Area and service code are printed in big endian."); + PrintAndLogEx(HINT, "Don't forget to convert to little endian when using hf felica rdbl."); PrintAndLogEx(INFO, "┌───────────────────────────────────────────────"); uint8_t flags = FELICA_APPEND_CRC | FELICA_RAW; From 8014aa03618673aa37fc3018f4a0b13ed1f46e9c Mon Sep 17 00:00:00 2001 From: zinongli <131403964+zinongli@users.noreply.github.com> Date: Sat, 26 Jul 2025 01:08:12 -0400 Subject: [PATCH 5/6] Update CHANGELOG.md per Github bot's suggestion --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d7281d870..f71c9634f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Changed `mem load` - now handles UL-C and UL-AES dictionary files (@iceman1001) - Changed `hf mfu sim` - now support UL-C simulation (@iceman1001) - Added `!` - run system commands from inside the client. Potentially dangerous if running client as SUDO, SU, ROOT (@iceman1001) +- Implemented `hf felica scsvcode` - now dumps all service and area codes. (@zinongli) ## [Daddy Iceman.4.20469][2025-06-16] - Fixed edge case in fm11rf08s key recovery tools (@doegox) From e94921c1afa95f65fd88717a350004f174f5ad4a Mon Sep 17 00:00:00 2001 From: zinongli <131403964+zinongli@users.noreply.github.com> Date: Sat, 26 Jul 2025 01:12:18 -0400 Subject: [PATCH 6/6] format --- client/src/cmdhffelica.c | 68 ++++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/client/src/cmdhffelica.c b/client/src/cmdhffelica.c index b06ea860c..9b28ee222 100644 --- a/client/src/cmdhffelica.c +++ b/client/src/cmdhffelica.c @@ -47,10 +47,10 @@ static void print_status_flag1_interpretation(void) { PrintAndLogEx(INFO, "----+--------------------------------------------------------------------------------------------------------------------"); PrintAndLogEx(INFO, " 00 | Indicates the successful completion of a command."); PrintAndLogEx(INFO, " FF | If an error occurs during the processing of a command that includes no list in the command packet, \n" - " | or if an error occurs independently of any list, the card returns a response by setting FFh to Status Flag1."); + " | or if an error occurs independently of any list, the card returns a response by setting FFh to Status Flag1."); PrintAndLogEx(INFO, " XX | If an error occurs while processing a command that includes Service Code List or Block List \n" - " | in the command packet, the card returns a response by setting a number in the list to Status Flag1,\n" - " | indicating the location of the error."); + " | in the command packet, the card returns a response by setting a number in the list to Status Flag1,\n" + " | indicating the location of the error."); PrintAndLogEx(INFO, "----+--------------------------------------------------------------------------------------------------------------------"); } @@ -59,28 +59,28 @@ static void print_status_flag2_interpration(void) { PrintAndLogEx(INFO, "----+--------------------------------------------------------------------------------------------------------------------"); PrintAndLogEx(INFO, " 00 | Indicates the successful completion of a command."); PrintAndLogEx(INFO, " 01 | The calculated result is either less than zero when the purse data is decremented, or exceeds 4\n" - " | Bytes when the purse data is incremented."); + " | Bytes when the purse data is incremented."); PrintAndLogEx(INFO, " 02 | The specified data exceeds the value of cashback data at cashback of purse."); PrintAndLogEx(INFO, " 70 | Memory error (fatal error)."); PrintAndLogEx(INFO, " 71 | The number of memory rewrites exceeds the upper limit (this is only a warning; data writing is performed as normal).\n" - " | The maximum number of rewrites can differ, depending on the product being used.\n" - " | In addition, Status Flag1 is either 00h or FFh depending on the product being used."); + " | The maximum number of rewrites can differ, depending on the product being used.\n" + " | In addition, Status Flag1 is either 00h or FFh depending on the product being used."); PrintAndLogEx(INFO, " A1 | Illegal Number of Service| Number of Service or Number of Node specified by the command \n" - " | falls outside the range of the prescribed value."); + " | falls outside the range of the prescribed value."); PrintAndLogEx(INFO, " A2 | Illegal command packet (specified Number of Block) : Number of Block specified by the \n" - " | command falls outside the range of the prescribed values for the product."); + " | command falls outside the range of the prescribed values for the product."); PrintAndLogEx(INFO, " A3 | Illegal Block List (specified order of Service) : Service Code List Order specified by \n" - " | Block List Element falls outside the Number of Service specified by the command \n" - " | (or the Number of Service specified at the times of mutual authentication)."); + " | Block List Element falls outside the Number of Service specified by the command \n" + " | (or the Number of Service specified at the times of mutual authentication)."); PrintAndLogEx(INFO, " A4 | Illegal Service type : Area Attribute specified by the command or Service Attribute of Service Code is incorrect."); PrintAndLogEx(INFO, " A5 | Access is not allowed : Area or Service specified by the command cannot be accessed.\n" - " | 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(INFO, " A6 | Illegal Service Code List : Target to be accessed, identified by Service Code List Order, specified by Block\n" - " | 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(INFO, " A7 | Illegal Block List (Access Mode) : Access Mode specified by Block List Element is incorrect."); PrintAndLogEx(INFO, " A8 | Illegal Block Number Block Number (access to the specified data is inhibited) :\n" - " | specified by Block List Element exceeds the number of Blocks assigned to Service."); + " | specified by Block List Element exceeds the number of Blocks assigned to Service."); PrintAndLogEx(INFO, " A9 | Data write failure : This is the error that occurs in issuance commands."); PrintAndLogEx(INFO, " AA | Key-change failure : Key change failed."); PrintAndLogEx(INFO, " AB | Illegal Package Parity or illegal Package MAC : This is the error that occurs in issuance commands."); @@ -88,7 +88,7 @@ static void print_status_flag2_interpration(void) { PrintAndLogEx(INFO, " AD | Service exists already : This is the error that occurs in issuance commands."); PrintAndLogEx(INFO, " AE | Illegal System Code : This is the error that occurs in issuance commands."); PrintAndLogEx(INFO, " AF | Too many simultaneous cyclic write operations : Number of simultaneous write Blocks\n" - " | specified by the command to Cyclic Service exceeds the number of Blocks assigned to Service."); + " | specified by the command to Cyclic Service exceeds the number of Blocks assigned to Service."); PrintAndLogEx(INFO, " C0 | Illegal Package Identifier : This is the error that occurs in issuance commands."); PrintAndLogEx(INFO, " C1 | Discrepancy of parameters inside and outside Package : This is the error that occurs in issuance commands."); PrintAndLogEx(INFO, " C2 | Command is disabled already : This is the error that occurs in issuance commands."); @@ -112,16 +112,16 @@ static void print_number_of_service_constraints(void) { static void print_number_of_block_constraints(void) { PrintAndLogEx(INFO, " - Number of Block: shall be less than or equal to the maximum number of Blocks that can be read simultaneously.\n" - " The maximum number of Blocks that can be read simultaneously can differ, depending on the product being used.\n" - " Use as default 01"); + " The maximum number of Blocks that can be read simultaneously can differ, depending on the product being used.\n" + " Use as default 01"); } static void print_service_code_list_constraints(void) { PrintAndLogEx(INFO, " - Service Code List: For Service Code List, only Service Code existing in the product shall be specified:"); PrintAndLogEx(INFO, " - Even when Service Code exists in the product, Service Code not referenced from Block List shall not \n" - " be specified to Service Code List."); + " be specified to Service Code List."); PrintAndLogEx(INFO, " - For existence or nonexistence of Service in a product, please check using the Request Service \n" - " (or Request Service v2) command."); + " (or Request Service v2) command."); } /* @@ -1786,13 +1786,13 @@ static int CmdHFFelicaDumpServiceArea(const char *Cmd) { data[1] = 0x0A; /* CMD = 0x0A */ uint16_t datalen = 12; /* LEN + CMD + IDm + cursor */ - if(!check_last_idm(data, datalen)) + if (!check_last_idm(data, datalen)) return PM3_EINVARG; - + PrintAndLogEx(HINT, "Area and service code are printed in big endian."); PrintAndLogEx(HINT, "Don't forget to convert to little endian when using hf felica rdbl."); PrintAndLogEx(INFO, "┌───────────────────────────────────────────────"); - + uint8_t flags = FELICA_APPEND_CRC | FELICA_RAW; /* ── traversal state ────────────────────────────────────────── */ @@ -1802,19 +1802,19 @@ static int CmdHFFelicaDumpServiceArea(const char *Cmd) { felica_service_dump_response_t resp; - while(true){ + while (true) { /* insert cursor LE */ data[10] = cursor & 0xFF; data[11] = cursor >> 8; AddCrc(data, datalen); - if(send_dump_sv_plain(flags, datalen + 2, data, 0, - &resp, false) != PM3_SUCCESS){ + if (send_dump_sv_plain(flags, datalen + 2, data, 0, + &resp, false) != PM3_SUCCESS) { PrintAndLogEx(FAILED, "No response at cursor 0x%04X", cursor); return PM3_ERFTRANS; } - if(resp.frame_response.cmd_code[0] != 0x0B){ + if (resp.frame_response.cmd_code[0] != 0x0B) { PrintAndLogEx(FAILED, "Bad response cmd 0x%02X @ 0x%04X.", resp.frame_response.cmd_code[0], cursor); PrintAndLogEx(INFO, "This is a normal signal issue. Please try again."); @@ -1825,12 +1825,12 @@ static int CmdHFFelicaDumpServiceArea(const char *Cmd) { uint8_t len = resp.frame_response.length[0]; uint16_t node_code = resp.payload[0] | (resp.payload[1] << 8); - if(node_code == 0xFFFF) break; /* end-marker */ + if (node_code == 0xFFFF) break; /* end-marker */ /* pop finished areas */ - while(depth && node_code > area_end_stack[depth]) depth--; + while (depth && node_code > area_end_stack[depth]) depth--; + - /* ----- compose nice prefix ------------------------------------ */ char prefix[64] = ""; for (int i = 1; i < depth; i++) { @@ -1846,18 +1846,18 @@ static int CmdHFFelicaDumpServiceArea(const char *Cmd) { uint16_t end_code = resp.payload[2] | (resp.payload[3] << 8); PrintAndLogEx(INFO, "%sAREA_%04X", prefix, node_code >> 6); - if (depth < 7) { - area_end_stack[++depth] = end_code; + if (depth < 7) { + area_end_stack[++depth] = end_code; } } else if (len == 0x0C) { /* SERVICE */ PrintAndLogEx(INFO, "%ssvc_%04X", prefix, node_code); - } else{ + } else { PrintAndLogEx(FAILED, "Unexpected length 0x%02X @ 0x%04X", - len, cursor); + len, cursor); return PM3_ERFTRANS; } cursor++; - if(cursor == 0) break; /* overflow safety */ + if (cursor == 0) break; /* overflow safety */ } /* draw closing bar └─┴─... based on final depth */ @@ -1868,7 +1868,7 @@ static int CmdHFFelicaDumpServiceArea(const char *Cmd) { pos += snprintf(bar + pos, sizeof(bar) - pos, "└"); /* one segment per level-1 */ - for(int i = 0; i < depth - 1 && pos < sizeof(bar); i++) + for (int i = 0; i < depth - 1 && pos < sizeof(bar); i++) pos += snprintf(bar + pos, sizeof(bar) - pos, "───┴"); /* tail */