From ef3d17ea4ecc7f306f238fdac230b3720ca6947a Mon Sep 17 00:00:00 2001 From: Mykhailo Shevchuk Date: Tue, 29 Apr 2025 00:07:54 +0300 Subject: [PATCH 1/2] Extracted TDES auth to separate method --- .../notification_settings_app.c | 2 +- .../mf_ultralight/mf_ultralight_poller.c | 26 +++------------ .../mf_ultralight/mf_ultralight_poller.h | 13 ++++++++ .../mf_ultralight/mf_ultralight_poller_i.c | 33 +++++++++++++++++++ targets/f7/api_symbols.csv | 3 +- 5 files changed, 53 insertions(+), 24 deletions(-) diff --git a/applications/settings/notification_settings/notification_settings_app.c b/applications/settings/notification_settings/notification_settings_app.c index be7af4c42..9c6957c0b 100644 --- a/applications/settings/notification_settings/notification_settings_app.c +++ b/applications/settings/notification_settings/notification_settings_app.c @@ -556,7 +556,7 @@ static void night_shift_changed(VariableItem* item) { // force demo night_shift brightness to rgb backlight and stock backlight notification_message(app->notification, &sequence_display_backlight_on); - + for(int i = 4; i < 6; i++) { VariableItem* t_item = variable_item_list_get(app->variable_item_list, i); if(index == 0) { diff --git a/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.c b/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.c index 7d51f6c6e..3eb6524ed 100644 --- a/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.c +++ b/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.c @@ -453,29 +453,11 @@ static NfcCommand mf_ultralight_poller_handler_auth_ultralight_c(MfUltralightPol if(!instance->mfu_event.data->auth_context.skip_auth) { FURI_LOG_D(TAG, "Trying to authenticate with 3des key"); instance->auth_context.tdes_key = instance->mfu_event.data->auth_context.tdes_key; - do { - uint8_t output[MF_ULTRALIGHT_C_AUTH_DATA_SIZE]; - uint8_t RndA[MF_ULTRALIGHT_C_AUTH_RND_BLOCK_SIZE] = {0}; - furi_hal_random_fill_buf(RndA, sizeof(RndA)); - instance->error = mf_ultralight_poller_authenticate_start(instance, RndA, output); - if(instance->error != MfUltralightErrorNone) break; + instance->error = mf_ultralight_poller_auth_tdes(instance, &instance->auth_context); - uint8_t decoded_shifted_RndA[MF_ULTRALIGHT_C_AUTH_RND_BLOCK_SIZE] = {0}; - const uint8_t* RndB = output + MF_ULTRALIGHT_C_AUTH_RND_B_BLOCK_OFFSET; - instance->error = mf_ultralight_poller_authenticate_end( - instance, RndB, output, decoded_shifted_RndA); - if(instance->error != MfUltralightErrorNone) break; - - mf_ultralight_3des_shift_data(RndA); - instance->auth_context.auth_success = - (memcmp(RndA, decoded_shifted_RndA, sizeof(decoded_shifted_RndA)) == 0); - - if(instance->auth_context.auth_success) { - FURI_LOG_D(TAG, "Auth success"); - } - } while(false); - - if(instance->error != MfUltralightErrorNone || !instance->auth_context.auth_success) { + if(instance->error == MfUltralightErrorNone && instance->auth_context.auth_success) { + FURI_LOG_D(TAG, "Auth success"); + } else { FURI_LOG_D(TAG, "Auth failed"); iso14443_3a_poller_halt(instance->iso14443_3a_poller); } diff --git a/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.h b/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.h index e50017324..661c6db74 100644 --- a/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.h +++ b/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.h @@ -81,6 +81,19 @@ MfUltralightError mf_ultralight_poller_auth_pwd( MfUltralightPoller* instance, MfUltralightPollerAuthContext* data); +/** + * @brief Perform 3DES authentication with key. + * + * Must ONLY be used inside the callback function. + * + * @param[in, out] instance pointer to the instance to be used in the transaction. + * @param[in, out] data pointer to the authentication context. + * @return MfUltralightErrorNone on success, an error code on failure. + */ +MfUltralightError mf_ultralight_poller_auth_tdes( + MfUltralightPoller* instance, + MfUltralightPollerAuthContext* data); + /** * @brief Start authentication procedure. * diff --git a/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller_i.c b/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller_i.c index d84377612..79c7b1d1a 100644 --- a/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller_i.c +++ b/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller_i.c @@ -1,6 +1,7 @@ #include "mf_ultralight_poller_i.h" #include +#include #define TAG "MfUltralightPoller" @@ -62,6 +63,38 @@ MfUltralightError mf_ultralight_poller_auth_pwd( return ret; } +MfUltralightError mf_ultralight_poller_auth_tdes( + MfUltralightPoller* instance, + MfUltralightPollerAuthContext* data) { + furi_check(instance); + furi_check(data); + + MfUltralightError ret = MfUltralightErrorNone; + + uint8_t output[MF_ULTRALIGHT_C_AUTH_DATA_SIZE]; + uint8_t RndA[MF_ULTRALIGHT_C_AUTH_RND_BLOCK_SIZE] = {0}; + furi_hal_random_fill_buf(RndA, sizeof(RndA)); + + ret = mf_ultralight_poller_authenticate_start(instance, RndA, output); + + if(ret != MfUltralightErrorNone) { + return ret; + } + + uint8_t decoded_shifted_RndA[MF_ULTRALIGHT_C_AUTH_RND_BLOCK_SIZE] = {0}; + const uint8_t* RndB = output + MF_ULTRALIGHT_C_AUTH_RND_B_BLOCK_OFFSET; + ret = mf_ultralight_poller_authenticate_end(instance, RndB, output, decoded_shifted_RndA); + + if(ret != MfUltralightErrorNone) { + return ret; + } + + mf_ultralight_3des_shift_data(RndA); + data->auth_success = (memcmp(RndA, decoded_shifted_RndA, sizeof(decoded_shifted_RndA)) == 0); + + return ret; +} + static MfUltralightError mf_ultralight_poller_send_authenticate_cmd( MfUltralightPoller* instance, const uint8_t* cmd, diff --git a/targets/f7/api_symbols.csv b/targets/f7/api_symbols.csv index 7c4dca564..66b8bb703 100755 --- a/targets/f7/api_symbols.csv +++ b/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,86.0,, +Version,+,86.2,, Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/bt/bt_service/bt_keys_storage.h,, @@ -2741,6 +2741,7 @@ Function,+,mf_ultralight_is_equal,_Bool,"const MfUltralightData*, const MfUltral Function,+,mf_ultralight_is_page_pwd_or_pack,_Bool,"MfUltralightType, uint16_t" Function,+,mf_ultralight_load,_Bool,"MfUltralightData*, FlipperFormat*, uint32_t" Function,+,mf_ultralight_poller_auth_pwd,MfUltralightError,"MfUltralightPoller*, MfUltralightPollerAuthContext*" +Function,+,mf_ultralight_poller_auth_tdes,MfUltralightError,"MfUltralightPoller*, MfUltralightPollerAuthContext*" Function,+,mf_ultralight_poller_authenticate_end,MfUltralightError,"MfUltralightPoller*, const uint8_t*, const uint8_t*, uint8_t*" Function,+,mf_ultralight_poller_authenticate_start,MfUltralightError,"MfUltralightPoller*, const uint8_t*, uint8_t*" Function,+,mf_ultralight_poller_read_counter,MfUltralightError,"MfUltralightPoller*, uint8_t, MfUltralightCounter*" From c0e169a22940973ad503e29af3de0b79fefc3c81 Mon Sep 17 00:00:00 2001 From: Mykhailo Shevchuk Date: Tue, 29 Apr 2025 02:31:41 +0300 Subject: [PATCH 2/2] Attempt to auth with default 3DES key --- .../mf_ultralight/mf_ultralight_poller.c | 74 +++++++++++++++---- .../mf_ultralight/mf_ultralight_poller_i.c | 6 +- .../mf_ultralight/mf_ultralight_poller_i.h | 1 + targets/f7/api_symbols.csv | 2 +- 4 files changed, 65 insertions(+), 18 deletions(-) diff --git a/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.c b/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.c index 3eb6524ed..6c6e230f0 100644 --- a/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.c +++ b/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.c @@ -445,25 +445,35 @@ static NfcCommand mf_ultralight_poller_handler_auth(MfUltralightPoller* instance static NfcCommand mf_ultralight_poller_handler_auth_ultralight_c(MfUltralightPoller* instance) { NfcCommand command = NfcCommandContinue; FURI_LOG_D(TAG, "MfulC auth"); - if(mf_ultralight_support_feature( - instance->feature_set, MfUltralightFeatureSupportAuthenticate)) { - instance->mfu_event.type = MfUltralightPollerEventTypeAuthRequest; - command = instance->callback(instance->general_event, instance->context); - if(!instance->mfu_event.data->auth_context.skip_auth) { - FURI_LOG_D(TAG, "Trying to authenticate with 3des key"); - instance->auth_context.tdes_key = instance->mfu_event.data->auth_context.tdes_key; - instance->error = mf_ultralight_poller_auth_tdes(instance, &instance->auth_context); + do { + if(mf_ultralight_support_feature( + instance->feature_set, MfUltralightFeatureSupportAuthenticate)) { + instance->mfu_event.type = MfUltralightPollerEventTypeAuthRequest; - if(instance->error == MfUltralightErrorNone && instance->auth_context.auth_success) { - FURI_LOG_D(TAG, "Auth success"); + command = instance->callback(instance->general_event, instance->context); + if(!instance->mfu_event.data->auth_context.skip_auth) { + FURI_LOG_D(TAG, "Trying to authenticate with 3des key"); + instance->auth_context.tdes_key = instance->mfu_event.data->auth_context.tdes_key; + instance->error = + mf_ultralight_poller_auth_tdes(instance, &instance->auth_context); + + if(instance->error == MfUltralightErrorNone && + instance->auth_context.auth_success) { + FURI_LOG_D(TAG, "Auth success"); + } else { + FURI_LOG_D(TAG, "Auth failed"); + iso14443_3a_poller_halt(instance->iso14443_3a_poller); + } } else { - FURI_LOG_D(TAG, "Auth failed"); - iso14443_3a_poller_halt(instance->iso14443_3a_poller); + // We assume here that it is card read without explicitly provided key + // So we try to auth with default one + instance->state = MfUltralightPollerStateTryDefaultMfulCKey; + break; } } - } - instance->state = MfUltralightPollerStateReadPages; + instance->state = MfUltralightPollerStateReadPages; + } while(false); return command; } @@ -560,6 +570,40 @@ static NfcCommand mf_ultralight_poller_handler_try_default_pass(MfUltralightPoll return NfcCommandContinue; } +static NfcCommand + mf_ultralight_poller_handler_try_default_ultralight_c_key(MfUltralightPoller* instance) { + do { + if(!mf_ultralight_support_feature( + instance->feature_set, MfUltralightFeatureSupportAuthenticate)) { + break; + } + + if(instance->auth_context.auth_success) { + break; + } + + FURI_LOG_D(TAG, "Trying authentication with default 3DES key"); + + memcpy( + &instance->auth_context.tdes_key.data, + MF_ULTRALIGHT_C_DEFAULT_KEY, + MF_ULTRALIGHT_C_AUTH_DES_KEY_SIZE); + + instance->error = mf_ultralight_poller_auth_tdes(instance, &instance->auth_context); + + if(instance->error == MfUltralightErrorNone && instance->auth_context.auth_success) { + FURI_LOG_D(TAG, "Default 3DES key detected"); + } else { + FURI_LOG_D(TAG, "Authentication attempt with default 3DES key failed"); + iso14443_3a_poller_halt(instance->iso14443_3a_poller); + } + + } while(false); + + instance->state = MfUltralightPollerStateReadPages; + return NfcCommandContinue; +} + static NfcCommand mf_ultralight_poller_handler_check_mfuc_auth_status(MfUltralightPoller* instance) { instance->state = MfUltralightPollerStateReadSuccess; @@ -724,6 +768,8 @@ static const MfUltralightPollerReadHandler mf_ultralight_poller_handler_read_tearing_flags, [MfUltralightPollerStateAuth] = mf_ultralight_poller_handler_auth, [MfUltralightPollerStateTryDefaultPass] = mf_ultralight_poller_handler_try_default_pass, + [MfUltralightPollerStateTryDefaultMfulCKey] = + mf_ultralight_poller_handler_try_default_ultralight_c_key, [MfUltralightPollerStateCheckMfulCAuthStatus] = mf_ultralight_poller_handler_check_mfuc_auth_status, [MfUltralightPollerStateAuthMfulC] = mf_ultralight_poller_handler_auth_ultralight_c, diff --git a/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller_i.c b/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller_i.c index 79c7b1d1a..fdafaf37d 100644 --- a/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller_i.c +++ b/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller_i.c @@ -167,7 +167,7 @@ MfUltralightError mf_ultralight_poller_authenticate_start( uint8_t* RndB = output + MF_ULTRALIGHT_C_AUTH_RND_B_BLOCK_OFFSET; mf_ultralight_3des_decrypt( &instance->des_context, - instance->mfu_event.data->auth_context.tdes_key.data, + instance->auth_context.tdes_key.data, iv, encRndB, sizeof(encRndB), @@ -178,7 +178,7 @@ MfUltralightError mf_ultralight_poller_authenticate_start( mf_ultralight_3des_encrypt( &instance->des_context, - instance->mfu_event.data->auth_context.tdes_key.data, + instance->auth_context.tdes_key.data, encRndB, output, MF_ULTRALIGHT_C_AUTH_DATA_SIZE, @@ -212,7 +212,7 @@ MfUltralightError mf_ultralight_poller_authenticate_end( mf_ultralight_3des_decrypt( &instance->des_context, - instance->mfu_event.data->auth_context.tdes_key.data, + instance->auth_context.tdes_key.data, RndB, bit_buffer_get_data(instance->rx_buffer) + 1, MF_ULTRALIGHT_C_AUTH_RND_BLOCK_SIZE, diff --git a/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller_i.h b/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller_i.h index 6880a0c43..7db9a77d9 100644 --- a/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller_i.h +++ b/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller_i.h @@ -59,6 +59,7 @@ typedef enum { MfUltralightPollerStateAuthMfulC, MfUltralightPollerStateReadPages, MfUltralightPollerStateTryDefaultPass, + MfUltralightPollerStateTryDefaultMfulCKey, MfUltralightPollerStateCheckMfulCAuthStatus, MfUltralightPollerStateReadFailed, MfUltralightPollerStateReadSuccess, diff --git a/targets/f7/api_symbols.csv b/targets/f7/api_symbols.csv index 66b8bb703..101a9f1bb 100755 --- a/targets/f7/api_symbols.csv +++ b/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,86.2,, +Version,+,86.0,, Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/bt/bt_service/bt_keys_storage.h,,