hf felica resetmode - now uses cliparser

This commit is contained in:
iceman1001 2021-04-12 21:30:53 +02:00
commit 37751e1b2b

View file

@ -33,50 +33,59 @@ static void set_last_known_card(felica_card_select_t 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.");
PrintAndLogEx(INFO, _CYAN_("Status Flag 1"));
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.");
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.");
PrintAndLogEx(INFO, "----+--------------------------------------------------------------------------------------------------------------------");
}
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.");
PrintAndLogEx(INFO, _CYAN_("Status Flag 2"));
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.");
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.");
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.");
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.");
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).");
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.");
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.");
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.");
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.");
PrintAndLogEx(INFO, " AC | Illegal parameter : This is the error that occurs in issuance commands.");
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.");
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.");
PrintAndLogEx(INFO, "----+--------------------------------------------------------------------------------------------------------------------");
PrintAndLogEx(NORMAL, "");
}
static void print_block_list_element_constraints(void) {
@ -94,14 +103,17 @@ 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. Use as default 01");
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");
}
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.");
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.");
PrintAndLogEx(INFO, " - For existence or nonexistence of Service in a product, please check using the Request Service \n"
" (or Request Service v2) command.");
}
/*
@ -119,8 +131,6 @@ static int usage_hf_felica_sim(void) {
}
*/
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.");
@ -185,21 +195,6 @@ static int usage_hf_felica_request_system_code(void) {
return PM3_SUCCESS;
}
static int usage_hf_felica_reset_mode(void) {
PrintAndLogEx(NORMAL, "\nInfo: Use this command to reset Mode to Mode 0.");
print_status_flag1_interpretation();
print_status_flag2_interpration();
PrintAndLogEx(NORMAL, "\nUsage: hf felica resetmode [-h][-i][-r]");
PrintAndLogEx(NORMAL, " -h this help");
PrintAndLogEx(NORMAL, " -i <0A0B0C ... hex> set custom IDm to use");
PrintAndLogEx(NORMAL, " -r <0A0B hex> set custom reserve to use");
PrintAndLogEx(NORMAL, "\nExamples: ");
PrintAndLogEx(NORMAL, " hf felica resetmode ");
PrintAndLogEx(NORMAL, " hf felica resetmode -r 0001");
PrintAndLogEx(NORMAL, " hf felica resetmode -i 11100910C11BC407\n\n");
return PM3_SUCCESS;
}
static int usage_hf_felica_request_specification_version(void) {
PrintAndLogEx(NORMAL, "\nInfo: Use this command to acquire the version of card OS.");
PrintAndLogEx(NORMAL, " - Response:");
@ -366,7 +361,9 @@ int read_felica_uid(bool loop, bool verbose) {
felica_card_select_t card;
memcpy(&card, (felica_card_select_t *)resp.data.asBytes, sizeof(felica_card_select_t));
if (loop == false) {
PrintAndLogEx(NORMAL, "");
}
PrintAndLogEx(SUCCESS, "IDm: " _GREEN_("%s"), sprint_hex_inrow(card.IDm, sizeof(card.IDm)));
set_last_known_card(card);
}
@ -581,12 +578,12 @@ int send_rd_unencrypted(uint8_t flags, uint16_t datalen, uint8_t *data, bool ver
* @return
*/
static bool check_last_idm(uint8_t *data, uint16_t datalen) {
if (!add_last_IDm(2, data)) {
PrintAndLogEx(ERR, "No last known card! Use reader first or set a custom IDm!");
return 0;
if (add_last_IDm(2, data) == false) {
PrintAndLogEx(WARNING, "No last known card! Use `" _YELLOW_("hf felica reader") "` first or set a custom IDm");
return false;
} else {
PrintAndLogEx(INFO, "Used last known IDm. %s", sprint_hex(data, datalen));
return 1;
PrintAndLogEx(INFO, "Using last known IDm... " _GREEN_("%s"), sprint_hex_inrow(data, datalen));
return true;
}
}
@ -1208,69 +1205,85 @@ static int CmdHFFelicaRequestSpecificationVersion(const char *Cmd) {
* @return client result code.
*/
static int CmdHFFelicaResetMode(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf felica resetmode",
"Use this command to reset Mode to Mode 0.",
"hf felica resetmode\n"
"hf felica resetmode -r 0001\n"
"hf felica resetmode -i 11100910C11BC407 \n"
);
void *argtable[] = {
arg_param_begin,
arg_str0("i", NULL, "<hex>", "set custom IDm"),
arg_str0("r", NULL, "<hex>", "set custom reserve"),
arg_lit0("v", "verbose", "verbose helptext"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
uint8_t idm[8] = {0};
int ilen = 0;
int res = CLIParamHexToBuf(arg_get_str(ctx, 1), idm, sizeof(idm), &ilen);
if (res) {
CLIParserFree(ctx);
return PM3_EINVARG;
}
uint8_t reserved[2] = {0,0};
int rlen = 0;
res = CLIParamHexToBuf(arg_get_str(ctx, 2), reserved, sizeof(reserved), &rlen);
if (res) {
CLIParserFree(ctx);
return PM3_EINVARG;
}
bool verbose = arg_get_lit(ctx, 3);
if (verbose) {
print_status_flag1_interpretation();
print_status_flag2_interpration();
}
CLIParserFree(ctx);
uint8_t data[PM3_CMD_DATA_SIZE];
bool custom_IDm = false;
bool custom_reserve = false;
strip_cmds(Cmd);
uint16_t datalen = 12; // Length (1), Command ID (1), IDm (8), Reserved (2)
uint8_t paramCount = 0;
uint8_t flags = 0;
int i = 0;
while (Cmd[i] != '\0') {
if (Cmd[i] == '-') {
switch (tolower(Cmd[i + 1])) {
case 'h':
return usage_hf_felica_reset_mode();
case 'i':
paramCount++;
custom_IDm = true;
if (!add_param(Cmd, paramCount, data, 2, 16)) {
return PM3_EINVARG;
}
paramCount++;
i += 16;
break;
case 'r':
paramCount++;
custom_reserve = true;
if (!add_param(Cmd, paramCount, data, 10, 4)) {
return PM3_EINVARG;
}
paramCount++;
i += 4;
break;
default:
return usage_hf_felica_reset_mode();
}
}
i++;
}
data[0] = 0x0C; // Static length
data[1] = 0x3E; // Command ID
if (!custom_reserve) {
bool custom_IDm = false;
if (ilen) {
custom_IDm = true;
memcpy(data + 2, idm, 8);
}
if (rlen) {
memcpy(data + 10, reserved, 2);
} else {
data[10] = 0x00; // Reserved Value
data[11] = 0x00; // Reserved Value
}
if (!custom_IDm && !check_last_idm(data, datalen)) {
uint16_t datalen = 12; // Length (1), Command ID (1), IDm (8), Reserved (2)
if (custom_IDm == false && !check_last_idm(data, datalen)) {
return PM3_EINVARG;
}
AddCrc(data, datalen);
datalen += 2;
flags |= FELICA_APPEND_CRC;
flags |= FELICA_RAW;
uint8_t flags = (FELICA_APPEND_CRC | FELICA_RAW);
clear_and_send_command(flags, datalen, data, 0);
PacketResponseNG resp;
if (!waitCmdFelica(0, &resp, 1)) {
if (waitCmdFelica(0, &resp, 1) == false) {
PrintAndLogEx(ERR, "\nGot no response from card");
return PM3_ERFTRANS;
} else {
felica_status_response_t reset_mode_response;
memcpy(&reset_mode_response, (felica_status_response_t *)resp.data.asBytes, sizeof(felica_status_response_t));
if (reset_mode_response.frame_response.IDm[0] != 0) {
PrintAndLogEx(SUCCESS, "\nGot Request Response:");
PrintAndLogEx(SUCCESS, "\nIDm: %s", sprint_hex(reset_mode_response.frame_response.IDm, sizeof(reset_mode_response.frame_response.IDm)));
PrintAndLogEx(SUCCESS, "Got Request Response:");
PrintAndLogEx(SUCCESS, "IDm: %s", sprint_hex(reset_mode_response.frame_response.IDm, sizeof(reset_mode_response.frame_response.IDm)));
PrintAndLogEx(SUCCESS, "Status Flag1: %s", sprint_hex(reset_mode_response.status_flags.status_flag1, sizeof(reset_mode_response.status_flags.status_flag1)));
PrintAndLogEx(SUCCESS, "Status Flag2: %s\n", sprint_hex(reset_mode_response.status_flags.status_flag2, sizeof(reset_mode_response.status_flags.status_flag2)));
PrintAndLogEx(SUCCESS, "Status Flag2: %s", sprint_hex(reset_mode_response.status_flags.status_flag2, sizeof(reset_mode_response.status_flags.status_flag2)));
}
}
return PM3_SUCCESS;