diff --git a/armsrc/appmain.c b/armsrc/appmain.c index dcb7d63a0..5011c1979 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -1589,10 +1589,10 @@ static void PacketReceived(PacketCommandNG *packet) { BigBuf_free(); } uint16_t offset = MIN(BIGBUF_SIZE - PM3_CMD_DATA_SIZE - 3, payload->offset); - + // need to copy len bytes of data, not PM3_CMD_DATA_SIZE - 3 - offset // ensure len bytes copied wont go past end of bigbuf - uint16_t len = MIN(BIGBUF_SIZE - offset,PM3_CMD_DATA_SIZE - 3); + uint16_t len = MIN(BIGBUF_SIZE - offset, PM3_CMD_DATA_SIZE - 3); uint8_t *mem = BigBuf_get_addr(); memcpy(mem + offset, &payload->data, len); diff --git a/armsrc/felica.h b/armsrc/felica.h index 95e13a588..ef34dc108 100644 --- a/armsrc/felica.h +++ b/armsrc/felica.h @@ -18,7 +18,5 @@ void felica_sendraw(PacketCommandNG *c); void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip); void felica_sim_lite(uint64_t uid); void felica_dump_lite_s(); -void felica_create_read_block_frame(uint16_t blockNr); -void felica_send_request_service(uint8_t *request_service); #endif diff --git a/client/cmdhf14b.c b/client/cmdhf14b.c index 03a5f9b9f..ba8db1f92 100644 --- a/client/cmdhf14b.c +++ b/client/cmdhf14b.c @@ -147,15 +147,15 @@ static bool waitCmd14b(bool verbose) { if (len >= 3) { 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, sprint_hex(data, len - 2), data[len - 2], data[len - 1], - (crc) ? "OK" : "FAIL" + (crc) ? _GREEN_("OK") : _RED_("FAIL") ); } else { - PrintAndLogEx(NORMAL, "[LEN %u] %s", len, sprint_hex(data, len)); + PrintAndLogEx(SUCCESS, "[LEN %u] %s", len, sprint_hex(data, len)); } } return true; @@ -182,7 +182,7 @@ static int CmdHF14BSim(const char *Cmd) { clearCommandBuffer(); SendCommandMIX(CMD_HF_ISO14443B_SIMULATE, pupi, 0, 0, NULL, 0); - return 0; + return PM3_SUCCESS; } static int CmdHF14BSniff(const char *Cmd) { @@ -192,7 +192,7 @@ static int CmdHF14BSniff(const char *Cmd) { clearCommandBuffer(); SendCommandNG(CMD_HF_ISO14443B_SNIFF, NULL, 0); - return 0; + return PM3_SUCCESS; } static int CmdHF14BCmdRaw(const char *Cmd) { @@ -262,15 +262,16 @@ static int CmdHF14BCmdRaw(const char *Cmd) { continue; } PrintAndLogEx(WARNING, "unknown parameter '%c'\n", param_getchar(Cmd, i)); - return 0; + return PM3_EINVARG; } 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; - if (user_timeout > MAX_TIMEOUT) { - user_timeout = MAX_TIMEOUT; - PrintAndLogEx(NORMAL, "Set timeout to 40542 seconds (11.26 hours). The max we can wait for response"); + if (user_timeout > MAX_14B_TIMEOUT) { + user_timeout = MAX_14B_TIMEOUT; + 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) } @@ -287,7 +288,7 @@ static int CmdHF14BCmdRaw(const char *Cmd) { clearCommandBuffer(); SendCommandOLD(CMD_HF_ISO14443B_COMMAND, flags, datalen, time_wait, data, datalen); - if (!reply) return 1; + if (!reply) return PM3_SUCCESS; bool success = true; // 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. if (success && datalen > 0) waitCmd14b(true); - return 1; + return PM3_SUCCESS; } 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, " MFG: %02X, %s", data[6], getTagInfo(data[6])); PrintAndLogEx(NORMAL, "Chip: %02X, %s", data[5] >> 2, get_ST_Chip_Model(data[5] >> 2)); - return; } //05 00 00 = find one tag in field @@ -793,18 +793,18 @@ static int CmdHF14BWriteSri(const char *Cmd) { if (isSrix4k) { if (blockno > 0x7f && blockno != 0xff) { PrintAndLogEx(FAILED, "block number out of range"); - return 0; + return PM3_ESOFT; } } else { if (blockno > 0x0f && blockno != 0xff) { PrintAndLogEx(FAILED, "block number out of range"); - return 0; + return PM3_ESOFT; } } if (param_gethex(Cmd, 2, data, 8)) { PrintAndLogEx(WARNING, "data must include 8 HEX symbols"); - return 0; + return PM3_ESOFT; } 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]); - CmdHF14BCmdRaw(str); - return 0; + return CmdHF14BCmdRaw(str); } // need to write to file @@ -875,7 +874,7 @@ static int CmdHF14BDump(const char *Cmd) { if (!get_14b_UID(&card)) { PrintAndLogEx(WARNING, "No tag found."); - return 1; + return PM3_SUCCESS; } if (fileNameLen < 1) { @@ -1102,7 +1101,7 @@ static command_t CommandTable[] = { static int CmdHelp(const char *Cmd) { (void)Cmd; // Cmd is not used so far CmdsHelp(CommandTable); - return 0; + return PM3_SUCCESS; } int CmdHF14B(const char *Cmd) { diff --git a/client/cmdhffelica.c b/client/cmdhffelica.c index b5a31b666..2afb5f3aa 100644 --- a/client/cmdhffelica.c +++ b/client/cmdhffelica.c @@ -112,6 +112,7 @@ static int usage_hf_felica_request_response(void) { PrintAndLogEx(NORMAL, "\nUsage: hf felica rqresponse [-h]"); PrintAndLogEx(NORMAL, " -h this help"); PrintAndLogEx(NORMAL, " -i <0A0B0C ... hex> set custom IDm to use"); + PrintAndLogEx(NORMAL, " hf felica rqresponse -i 01100910c11bc407"); 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."); } -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."); - 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."); +static void print_block_list_element_constraints() { 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."); @@ -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 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() { + 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, " - Unsuccessful read: Card responses with Status Flag1 and Flag2"); print_status_flag1_interpretation(); @@ -187,7 +204,27 @@ static int usage_hf_felica_read_without_encryption() { PrintAndLogEx(NORMAL, "\nExamples: "); 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 -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; } @@ -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)) { 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; } 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); return true; } 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; } } @@ -304,7 +346,7 @@ static bool add_param(const char *Cmd, uint8_t paramCount, uint8_t *data, uint8_ * @param rd_noCry_resp Response frame. */ 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 bl_data[256]; strcpy(bl_data, temp); @@ -314,9 +356,9 @@ static void print_rd_noEncrpytion_response(felica_read_without_encryption_respon strcpy(bl_element_number, temp); PrintAndLogEx(NORMAL, "\t%s\t| %s ", bl_element_number, bl_data); } else { - PrintAndLogEx(NORMAL, "IDm: %s", sprint_hex(rd_noCry_resp->IDm, sizeof(rd_noCry_resp->IDm))); - PrintAndLogEx(NORMAL, "Status Flag1: %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_flag1, sizeof(rd_noCry_resp->status_flag1))); + 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_flags.status_flag1, sizeof(rd_noCry_resp->status_flags.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; 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(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 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 data frame to be send. * @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. */ 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. * @param Cmd input data of the user. @@ -393,9 +539,11 @@ static int CmdHFFelicaReadWithoutEncryption(const char *Cmd) { case 'i': paramCount++; custom_IDm = true; - if (!add_param(Cmd, paramCount, data, 3, 8)) { + if (!add_param(Cmd, paramCount, data, 2, 16)) { return PM3_EINVARG; } + paramCount++; + i += 16; break; case 'b': paramCount++; @@ -411,13 +559,8 @@ static int CmdHFFelicaReadWithoutEncryption(const char *Cmd) { } data[0] = 0x10; // Static length data[1] = 0x06; // Command ID - if (!custom_IDm) { - if (!add_last_IDm(2, data)) { - PrintAndLogEx(ERR, "No last known card! Use reader first or set a custom IDm!"); - return PM3_EINVARG; - } else { - PrintAndLogEx(INFO, "Used last known IDm.", sprint_hex(data, datalen)); - } + 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 uint8_t lengths[] = {2, 4, 2, 4}; @@ -448,7 +591,7 @@ static int CmdHFFelicaReadWithoutEncryption(const char *Cmd) { datalen += 2; felica_read_without_encryption_response_t rd_noCry_resp; 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); } else { break; @@ -462,9 +605,10 @@ static int CmdHFFelicaReadWithoutEncryption(const char *Cmd) { AddCrc(data, datalen); datalen += 2; felica_read_without_encryption_response_t rd_noCry_resp; - send_rd_unencrypted(flags, datalen, data, 1, &rd_noCry_resp); - PrintAndLogEx(NORMAL, "Block Element\t| Data "); - print_rd_noEncrpytion_response(&rd_noCry_resp); + if (send_rd_unencrypted(flags, datalen, data, 1, &rd_noCry_resp) == PM3_SUCCESS) { + PrintAndLogEx(NORMAL, "Block Element\t| Data "); + print_rd_noEncrpytion_response(&rd_noCry_resp); + } } return PM3_SUCCESS; } @@ -491,12 +635,11 @@ static int CmdHFFelicaRequestResponse(const char *Cmd) { case 'i': paramCount++; custom_IDm = true; - if (param_getlength(Cmd, paramCount) == 16) { - param_gethex(Cmd, paramCount++, data + 2, 16); - } else { - PrintAndLogEx(ERR, "Incorrect IDm length! IDm must be 8-Byte."); + if (!add_param(Cmd, paramCount, data, 2, 16)) { return PM3_EINVARG; } + paramCount++; + i += 16; break; } } @@ -504,13 +647,8 @@ static int CmdHFFelicaRequestResponse(const char *Cmd) { } data[0] = 0x0A; // Static length data[1] = 0x04; // Command ID - if (!custom_IDm) { - if (!add_last_IDm(2, data)) { - PrintAndLogEx(ERR, "No last known card! Use reader first or set a custom IDm!"); - return PM3_EINVARG; - } else { - PrintAndLogEx(INFO, "Used last known IDm.", sprint_hex(data, datalen)); - } + if (!custom_IDm && !check_last_idm(data, datalen)) { + return PM3_EINVARG; } AddCrc(data, datalen); datalen += 2; @@ -524,9 +662,9 @@ static int CmdHFFelicaRequestResponse(const char *Cmd) { } else { felica_request_request_response_t rq_response; 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(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))); } } @@ -558,13 +696,11 @@ static int CmdHFFelicaRequestService(const char *Cmd) { case 'i': paramCount++; custom_IDm = true; - if (param_getlength(Cmd, paramCount) == 16) { - param_gethex(Cmd, paramCount++, data + 2, 16); - } else { - PrintAndLogEx(ERR, "Incorrect IDm length! IDm must be 8-Byte."); + if (!add_param(Cmd, paramCount, data, 2, 16)) { return PM3_EINVARG; } - i += 8; + paramCount++; + i += 16; break; case 'a': paramCount++; @@ -603,13 +739,8 @@ static int CmdHFFelicaRequestService(const char *Cmd) { flags |= FELICA_RAW; } datalen = (datalen > PM3_CMD_DATA_SIZE) ? PM3_CMD_DATA_SIZE : datalen; - if (!custom_IDm) { - if (!add_last_IDm(2, data)) { - PrintAndLogEx(ERR, "No last known card! Use reader first or set a custom IDm!"); - return PM3_EINVARG; - } else { - PrintAndLogEx(INFO, "Used last known IDm.", sprint_hex(data, datalen)); - } + if (!custom_IDm && !check_last_idm(data, datalen)) { + return PM3_EINVARG; } data[0] = int_to_hex(&datalen); data[1] = 0x02; // Service Request Command ID @@ -1139,27 +1270,27 @@ static command_t CommandTable[] = { {"reader", CmdHFFelicaReader, IfPm3Felica, "Act like an ISO18092/FeliCa reader"}, {"sniff", CmdHFFelicaSniff, IfPm3Felica, "Sniff ISO 18092/FeliCa traffic"}, {"raw", CmdHFFelicaCmdRaw, IfPm3Felica, "Send raw hex data to tag"}, - {"----------- FeliCa Standard (support in progress) -----------", CmdHelp, IfPm3Iso14443a, ""}, - //{"dump", CmdHFFelicaDump, IfPm3Felica, "Wait for and try dumping FeliCa"}, - {"rqservice", CmdHFFelicaRequestService, IfPm3Felica, "verify the existence of Area and Service, and to acquire Key Version."}, - {"rqresponse", CmdHFFelicaRequestResponse, IfPm3Felica, "verify the existence of a card and its Mode."}, - {"rdunencrypted", CmdHFFelicaReadWithoutEncryption, IfPm3Felica, "read Block Data from authentication-not-required Service."}, - {"wrunencrypted", CmdHFFelicaNotImplementedYet, IfPm3Felica, "write Block Data to an authentication-not-required Service."}, - //{"scsvcode", CmdHFFelicaNotImplementedYet, IfPm3Felica, "acquire Area Code and Service Code."}, - //{"rqsyscode", CmdHFFelicaNotImplementedYet, IfPm3Felica, "acquire System Code registered to the card."}, - //{"auth1", CmdHFFelicaNotImplementedYet, IfPm3Felica, "authenticate a card."}, - //{"auth2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "allow a card to authenticate a Reader/Writer."}, - //{"read", CmdHFFelicaNotImplementedYet, IfPm3Felica, "read Block Data from authentication-required Service."}, - //{"write", CmdHFFelicaNotImplementedYet, IfPm3Felica, "write Block Data to an authentication-required Service."}, - //{"scsvcodev2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "verify the existence of Area or Service, and to acquire Key Version."}, - //{"getsysstatus", CmdHFFelicaNotImplementedYet, IfPm3Felica, "acquire the setup information in System."}, - //{"rqspecver", CmdHFFelicaNotImplementedYet, IfPm3Felica, "acquire the version of card OS."}, - //{"resetmode", CmdHFFelicaNotImplementedYet, IfPm3Felica, "reset Mode to Mode 0."}, - //{"auth1v2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "authenticate a card."}, - //{"auth2v2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "allow a card to authenticate a Reader/Writer."}, - //{"readv2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "read Block Data from authentication-required Service."}, - //{"writev2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "write Block Data to authentication-required Service."}, - //{"uprandomid", CmdHFFelicaNotImplementedYet, IfPm3Felica, "update Random ID (IDr)."}, + {"----------- FeliCa Standard (support in progress) -----------", CmdHelp, IfPm3Iso14443a, ""}, + //{"dump", CmdHFFelicaDump, IfPm3Felica, "Wait for and try dumping FeliCa"}, + {"rqservice", CmdHFFelicaRequestService, IfPm3Felica, "verify the existence of Area and Service, and to acquire Key Version."}, + {"rqresponse", CmdHFFelicaRequestResponse, IfPm3Felica, "verify the existence of a card and its Mode."}, + {"rdunencrypted", CmdHFFelicaReadWithoutEncryption, IfPm3Felica, "read Block Data from 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."}, + //{"rqsyscode", CmdHFFelicaNotImplementedYet, IfPm3Felica, "acquire System Code registered to the card."}, + //{"auth1", CmdHFFelicaNotImplementedYet, IfPm3Felica, "authenticate a card."}, + //{"auth2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "allow a card to authenticate a Reader/Writer."}, + //{"read", CmdHFFelicaNotImplementedYet, IfPm3Felica, "read Block Data from authentication-required Service."}, + //{"write", CmdHFFelicaNotImplementedYet, IfPm3Felica, "write Block Data to an authentication-required Service."}, + //{"scsvcodev2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "verify the existence of Area or Service, and to acquire Key Version."}, + //{"getsysstatus", CmdHFFelicaNotImplementedYet, IfPm3Felica, "acquire the setup information in System."}, + //{"rqspecver", CmdHFFelicaNotImplementedYet, IfPm3Felica, "acquire the version of card OS."}, + //{"resetmode", CmdHFFelicaNotImplementedYet, IfPm3Felica, "reset Mode to Mode 0."}, + //{"auth1v2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "authenticate a card."}, + //{"auth2v2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "allow a card to authenticate a Reader/Writer."}, + //{"readv2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "read Block Data from authentication-required Service."}, + //{"writev2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "write Block Data to authentication-required Service."}, + //{"uprandomid", CmdHFFelicaNotImplementedYet, IfPm3Felica, "update Random ID (IDr)."}, {"----------- FeliCa Light -----------", CmdHelp, IfPm3Iso14443a, ""}, {"litesim", CmdHFFelicaSimLite, IfPm3Felica, " - only reply to poll request"}, {"litedump", CmdHFFelicaDumpLite, IfPm3Felica, "Wait for and try dumping FelicaLite"}, diff --git a/client/cmdhffelica.h b/client/cmdhffelica.h index 7626d002b..8d8156006 100644 --- a/client/cmdhffelica.h +++ b/client/cmdhffelica.h @@ -18,4 +18,5 @@ int CmdHFFelica(const char *Cmd); int readFelicaUid(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); + #endif diff --git a/client/cmdhw.c b/client/cmdhw.c index 619e73abe..5eb6c7100 100644 --- a/client/cmdhw.c +++ b/client/cmdhw.c @@ -542,7 +542,7 @@ static int CmdPing(const char *Cmd) { bool error = false; if (len) { 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 { PrintAndLogEx(SUCCESS, "Ping response " _GREEN_("received")); } diff --git a/client/cmdlffdx.c b/client/cmdlffdx.c index 244c0caf3..17dbd2fd0 100644 --- a/client/cmdlffdx.c +++ b/client/cmdlffdx.c @@ -13,6 +13,7 @@ #include #include #include +#include // tolower #include "cmdparser.h" // command_t #include "comms.h" @@ -49,15 +50,14 @@ static int CmdHelp(const char *Cmd); static int usage_lf_fdx_clone(void) { PrintAndLogEx(NORMAL, "Clone a FDX-B animal tag to a T55x7 tag."); - PrintAndLogEx(NORMAL, "Usage: lf fdx clone [h] "); + PrintAndLogEx(NORMAL, "Usage: lf fdx clone [h] "); PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h : This help"); PrintAndLogEx(NORMAL, " : Country id"); PrintAndLogEx(NORMAL, " : Animal id"); - // has extended data? + PrintAndLogEx(NORMAL, " : Extended data"); //reserved/rfu //is animal tag - // extended data PrintAndLogEx(NORMAL, " : Specify write to Q5 (t5555 instead of t55x7)"); PrintAndLogEx(NORMAL, ""); 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, "Simulation runs until the button is pressed or another USB command is issued."); PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Usage: lf fdx sim [h] "); + PrintAndLogEx(NORMAL, "Usage: lf fdx sim [h] "); PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h : This help"); PrintAndLogEx(NORMAL, " : Country ID"); PrintAndLogEx(NORMAL, " : Animal ID"); + PrintAndLogEx(NORMAL, " : Extended data"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); 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. -static void verify_values(uint32_t countryid, uint64_t animalid) { - if ((animalid & 0x3FFFFFFFFF) != animalid) { - animalid &= 0x3FFFFFFFFF; - PrintAndLogEx(INFO, "Animal ID Truncated to 38bits: %"PRIx64, animalid); +static void verify_values(uint64_t *animalid, uint32_t *countryid) { + if ((*animalid & 0x3FFFFFFFFF) != *animalid) { + *animalid &= 0x3FFFFFFFFF; + PrintAndLogEx(INFO, "Animal ID Truncated to 38bits: %"PRIx64, *animalid); } - if ((countryid & 0x3ff) != countryid) { - countryid &= 0x3ff; - PrintAndLogEx(INFO, "Country ID Truncated to 10bits: %03d", countryid); + if ((*countryid & 0x3ff) != *countryid) { + *countryid &= 0x3ff; + PrintAndLogEx(INFO, "Country ID Truncated to 10bits: %03d", *countryid); } } @@ -226,15 +227,12 @@ static int CmdFdxDemod(const char *Cmd) { uint8_t dataBlockBit = DemodBuffer[48]; uint32_t reservedCode = bytebits_to_byteLSBF(DemodBuffer + 49, 14); 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); uint64_t rawid = (uint64_t)(bytebits_to_byte(DemodBuffer, 32)) << 32 | bytebits_to_byte(DemodBuffer + 32, 32); uint8_t raw[8]; 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, "Animal ID %04u-%012" PRIu64, countryCode, 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, "Animal Tag %s", animalBit ? _YELLOW_("True") : "False"); 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) { 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) { - uint32_t countryid = 0; + uint32_t countryid = 0, extended = 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); 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)); - 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."); free(bits); 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}; //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; // convert from bit stream to block data @@ -302,33 +305,41 @@ static int CmdFdxClone(const char *Cmd) { } static int CmdFdxSim(const char *Cmd) { - uint32_t countryid = 0; + uint32_t countryid = 0, extended = 0; uint64_t animalid = 0; - char cmdp = param_getchar(Cmd, 0); - if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') return usage_lf_fdx_sim(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) == 0 || cmdp == 'h') return usage_lf_fdx_sim(); countryid = param_get32ex(Cmd, 0, 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); - 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(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 - 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->invert = 1; payload->separator = 0; payload->clock = 32; - memcpy(payload->data, bs, sizeof(bs)); + memcpy(payload->data, bits, 128); 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); PacketResponseNG resp; @@ -337,6 +348,7 @@ static int CmdFdxSim(const char *Cmd) { PrintAndLogEx(INFO, "Done"); if (resp.status != PM3_EOPABORTED) return resp.status; + return PM3_SUCCESS; } @@ -378,7 +390,7 @@ int demodFDX(void) { 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 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); // add animal flag - OK - bits[65] = isanimal; + bits[65] = is_animal; // add extended flag - OK - bits[81] = isextended; + bits[81] = is_extended; // add national code 40bits - OK 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) 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 >> 8, 8, bits + 92); diff --git a/client/dictionaries/mfc_default_keys.dic b/client/dictionaries/mfc_default_keys.dic index 376676f1a..ab113b0f5 100644 --- a/client/dictionaries/mfc_default_keys.dic +++ b/client/dictionaries/mfc_default_keys.dic @@ -21,6 +21,8 @@ a0478cc39091 8fd0a4f256e9 # d2ece8b9395e # lib +# NSCP default key +☻1494E81663D7 # # more Keys from mfc_default_keys.lua 000000000001 diff --git a/client/proxmark3.c b/client/proxmark3.c index c1d6a5dc7..bb291ee6c 100644 --- a/client/proxmark3.c +++ b/client/proxmark3.c @@ -482,7 +482,7 @@ static bool DetectWindowsAnsiSupport(void) { HKEY hKey = NULL; bool virtualTerminalLevelSet = false; bool forceV2Set = false; - + if (RegOpenKeyA(HKEY_CURRENT_USER, "Console", &hKey) == ERROR_SUCCESS) { DWORD dwType = REG_SZ; BYTE KeyValue[sizeof(dwType)]; diff --git a/common/crc16.c b/common/crc16.c index 22445beda..b1c2ac248 100644 --- a/common/crc16.c +++ b/common/crc16.c @@ -46,6 +46,9 @@ void init_table(CrcType_t crctype) { case CRC_KERMIT: generate_table(CRC16_POLY_CCITT, true); break; + case CRC_11784: + generate_table(CRC16_POLY_CCITT, false); + break; case CRC_NONE: crc_table_init = false; 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: crc = crc16_kermit(d, n); break; + case CRC_11784: + crc = crc16_fdx(d, n); + break; case CRC_LEGIC: // TODO return; @@ -215,6 +221,8 @@ uint16_t Crc16ex(CrcType_t ct, const uint8_t *d, size_t n) { return crc16_ccitt(d, n); case CRC_KERMIT: return crc16_kermit(d, n); + case CRC_11784: + return crc16_fdx(d, n); case CRC_LEGIC: // TODO 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); case CRC_KERMIT: return (crc16_kermit(d, n) == 0); + case CRC_11784: + return (crc16_fdx(d, n) == 0); case CRC_LEGIC: // TODO 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); } -// 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" uint16_t crc16_kermit(uint8_t const *d, size_t n) { return crc16_fast(d, n, 0x0000, true, true); diff --git a/common/crc16.h b/common/crc16.h index 6989af22e..7a273683c 100644 --- a/common/crc16.h +++ b/common/crc16.h @@ -10,14 +10,16 @@ #include "common.h" -#define CRC16_POLY_CCITT 0x1021 -#define CRC16_POLY_LEGIC 0xc6c6 //0x6363 -#define CRC16_POLY_DNP 0x3d65 +#define CRC16_POLY_CCITT 0x1021 +#define CRC16_POLY_KERMIT 0x8408 +#define CRC16_POLY_LEGIC 0xc6c6 //0x6363 +#define CRC16_POLY_DNP 0x3d65 #define X25_CRC_CHECK ((uint16_t)(~0xF0B8 & 0xFFFF)) // use this for checking of a correct crc typedef enum { CRC_NONE, + CRC_11784, CRC_14443_A, CRC_14443_B, 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); // 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); // Calculate CRC-16/XMODEM (FeliCa) diff --git a/doc/md/Installation_Instructions/Linux-Installation-Instructions.md b/doc/md/Installation_Instructions/Linux-Installation-Instructions.md index f82d0f677..d56d1056c 100644 --- a/doc/md/Installation_Instructions/Linux-Installation-Instructions.md +++ b/doc/md/Installation_Instructions/Linux-Installation-Instructions.md @@ -58,7 +58,8 @@ git clone https://github.com/RfidResearchGroup/proxmark3.git # 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. # Check connection diff --git a/include/mifare.h b/include/mifare.h index 7a40a26e4..4a65357e5 100644 --- a/include/mifare.h +++ b/include/mifare.h @@ -174,30 +174,37 @@ typedef struct { uint8_t length[1]; uint8_t cmd_code[1]; 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_key_versions[2]; } PACKED felica_request_service_response_t; typedef struct { - uint8_t sync[2]; - uint8_t length[1]; - uint8_t cmd_code[1]; - uint8_t IDm[8]; + felica_frame_response_t frame_response; uint8_t mode[1]; } PACKED felica_request_request_response_t; typedef struct { - uint8_t sync[2]; - uint8_t length[1]; - uint8_t cmd_code[1]; - uint8_t IDm[8]; - uint8_t status_flag1[1]; - uint8_t status_flag2[1]; + felica_frame_response_t frame_response; + felica_status_flags_t status_flags; uint8_t number_of_block[1]; uint8_t block_data[16]; uint8_t block_element_number[1]; } 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 { FELICA_CONNECT = (1 << 0), FELICA_NO_DISCONNECT = (1 << 1),