diff --git a/docs/protocol.md b/docs/protocol.md index 3427d7f..4afa1c4 100644 --- a/docs/protocol.md +++ b/docs/protocol.md @@ -428,6 +428,10 @@ Notes: * Command: 1 byte where the lower 7 bits are the counter index and the top bit indicates whether tearing event flag should be reset + 3 bytes of the counter value (big-endian). * Response: no data * CLI: cf `hf mfu ewcnt` +### 4029: MF0_NTAG_RESET_AUTH_CNT +* Command: no data +* Response: 1 byte for the old value of the unsuccessful auth counter. +* CLI: cf `hf mfu econfig --reset-auth-cnt` ### 5000: EM410X_SET_EMU_ID * Command: 5 bytes. `id[5]`. ID as 5 bytes. * Response: no data diff --git a/firmware/application/src/app_cmd.c b/firmware/application/src/app_cmd.c index 6820f2e..85462ca 100644 --- a/firmware/application/src/app_cmd.c +++ b/firmware/application/src/app_cmd.c @@ -927,6 +927,17 @@ static data_frame_tx_t *cmd_processor_mf0_ntag_set_counter_data(uint16_t cmd, ui return data_frame_make(cmd, STATUS_SUCCESS, 0, NULL); } +static data_frame_tx_t *cmd_processor_mf0_ntag_reset_auth_cnt(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) { + // all tags with counters support auth + uint8_t *counter_data = nfc_tag_mf0_ntag_get_counter_data_by_index(0); + if (counter_data == NULL) return data_frame_make(cmd, STATUS_INVALID_SLOT_TYPE, 0, NULL); + + uint8_t old_value = counter_data[MF0_NTAG_AUTHLIM_OFF_IN_CTR] & MF0_NTAG_AUTHLIM_MASK_IN_CTR; + counter_data[MF0_NTAG_AUTHLIM_OFF_IN_CTR] &= ~MF0_NTAG_AUTHLIM_MASK_IN_CTR; + + return data_frame_make(cmd, STATUS_SUCCESS, 1, &old_value); +} + static data_frame_tx_t *cmd_processor_hf14a_set_anti_coll_data(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) { // uidlen[1]|uid[uidlen]|atqa[2]|sak[1]|atslen[1]|ats[atslen] // dynamic length, so no struct @@ -1273,7 +1284,8 @@ static cmd_data_map_t m_data_cmd_map[] = { { DATA_CMD_MF0_NTAG_GET_SIGNATURE_DATA, NULL, cmd_processor_mf0_ntag_get_signature_data, NULL }, { DATA_CMD_MF0_NTAG_SET_SIGNATURE_DATA, NULL, cmd_processor_mf0_ntag_set_signature_data, NULL }, { DATA_CMD_MF0_NTAG_GET_COUNTER_DATA, NULL, cmd_processor_mf0_ntag_get_counter_data, NULL }, - { DATA_CMD_MF0_NTAG_SET_COUNTER_DATA, NULL, cmd_processor_mf0_ntag_set_counter_data, NULL }, + { DATA_CMD_MF0_NTAG_SET_COUNTER_DATA, NULL, cmd_processor_mf0_ntag_set_counter_data, NULL }, + { DATA_CMD_MF0_NTAG_RESET_AUTH_CNT, NULL, cmd_processor_mf0_ntag_reset_auth_cnt, NULL }, { DATA_CMD_EM410X_SET_EMU_ID, NULL, cmd_processor_em410x_set_emu_id, NULL }, { DATA_CMD_EM410X_GET_EMU_ID, NULL, cmd_processor_em410x_get_emu_id, NULL }, diff --git a/firmware/application/src/data_cmd.h b/firmware/application/src/data_cmd.h index 2000d47..16fd864 100644 --- a/firmware/application/src/data_cmd.h +++ b/firmware/application/src/data_cmd.h @@ -116,6 +116,7 @@ #define DATA_CMD_MF0_NTAG_SET_SIGNATURE_DATA (4026) #define DATA_CMD_MF0_NTAG_GET_COUNTER_DATA (4027) #define DATA_CMD_MF0_NTAG_SET_COUNTER_DATA (4028) +#define DATA_CMD_MF0_NTAG_RESET_AUTH_CNT (4029) // // ****************************************************************** diff --git a/software/script/chameleon_cli_unit.py b/software/script/chameleon_cli_unit.py index 944ef1f..4a8043f 100644 --- a/software/script/chameleon_cli_unit.py +++ b/software/script/chameleon_cli_unit.py @@ -2216,12 +2216,15 @@ class HFMFUEConfig(SlotIndexArgsAndGoUnit, HF14AAntiCollArgsUnit, DeviceRequired uid_magic_group.add_argument('--disable-uid-magic', action='store_true', help="Disable UID magic mode") parser.add_argument('--set-version', type=bytes.fromhex, help="Set data to be returned by the GET_VERSION command.") parser.add_argument('--set-signature', type=bytes.fromhex, help="Set data to be returned by the READ_SIG command.") + parser.add_argument('--reset-auth-cnt', action='store_true', help="Resets the counter of unsuccessful authentication attempts.") return parser def on_exec(self, args: argparse.Namespace): aux_data_changed = False + aux_data_change_requested = False if args.set_version is not None: + aux_data_change_requested = True aux_data_changed = True if len(args.set_version) != 8: @@ -2235,6 +2238,7 @@ class HFMFUEConfig(SlotIndexArgsAndGoUnit, HF14AAntiCollArgsUnit, DeviceRequired return if args.set_signature is not None: + aux_data_change_requested = True aux_data_changed = True if len(args.set_signature) != 32: @@ -2246,6 +2250,13 @@ class HFMFUEConfig(SlotIndexArgsAndGoUnit, HF14AAntiCollArgsUnit, DeviceRequired except: print(f"{CR}Tag type does not support READ_SIG command.{C0}") return + + if args.reset_auth_cnt: + aux_data_change_requested = True + old_value = self.cmd.mfu_reset_auth_cnt() + if old_value != 0: + aux_data_changed = True + print(f"- Unsuccessful auth counter has been reset from {old_value} to 0.") # collect current settings anti_coll_data = self.cmd.hf14a_get_anti_coll_data() @@ -2285,7 +2296,7 @@ class HFMFUEConfig(SlotIndexArgsAndGoUnit, HF14AAntiCollArgsUnit, DeviceRequired if change_done or aux_data_changed: print(' - MFU/NTAG Emulator settings updated') - if not (change_requested or aux_data_changed): + if not (change_requested or aux_data_change_requested): print(f'- {"Type:":40}{CY}{hf_tag_type}{C0}') print(f'- {"UID:":40}{CY}{uid.hex().upper()}{C0}') print(f'- {"ATQA:":40}{CY}{atqa.hex().upper()} ' diff --git a/software/script/chameleon_cmd.py b/software/script/chameleon_cmd.py index 43bbd57..55e7205 100644 --- a/software/script/chameleon_cmd.py +++ b/software/script/chameleon_cmd.py @@ -628,6 +628,16 @@ class ChameleonCMD: resp = self.device.send_cmd_sync(Command.MF0_NTAG_SET_COUNTER_DATA, data) return resp + @expect_response(Status.SUCCESS) + def mfu_reset_auth_cnt(self): + """ + Resets authentication counter + """ + resp = self.device.send_cmd_sync(Command.MF0_NTAG_RESET_AUTH_CNT, bytes()) + if resp.status == Status.SUCCESS: + resp.parsed = resp.data[0] + return resp + @expect_response(Status.SUCCESS) def hf14a_set_anti_coll_data(self, uid: bytes, atqa: bytes, sak: bytes, ats: bytes = b''): """ diff --git a/software/script/chameleon_enum.py b/software/script/chameleon_enum.py index c250afd..4592d8b 100644 --- a/software/script/chameleon_enum.py +++ b/software/script/chameleon_enum.py @@ -105,6 +105,7 @@ class Command(enum.IntEnum): MF0_NTAG_SET_SIGNATURE_DATA = 4026 MF0_NTAG_GET_COUNTER_DATA = 4027 MF0_NTAG_SET_COUNTER_DATA = 4028 + MF0_NTAG_RESET_AUTH_CNT = 4029 EM410X_SET_EMU_ID = 5000 EM410X_GET_EMU_ID = 5001