Add felica request service all nodes command.

Make style.
This commit is contained in:
Thomas Sutter 2019-10-22 17:03:54 +02:00
commit 3f56116615
5 changed files with 71 additions and 45 deletions

View file

@ -420,8 +420,8 @@ bool WaitForFelicaReply(uint16_t maxbytes) {
Process18092Byte(b); Process18092Byte(b);
if (FelicaFrame.state == STATE_FULL) { 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 (GetCountSspClk() & 0xfffffff8) - (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER) / 16 + FELICA_FRAME_DELAY_TIME
); );
LogTrace( LogTrace(
FelicaFrame.framebytes, FelicaFrame.framebytes,
FelicaFrame.len, FelicaFrame.len,

View file

@ -26,7 +26,7 @@
static int CmdHelp(const char *Cmd); static int CmdHelp(const char *Cmd);
static felica_card_select_t last_known_card; 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; 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 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, " - 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 " 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 " "If Key Version of System is the target of acquisition, FFFFh shall be specified "
"in the command packet."); "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> <0A 0B Node Code List hex (Little Endian)>");
PrintAndLogEx(NORMAL, " -h this help"); PrintAndLogEx(NORMAL, " -h this help");
PrintAndLogEx(NORMAL, " -i <0A 0B 0C ... hex> set custom IDm to use"); 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; return PM3_SUCCESS;
} }
@ -109,7 +112,7 @@ static bool waitCmdFelica(uint8_t iSelect, PacketResponseNG *resp) {
if (WaitForResponseTimeout(CMD_ACK, resp, 2000)) { if (WaitForResponseTimeout(CMD_ACK, resp, 2000)) {
uint16_t len = iSelect ? (resp->oldarg[1] & 0xffff) : (resp->oldarg[0] & 0xffff); uint16_t len = iSelect ? (resp->oldarg[1] & 0xffff) : (resp->oldarg[0] & 0xffff);
PrintAndLogEx(NORMAL, "Client Received %i octets", len); PrintAndLogEx(NORMAL, "Client Received %i octets", len);
if (!len || len < 2){ if (!len || len < 2) {
PrintAndLogEx(ERR, "Could not receive data correctly!"); PrintAndLogEx(ERR, "Could not receive data correctly!");
} }
PrintAndLogEx(NORMAL, "%s", sprint_hex(resp->data.asBytes, len)); PrintAndLogEx(NORMAL, "%s", sprint_hex(resp->data.asBytes, len));
@ -120,7 +123,7 @@ static bool waitCmdFelica(uint8_t iSelect, PacketResponseNG *resp) {
} else { } else {
PrintAndLogEx(WARNING, "Timeout while waiting for reply."); 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 datalen length of the data frame.
* @param data frame on which the crc is calculated. * @param data frame on which the crc is calculated.
* @param size of the data. * @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. * @param number number of hex bytes.
* @return number as hex value. * @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; uint32_t hex;
char dataLengthChar[5]; char dataLengthChar[5];
sprintf(dataLengthChar, "%x", *number); 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. * @param data frame in where the IDM is added.
* @return true if IDm was added; * @return true if IDm was added;
*/ */
static bool add_last_IDm(uint8_t position, uint8_t *data){ static bool add_last_IDm(uint8_t position, uint8_t *data) {
if(last_known_card.IDm[0] != 0 && last_known_card.IDm[1] != 0){ if (last_known_card.IDm[0] != 0 && last_known_card.IDm[1] != 0) {
for(int i = 0; i < 8; i++){ for (int i = 0; i < 8; i++) {
uint16_t number = (uint16_t)last_known_card.IDm[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; return true;
}else{ } else {
return false; return false;
} }
} }
@ -242,6 +245,32 @@ static int CmdHFFelicaDump(const char *Cmd) {
return PM3_SUCCESS; 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. * Command parser for rqservice.
* @param Cmd input data of the user. * @param Cmd input data of the user.
@ -252,23 +281,29 @@ static int CmdHFFelicaRequestService(const char *Cmd) {
int i = 0; int i = 0;
uint8_t data[PM3_CMD_DATA_SIZE]; uint8_t data[PM3_CMD_DATA_SIZE];
bool custom_IDm = false; bool custom_IDm = false;
bool all_nodes = false;
uint16_t datalen = 0; uint16_t datalen = 0;
uint8_t flags = 0; uint8_t flags = 0;
uint16_t numbits = 0;
char buf[5] = ""; char buf[5] = "";
datalen += 10; // length (1) + CMD (1) + IDm (8) datalen += 10; // length (1) + CMD (1) + IDm(8)
strip_cmds(Cmd); strip_cmds(Cmd);
while (Cmd[i] != '\0') { while (Cmd[i] != '\0') {
if (Cmd[i] == '-') { if (Cmd[i] == '-') {
switch (Cmd[i + 1]) { switch (Cmd[i + 1]) {
case 'H': case 'H':
case 'h': case 'h':
return usage_hf_felica_raw(); return usage_hf_felica_request_service();
case 'i': case 'i':
custom_IDm = true; custom_IDm = true;
datalen -= 8;
break;
case 'a':
all_nodes = true;
datalen += 1;
break; break;
default: default:
return usage_hf_felica_raw(); return usage_hf_felica_request_service();
} }
i += 2; i += 2;
} }
@ -290,38 +325,28 @@ static int CmdHFFelicaRequestService(const char *Cmd) {
flags |= FELICA_RAW; flags |= FELICA_RAW;
} }
datalen = (datalen > PM3_CMD_DATA_SIZE) ? PM3_CMD_DATA_SIZE : datalen; datalen = (datalen > PM3_CMD_DATA_SIZE) ? PM3_CMD_DATA_SIZE : datalen;
if(!custom_IDm){ if (!custom_IDm) {
if(!add_last_IDm(2, data)){ if (!add_last_IDm(2, data)) {
PrintAndLogEx(ERR, "No last known card! Use reader first or set a custom IDm!"); PrintAndLogEx(ERR, "No last known card! Use reader first or set a custom IDm!");
return PM3_EINVARG; return PM3_EINVARG;
}else{ } else {
PrintAndLogEx(INFO, "Used last known IDm.", sprint_hex(data, datalen)); PrintAndLogEx(INFO, "Used last known IDm.", sprint_hex(data, datalen));
} }
} }
data[0] = int_to_hex(&datalen); data[0] = int_to_hex(&datalen);
data[1] = 0x02; // Request Command ID data[1] = 0x02; // Request Command ID
add_crc_bytes(&datalen, data, sizeof(data)); if (all_nodes) {
PrintAndLogEx(NORMAL, "Send Service Request Frame: %s", sprint_hex(data, datalen)); for (uint16_t y = 1; y < 32; y++) {
clearCommandBuffer(); data[10] = int_to_hex(&y);
SendCommandMIX(CMD_HF_FELICA_COMMAND, flags, (datalen & 0xFFFF) | (uint32_t)(numbits << 16), 0, data, datalen); add_crc_bytes(&datalen, data, sizeof(data));
PacketResponseNG resp; send_request_service(flags, datalen, data);
if (custom_IDm) { datalen -= 2; // Remove CRC bytes before adding new ones
waitCmdFelica(1, &resp);
}
if (datalen > 0) {
if(!waitCmdFelica(0, &resp)){
return PM3_ESOFT;
} }
felica_request_service_response_t rqs_response; } else {
memcpy(&rqs_response, (felica_request_service_response_t *)resp.data.asBytes, sizeof(felica_request_service_response_t)); add_crc_bytes(&datalen, data, sizeof(data));
send_request_service(flags, datalen, data);
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; return PM3_SUCCESS;
} }

View file

@ -15,4 +15,5 @@
int CmdHFFelica(const char *Cmd); int CmdHFFelica(const char *Cmd);
int readFelicaUid(bool verbose); int readFelicaUid(bool verbose);
void send_request_service(uint8_t flags, uint16_t datalen, uint8_t *data);
#endif #endif

View file

@ -170,7 +170,7 @@ typedef struct {
} PACKED felica_card_select_t; } PACKED felica_card_select_t;
typedef struct { typedef struct {
uint8_t sync[4]; uint8_t sync[2];
uint8_t length[1]; uint8_t length[1];
uint8_t cmd_code[1]; uint8_t cmd_code[1];
uint8_t IDm[8]; uint8_t IDm[8];