hf felica raw - now uses cliparser

This commit is contained in:
iceman1001 2021-03-24 19:30:40 +01:00
commit db3719792b

View file

@ -1,6 +1,6 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 2017 October, Satsuoni // Copyright (C) 2017 October, Satsuoni
// 2017 iceman // 2017,2021 iceman
// This code is licensed to you under the terms of the GNU GPL, version 2 or, // This code is licensed to you under the terms of the GNU GPL, version 2 or,
// at your option, any later version. See the LICENSE.txt file for the text of // at your option, any later version. See the LICENSE.txt file for the text of
// the license. // the license.
@ -23,6 +23,8 @@
#include "ui.h" #include "ui.h"
#include "iso18.h" // felica_card_select_t struct #include "iso18.h" // felica_card_select_t struct
#include "des.h" #include "des.h"
#include "cliparser.h" // cliparser
#define AddCrc(data, len) compute_crc(CRC_FELICA, (data), (len), (data)+(len)+1, (data)+(len)) #define AddCrc(data, len) compute_crc(CRC_FELICA, (data), (len), (data)+(len)+1, (data)+(len))
static int CmdHelp(const char *Cmd); static int CmdHelp(const char *Cmd);
@ -32,17 +34,90 @@ static void set_last_known_card(felica_card_select_t card) {
last_known_card = card; last_known_card = card;
} }
static void print_status_flag1_interpretation(void) {
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "Status Flag1:");
PrintAndLogEx(INFO, " - 00h : Indicates the successful completion of a command.");
PrintAndLogEx(INFO, " - 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(INFO, " - 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.");
}
static void print_status_flag2_interpration(void) {
PrintAndLogEx(INFO, "\nStatus Flag2:");
PrintAndLogEx(INFO, " - 00h : Indicates the successful completion of a command.");
PrintAndLogEx(INFO, " - 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(INFO, " - 02h : The specified data exceeds the value of cashback data at cashback of purse.");
PrintAndLogEx(INFO, " - 70h : Memory error (fatal error).");
PrintAndLogEx(INFO, " - 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.");
PrintAndLogEx(INFO, " In addition, Status Flag1 is either 00h or FFh depending on the product being used.");
PrintAndLogEx(INFO, " - 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(INFO, " - 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(INFO, " - 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(INFO, " - A4h : Illegal Service type: Area Attribute specified by the command or Service Attribute of Service Code is incorrect.");
PrintAndLogEx(INFO, " - 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(INFO, " - 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(INFO, " - A7h : Illegal Block List (Access Mode): Access Mode specified by Block List Element is incorrect.");
PrintAndLogEx(INFO, " - 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(INFO, " - A9h : Data write failure: This is the error that occurs in issuance commands.");
PrintAndLogEx(INFO, " - AAh : Key-change failure: Key change failed.");
PrintAndLogEx(INFO, " - ABh : Illegal Package Parity or illegal Package MAC: This is the error that occurs in issuance commands.");
PrintAndLogEx(INFO, " - ACh : Illegal parameter: This is the error that occurs in issuance commands.");
PrintAndLogEx(INFO, " - ADh : Service exists already: This is the error that occurs in issuance commands.");
PrintAndLogEx(INFO, " - AEh : Illegal System Code: This is the error that occurs in issuance commands.");
PrintAndLogEx(INFO, " - 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(INFO, " - C0h : Illegal Package Identifier: This is the error that occurs in issuance commands.");
PrintAndLogEx(INFO, " - C1h : Discrepancy of parameters inside and outside Package: This is the error that occurs in issuance commands.");
PrintAndLogEx(INFO, " - C2h : Command is disabled already: This is the error that occurs in issuance commands.");
}
static void print_block_list_element_constraints(void) {
PrintAndLogEx(INFO, " - Each Block List Element shall satisfy the following conditions:");
PrintAndLogEx(INFO, " - The value of Service Code List Order shall not exceed Number of Service.");
PrintAndLogEx(INFO, " - Access Mode shall be 000b.");
PrintAndLogEx(INFO, " - The target specified by Service Code shall not be Area or System.");
PrintAndLogEx(INFO, " - Service specified in Service Code List shall exist in System.");
PrintAndLogEx(INFO, " - Service Attribute of Service specified in Service Code List shall be authentication-not-required Service.");
PrintAndLogEx(INFO, " - Block Number shall be in the range of the number of Blocks assigned to the specified Service.");
}
static void print_number_of_service_constraints(void) {
PrintAndLogEx(INFO, " - Number of Service: shall be a positive integer in the range of 1 to 16, inclusive.");
}
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. 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 be specified to Service Code List.");
PrintAndLogEx(INFO, " - For existence or nonexistence of Service in a product, please check using the Request Service (or Request Service v2) command.");
}
/* /*
static int usage_hf_felica_sim(void) { static int usage_hf_felica_sim(void) {
PrintAndLogEx(NORMAL, "\n Emulating ISO/18092 FeliCa tag \n"); PrintAndLogEx(INFO, "\n Emulating ISO/18092 FeliCa tag \n");
PrintAndLogEx(NORMAL, "Usage: hf felica sim [h] t <type> [v]"); PrintAndLogEx(INFO, "Usage: hf felica sim [h] t <type> [v]");
PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(INFO, "Options:");
PrintAndLogEx(NORMAL, " h : This help"); PrintAndLogEx(INFO, " h : This help");
PrintAndLogEx(NORMAL, " t : 1 = FeliCa"); PrintAndLogEx(INFO, " t : 1 = FeliCa");
PrintAndLogEx(NORMAL, " : 2 = FeliCaLiteS"); PrintAndLogEx(INFO, " : 2 = FeliCaLiteS");
PrintAndLogEx(NORMAL, " v : (Optional) Verbose"); PrintAndLogEx(INFO, " v : (Optional) Verbose");
PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(INFO, "Examples:");
PrintAndLogEx(NORMAL, " hf felica sim t 1 "); PrintAndLogEx(INFO, " hf felica sim t 1 ");
return PM3_SUCCESS; return PM3_SUCCESS;
} }
*/ */
@ -83,17 +158,6 @@ static int usage_hf_felica_dumplite(void) {
return PM3_SUCCESS; return PM3_SUCCESS;
} }
static int usage_hf_felica_raw(void) {
PrintAndLogEx(NORMAL, "Usage: hf felica raw [-h] [-r] [-c] [-k] [-a] <0A 0B 0C ... hex>");
PrintAndLogEx(NORMAL, " -h this help");
PrintAndLogEx(NORMAL, " -r do not read response");
PrintAndLogEx(NORMAL, " -c calculate and append CRC");
PrintAndLogEx(NORMAL, " -k keep signal field ON after receive");
PrintAndLogEx(NORMAL, " -a active signal field ON without select");
PrintAndLogEx(NORMAL, " -s active signal field ON with select");
return PM3_SUCCESS;
}
static int usage_hf_felica_request_service(void) { 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, "\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 exists, the card returns Key Version.");
@ -123,75 +187,6 @@ static int usage_hf_felica_request_response(void) {
return PM3_SUCCESS; return PM3_SUCCESS;
} }
static void print_status_flag1_interpretation(void) {
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.");
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.");
}
static void print_status_flag2_interpration(void) {
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.");
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.");
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).");
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 void print_block_list_element_constraints(void) {
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.");
}
static void print_number_of_service_constraints(void) {
PrintAndLogEx(NORMAL, " - Number of Service: shall be a positive integer in the range of 1 to 16, inclusive.");
}
static void print_number_of_block_constraints(void) {
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");
}
static void print_service_code_list_constraints(void) {
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.");
}
static int usage_hf_felica_read_without_encryption(void) { 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, "\nInfo: Use this command to read Block Data from authentication-not-required Service.");
PrintAndLogEx(NORMAL, " - Mode shall be Mode0."); PrintAndLogEx(NORMAL, " - Mode shall be Mode0.");
@ -335,6 +330,7 @@ static int usage_hf_felica_authentication2(void) {
return PM3_SUCCESS; return PM3_SUCCESS;
} }
/** /**
* Wait for response from pm3 or timeout. * Wait for response from pm3 or timeout.
* Checks if receveid bytes have a valid CRC. * Checks if receveid bytes have a valid CRC.
@ -1689,79 +1685,37 @@ static int CmdHFFelicaDumpLite(const char *Cmd) {
} }
static int CmdHFFelicaCmdRaw(const char *Cmd) { static int CmdHFFelicaCmdRaw(const char *Cmd) {
bool reply = 1;
bool crc = false; CLIParserContext *ctx;
bool keep_field_on = false; CLIParserInit(&ctx, "hf felica raw ",
bool active = false; "Send raw hex data to tag",
bool active_select = false; "hf felica raw -s 20"
uint16_t numbits = 0; );
char buf[5] = "";
int i = 0; void *argtable[] = {
arg_param_begin,
arg_lit0("a", NULL, "active signal field ON without select"),
arg_lit0("c", NULL, "calculate and append CRC"),
arg_lit0("k", NULL, "keep signal field ON after receive"),
arg_u64_0("n", NULL, "<dec>", "number of bits"),
arg_lit0("r", NULL, "do not read response"),
arg_lit0("s", NULL, "active signal field ON with select"),
arg_strx1(NULL, NULL, "<hex>", "raw bytes to send"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
bool active = arg_get_lit(ctx, 1);
bool crc = arg_get_lit(ctx, 2);
bool keep_field_on = arg_get_lit(ctx, 3);
uint16_t numbits = arg_get_u32_def(ctx, 4, 0) &0xFFFF;
bool reply = (arg_get_lit(ctx, 5) == false);
bool active_select = arg_get_lit(ctx, 6);
int datalen = 0;
uint8_t data[PM3_CMD_DATA_SIZE]; uint8_t data[PM3_CMD_DATA_SIZE];
uint16_t datalen = 0; CLIGetHexWithReturn(ctx, 6, data, &datalen);
uint32_t temp; CLIParserFree(ctx);
if (strlen(Cmd) < 2) return usage_hf_felica_raw();
// strip
while (*Cmd == ' ' || *Cmd == '\t') Cmd++;
while (Cmd[i] != '\0') {
if (Cmd[i] == ' ' || Cmd[i] == '\t') { i++; continue; }
if (Cmd[i] == '-') {
switch (tolower(Cmd[i + 1])) {
case 'h':
return usage_hf_felica_raw();
case 'r':
reply = false;
break;
case 'c':
crc = true;
break;
case 'k':
keep_field_on = true;
break;
case 'a':
active = true;
break;
case 's':
active_select = true;
break;
case 'b':
sscanf(Cmd + i + 2, "%d", &temp);
numbits = temp & 0xFFFF;
i += 3;
while (Cmd[i] != ' ' && Cmd[i] != '\0') { i++; }
i -= 2;
break;
default:
return usage_hf_felica_raw();
}
i += 2;
continue;
}
if ((Cmd[i] >= '0' && Cmd[i] <= '9') ||
(Cmd[i] >= 'a' && Cmd[i] <= 'f') ||
(Cmd[i] >= 'A' && Cmd[i] <= 'F')) {
buf[strlen(buf) + 1] = 0;
buf[strlen(buf)] = Cmd[i];
i++;
if (strlen(buf) >= 2) {
sscanf(buf, "%x", &temp);
data[datalen] = (uint8_t)(temp & 0xff);
*buf = 0;
if (++datalen >= (sizeof(data) - 2)) {
if (crc)
PrintAndLogEx(WARNING, "Buffer is full, we can't add CRC to your data");
break;
}
}
continue;
}
PrintAndLogEx(WARNING, "Invalid char on input");
return PM3_EINVARG;
}
if (crc) { if (crc) {
AddCrc(data, datalen); AddCrc(data, datalen);
@ -1788,6 +1742,7 @@ static int CmdHFFelicaCmdRaw(const char *Cmd) {
clearCommandBuffer(); clearCommandBuffer();
PrintAndLogEx(SUCCESS, "Data: %s", sprint_hex(data, datalen)); PrintAndLogEx(SUCCESS, "Data: %s", sprint_hex(data, datalen));
SendCommandMIX(CMD_HF_FELICA_COMMAND, flags, (datalen & 0xFFFF) | (uint32_t)(numbits << 16), 0, data, datalen); SendCommandMIX(CMD_HF_FELICA_COMMAND, flags, (datalen & 0xFFFF) | (uint32_t)(numbits << 16), 0, data, datalen);
if (reply) { if (reply) {