diff --git a/lib/nfc/protocols/mf_ultralight/mf_ultralight.h b/lib/nfc/protocols/mf_ultralight/mf_ultralight.h index ddedf530726..747f5937ad2 100644 --- a/lib/nfc/protocols/mf_ultralight/mf_ultralight.h +++ b/lib/nfc/protocols/mf_ultralight/mf_ultralight.h @@ -25,6 +25,7 @@ extern "C" { #define MF_ULTRALIGHT_CMD_ACK (0x0A) #define MF_ULTRALIGHT_CMD_NACK (0x00) +#define MF_ULTRALIGHT_CMD_AUTH_NAK (0x04) #define MF_ULTRALIGHT_MAX_CNTR_VAL (0x00FFFFFF) #define MF_ULTRALIGHT_MAX_PAGE_NUM (510) diff --git a/lib/nfc/protocols/mf_ultralight/mf_ultralight_listener.c b/lib/nfc/protocols/mf_ultralight/mf_ultralight_listener.c index ee02b22f251..2051b378bf6 100644 --- a/lib/nfc/protocols/mf_ultralight/mf_ultralight_listener.c +++ b/lib/nfc/protocols/mf_ultralight/mf_ultralight_listener.c @@ -442,9 +442,19 @@ static MfUltralightCommand instance->callback(instance->generic_event, instance->context); } - uint8_t* config_pass = instance->config->password.data; - uint8_t* auth_pass = password.data; - if(memcmp(config_pass, auth_pass, sizeof(MfUltralightAuthPassword)) != 0) break; + bool auth_success = + mf_ultralight_auth_check_password(&instance->config->password, &password); + bool card_locked = mf_ultralight_auth_limit_check_and_update(instance, auth_success); + + if(card_locked) { + command = MfUltralightCommandNotProcessedAuthNAK; + break; + } + + if(!auth_success) { + command = MfUltralightCommandNotProcessedNAK; + break; + } bit_buffer_copy_bytes( instance->tx_buffer, instance->config->pack.data, sizeof(MfUltralightAuthPack)); @@ -645,6 +655,8 @@ static NfcCommand mf_ultralight_command_postprocess( if(mfu_command == MfUltralightCommandNotProcessedNAK) { mf_ultralight_listener_send_short_resp(instance, MF_ULTRALIGHT_CMD_NACK); + } else if(mfu_command == MfUltralightCommandNotProcessedAuthNAK) { + mf_ultralight_listener_send_short_resp(instance, MF_ULTRALIGHT_CMD_AUTH_NAK); } } diff --git a/lib/nfc/protocols/mf_ultralight/mf_ultralight_listener_i.c b/lib/nfc/protocols/mf_ultralight/mf_ultralight_listener_i.c index 44524495a1e..3d6b9a94fdf 100644 --- a/lib/nfc/protocols/mf_ultralight/mf_ultralight_listener_i.c +++ b/lib/nfc/protocols/mf_ultralight/mf_ultralight_listener_i.c @@ -35,6 +35,9 @@ #define MF_ULTRALIGHT_I2C_PAGE_ON_MIRRORED_SESSION_REG(page) \ MF_ULTRALIGHT_PAGE_IN_BOUNDS(page, 0x00F8, 0x00F9) +#define MF_ULTRALIGHT_AUTH_RESET_ATTEMPTS(instance) (instance->data->auth_attempts = 0) +#define MF_ULTRALIGHT_AUTH_INCREASE_ATTEMPTS(instance) (instance->data->auth_attempts++) + static MfUltralightMirrorConf mf_ultralight_mirror_check_mode( const MfUltralightConfigPages* const config, const MfUltralightListenerAuthState auth_state) { @@ -536,4 +539,39 @@ bool mf_ultralight_dynamic_lock_check_page(const MfUltralightListener* instance, locked = MF_ULTRALIGHT_PAGE_LOCKED(current_locks, bit); } return locked; +} + +static bool mf_ultralight_auth_check_attempts(const MfUltralightListener* instance) { + uint8_t authlim = ((instance->data->type == MfUltralightTypeNTAGI2CPlus1K) || + (instance->data->type == MfUltralightTypeNTAGI2CPlus2K)) ? + (1U << instance->config->access.authlim) : + instance->config->access.authlim; + + return (instance->data->auth_attempts >= authlim); +} + +bool mf_ultralight_auth_limit_check_and_update(MfUltralightListener* instance, bool auth_success) { + bool card_locked = false; + + do { + if(instance->config->access.authlim == 0) break; + card_locked = mf_ultralight_auth_check_attempts(instance); + if(card_locked) break; + + if(auth_success) { + MF_ULTRALIGHT_AUTH_RESET_ATTEMPTS(instance); + } else { + MF_ULTRALIGHT_AUTH_INCREASE_ATTEMPTS(instance); + } + + card_locked = mf_ultralight_auth_check_attempts(instance); + } while(false); + + return card_locked; +} + +bool mf_ultralight_auth_check_password( + const MfUltralightAuthPassword* config_pass, + const MfUltralightAuthPassword* auth_pass) { + return memcmp(config_pass->data, auth_pass->data, sizeof(MfUltralightAuthPassword)) == 0; } \ No newline at end of file diff --git a/lib/nfc/protocols/mf_ultralight/mf_ultralight_listener_i.h b/lib/nfc/protocols/mf_ultralight/mf_ultralight_listener_i.h index fc95ac54685..ba448d0879c 100644 --- a/lib/nfc/protocols/mf_ultralight/mf_ultralight_listener_i.h +++ b/lib/nfc/protocols/mf_ultralight/mf_ultralight_listener_i.h @@ -20,6 +20,7 @@ typedef enum { MfUltralightCommandProcessedSilent, MfUltralightCommandNotProcessedNAK, MfUltralightCommandNotProcessedSilent, + MfUltralightCommandNotProcessedAuthNAK, } MfUltralightCommand; typedef MfUltralightCommand ( @@ -113,7 +114,10 @@ void mf_ultralight_dynamic_lock_bytes_write( MfUltralightDynamicLockData* const lock_bits, uint32_t new_bits); bool mf_ultralight_dynamic_lock_check_page(const MfUltralightListener* instance, uint16_t page); - +bool mf_ultralight_auth_limit_check_and_update(MfUltralightListener* instance, bool auth_success); +bool mf_ultralight_auth_check_password( + const MfUltralightAuthPassword* config_pass, + const MfUltralightAuthPassword* auth_pass); #ifdef __cplusplus } #endif