mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2024-09-25 09:46:13 +08:00
commit
f8bedb8e01
|
@ -18,7 +18,5 @@ void felica_sendraw(PacketCommandNG *c);
|
||||||
void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip);
|
void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip);
|
||||||
void felica_sim_lite(uint64_t uid);
|
void felica_sim_lite(uint64_t uid);
|
||||||
void felica_dump_lite_s();
|
void felica_dump_lite_s();
|
||||||
void felica_create_read_block_frame(uint16_t blockNr);
|
|
||||||
void felica_send_request_service(uint8_t *request_service);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -147,15 +147,15 @@ static bool waitCmd14b(bool verbose) {
|
||||||
if (len >= 3) {
|
if (len >= 3) {
|
||||||
bool crc = check_crc(CRC_14443_B, data, len);
|
bool crc = check_crc(CRC_14443_B, data, len);
|
||||||
|
|
||||||
PrintAndLogEx(NORMAL, "[LEN %u] %s[%02X %02X] %s",
|
PrintAndLogEx(SUCCESS, "[LEN %u] %s[%02X %02X] %s",
|
||||||
len,
|
len,
|
||||||
sprint_hex(data, len - 2),
|
sprint_hex(data, len - 2),
|
||||||
data[len - 2],
|
data[len - 2],
|
||||||
data[len - 1],
|
data[len - 1],
|
||||||
(crc) ? "OK" : "FAIL"
|
(crc) ? _GREEN_("OK") : _RED_("FAIL")
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
PrintAndLogEx(NORMAL, "[LEN %u] %s", len, sprint_hex(data, len));
|
PrintAndLogEx(SUCCESS, "[LEN %u] %s", len, sprint_hex(data, len));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -182,7 +182,7 @@ static int CmdHF14BSim(const char *Cmd) {
|
||||||
|
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommandMIX(CMD_HF_ISO14443B_SIMULATE, pupi, 0, 0, NULL, 0);
|
SendCommandMIX(CMD_HF_ISO14443B_SIMULATE, pupi, 0, 0, NULL, 0);
|
||||||
return 0;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int CmdHF14BSniff(const char *Cmd) {
|
static int CmdHF14BSniff(const char *Cmd) {
|
||||||
|
@ -192,7 +192,7 @@ static int CmdHF14BSniff(const char *Cmd) {
|
||||||
|
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommandNG(CMD_HF_ISO14443B_SNIFF, NULL, 0);
|
SendCommandNG(CMD_HF_ISO14443B_SNIFF, NULL, 0);
|
||||||
return 0;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int CmdHF14BCmdRaw(const char *Cmd) {
|
static int CmdHF14BCmdRaw(const char *Cmd) {
|
||||||
|
@ -262,15 +262,16 @@ static int CmdHF14BCmdRaw(const char *Cmd) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
PrintAndLogEx(WARNING, "unknown parameter '%c'\n", param_getchar(Cmd, i));
|
PrintAndLogEx(WARNING, "unknown parameter '%c'\n", param_getchar(Cmd, i));
|
||||||
return 0;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasTimeout) {
|
if (hasTimeout) {
|
||||||
#define MAX_TIMEOUT 40542464 // = (2^32-1) * (8*16) / 13560000Hz * 1000ms/s
|
|
||||||
|
#define MAX_14B_TIMEOUT 40542464 // = (2^32-1) * (8*16) / 13560000Hz * 1000ms/s
|
||||||
flags |= ISO14B_SET_TIMEOUT;
|
flags |= ISO14B_SET_TIMEOUT;
|
||||||
if (user_timeout > MAX_TIMEOUT) {
|
if (user_timeout > MAX_14B_TIMEOUT) {
|
||||||
user_timeout = MAX_TIMEOUT;
|
user_timeout = MAX_14B_TIMEOUT;
|
||||||
PrintAndLogEx(NORMAL, "Set timeout to 40542 seconds (11.26 hours). The max we can wait for response");
|
PrintAndLogEx(INFO, "Set timeout to 40542 seconds (11.26 hours). The max we can wait for response");
|
||||||
}
|
}
|
||||||
time_wait = 13560000 / 1000 / (8 * 16) * user_timeout; // timeout in ETUs (time to transfer 1 bit, approx. 9.4 us)
|
time_wait = 13560000 / 1000 / (8 * 16) * user_timeout; // timeout in ETUs (time to transfer 1 bit, approx. 9.4 us)
|
||||||
}
|
}
|
||||||
|
@ -287,7 +288,7 @@ static int CmdHF14BCmdRaw(const char *Cmd) {
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommandOLD(CMD_HF_ISO14443B_COMMAND, flags, datalen, time_wait, data, datalen);
|
SendCommandOLD(CMD_HF_ISO14443B_COMMAND, flags, datalen, time_wait, data, datalen);
|
||||||
|
|
||||||
if (!reply) return 1;
|
if (!reply) return PM3_SUCCESS;
|
||||||
|
|
||||||
bool success = true;
|
bool success = true;
|
||||||
// get back iso14b_card_select_t, don't print it.
|
// get back iso14b_card_select_t, don't print it.
|
||||||
|
@ -297,7 +298,7 @@ static int CmdHF14BCmdRaw(const char *Cmd) {
|
||||||
// get back response from the raw bytes you sent.
|
// get back response from the raw bytes you sent.
|
||||||
if (success && datalen > 0) waitCmd14b(true);
|
if (success && datalen > 0) waitCmd14b(true);
|
||||||
|
|
||||||
return 1;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool get_14b_UID(iso14b_card_select_t *card) {
|
static bool get_14b_UID(iso14b_card_select_t *card) {
|
||||||
|
@ -484,7 +485,6 @@ static void print_st_general_info(uint8_t *data, uint8_t len) {
|
||||||
PrintAndLogEx(NORMAL, " UID: %s", sprint_hex(SwapEndian64(data, 8, 8), len));
|
PrintAndLogEx(NORMAL, " UID: %s", sprint_hex(SwapEndian64(data, 8, 8), len));
|
||||||
PrintAndLogEx(NORMAL, " MFG: %02X, %s", data[6], getTagInfo(data[6]));
|
PrintAndLogEx(NORMAL, " MFG: %02X, %s", data[6], getTagInfo(data[6]));
|
||||||
PrintAndLogEx(NORMAL, "Chip: %02X, %s", data[5] >> 2, get_ST_Chip_Model(data[5] >> 2));
|
PrintAndLogEx(NORMAL, "Chip: %02X, %s", data[5] >> 2, get_ST_Chip_Model(data[5] >> 2));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//05 00 00 = find one tag in field
|
//05 00 00 = find one tag in field
|
||||||
|
@ -793,18 +793,18 @@ static int CmdHF14BWriteSri(const char *Cmd) {
|
||||||
if (isSrix4k) {
|
if (isSrix4k) {
|
||||||
if (blockno > 0x7f && blockno != 0xff) {
|
if (blockno > 0x7f && blockno != 0xff) {
|
||||||
PrintAndLogEx(FAILED, "block number out of range");
|
PrintAndLogEx(FAILED, "block number out of range");
|
||||||
return 0;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (blockno > 0x0f && blockno != 0xff) {
|
if (blockno > 0x0f && blockno != 0xff) {
|
||||||
PrintAndLogEx(FAILED, "block number out of range");
|
PrintAndLogEx(FAILED, "block number out of range");
|
||||||
return 0;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (param_gethex(Cmd, 2, data, 8)) {
|
if (param_gethex(Cmd, 2, data, 8)) {
|
||||||
PrintAndLogEx(WARNING, "data must include 8 HEX symbols");
|
PrintAndLogEx(WARNING, "data must include 8 HEX symbols");
|
||||||
return 0;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (blockno == 0xff) {
|
if (blockno == 0xff) {
|
||||||
|
@ -822,8 +822,7 @@ static int CmdHF14BWriteSri(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
sprintf(str, "-ss -c %02x %02x %02x %02x %02x %02x", ISO14443B_WRITE_BLK, blockno, data[0], data[1], data[2], data[3]);
|
sprintf(str, "-ss -c %02x %02x %02x %02x %02x %02x", ISO14443B_WRITE_BLK, blockno, data[0], data[1], data[2], data[3]);
|
||||||
CmdHF14BCmdRaw(str);
|
return CmdHF14BCmdRaw(str);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// need to write to file
|
// need to write to file
|
||||||
|
@ -875,7 +874,7 @@ static int CmdHF14BDump(const char *Cmd) {
|
||||||
|
|
||||||
if (!get_14b_UID(&card)) {
|
if (!get_14b_UID(&card)) {
|
||||||
PrintAndLogEx(WARNING, "No tag found.");
|
PrintAndLogEx(WARNING, "No tag found.");
|
||||||
return 1;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fileNameLen < 1) {
|
if (fileNameLen < 1) {
|
||||||
|
@ -1102,7 +1101,7 @@ static command_t CommandTable[] = {
|
||||||
static int CmdHelp(const char *Cmd) {
|
static int CmdHelp(const char *Cmd) {
|
||||||
(void)Cmd; // Cmd is not used so far
|
(void)Cmd; // Cmd is not used so far
|
||||||
CmdsHelp(CommandTable);
|
CmdsHelp(CommandTable);
|
||||||
return 0;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CmdHF14B(const char *Cmd) {
|
int CmdHF14B(const char *Cmd) {
|
||||||
|
|
|
@ -112,6 +112,7 @@ static int usage_hf_felica_request_response(void) {
|
||||||
PrintAndLogEx(NORMAL, "\nUsage: hf felica rqresponse [-h]");
|
PrintAndLogEx(NORMAL, "\nUsage: hf felica rqresponse [-h]");
|
||||||
PrintAndLogEx(NORMAL, " -h this help");
|
PrintAndLogEx(NORMAL, " -h this help");
|
||||||
PrintAndLogEx(NORMAL, " -i <0A0B0C ... hex> set custom IDm to use");
|
PrintAndLogEx(NORMAL, " -i <0A0B0C ... hex> set custom IDm to use");
|
||||||
|
PrintAndLogEx(NORMAL, " hf felica rqresponse -i 01100910c11bc407");
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,15 +160,7 @@ static void print_status_flag2_interpration() {
|
||||||
PrintAndLogEx(NORMAL, " - C2h : Command is disabled already: 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() {
|
static void print_block_list_element_constraints() {
|
||||||
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. 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, " - 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, " - The value of Service Code List Order shall not exceed Number of Service.");
|
||||||
PrintAndLogEx(NORMAL, " - Access Mode shall be 000b.");
|
PrintAndLogEx(NORMAL, " - Access Mode shall be 000b.");
|
||||||
|
@ -175,6 +168,30 @@ static int usage_hf_felica_read_without_encryption() {
|
||||||
PrintAndLogEx(NORMAL, " - Service specified in Service Code List shall exist in 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, " - 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, " - Block Number shall be in the range of the number of Blocks assigned to the specified Service.");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_number_of_service_constraints() {
|
||||||
|
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() {
|
||||||
|
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() {
|
||||||
|
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() {
|
||||||
|
PrintAndLogEx(NORMAL, "\nInfo: Use this command to read Block Data from authentication-not-required Service.");
|
||||||
|
PrintAndLogEx(NORMAL, " - Mode shall be Mode0.");
|
||||||
|
print_number_of_service_constraints();
|
||||||
|
print_number_of_block_constraints();
|
||||||
|
print_service_code_list_constraints();
|
||||||
|
print_block_list_element_constraints();
|
||||||
PrintAndLogEx(NORMAL, " - Successful read: Card responses the block data");
|
PrintAndLogEx(NORMAL, " - Successful read: Card responses the block data");
|
||||||
PrintAndLogEx(NORMAL, " - Unsuccessful read: Card responses with Status Flag1 and Flag2");
|
PrintAndLogEx(NORMAL, " - Unsuccessful read: Card responses with Status Flag1 and Flag2");
|
||||||
print_status_flag1_interpretation();
|
print_status_flag1_interpretation();
|
||||||
|
@ -187,7 +204,27 @@ static int usage_hf_felica_read_without_encryption() {
|
||||||
PrintAndLogEx(NORMAL, "\nExamples: ");
|
PrintAndLogEx(NORMAL, "\nExamples: ");
|
||||||
PrintAndLogEx(NORMAL, " hf felica rdunencrypted 01 8B00 01 8000");
|
PrintAndLogEx(NORMAL, " hf felica rdunencrypted 01 8B00 01 8000");
|
||||||
PrintAndLogEx(NORMAL, " hf felica rdunencrypted -i 01100910c11bc407 01 8B00 01 8000");
|
PrintAndLogEx(NORMAL, " hf felica rdunencrypted -i 01100910c11bc407 01 8B00 01 8000");
|
||||||
PrintAndLogEx(NORMAL, " hf felica rdunencrypted -b 01 8B00 01 8000\n\n");
|
PrintAndLogEx(NORMAL, " hf felica rdunencrypted -b 01 4B18 01 8000\n\n");
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usage_hf_felica_write_without_encryption() {
|
||||||
|
PrintAndLogEx(NORMAL, "\nInfo: Use this command to write Block Data to authentication-not-required Service.");
|
||||||
|
PrintAndLogEx(NORMAL, " - Mode shall be Mode0.");
|
||||||
|
print_number_of_service_constraints();
|
||||||
|
print_number_of_block_constraints();
|
||||||
|
print_service_code_list_constraints();
|
||||||
|
print_block_list_element_constraints();
|
||||||
|
PrintAndLogEx(NORMAL, " - Un-/Successful read: Card responses with Status Flag1 and Flag2");
|
||||||
|
print_status_flag1_interpretation();
|
||||||
|
print_status_flag2_interpration();
|
||||||
|
PrintAndLogEx(NORMAL, "\nUsage: hf felica wrunencrypted [-h] <01 Number of Service hex> <0A0B Service Code List (Little Endian) hex> <01 Number of Block hex> <0A0B Block List Element hex> <0A0B0C0D0E0F... Data hex (16-Byte)>");
|
||||||
|
PrintAndLogEx(NORMAL, " -h this help");
|
||||||
|
PrintAndLogEx(NORMAL, " -i <0A0B0C ... hex> set custom IDm to use\n");
|
||||||
|
PrintAndLogEx(NORMAL, " hf felica wrunencrypted 01 CB10 01 8001 0102030405060708090A0B0C0D0E0F10\n\n");
|
||||||
|
|
||||||
|
PrintAndLogEx(NORMAL, "\nExamples: ");
|
||||||
|
PrintAndLogEx(NORMAL, " hf felica wrunencrypted ");
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,6 +245,10 @@ static bool waitCmdFelica(uint8_t iSelect, PacketResponseNG *resp, bool verbose)
|
||||||
if (!check_crc(CRC_FELICA, resp->data.asBytes + 2, len - 2)) {
|
if (!check_crc(CRC_FELICA, resp->data.asBytes + 2, len - 2)) {
|
||||||
PrintAndLogEx(WARNING, "Wrong or no CRC bytes");
|
PrintAndLogEx(WARNING, "Wrong or no CRC bytes");
|
||||||
}
|
}
|
||||||
|
if (resp->data.asBytes[0] != 0xB2 && resp->data.asBytes[1] != 0x4D) {
|
||||||
|
PrintAndLogEx(ERR, "Received incorrect Frame Format!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
|
@ -294,7 +335,8 @@ static bool add_param(const char *Cmd, uint8_t paramCount, uint8_t *data, uint8_
|
||||||
param_gethex(Cmd, paramCount, data + dataPosition, length);
|
param_gethex(Cmd, paramCount, data + dataPosition, length);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
PrintAndLogEx(ERR, "Incorrect Parameter length! Param %i", paramCount);
|
PrintAndLogEx(ERR, "Param %s", Cmd);
|
||||||
|
PrintAndLogEx(ERR, "Incorrect Parameter length! Param %i should be %i", paramCount, length);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -304,7 +346,7 @@ static bool add_param(const char *Cmd, uint8_t paramCount, uint8_t *data, uint8_
|
||||||
* @param rd_noCry_resp Response frame.
|
* @param rd_noCry_resp Response frame.
|
||||||
*/
|
*/
|
||||||
static void print_rd_noEncrpytion_response(felica_read_without_encryption_response_t *rd_noCry_resp) {
|
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) {
|
if (rd_noCry_resp->status_flags.status_flag1[0] == 00 && rd_noCry_resp->status_flags.status_flag2[0] == 00) {
|
||||||
char *temp = sprint_hex(rd_noCry_resp->block_data, sizeof(rd_noCry_resp->block_data));
|
char *temp = sprint_hex(rd_noCry_resp->block_data, sizeof(rd_noCry_resp->block_data));
|
||||||
char bl_data[256];
|
char bl_data[256];
|
||||||
strcpy(bl_data, temp);
|
strcpy(bl_data, temp);
|
||||||
|
@ -314,9 +356,9 @@ static void print_rd_noEncrpytion_response(felica_read_without_encryption_respon
|
||||||
strcpy(bl_element_number, temp);
|
strcpy(bl_element_number, temp);
|
||||||
PrintAndLogEx(NORMAL, "\t%s\t| %s ", bl_element_number, bl_data);
|
PrintAndLogEx(NORMAL, "\t%s\t| %s ", bl_element_number, bl_data);
|
||||||
} else {
|
} else {
|
||||||
PrintAndLogEx(NORMAL, "IDm: %s", sprint_hex(rd_noCry_resp->IDm, sizeof(rd_noCry_resp->IDm)));
|
PrintAndLogEx(NORMAL, "IDm: %s", sprint_hex(rd_noCry_resp->frame_response.IDm, sizeof(rd_noCry_resp->frame_response.IDm)));
|
||||||
PrintAndLogEx(NORMAL, "Status Flag1: %s", sprint_hex(rd_noCry_resp->status_flag1, sizeof(rd_noCry_resp->status_flag1)));
|
PrintAndLogEx(NORMAL, "Status Flag1: %s", sprint_hex(rd_noCry_resp->status_flags.status_flag1, sizeof(rd_noCry_resp->status_flags.status_flag1)));
|
||||||
PrintAndLogEx(NORMAL, "Status Flag2: %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_flags.status_flag1, sizeof(rd_noCry_resp->status_flags.status_flag1)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,9 +376,9 @@ int send_request_service(uint8_t flags, uint16_t datalen, uint8_t *data, bool ve
|
||||||
felica_request_service_response_t rqs_response;
|
felica_request_service_response_t rqs_response;
|
||||||
memcpy(&rqs_response, (felica_request_service_response_t *)resp.data.asBytes, sizeof(felica_request_service_response_t));
|
memcpy(&rqs_response, (felica_request_service_response_t *)resp.data.asBytes, sizeof(felica_request_service_response_t));
|
||||||
|
|
||||||
if (rqs_response.IDm[0] != 0) {
|
if (rqs_response.frame_response.IDm[0] != 0) {
|
||||||
PrintAndLogEx(SUCCESS, "\nGot Service Response:");
|
PrintAndLogEx(SUCCESS, "\nGot Service Response:");
|
||||||
PrintAndLogEx(NORMAL, "IDm: %s", sprint_hex(rqs_response.IDm, sizeof(rqs_response.IDm)));
|
PrintAndLogEx(NORMAL, "IDm: %s", sprint_hex(rqs_response.frame_response.IDm, sizeof(rqs_response.frame_response.IDm)));
|
||||||
PrintAndLogEx(NORMAL, " -Node Number: %s", sprint_hex(rqs_response.node_number, sizeof(rqs_response.node_number)));
|
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)));
|
PrintAndLogEx(NORMAL, " -Node Key Version List: %s\n", sprint_hex(rqs_response.node_key_versions, sizeof(rqs_response.node_key_versions)));
|
||||||
}
|
}
|
||||||
|
@ -351,7 +393,7 @@ int send_request_service(uint8_t flags, uint16_t datalen, uint8_t *data, bool ve
|
||||||
* @param datalen frame length.
|
* @param datalen frame length.
|
||||||
* @param data frame to be send.
|
* @param data frame to be send.
|
||||||
* @param verbose display additional output.
|
* @param verbose display additional output.
|
||||||
* @param rd_noCry_resp frame in which the response will be saved
|
* @param rd_noCry_resp frame in which the response will be saved.
|
||||||
* @return success if response was received.
|
* @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) {
|
||||||
|
@ -367,6 +409,110 @@ int send_rd_unencrypted(uint8_t flags, uint16_t datalen, uint8_t *data, bool ver
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if last known card can be added to data and adds it if possible.
|
||||||
|
* @param custom_IDm
|
||||||
|
* @param data
|
||||||
|
* @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;
|
||||||
|
} else {
|
||||||
|
PrintAndLogEx(INFO, "Used last known IDm.", sprint_hex(data, datalen));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 wr_noCry_resp frame in which the response will be saved.
|
||||||
|
* @return success if response was received.
|
||||||
|
*/
|
||||||
|
int send_wr_unencrypted(uint8_t flags, uint16_t datalen, uint8_t *data, bool verbose, felica_status_response_t *wr_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(wr_noCry_resp, (felica_status_response_t *)resp.data.asBytes, sizeof(felica_status_response_t));
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command parser for wrunencrypted.
|
||||||
|
* @param Cmd input data of the user.
|
||||||
|
* @return client result code.
|
||||||
|
*/
|
||||||
|
static int CmdHFFelicaWriteWithoutEncryption(const char *Cmd) {
|
||||||
|
if (strlen(Cmd) < 5)
|
||||||
|
return usage_hf_felica_write_without_encryption();
|
||||||
|
uint8_t data[PM3_CMD_DATA_SIZE];
|
||||||
|
bool custom_IDm = false;
|
||||||
|
strip_cmds(Cmd);
|
||||||
|
uint16_t datalen = 32; // Length (1), Command ID (1), IDm (8), Number of Service (1), Service Code List(2), Number of Block(1), Block List(3), Block Data(16)
|
||||||
|
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 (!add_param(Cmd, paramCount, data, 2, 16)) {
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
|
paramCount++;
|
||||||
|
i += 16;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
data[0] = 0x20; // Static length
|
||||||
|
data[1] = 0x08; // Command ID
|
||||||
|
if (!custom_IDm && !check_last_idm(data, datalen)) {
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
|
// Number of Service 2, Service Code List 4, Number of Block 2, Block List Element 4, Data 16
|
||||||
|
uint8_t lengths[] = {2, 4, 2, 4, 32};
|
||||||
|
uint8_t dataPositions[] = {10, 11, 13, 14, 16};
|
||||||
|
for (int i = 0; i < 5; i++) {
|
||||||
|
if (add_param(Cmd, paramCount, data, dataPositions[i], lengths[i])) {
|
||||||
|
paramCount++;
|
||||||
|
} else {
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
flags |= FELICA_APPEND_CRC;
|
||||||
|
flags |= FELICA_RAW;
|
||||||
|
AddCrc(data, datalen);
|
||||||
|
datalen += 2;
|
||||||
|
felica_status_response_t wr_noCry_resp;
|
||||||
|
if (send_wr_unencrypted(flags, datalen, data, 1, &wr_noCry_resp) == PM3_SUCCESS) {
|
||||||
|
PrintAndLogEx(NORMAL, "\nIDm: %s", sprint_hex(wr_noCry_resp.frame_response.IDm, sizeof(wr_noCry_resp.frame_response.IDm)));
|
||||||
|
PrintAndLogEx(NORMAL, "Status Flag1: %s", sprint_hex(wr_noCry_resp.status_flags.status_flag1, sizeof(wr_noCry_resp.status_flags.status_flag1)));
|
||||||
|
PrintAndLogEx(NORMAL, "Status Flag2: %s\n", sprint_hex(wr_noCry_resp.status_flags.status_flag2, sizeof(wr_noCry_resp.status_flags.status_flag2)));
|
||||||
|
if (wr_noCry_resp.status_flags.status_flag1[0] == 0x00 && wr_noCry_resp.status_flags.status_flag2[0] == 0x00) {
|
||||||
|
PrintAndLogEx(SUCCESS, "Writing data successful!\n");
|
||||||
|
} else {
|
||||||
|
PrintAndLogEx(ERR, "Something went wrong! Check status flags.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Command parser for rdunencrypted.
|
* Command parser for rdunencrypted.
|
||||||
* @param Cmd input data of the user.
|
* @param Cmd input data of the user.
|
||||||
|
@ -393,9 +539,11 @@ static int CmdHFFelicaReadWithoutEncryption(const char *Cmd) {
|
||||||
case 'i':
|
case 'i':
|
||||||
paramCount++;
|
paramCount++;
|
||||||
custom_IDm = true;
|
custom_IDm = true;
|
||||||
if (!add_param(Cmd, paramCount, data, 3, 8)) {
|
if (!add_param(Cmd, paramCount, data, 2, 16)) {
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
paramCount++;
|
||||||
|
i += 16;
|
||||||
break;
|
break;
|
||||||
case 'b':
|
case 'b':
|
||||||
paramCount++;
|
paramCount++;
|
||||||
|
@ -411,13 +559,8 @@ static int CmdHFFelicaReadWithoutEncryption(const char *Cmd) {
|
||||||
}
|
}
|
||||||
data[0] = 0x10; // Static length
|
data[0] = 0x10; // Static length
|
||||||
data[1] = 0x06; // Command ID
|
data[1] = 0x06; // Command ID
|
||||||
if (!custom_IDm) {
|
if (!custom_IDm && !check_last_idm(data, datalen)) {
|
||||||
if (!add_last_IDm(2, data)) {
|
|
||||||
PrintAndLogEx(ERR, "No last known card! Use reader first or set a custom IDm!");
|
|
||||||
return PM3_EINVARG;
|
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
|
// 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 lengths[] = {2, 4, 2, 4};
|
||||||
|
@ -448,7 +591,7 @@ static int CmdHFFelicaReadWithoutEncryption(const char *Cmd) {
|
||||||
datalen += 2;
|
datalen += 2;
|
||||||
felica_read_without_encryption_response_t rd_noCry_resp;
|
felica_read_without_encryption_response_t rd_noCry_resp;
|
||||||
if ((send_rd_unencrypted(flags, datalen, data, 0, &rd_noCry_resp) == PM3_SUCCESS)) {
|
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 (rd_noCry_resp.status_flags.status_flag1[0] == 00 && rd_noCry_resp.status_flags.status_flag2[0] == 00) {
|
||||||
print_rd_noEncrpytion_response(&rd_noCry_resp);
|
print_rd_noEncrpytion_response(&rd_noCry_resp);
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
|
@ -462,10 +605,11 @@ static int CmdHFFelicaReadWithoutEncryption(const char *Cmd) {
|
||||||
AddCrc(data, datalen);
|
AddCrc(data, datalen);
|
||||||
datalen += 2;
|
datalen += 2;
|
||||||
felica_read_without_encryption_response_t rd_noCry_resp;
|
felica_read_without_encryption_response_t rd_noCry_resp;
|
||||||
send_rd_unencrypted(flags, datalen, data, 1, &rd_noCry_resp);
|
if (send_rd_unencrypted(flags, datalen, data, 1, &rd_noCry_resp) == PM3_SUCCESS) {
|
||||||
PrintAndLogEx(NORMAL, "Block Element\t| Data ");
|
PrintAndLogEx(NORMAL, "Block Element\t| Data ");
|
||||||
print_rd_noEncrpytion_response(&rd_noCry_resp);
|
print_rd_noEncrpytion_response(&rd_noCry_resp);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -491,12 +635,11 @@ static int CmdHFFelicaRequestResponse(const char *Cmd) {
|
||||||
case 'i':
|
case 'i':
|
||||||
paramCount++;
|
paramCount++;
|
||||||
custom_IDm = true;
|
custom_IDm = true;
|
||||||
if (param_getlength(Cmd, paramCount) == 16) {
|
if (!add_param(Cmd, paramCount, data, 2, 16)) {
|
||||||
param_gethex(Cmd, paramCount++, data + 2, 16);
|
|
||||||
} else {
|
|
||||||
PrintAndLogEx(ERR, "Incorrect IDm length! IDm must be 8-Byte.");
|
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
paramCount++;
|
||||||
|
i += 16;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -504,13 +647,8 @@ static int CmdHFFelicaRequestResponse(const char *Cmd) {
|
||||||
}
|
}
|
||||||
data[0] = 0x0A; // Static length
|
data[0] = 0x0A; // Static length
|
||||||
data[1] = 0x04; // Command ID
|
data[1] = 0x04; // Command ID
|
||||||
if (!custom_IDm) {
|
if (!custom_IDm && !check_last_idm(data, datalen)) {
|
||||||
if (!add_last_IDm(2, data)) {
|
|
||||||
PrintAndLogEx(ERR, "No last known card! Use reader first or set a custom IDm!");
|
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
} else {
|
|
||||||
PrintAndLogEx(INFO, "Used last known IDm.", sprint_hex(data, datalen));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
AddCrc(data, datalen);
|
AddCrc(data, datalen);
|
||||||
datalen += 2;
|
datalen += 2;
|
||||||
|
@ -524,9 +662,9 @@ static int CmdHFFelicaRequestResponse(const char *Cmd) {
|
||||||
} else {
|
} else {
|
||||||
felica_request_request_response_t rq_response;
|
felica_request_request_response_t rq_response;
|
||||||
memcpy(&rq_response, (felica_request_request_response_t *)resp.data.asBytes, sizeof(felica_request_request_response_t));
|
memcpy(&rq_response, (felica_request_request_response_t *)resp.data.asBytes, sizeof(felica_request_request_response_t));
|
||||||
if (rq_response.IDm[0] != 0) {
|
if (rq_response.frame_response.IDm[0] != 0) {
|
||||||
PrintAndLogEx(SUCCESS, "\nGot Request Response:");
|
PrintAndLogEx(SUCCESS, "\nGot Request Response:");
|
||||||
PrintAndLogEx(NORMAL, "IDm: %s", sprint_hex(rq_response.IDm, sizeof(rq_response.IDm)));
|
PrintAndLogEx(NORMAL, "IDm: %s", sprint_hex(rq_response.frame_response.IDm, sizeof(rq_response.frame_response.IDm)));
|
||||||
PrintAndLogEx(NORMAL, " -Mode: %s\n\n", sprint_hex(rq_response.mode, sizeof(rq_response.mode)));
|
PrintAndLogEx(NORMAL, " -Mode: %s\n\n", sprint_hex(rq_response.mode, sizeof(rq_response.mode)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -558,13 +696,11 @@ static int CmdHFFelicaRequestService(const char *Cmd) {
|
||||||
case 'i':
|
case 'i':
|
||||||
paramCount++;
|
paramCount++;
|
||||||
custom_IDm = true;
|
custom_IDm = true;
|
||||||
if (param_getlength(Cmd, paramCount) == 16) {
|
if (!add_param(Cmd, paramCount, data, 2, 16)) {
|
||||||
param_gethex(Cmd, paramCount++, data + 2, 16);
|
|
||||||
} else {
|
|
||||||
PrintAndLogEx(ERR, "Incorrect IDm length! IDm must be 8-Byte.");
|
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
i += 8;
|
paramCount++;
|
||||||
|
i += 16;
|
||||||
break;
|
break;
|
||||||
case 'a':
|
case 'a':
|
||||||
paramCount++;
|
paramCount++;
|
||||||
|
@ -603,13 +739,8 @@ 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 && !check_last_idm(data, datalen)) {
|
||||||
if (!add_last_IDm(2, data)) {
|
|
||||||
PrintAndLogEx(ERR, "No last known card! Use reader first or set a custom IDm!");
|
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
} else {
|
|
||||||
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; // Service Request Command ID
|
data[1] = 0x02; // Service Request Command ID
|
||||||
|
@ -1144,8 +1275,8 @@ static command_t CommandTable[] = {
|
||||||
{"rqservice", CmdHFFelicaRequestService, IfPm3Felica, "verify the existence of Area and Service, and to acquire Key Version."},
|
{"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."},
|
{"rqresponse", CmdHFFelicaRequestResponse, IfPm3Felica, "verify the existence of a card and its Mode."},
|
||||||
{"rdunencrypted", CmdHFFelicaReadWithoutEncryption, IfPm3Felica, "read Block Data from authentication-not-required Service."},
|
{"rdunencrypted", CmdHFFelicaReadWithoutEncryption, IfPm3Felica, "read Block Data from authentication-not-required Service."},
|
||||||
{"wrunencrypted", CmdHFFelicaNotImplementedYet, IfPm3Felica, "write Block Data to an authentication-not-required Service."},
|
{"wrunencrypted", CmdHFFelicaWriteWithoutEncryption, IfPm3Felica, "write Block Data to an authentication-not-required Service."},
|
||||||
//{"scsvcode", CmdHFFelicaNotImplementedYet, IfPm3Felica, "acquire Area Code and Service Code."},
|
{"scsvcode", CmdHFFelicaNotImplementedYet, IfPm3Felica, "acquire Area Code and Service Code."},
|
||||||
//{"rqsyscode", CmdHFFelicaNotImplementedYet, IfPm3Felica, "acquire System Code registered to the card."},
|
//{"rqsyscode", CmdHFFelicaNotImplementedYet, IfPm3Felica, "acquire System Code registered to the card."},
|
||||||
//{"auth1", CmdHFFelicaNotImplementedYet, IfPm3Felica, "authenticate a card."},
|
//{"auth1", CmdHFFelicaNotImplementedYet, IfPm3Felica, "authenticate a card."},
|
||||||
//{"auth2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "allow a card to authenticate a Reader/Writer."},
|
//{"auth2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "allow a card to authenticate a Reader/Writer."},
|
||||||
|
|
|
@ -18,4 +18,5 @@ int CmdHFFelica(const char *Cmd);
|
||||||
int readFelicaUid(bool verbose);
|
int readFelicaUid(bool verbose);
|
||||||
int send_request_service(uint8_t flags, uint16_t datalen, uint8_t *data, bool verbose);
|
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);
|
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
|
#endif
|
||||||
|
|
|
@ -542,7 +542,7 @@ static int CmdPing(const char *Cmd) {
|
||||||
bool error = false;
|
bool error = false;
|
||||||
if (len) {
|
if (len) {
|
||||||
error = memcmp(data, resp.data.asBytes, len) != 0;
|
error = memcmp(data, resp.data.asBytes, len) != 0;
|
||||||
PrintAndLogEx((error) ? ERR : SUCCESS, "Ping response " _GREEN_("received") "and content is %s", error ? _RED_("NOT ok") : _GREEN_("ok"));
|
PrintAndLogEx((error) ? ERR : SUCCESS, "Ping response " _GREEN_("received") "and content is %s", error ? _RED_("NOT ok") : _GREEN_("OK"));
|
||||||
} else {
|
} else {
|
||||||
PrintAndLogEx(SUCCESS, "Ping response " _GREEN_("received"));
|
PrintAndLogEx(SUCCESS, "Ping response " _GREEN_("received"));
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <ctype.h> // tolower
|
||||||
|
|
||||||
#include "cmdparser.h" // command_t
|
#include "cmdparser.h" // command_t
|
||||||
#include "comms.h"
|
#include "comms.h"
|
||||||
|
@ -49,15 +50,14 @@ static int CmdHelp(const char *Cmd);
|
||||||
|
|
||||||
static int usage_lf_fdx_clone(void) {
|
static int usage_lf_fdx_clone(void) {
|
||||||
PrintAndLogEx(NORMAL, "Clone a FDX-B animal tag to a T55x7 tag.");
|
PrintAndLogEx(NORMAL, "Clone a FDX-B animal tag to a T55x7 tag.");
|
||||||
PrintAndLogEx(NORMAL, "Usage: lf fdx clone [h] <country id> <animal id> <Q5>");
|
PrintAndLogEx(NORMAL, "Usage: lf fdx clone [h] <country id> <animal id> <extended> <Q5>");
|
||||||
PrintAndLogEx(NORMAL, "Options:");
|
PrintAndLogEx(NORMAL, "Options:");
|
||||||
PrintAndLogEx(NORMAL, " h : This help");
|
PrintAndLogEx(NORMAL, " h : This help");
|
||||||
PrintAndLogEx(NORMAL, " <country id> : Country id");
|
PrintAndLogEx(NORMAL, " <country id> : Country id");
|
||||||
PrintAndLogEx(NORMAL, " <animal id> : Animal id");
|
PrintAndLogEx(NORMAL, " <animal id> : Animal id");
|
||||||
// has extended data?
|
PrintAndLogEx(NORMAL, " <extended> : Extended data");
|
||||||
//reserved/rfu
|
//reserved/rfu
|
||||||
//is animal tag
|
//is animal tag
|
||||||
// extended data
|
|
||||||
PrintAndLogEx(NORMAL, " <Q5> : Specify write to Q5 (t5555 instead of t55x7)");
|
PrintAndLogEx(NORMAL, " <Q5> : Specify write to Q5 (t5555 instead of t55x7)");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
|
@ -69,11 +69,12 @@ static int usage_lf_fdx_sim(void) {
|
||||||
PrintAndLogEx(NORMAL, "Enables simulation of FDX-B animal tag");
|
PrintAndLogEx(NORMAL, "Enables simulation of FDX-B animal tag");
|
||||||
PrintAndLogEx(NORMAL, "Simulation runs until the button is pressed or another USB command is issued.");
|
PrintAndLogEx(NORMAL, "Simulation runs until the button is pressed or another USB command is issued.");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "Usage: lf fdx sim [h] <country id> <animal id>");
|
PrintAndLogEx(NORMAL, "Usage: lf fdx sim [h] <country id> <animal id> <extended>");
|
||||||
PrintAndLogEx(NORMAL, "Options:");
|
PrintAndLogEx(NORMAL, "Options:");
|
||||||
PrintAndLogEx(NORMAL, " h : This help");
|
PrintAndLogEx(NORMAL, " h : This help");
|
||||||
PrintAndLogEx(NORMAL, " <country id> : Country ID");
|
PrintAndLogEx(NORMAL, " <country id> : Country ID");
|
||||||
PrintAndLogEx(NORMAL, " <animal id> : Animal ID");
|
PrintAndLogEx(NORMAL, " <animal id> : Animal ID");
|
||||||
|
PrintAndLogEx(NORMAL, " <extended> : Extended data");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
PrintAndLogEx(NORMAL, " lf fdx sim 999 112233");
|
PrintAndLogEx(NORMAL, " lf fdx sim 999 112233");
|
||||||
|
@ -81,14 +82,14 @@ static int usage_lf_fdx_sim(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// clearing the topbit needed for the preambl detection.
|
// clearing the topbit needed for the preambl detection.
|
||||||
static void verify_values(uint32_t countryid, uint64_t animalid) {
|
static void verify_values(uint64_t *animalid, uint32_t *countryid) {
|
||||||
if ((animalid & 0x3FFFFFFFFF) != animalid) {
|
if ((*animalid & 0x3FFFFFFFFF) != *animalid) {
|
||||||
animalid &= 0x3FFFFFFFFF;
|
*animalid &= 0x3FFFFFFFFF;
|
||||||
PrintAndLogEx(INFO, "Animal ID Truncated to 38bits: %"PRIx64, animalid);
|
PrintAndLogEx(INFO, "Animal ID Truncated to 38bits: %"PRIx64, *animalid);
|
||||||
}
|
}
|
||||||
if ((countryid & 0x3ff) != countryid) {
|
if ((*countryid & 0x3ff) != *countryid) {
|
||||||
countryid &= 0x3ff;
|
*countryid &= 0x3ff;
|
||||||
PrintAndLogEx(INFO, "Country ID Truncated to 10bits: %03d", countryid);
|
PrintAndLogEx(INFO, "Country ID Truncated to 10bits: %03d", *countryid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -226,15 +227,12 @@ static int CmdFdxDemod(const char *Cmd) {
|
||||||
uint8_t dataBlockBit = DemodBuffer[48];
|
uint8_t dataBlockBit = DemodBuffer[48];
|
||||||
uint32_t reservedCode = bytebits_to_byteLSBF(DemodBuffer + 49, 14);
|
uint32_t reservedCode = bytebits_to_byteLSBF(DemodBuffer + 49, 14);
|
||||||
uint8_t animalBit = DemodBuffer[63];
|
uint8_t animalBit = DemodBuffer[63];
|
||||||
uint32_t crc_16 = bytebits_to_byteLSBF(DemodBuffer + 64, 16);
|
uint16_t crc = bytebits_to_byteLSBF(DemodBuffer + 64, 16);
|
||||||
uint32_t extended = bytebits_to_byteLSBF(DemodBuffer + 80, 24);
|
uint32_t extended = bytebits_to_byteLSBF(DemodBuffer + 80, 24);
|
||||||
uint64_t rawid = (uint64_t)(bytebits_to_byte(DemodBuffer, 32)) << 32 | bytebits_to_byte(DemodBuffer + 32, 32);
|
uint64_t rawid = (uint64_t)(bytebits_to_byte(DemodBuffer, 32)) << 32 | bytebits_to_byte(DemodBuffer + 32, 32);
|
||||||
uint8_t raw[8];
|
uint8_t raw[8];
|
||||||
num_to_bytes(rawid, 8, raw);
|
num_to_bytes(rawid, 8, raw);
|
||||||
|
|
||||||
|
|
||||||
uint16_t calcCrc = crc16_kermit(raw, 8);
|
|
||||||
|
|
||||||
PrintAndLogEx(SUCCESS, "\nFDX-B / ISO 11784/5 Animal Tag ID Found: Raw : %s", sprint_hex(raw, 8));
|
PrintAndLogEx(SUCCESS, "\nFDX-B / ISO 11784/5 Animal Tag ID Found: Raw : %s", sprint_hex(raw, 8));
|
||||||
PrintAndLogEx(SUCCESS, "Animal ID %04u-%012" PRIu64, countryCode, NationalCode);
|
PrintAndLogEx(SUCCESS, "Animal ID %04u-%012" PRIu64, countryCode, NationalCode);
|
||||||
PrintAndLogEx(SUCCESS, "National Code %012" PRIu64 " (0x%" PRIx64 ")", NationalCode, NationalCode);
|
PrintAndLogEx(SUCCESS, "National Code %012" PRIu64 " (0x%" PRIx64 ")", NationalCode, NationalCode);
|
||||||
|
@ -242,7 +240,10 @@ static int CmdFdxDemod(const char *Cmd) {
|
||||||
PrintAndLogEx(SUCCESS, "Reserved/RFU %u (0x04%X)", reservedCode, reservedCode);
|
PrintAndLogEx(SUCCESS, "Reserved/RFU %u (0x04%X)", reservedCode, reservedCode);
|
||||||
PrintAndLogEx(SUCCESS, "Animal Tag %s", animalBit ? _YELLOW_("True") : "False");
|
PrintAndLogEx(SUCCESS, "Animal Tag %s", animalBit ? _YELLOW_("True") : "False");
|
||||||
PrintAndLogEx(SUCCESS, "Has extended data %s [0x%X]", dataBlockBit ? _YELLOW_("True") : "False", extended);
|
PrintAndLogEx(SUCCESS, "Has extended data %s [0x%X]", dataBlockBit ? _YELLOW_("True") : "False", extended);
|
||||||
PrintAndLogEx(SUCCESS, "CRC-16 0x%04X - 0x%04X [%s]", crc_16, calcCrc, (calcCrc == crc_16) ? _GREEN_("Ok") : _RED_("Fail"));
|
|
||||||
|
uint8_t c[] = {0, 0};
|
||||||
|
compute_crc(CRC_11784, raw, sizeof(raw), &c[0], &c[1]);
|
||||||
|
PrintAndLogEx(SUCCESS, "CRC-16 0x%04X [ %s] ", crc, (crc == (c[1] << 8 | c[0]) ) ? _GREEN_("OK") : _RED_("Fail"));
|
||||||
|
|
||||||
if (g_debugMode) {
|
if (g_debugMode) {
|
||||||
PrintAndLogEx(DEBUG, "Start marker %d; Size %zu", preambleIndex, size);
|
PrintAndLogEx(DEBUG, "Start marker %d; Size %zu", preambleIndex, size);
|
||||||
|
@ -263,19 +264,21 @@ static int CmdFdxRead(const char *Cmd) {
|
||||||
|
|
||||||
static int CmdFdxClone(const char *Cmd) {
|
static int CmdFdxClone(const char *Cmd) {
|
||||||
|
|
||||||
uint32_t countryid = 0;
|
uint32_t countryid = 0, extended = 0;
|
||||||
uint64_t animalid = 0;
|
uint64_t animalid = 0;
|
||||||
char cmdp = param_getchar(Cmd, 0);
|
|
||||||
if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') return usage_lf_fdx_clone();
|
char cmdp = tolower(param_getchar(Cmd, 0));
|
||||||
|
if (strlen(Cmd) == 0 || cmdp == 'h') return usage_lf_fdx_clone();
|
||||||
|
|
||||||
countryid = param_get32ex(Cmd, 0, 0, 10);
|
countryid = param_get32ex(Cmd, 0, 0, 10);
|
||||||
animalid = param_get64ex(Cmd, 1, 0, 10);
|
animalid = param_get64ex(Cmd, 1, 0, 10);
|
||||||
|
extended = param_get32ex(Cmd, 2, 0, 10);
|
||||||
|
|
||||||
verify_values(countryid, animalid);
|
verify_values(&animalid, &countryid);
|
||||||
|
|
||||||
uint8_t *bits = calloc(128, sizeof(uint8_t));
|
uint8_t *bits = calloc(128, sizeof(uint8_t));
|
||||||
|
|
||||||
if (getFDXBits(animalid, countryid, 1, 0, 0, bits) != PM3_SUCCESS) {
|
if (getFDXBits(animalid, countryid, 1, (extended > 0), extended, bits) != PM3_SUCCESS) {
|
||||||
PrintAndLogEx(ERR, "Error with tag bitstream generation.");
|
PrintAndLogEx(ERR, "Error with tag bitstream generation.");
|
||||||
free(bits);
|
free(bits);
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
|
@ -284,7 +287,7 @@ static int CmdFdxClone(const char *Cmd) {
|
||||||
uint32_t blocks[5] = {T55x7_MODULATION_DIPHASE | T55x7_BITRATE_RF_32 | 4 << T55x7_MAXBLOCK_SHIFT, 0, 0, 0, 0};
|
uint32_t blocks[5] = {T55x7_MODULATION_DIPHASE | T55x7_BITRATE_RF_32 | 4 << T55x7_MAXBLOCK_SHIFT, 0, 0, 0, 0};
|
||||||
|
|
||||||
//Q5
|
//Q5
|
||||||
if (param_getchar(Cmd, 2) == 'Q' || param_getchar(Cmd, 2) == 'q')
|
if (tolower(param_getchar(Cmd, 2)) == 'q')
|
||||||
blocks[0] = T5555_MODULATION_BIPHASE | T5555_INVERT_OUTPUT | T5555_SET_BITRATE(32) | 4 << T5555_MAXBLOCK_SHIFT;
|
blocks[0] = T5555_MODULATION_BIPHASE | T5555_INVERT_OUTPUT | T5555_SET_BITRATE(32) | 4 << T5555_MAXBLOCK_SHIFT;
|
||||||
|
|
||||||
// convert from bit stream to block data
|
// convert from bit stream to block data
|
||||||
|
@ -302,33 +305,41 @@ static int CmdFdxClone(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int CmdFdxSim(const char *Cmd) {
|
static int CmdFdxSim(const char *Cmd) {
|
||||||
uint32_t countryid = 0;
|
uint32_t countryid = 0, extended = 0;
|
||||||
uint64_t animalid = 0;
|
uint64_t animalid = 0;
|
||||||
|
|
||||||
char cmdp = param_getchar(Cmd, 0);
|
char cmdp = tolower(param_getchar(Cmd, 0));
|
||||||
if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') return usage_lf_fdx_sim();
|
if (strlen(Cmd) == 0 || cmdp == 'h') return usage_lf_fdx_sim();
|
||||||
|
|
||||||
countryid = param_get32ex(Cmd, 0, 0, 10);
|
countryid = param_get32ex(Cmd, 0, 0, 10);
|
||||||
animalid = param_get64ex(Cmd, 1, 0, 10);
|
animalid = param_get64ex(Cmd, 1, 0, 10);
|
||||||
|
extended = param_get32ex(Cmd, 2, 0 , 10);
|
||||||
|
|
||||||
verify_values(countryid, animalid);
|
verify_values(&animalid, &countryid);
|
||||||
|
|
||||||
PrintAndLogEx(SUCCESS, "Simulating FDX-B animal ID: %04u-%"PRIu64, countryid, animalid);
|
PrintAndLogEx(SUCCESS, "Simulating FDX-B animal ID: %04u-%"PRIu64, countryid, animalid);
|
||||||
|
|
||||||
uint8_t bs[128];
|
|
||||||
//getFDXBits(uint64_t national_id, uint16_t country, uint8_t isanimal, uint8_t isextended, uint32_t extended, uint8_t *bits)
|
//getFDXBits(uint64_t national_id, uint16_t country, uint8_t isanimal, uint8_t isextended, uint32_t extended, uint8_t *bits)
|
||||||
getFDXBits(animalid, countryid, 1, 0, 0, bs);
|
uint8_t *bits = calloc(128, sizeof(uint8_t));
|
||||||
|
|
||||||
|
if (getFDXBits(animalid, countryid, 1, (extended > 0), extended, bits) != PM3_SUCCESS) {
|
||||||
|
PrintAndLogEx(ERR, "Error with tag bitstream generation.");
|
||||||
|
free(bits);
|
||||||
|
return PM3_ESOFT;
|
||||||
|
}
|
||||||
|
|
||||||
// 32, no STT, BIPHASE INVERTED == diphase
|
// 32, no STT, BIPHASE INVERTED == diphase
|
||||||
lf_asksim_t *payload = calloc(1, sizeof(lf_asksim_t) + sizeof(bs));
|
lf_asksim_t *payload = calloc(1, sizeof(lf_asksim_t) + 128);
|
||||||
payload->encoding = 2;
|
payload->encoding = 2;
|
||||||
payload->invert = 1;
|
payload->invert = 1;
|
||||||
payload->separator = 0;
|
payload->separator = 0;
|
||||||
payload->clock = 32;
|
payload->clock = 32;
|
||||||
memcpy(payload->data, bs, sizeof(bs));
|
memcpy(payload->data, bits, 128);
|
||||||
|
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommandNG(CMD_LF_ASK_SIMULATE, (uint8_t *)payload, sizeof(lf_asksim_t) + sizeof(bs));
|
SendCommandNG(CMD_LF_ASK_SIMULATE, (uint8_t *)payload, sizeof(lf_asksim_t) + 128);
|
||||||
|
|
||||||
|
free(bits);
|
||||||
free(payload);
|
free(payload);
|
||||||
|
|
||||||
PacketResponseNG resp;
|
PacketResponseNG resp;
|
||||||
|
@ -337,6 +348,7 @@ static int CmdFdxSim(const char *Cmd) {
|
||||||
PrintAndLogEx(INFO, "Done");
|
PrintAndLogEx(INFO, "Done");
|
||||||
if (resp.status != PM3_EOPABORTED)
|
if (resp.status != PM3_EOPABORTED)
|
||||||
return resp.status;
|
return resp.status;
|
||||||
|
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -378,7 +390,7 @@ int demodFDX(void) {
|
||||||
return CmdFdxDemod("");
|
return CmdFdxDemod("");
|
||||||
}
|
}
|
||||||
|
|
||||||
int getFDXBits(uint64_t national_id, uint16_t country, uint8_t isanimal, uint8_t isextended, uint32_t extended, uint8_t *bits) {
|
int getFDXBits(uint64_t national_id, uint16_t country, uint8_t is_animal, uint8_t is_extended, uint32_t extended, uint8_t *bits) {
|
||||||
|
|
||||||
// add preamble ten 0x00 and one 0x01
|
// add preamble ten 0x00 and one 0x01
|
||||||
memset(bits, 0x00, 10);
|
memset(bits, 0x00, 10);
|
||||||
|
@ -396,10 +408,10 @@ int getFDXBits(uint64_t national_id, uint16_t country, uint8_t isanimal, uint8_t
|
||||||
num_to_bytebitsLSBF(0x00 >> 7, 7, bits + 74);
|
num_to_bytebitsLSBF(0x00 >> 7, 7, bits + 74);
|
||||||
|
|
||||||
// add animal flag - OK
|
// add animal flag - OK
|
||||||
bits[65] = isanimal;
|
bits[65] = is_animal;
|
||||||
|
|
||||||
// add extended flag - OK
|
// add extended flag - OK
|
||||||
bits[81] = isextended;
|
bits[81] = is_extended;
|
||||||
|
|
||||||
// add national code 40bits - OK
|
// add national code 40bits - OK
|
||||||
num_to_bytebitsLSBF(national_id >> 0, 8, bits + 11);
|
num_to_bytebitsLSBF(national_id >> 0, 8, bits + 11);
|
||||||
|
@ -417,7 +429,8 @@ int getFDXBits(uint64_t national_id, uint16_t country, uint8_t isanimal, uint8_t
|
||||||
for (uint8_t i = 0; i < 8; ++i)
|
for (uint8_t i = 0; i < 8; ++i)
|
||||||
raw[i] = bytebits_to_byte(bits + 11 + i * 9, 8);
|
raw[i] = bytebits_to_byte(bits + 11 + i * 9, 8);
|
||||||
|
|
||||||
uint16_t crc = crc16_kermit(raw, 8);
|
init_table(CRC_11784);
|
||||||
|
uint16_t crc = crc16_fdx(raw, 8);
|
||||||
num_to_bytebitsLSBF(crc >> 0, 8, bits + 83);
|
num_to_bytebitsLSBF(crc >> 0, 8, bits + 83);
|
||||||
num_to_bytebitsLSBF(crc >> 8, 8, bits + 92);
|
num_to_bytebitsLSBF(crc >> 8, 8, bits + 92);
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,8 @@ a0478cc39091
|
||||||
8fd0a4f256e9
|
8fd0a4f256e9
|
||||||
#
|
#
|
||||||
d2ece8b9395e # lib
|
d2ece8b9395e # lib
|
||||||
|
# NSCP default key
|
||||||
|
☻1494E81663D7
|
||||||
#
|
#
|
||||||
# more Keys from mfc_default_keys.lua
|
# more Keys from mfc_default_keys.lua
|
||||||
000000000001
|
000000000001
|
||||||
|
|
|
@ -46,6 +46,9 @@ void init_table(CrcType_t crctype) {
|
||||||
case CRC_KERMIT:
|
case CRC_KERMIT:
|
||||||
generate_table(CRC16_POLY_CCITT, true);
|
generate_table(CRC16_POLY_CCITT, true);
|
||||||
break;
|
break;
|
||||||
|
case CRC_11784:
|
||||||
|
generate_table(CRC16_POLY_CCITT, false);
|
||||||
|
break;
|
||||||
case CRC_NONE:
|
case CRC_NONE:
|
||||||
crc_table_init = false;
|
crc_table_init = false;
|
||||||
current_crc_type = CRC_NONE;
|
current_crc_type = CRC_NONE;
|
||||||
|
@ -185,6 +188,9 @@ void compute_crc(CrcType_t ct, const uint8_t *d, size_t n, uint8_t *first, uint8
|
||||||
case CRC_KERMIT:
|
case CRC_KERMIT:
|
||||||
crc = crc16_kermit(d, n);
|
crc = crc16_kermit(d, n);
|
||||||
break;
|
break;
|
||||||
|
case CRC_11784:
|
||||||
|
crc = crc16_fdx(d, n);
|
||||||
|
break;
|
||||||
case CRC_LEGIC:
|
case CRC_LEGIC:
|
||||||
// TODO
|
// TODO
|
||||||
return;
|
return;
|
||||||
|
@ -215,6 +221,8 @@ uint16_t Crc16ex(CrcType_t ct, const uint8_t *d, size_t n) {
|
||||||
return crc16_ccitt(d, n);
|
return crc16_ccitt(d, n);
|
||||||
case CRC_KERMIT:
|
case CRC_KERMIT:
|
||||||
return crc16_kermit(d, n);
|
return crc16_kermit(d, n);
|
||||||
|
case CRC_11784:
|
||||||
|
return crc16_fdx(d, n);
|
||||||
case CRC_LEGIC:
|
case CRC_LEGIC:
|
||||||
// TODO
|
// TODO
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -257,6 +265,8 @@ bool check_crc(CrcType_t ct, const uint8_t *d, size_t n) {
|
||||||
return (crc16_ccitt(d, n) == 0);
|
return (crc16_ccitt(d, n) == 0);
|
||||||
case CRC_KERMIT:
|
case CRC_KERMIT:
|
||||||
return (crc16_kermit(d, n) == 0);
|
return (crc16_kermit(d, n) == 0);
|
||||||
|
case CRC_11784:
|
||||||
|
return (crc16_fdx(d, n) == 0);
|
||||||
case CRC_LEGIC:
|
case CRC_LEGIC:
|
||||||
// TODO
|
// TODO
|
||||||
return false;
|
return false;
|
||||||
|
@ -272,7 +282,12 @@ uint16_t crc16_ccitt(uint8_t const *d, size_t n) {
|
||||||
return crc16_fast(d, n, 0xffff, false, false);
|
return crc16_fast(d, n, 0xffff, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FDX-B ISO11784/85) uses KERMIT
|
// FDX-B ISO11784/85) uses KERMIT/CCITT
|
||||||
|
// poly 0x xx init=0x000 refin=false refout=true xorout=0x0000 ...
|
||||||
|
uint16_t crc16_fdx(uint8_t const *d, size_t n) {
|
||||||
|
return crc16_fast(d, n, 0x0000, false, true);
|
||||||
|
}
|
||||||
|
|
||||||
// poly=0x1021 init=0x0000 refin=true refout=true xorout=0x0000 name="KERMIT"
|
// poly=0x1021 init=0x0000 refin=true refout=true xorout=0x0000 name="KERMIT"
|
||||||
uint16_t crc16_kermit(uint8_t const *d, size_t n) {
|
uint16_t crc16_kermit(uint8_t const *d, size_t n) {
|
||||||
return crc16_fast(d, n, 0x0000, true, true);
|
return crc16_fast(d, n, 0x0000, true, true);
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
#define CRC16_POLY_CCITT 0x1021
|
#define CRC16_POLY_CCITT 0x1021
|
||||||
|
#define CRC16_POLY_KERMIT 0x8408
|
||||||
#define CRC16_POLY_LEGIC 0xc6c6 //0x6363
|
#define CRC16_POLY_LEGIC 0xc6c6 //0x6363
|
||||||
#define CRC16_POLY_DNP 0x3d65
|
#define CRC16_POLY_DNP 0x3d65
|
||||||
|
|
||||||
|
@ -18,6 +19,7 @@
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
CRC_NONE,
|
CRC_NONE,
|
||||||
|
CRC_11784,
|
||||||
CRC_14443_A,
|
CRC_14443_A,
|
||||||
CRC_14443_B,
|
CRC_14443_B,
|
||||||
CRC_15693,
|
CRC_15693,
|
||||||
|
@ -41,6 +43,9 @@ bool check_crc(CrcType_t ct, const uint8_t *d, size_t n);
|
||||||
uint16_t crc16_ccitt(uint8_t const *d, size_t n);
|
uint16_t crc16_ccitt(uint8_t const *d, size_t n);
|
||||||
|
|
||||||
// Calculate CRC-16/KERMIT (FDX-B ISO11784/85) LF
|
// Calculate CRC-16/KERMIT (FDX-B ISO11784/85) LF
|
||||||
|
uint16_t crc16_fdx(uint8_t const *d, size_t n);
|
||||||
|
|
||||||
|
// Calculate CRC-16/KERMIT
|
||||||
uint16_t crc16_kermit(uint8_t const *d, size_t n);
|
uint16_t crc16_kermit(uint8_t const *d, size_t n);
|
||||||
|
|
||||||
// Calculate CRC-16/XMODEM (FeliCa)
|
// Calculate CRC-16/XMODEM (FeliCa)
|
||||||
|
|
|
@ -58,7 +58,8 @@ git clone https://github.com/RfidResearchGroup/proxmark3.git
|
||||||
|
|
||||||
# Check ModemManager
|
# Check ModemManager
|
||||||
|
|
||||||
**Very important**: make sure ModemManager will not interfer, otherwise it could brick your Proxmark3!
|
### ⚠️ Very important ⚠️
|
||||||
|
make sure ModemManager will not interfer, otherwise it could brick your Proxmark3!
|
||||||
Read carefully [this page about ModemManager](ModemManager-Must-Be-Discarded.md) and follow its instructions.
|
Read carefully [this page about ModemManager](ModemManager-Must-Be-Discarded.md) and follow its instructions.
|
||||||
|
|
||||||
# Check connection
|
# Check connection
|
||||||
|
|
|
@ -174,30 +174,37 @@ typedef struct {
|
||||||
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];
|
||||||
|
} PACKED felica_frame_response_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t status_flag1[1];
|
||||||
|
uint8_t status_flag2[1];
|
||||||
|
} PACKED felica_status_flags_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
felica_frame_response_t frame_response;
|
||||||
uint8_t node_number[1];
|
uint8_t node_number[1];
|
||||||
uint8_t node_key_versions[2];
|
uint8_t node_key_versions[2];
|
||||||
} PACKED felica_request_service_response_t;
|
} PACKED felica_request_service_response_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t sync[2];
|
felica_frame_response_t frame_response;
|
||||||
uint8_t length[1];
|
|
||||||
uint8_t cmd_code[1];
|
|
||||||
uint8_t IDm[8];
|
|
||||||
uint8_t mode[1];
|
uint8_t mode[1];
|
||||||
} PACKED felica_request_request_response_t;
|
} PACKED felica_request_request_response_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t sync[2];
|
felica_frame_response_t frame_response;
|
||||||
uint8_t length[1];
|
felica_status_flags_t status_flags;
|
||||||
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 number_of_block[1];
|
||||||
uint8_t block_data[16];
|
uint8_t block_data[16];
|
||||||
uint8_t block_element_number[1];
|
uint8_t block_element_number[1];
|
||||||
} PACKED felica_read_without_encryption_response_t;
|
} PACKED felica_read_without_encryption_response_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
felica_frame_response_t frame_response;
|
||||||
|
felica_status_flags_t status_flags;
|
||||||
|
} PACKED felica_status_response_t;
|
||||||
|
|
||||||
typedef enum FELICA_COMMAND {
|
typedef enum FELICA_COMMAND {
|
||||||
FELICA_CONNECT = (1 << 0),
|
FELICA_CONNECT = (1 << 0),
|
||||||
FELICA_NO_DISCONNECT = (1 << 1),
|
FELICA_NO_DISCONNECT = (1 << 1),
|
||||||
|
|
Loading…
Reference in a new issue