From 2ce1bf6b58b07534a6ee2b0fddecdeacfb2edbce Mon Sep 17 00:00:00 2001 From: RebornedBrain Date: Mon, 10 Jun 2024 13:50:59 +0300 Subject: [PATCH 01/25] Update api_symbols.csv --- targets/f7/api_symbols.csv | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/targets/f7/api_symbols.csv b/targets/f7/api_symbols.csv index 32160b56e0f..64e0a2b252b 100644 --- a/targets/f7/api_symbols.csv +++ b/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,64.2,, +Version,v,68.1,, 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,, @@ -2524,6 +2524,8 @@ Function,+,mf_desfire_save,_Bool,"const MfDesfireData*, FlipperFormat*" Function,+,mf_desfire_send_chunks,MfDesfireError,"MfDesfirePoller*, const BitBuffer*, BitBuffer*" Function,+,mf_desfire_set_uid,_Bool,"MfDesfireData*, const uint8_t*, size_t" Function,+,mf_desfire_verify,_Bool,"MfDesfireData*, const FuriString*" +Function,+,mf_ultralight_3des_decrypt,void,"mbedtls_des3_context*, const uint8_t*, const uint8_t*, const uint8_t*, uint8_t*" +Function,?,mf_ultralight_3des_encrypt,void,"mbedtls_des3_context*, const uint8_t*, const uint8_t*, const uint8_t*, uint8_t*" Function,+,mf_ultralight_alloc,MfUltralightData*, Function,+,mf_ultralight_copy,void,"MfUltralightData*, const MfUltralightData*" Function,+,mf_ultralight_detect_protocol,_Bool,const Iso14443_3aData* From f61e773e1f4a7b373ef5c6d0ec53c52a00c80350 Mon Sep 17 00:00:00 2001 From: RebornedBrain Date: Thu, 13 Jun 2024 15:34:23 +0300 Subject: [PATCH 02/25] Ultralight C 3des implementation added --- .../protocols/mf_ultralight/mf_ultralight.c | 50 +++++++++++++++++++ .../protocols/mf_ultralight/mf_ultralight.h | 20 ++++++++ 2 files changed, 70 insertions(+) diff --git a/lib/nfc/protocols/mf_ultralight/mf_ultralight.c b/lib/nfc/protocols/mf_ultralight/mf_ultralight.c index 6300801ab8e..c61323f97da 100644 --- a/lib/nfc/protocols/mf_ultralight/mf_ultralight.c +++ b/lib/nfc/protocols/mf_ultralight/mf_ultralight.c @@ -667,3 +667,53 @@ bool mf_ultralight_is_counter_configured(const MfUltralightData* data) { return configured; } + +void mf_ultralight_3des_shift_data(uint8_t* const data) { + furi_check(data); + + uint8_t buf = data[0]; + for(uint8_t i = 1; i < 8; i++) { + data[i - 1] = data[i]; + } + data[7] = buf; +} + +const uint8_t* mf_ultralight_3des_get_key(const MfUltralightData* data) { + furi_check(data); + furi_check(data->type == MfUltralightTypeMfulC); + + return data->page[44].data; +} + +void mf_ultralight_3des_encrypt( + mbedtls_des3_context* ctx, + const uint8_t* ck, + const uint8_t* iv, + const uint8_t* input, + uint8_t* out) { + furi_check(ctx); + furi_check(ck); + furi_check(iv); + furi_check(input); + furi_check(out); + + mbedtls_des3_set2key_enc(ctx, ck); + mbedtls_des3_crypt_cbc(ctx, MBEDTLS_DES_ENCRYPT, 8, (uint8_t*)iv, input, out); +} + +void mf_ultralight_3des_decrypt( + mbedtls_des3_context* ctx, + const uint8_t* ck, + const uint8_t* iv, + const uint8_t* input, + const uint8_t length, + uint8_t* out) { + furi_check(ctx); + furi_check(ck); + furi_check(iv); + furi_check(input); + furi_check(out); + + mbedtls_des3_set2key_dec(ctx, ck); + mbedtls_des3_crypt_cbc(ctx, MBEDTLS_DES_DECRYPT, length, (uint8_t*)iv, input, out); +} \ No newline at end of file diff --git a/lib/nfc/protocols/mf_ultralight/mf_ultralight.h b/lib/nfc/protocols/mf_ultralight/mf_ultralight.h index 6c6a83a1702..48abddb6459 100644 --- a/lib/nfc/protocols/mf_ultralight/mf_ultralight.h +++ b/lib/nfc/protocols/mf_ultralight/mf_ultralight.h @@ -1,6 +1,7 @@ #pragma once #include +#include #ifdef __cplusplus extern "C" { @@ -226,6 +227,25 @@ bool mf_ultralight_detect_protocol(const Iso14443_3aData* iso14443_3a_data); bool mf_ultralight_is_counter_configured(const MfUltralightData* data); +void mf_ultralight_3des_shift_data(uint8_t* const arr); + +const uint8_t* mf_ultralight_3des_get_key(const MfUltralightData* data); + +void mf_ultralight_3des_encrypt( + mbedtls_des3_context* ctx, + const uint8_t* ck, + const uint8_t* iv, + const uint8_t* input, + uint8_t* out); + +void mf_ultralight_3des_decrypt( + mbedtls_des3_context* ctx, + const uint8_t* ck, + const uint8_t* iv, + const uint8_t* input, + const uint8_t length, + uint8_t* out); + #ifdef __cplusplus } #endif From e2471f080b2fa4961d1d9bf5b594154498f061c7 Mon Sep 17 00:00:00 2001 From: RebornedBrain Date: Thu, 13 Jun 2024 15:36:06 +0300 Subject: [PATCH 03/25] Access check for Ultralight cards is now splitted into 2 functions one for ULC card and another for common --- .../mf_ultralight/mf_ultralight_listener.c | 40 ++++---------- .../mf_ultralight/mf_ultralight_listener_i.c | 55 +++++++++++++++++++ .../mf_ultralight/mf_ultralight_listener_i.h | 16 ++++++ 3 files changed, 81 insertions(+), 30 deletions(-) diff --git a/lib/nfc/protocols/mf_ultralight/mf_ultralight_listener.c b/lib/nfc/protocols/mf_ultralight/mf_ultralight_listener.c index 5bef2a354c9..701e35f4563 100644 --- a/lib/nfc/protocols/mf_ultralight/mf_ultralight_listener.c +++ b/lib/nfc/protocols/mf_ultralight/mf_ultralight_listener.c @@ -4,16 +4,12 @@ #include #include +#include #define TAG "MfUltralightListener" #define MF_ULTRALIGHT_LISTENER_MAX_TX_BUFF_SIZE (256) -typedef enum { - MfUltralightListenerAccessTypeRead, - MfUltralightListenerAccessTypeWrite, -} MfUltralightListenerAccessType; - typedef struct { uint8_t cmd; size_t cmd_len_bits; @@ -24,31 +20,15 @@ static bool mf_ultralight_listener_check_access( MfUltralightListener* instance, uint16_t start_page, MfUltralightListenerAccessType access_type) { - bool access_success = false; - bool is_write_op = (access_type == MfUltralightListenerAccessTypeWrite); - - do { - if(!mf_ultralight_support_feature( - instance->features, MfUltralightFeatureSupportPasswordAuth)) { - access_success = true; - break; - } - if(instance->auth_state != MfUltralightListenerAuthStateSuccess) { - if((instance->config->auth0 <= start_page) && - (instance->config->access.prot || is_write_op)) { - break; - } - } - if(instance->config->access.cfglck && is_write_op) { - uint16_t config_page_start = instance->data->pages_total - 4; - if((start_page == config_page_start) || (start_page == config_page_start + 1)) { - break; - } - } - - access_success = true; - } while(false); - + bool access_success = true; + + if(mf_ultralight_support_feature(instance->features, MfUltralightFeatureSupportAuthenticate)) { + access_success = mf_ultralight_c_check_access( + instance->data, start_page, access_type, instance->auth_state); + } else if(mf_ultralight_support_feature( + instance->features, MfUltralightFeatureSupportPasswordAuth)) { + access_success = mf_ultralight_common_check_access(instance, start_page, access_type); + } return access_success; } 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 64647492de1..c09958ddd09 100644 --- a/lib/nfc/protocols/mf_ultralight/mf_ultralight_listener_i.c +++ b/lib/nfc/protocols/mf_ultralight/mf_ultralight_listener_i.c @@ -576,4 +576,59 @@ 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; +} + +bool mf_ultralight_common_check_access( + const MfUltralightListener* instance, + const uint16_t start_page, + const MfUltralightListenerAccessType access_type) { + bool access_success = false; + bool is_write_op = (access_type == MfUltralightListenerAccessTypeWrite); + + do { + if(instance->auth_state != MfUltralightListenerAuthStateSuccess) { + if((instance->config->auth0 <= start_page) && + (instance->config->access.prot || is_write_op)) { + break; + } + } + + if(instance->config->access.cfglck && is_write_op) { + uint16_t config_page_start = instance->data->pages_total - 4; + if((start_page == config_page_start) || (start_page == config_page_start + 1)) { + break; + } + } + + access_success = true; + } while(false); + + return access_success; +} + +bool mf_ultralight_c_check_access( + const MfUltralightData* data, + const uint16_t start_page, + const MfUltralightListenerAccessType access_type, + const MfUltralightListenerAuthState auth_state) { + bool access_success = false; + bool is_write_op = (access_type == MfUltralightListenerAccessTypeWrite); + + do { + const uint8_t auth0 = data->page[42].data[0]; + const uint8_t auth1 = data->page[43].data[0] & 0x01; + + if(auth0 < 0x03 || auth0 >= 0x30 || auth_state == MfUltralightListenerAuthStateSuccess) { + access_success = true; + break; + } + + if((auth0 <= start_page) && ((auth1 == 0) || (auth1 == 1 || is_write_op))) { + break; + } + + access_success = true; + } while(false); + + return access_success; } \ 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 ba448d0879c..1ac4714ec26 100644 --- a/lib/nfc/protocols/mf_ultralight/mf_ultralight_listener_i.h +++ b/lib/nfc/protocols/mf_ultralight/mf_ultralight_listener_i.h @@ -13,6 +13,11 @@ typedef enum { MfUltralightListenerAuthStateSuccess, } MfUltralightListenerAuthState; +typedef enum { + MfUltralightListenerAccessTypeRead, + MfUltralightListenerAccessTypeWrite, +} MfUltralightListenerAccessType; + typedef enum { MfUltralightCommandNotFound, MfUltralightCommandProcessed, @@ -118,6 +123,17 @@ bool mf_ultralight_auth_limit_check_and_update(MfUltralightListener* instance, b bool mf_ultralight_auth_check_password( const MfUltralightAuthPassword* config_pass, const MfUltralightAuthPassword* auth_pass); + +bool mf_ultralight_common_check_access( + const MfUltralightListener* instance, + const uint16_t start_page, + const MfUltralightListenerAccessType access_type); + +bool mf_ultralight_c_check_access( + const MfUltralightData* data, + const uint16_t start_page, + const MfUltralightListenerAccessType access_type, + const MfUltralightListenerAuthState auth_state); #ifdef __cplusplus } #endif From b7d30865cff04295b41a224ecdd0826e1c9b34d0 Mon Sep 17 00:00:00 2001 From: RebornedBrain Date: Thu, 13 Jun 2024 15:44:01 +0300 Subject: [PATCH 04/25] Ultralight C authentication command handlers added --- .../mf_ultralight/mf_ultralight_listener.c | 79 ++++++++++++++++++- .../mf_ultralight/mf_ultralight_listener_i.h | 3 + 2 files changed, 81 insertions(+), 1 deletion(-) diff --git a/lib/nfc/protocols/mf_ultralight/mf_ultralight_listener.c b/lib/nfc/protocols/mf_ultralight/mf_ultralight_listener.c index 701e35f4563..305b2a3f1ba 100644 --- a/lib/nfc/protocols/mf_ultralight/mf_ultralight_listener.c +++ b/lib/nfc/protocols/mf_ultralight/mf_ultralight_listener.c @@ -545,6 +545,78 @@ static MfUltralightCommand return command; } +static MfUltralightCommand + mf_ultralight_c_authenticate_handler_p2(MfUltralightListener* instance, BitBuffer* buffer) { + MfUltralightCommand command = MfUltralightCommandNotProcessedNAK; + FURI_LOG_T(TAG, "CMD_ULC_AUTH_2"); + UNUSED(instance); + do { + if(bit_buffer_get_byte(buffer, 0) != 0xAF || bit_buffer_get_size_bytes(buffer) != 16 + 1) + break; + + const uint8_t* data = bit_buffer_get_data(buffer) + 1; + const uint8_t* iv = data + 8; + + uint8_t out[16] = {0}; + + const uint8_t* ck = mf_ultralight_3des_get_key(instance->data); + mf_ultralight_3des_decrypt( + &instance->des_context, ck, instance->encB, data, sizeof(out), out); + + uint8_t* rndA = out; + const uint8_t* decoded_shifted_rndB = out + 8; + + mf_ultralight_3des_shift_data(rndA); + mf_ultralight_3des_shift_data(instance->rndB); + if(memcmp(decoded_shifted_rndB, instance->rndB, 8) == 0) { + instance->auth_state = MfUltralightListenerAuthStateSuccess; + } + + mf_ultralight_3des_encrypt(&instance->des_context, ck, iv, rndA, rndA); + + bit_buffer_reset(instance->tx_buffer); + bit_buffer_append_byte(instance->tx_buffer, 0x00); + bit_buffer_append_bytes(instance->tx_buffer, rndA, 8); + + iso14443_3a_listener_send_standard_frame( + instance->iso14443_3a_listener, instance->tx_buffer); + + command = MfUltralightCommandProcessed; + } while(false); + return command; +} + +static MfUltralightCommand + mf_ultralight_c_authenticate_handler_p1(MfUltralightListener* instance, BitBuffer* buffer) { + MfUltralightCommand command = MfUltralightCommandNotProcessedNAK; + FURI_LOG_T(TAG, "CMD_ULC_AUTH_1"); + do { + if(!mf_ultralight_support_feature( + instance->features, MfUltralightFeatureSupportAuthenticate) && + bit_buffer_get_byte(buffer, 1) == 0x00) + break; + + bit_buffer_reset(instance->tx_buffer); + bit_buffer_append_byte(instance->tx_buffer, 0xAF); + + furi_hal_random_fill_buf(instance->rndB, sizeof(instance->rndB)); + + const uint8_t iv[8] = {0}; + const uint8_t* ck = mf_ultralight_3des_get_key(instance->data); + + mf_ultralight_3des_encrypt(&instance->des_context, ck, iv, instance->rndB, instance->encB); + + bit_buffer_append_bytes(instance->tx_buffer, instance->encB, sizeof(instance->encB)); + + iso14443_3a_listener_send_standard_frame( + instance->iso14443_3a_listener, instance->tx_buffer); + command = MfUltralightCommandProcessed; + mf_ultralight_composite_command_set_next( + instance, mf_ultralight_c_authenticate_handler_p2); + } while(false); + return command; +} + static const MfUltralightListenerCmdHandler mf_ultralight_command[] = { { .cmd = MF_ULTRALIGHT_CMD_READ_PAGE, @@ -611,7 +683,11 @@ static const MfUltralightListenerCmdHandler mf_ultralight_command[] = { .cmd_len_bits = 21 * 8, .callback = mf_ultralight_listener_vcsl_handler, }, -}; + { + .cmd = MF_ULTRALIGHT_CMD_AUTH, + .cmd_len_bits = 2 * 8, + .callback = mf_ultralight_c_authenticate_handler_p1, + }}; static void mf_ultralight_listener_prepare_emulation(MfUltralightListener* instance) { MfUltralightData* data = instance->data; @@ -675,6 +751,7 @@ MfUltralightListener* mf_ultralight_listener_alloc( instance->generic_event.protocol = NfcProtocolMfUltralight; instance->generic_event.instance = instance; instance->generic_event.event_data = &instance->mfu_event; + mbedtls_des3_init(&instance->des_context); return instance; } 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 1ac4714ec26..d6efe02b478 100644 --- a/lib/nfc/protocols/mf_ultralight/mf_ultralight_listener_i.h +++ b/lib/nfc/protocols/mf_ultralight/mf_ultralight_listener_i.h @@ -68,6 +68,9 @@ struct MfUltralightListener { bool single_counter_increased; MfUltralightMirrorMode mirror; MfUltralightListenerCompositeCommandContext composite_cmd; + mbedtls_des3_context des_context; + uint8_t rndB[8]; + uint8_t encB[8]; void* context; }; From 7d7bd1102496009bf7f7e52314d52ec42f8b35ce Mon Sep 17 00:00:00 2001 From: RebornedBrain Date: Thu, 13 Jun 2024 15:45:04 +0300 Subject: [PATCH 05/25] Update api_symbols.csv and api_symbols.csv --- targets/f18/api_symbols.csv | 2 +- targets/f7/api_symbols.csv | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/targets/f18/api_symbols.csv b/targets/f18/api_symbols.csv index 91999f7a0ae..5ec647d33c0 100644 --- a/targets/f18/api_symbols.csv +++ b/targets/f18/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,64.2,, +Version,+,69.1,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/bt/bt_service/bt_keys_storage.h,, Header,+,applications/services/cli/cli.h,, diff --git a/targets/f7/api_symbols.csv b/targets/f7/api_symbols.csv index 64e0a2b252b..21c05ca7bf9 100644 --- a/targets/f7/api_symbols.csv +++ b/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,v,68.1,, +Version,+,69.1,, 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,, @@ -2524,8 +2524,10 @@ Function,+,mf_desfire_save,_Bool,"const MfDesfireData*, FlipperFormat*" Function,+,mf_desfire_send_chunks,MfDesfireError,"MfDesfirePoller*, const BitBuffer*, BitBuffer*" Function,+,mf_desfire_set_uid,_Bool,"MfDesfireData*, const uint8_t*, size_t" Function,+,mf_desfire_verify,_Bool,"MfDesfireData*, const FuriString*" -Function,+,mf_ultralight_3des_decrypt,void,"mbedtls_des3_context*, const uint8_t*, const uint8_t*, const uint8_t*, uint8_t*" -Function,?,mf_ultralight_3des_encrypt,void,"mbedtls_des3_context*, const uint8_t*, const uint8_t*, const uint8_t*, uint8_t*" +Function,+,mf_ultralight_3des_decrypt,void,"mbedtls_des3_context*, const uint8_t*, const uint8_t*, const uint8_t*, const uint8_t, uint8_t*" +Function,+,mf_ultralight_3des_encrypt,void,"mbedtls_des3_context*, const uint8_t*, const uint8_t*, const uint8_t*, uint8_t*" +Function,+,mf_ultralight_3des_get_key,const uint8_t*,const MfUltralightData* +Function,+,mf_ultralight_3des_shift_data,void,uint8_t* Function,+,mf_ultralight_alloc,MfUltralightData*, Function,+,mf_ultralight_copy,void,"MfUltralightData*, const MfUltralightData*" Function,+,mf_ultralight_detect_protocol,_Bool,const Iso14443_3aData* From 37ab0b5fcd84d28d4b8e077cd1a42ed8f33b1d62 Mon Sep 17 00:00:00 2001 From: RebornedBrain Date: Mon, 17 Jun 2024 15:50:03 +0300 Subject: [PATCH 06/25] Length added to ultralight encrypt function --- lib/nfc/protocols/mf_ultralight/mf_ultralight.c | 3 ++- lib/nfc/protocols/mf_ultralight/mf_ultralight.h | 1 + lib/nfc/protocols/mf_ultralight/mf_ultralight_listener.c | 5 +++-- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/nfc/protocols/mf_ultralight/mf_ultralight.c b/lib/nfc/protocols/mf_ultralight/mf_ultralight.c index c61323f97da..d9b0388d493 100644 --- a/lib/nfc/protocols/mf_ultralight/mf_ultralight.c +++ b/lib/nfc/protocols/mf_ultralight/mf_ultralight.c @@ -690,6 +690,7 @@ void mf_ultralight_3des_encrypt( const uint8_t* ck, const uint8_t* iv, const uint8_t* input, + const uint8_t length, uint8_t* out) { furi_check(ctx); furi_check(ck); @@ -698,7 +699,7 @@ void mf_ultralight_3des_encrypt( furi_check(out); mbedtls_des3_set2key_enc(ctx, ck); - mbedtls_des3_crypt_cbc(ctx, MBEDTLS_DES_ENCRYPT, 8, (uint8_t*)iv, input, out); + mbedtls_des3_crypt_cbc(ctx, MBEDTLS_DES_ENCRYPT, length, (uint8_t*)iv, input, out); } void mf_ultralight_3des_decrypt( diff --git a/lib/nfc/protocols/mf_ultralight/mf_ultralight.h b/lib/nfc/protocols/mf_ultralight/mf_ultralight.h index 48abddb6459..16ad1dad1f3 100644 --- a/lib/nfc/protocols/mf_ultralight/mf_ultralight.h +++ b/lib/nfc/protocols/mf_ultralight/mf_ultralight.h @@ -236,6 +236,7 @@ void mf_ultralight_3des_encrypt( const uint8_t* ck, const uint8_t* iv, const uint8_t* input, + const uint8_t length, uint8_t* out); void mf_ultralight_3des_decrypt( diff --git a/lib/nfc/protocols/mf_ultralight/mf_ultralight_listener.c b/lib/nfc/protocols/mf_ultralight/mf_ultralight_listener.c index 305b2a3f1ba..75e8940af71 100644 --- a/lib/nfc/protocols/mf_ultralight/mf_ultralight_listener.c +++ b/lib/nfc/protocols/mf_ultralight/mf_ultralight_listener.c @@ -572,7 +572,7 @@ static MfUltralightCommand instance->auth_state = MfUltralightListenerAuthStateSuccess; } - mf_ultralight_3des_encrypt(&instance->des_context, ck, iv, rndA, rndA); + mf_ultralight_3des_encrypt(&instance->des_context, ck, iv, rndA, 8, rndA); bit_buffer_reset(instance->tx_buffer); bit_buffer_append_byte(instance->tx_buffer, 0x00); @@ -604,7 +604,8 @@ static MfUltralightCommand const uint8_t iv[8] = {0}; const uint8_t* ck = mf_ultralight_3des_get_key(instance->data); - mf_ultralight_3des_encrypt(&instance->des_context, ck, iv, instance->rndB, instance->encB); + mf_ultralight_3des_encrypt( + &instance->des_context, ck, iv, instance->rndB, 8, instance->encB); bit_buffer_append_bytes(instance->tx_buffer, instance->encB, sizeof(instance->encB)); From fc8abff328aea2738ddca6f828c6a892d5a9bc85 Mon Sep 17 00:00:00 2001 From: RebornedBrain Date: Mon, 17 Jun 2024 15:50:54 +0300 Subject: [PATCH 07/25] New structure for storing 3des key added --- lib/nfc/protocols/mf_ultralight/mf_ultralight.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/nfc/protocols/mf_ultralight/mf_ultralight.h b/lib/nfc/protocols/mf_ultralight/mf_ultralight.h index 16ad1dad1f3..edc9e3975dd 100644 --- a/lib/nfc/protocols/mf_ultralight/mf_ultralight.h +++ b/lib/nfc/protocols/mf_ultralight/mf_ultralight.h @@ -120,6 +120,10 @@ typedef struct { uint8_t data[MF_ULTRALIGHT_AUTH_PASSWORD_SIZE]; } MfUltralightAuthPassword; +typedef struct { + uint8_t data[16]; +} MfUltralightC3DesAuthKey; + typedef struct { uint8_t data[MF_ULTRALIGHT_AUTH_PACK_SIZE]; } MfUltralightAuthPack; From 788df004538059e1e9a1d04a8dbe5c69fad4aabe Mon Sep 17 00:00:00 2001 From: RebornedBrain Date: Mon, 17 Jun 2024 15:51:21 +0300 Subject: [PATCH 08/25] Reseting of 3des_key added --- lib/nfc/protocols/mf_ultralight/mf_ultralight_listener.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/nfc/protocols/mf_ultralight/mf_ultralight_listener.c b/lib/nfc/protocols/mf_ultralight/mf_ultralight_listener.c index 75e8940af71..f3ed8fd55b5 100644 --- a/lib/nfc/protocols/mf_ultralight/mf_ultralight_listener.c +++ b/lib/nfc/protocols/mf_ultralight/mf_ultralight_listener.c @@ -764,6 +764,7 @@ void mf_ultralight_listener_free(MfUltralightListener* instance) { bit_buffer_free(instance->tx_buffer); furi_string_free(instance->mirror.ascii_mirror_data); + mbedtls_des3_free(&instance->des_context); free(instance); } From 62e7fc5bd188d569d617a5c0dbe47e891ee107f0 Mon Sep 17 00:00:00 2001 From: RebornedBrain Date: Mon, 17 Jun 2024 15:59:29 +0300 Subject: [PATCH 09/25] des_context init/deinit added to poller --- lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.c b/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.c index bc4ebd51559..d532d62919c 100644 --- a/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.c +++ b/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.c @@ -180,7 +180,7 @@ MfUltralightPoller* mf_ultralight_poller_alloc(Iso14443_3aPoller* iso14443_3a_po instance->general_event.protocol = NfcProtocolMfUltralight; instance->general_event.event_data = &instance->mfu_event; instance->general_event.instance = instance; - + mbedtls_des3_init(&instance->des_context); return instance; } @@ -193,6 +193,7 @@ void mf_ultralight_poller_free(MfUltralightPoller* instance) { bit_buffer_free(instance->tx_buffer); bit_buffer_free(instance->rx_buffer); mf_ultralight_free(instance->data); + mbedtls_des3_free(&instance->des_context); free(instance); } From f5301c460d299943ea99fe059f16b973a4cbd6e0 Mon Sep 17 00:00:00 2001 From: RebornedBrain Date: Mon, 17 Jun 2024 16:04:56 +0300 Subject: [PATCH 10/25] New poller step for ultralight c auth added --- .../mf_ultralight/mf_ultralight_poller.c | 38 +++++- .../mf_ultralight/mf_ultralight_poller.h | 14 ++- .../mf_ultralight/mf_ultralight_poller_i.c | 117 +++++++++++++++++- .../mf_ultralight/mf_ultralight_poller_i.h | 4 + 4 files changed, 164 insertions(+), 9 deletions(-) diff --git a/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.c b/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.c index d532d62919c..fa3690eb3f0 100644 --- a/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.c +++ b/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.c @@ -3,6 +3,7 @@ #include #include +#include #define TAG "MfUltralightPoller" @@ -259,7 +260,7 @@ static NfcCommand mf_ultralight_poller_handler_read_version(MfUltralightPoller* } static NfcCommand mf_ultralight_poller_handler_check_ultralight_c(MfUltralightPoller* instance) { - instance->error = mf_ultralight_poller_authenticate(instance); + instance->error = mf_ultralight_poller_authentication_test(instance); if(instance->error == MfUltralightErrorNone) { FURI_LOG_D(TAG, "Ultralight C detected"); instance->data->type = MfUltralightTypeMfulC; @@ -321,6 +322,10 @@ static NfcCommand mf_ultralight_poller_handler_read_signature(MfUltralightPoller } } else { FURI_LOG_D(TAG, "Skip reading signature"); + if(mf_ultralight_support_feature( + instance->feature_set, MfUltralightFeatureSupportAuthenticate)) { + next_state = MfUltralightPollerStateAuthMfulC; + } } instance->state = next_state; @@ -442,6 +447,36 @@ static NfcCommand mf_ultralight_poller_handler_auth(MfUltralightPoller* instance return command; } +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"); + + uint8_t output[16]; + uint8_t RndA[8] = {0}; + furi_hal_random_fill_buf(RndA, sizeof(RndA)); + instance->error = mf_ultralight_poller_authenticate_start(instance, RndA, output); + + uint8_t decoded_shifted_RndA[8] = {0}; + const uint8_t* RndB = output + 8; + instance->error = mf_ultralight_poller_authenticate_end( + instance, RndB, output, decoded_shifted_RndA); + + mf_ultralight_3des_shift_data(RndA); + instance->auth_context.auth_success = (memcmp(RndA, decoded_shifted_RndA, 8) == 0); + } + } + instance->state = MfUltralightPollerStateReadPages; + + return command; +} + static NfcCommand mf_ultralight_poller_handler_read_pages(MfUltralightPoller* instance) { MfUltralightPageReadCommandData data = {}; uint16_t start_page = instance->pages_read; @@ -667,6 +702,7 @@ static const MfUltralightPollerReadHandler mf_ultralight_poller_handler_read_tearing_flags, [MfUltralightPollerStateAuth] = mf_ultralight_poller_handler_auth, [MfUltralightPollerStateTryDefaultPass] = mf_ultralight_poller_handler_try_default_pass, + [MfUltralightPollerStateAuthMfulC] = mf_ultralight_poller_handler_auth_ultralight_c, [MfUltralightPollerStateReadPages] = mf_ultralight_poller_handler_read_pages, [MfUltralightPollerStateReadFailed] = mf_ultralight_poller_handler_read_fail, [MfUltralightPollerStateReadSuccess] = mf_ultralight_poller_handler_read_success, diff --git a/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.h b/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.h index 2343be089bf..0ed39519042 100644 --- a/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.h +++ b/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.h @@ -42,6 +42,7 @@ typedef enum { */ typedef struct { MfUltralightAuthPassword password; /**< Password to be used for authentication. */ + MfUltralightC3DesAuthKey _3des_key; MfUltralightAuthPack pack; /**< Pack received on successfull authentication. */ bool auth_success; /**< Set to true if authentication succeeded, false otherwise. */ bool skip_auth; /**< Set to true if authentication should be skipped, false otherwise. */ @@ -80,7 +81,7 @@ MfUltralightError mf_ultralight_poller_auth_pwd( MfUltralightPoller* instance, MfUltralightPollerAuthContext* data); -/** +/** TODO:Adjust this comment * @brief Start authentication procedure. * * Must ONLY be used inside the callback function. @@ -90,7 +91,16 @@ MfUltralightError mf_ultralight_poller_auth_pwd( * @param[in, out] instance pointer to the instance to be used in the transaction. * @return MfUltralightErrorNone if card supports authentication command, an error code on otherwise. */ -MfUltralightError mf_ultralight_poller_authenticate(MfUltralightPoller* instance); +MfUltralightError mf_ultralight_poller_authenticate_start( + MfUltralightPoller* instance, + const uint8_t* RndA, + uint8_t* output); + +MfUltralightError mf_ultralight_poller_authenticate_end( + MfUltralightPoller* instance, + const uint8_t* RndB, + const uint8_t* request, + uint8_t* response); /** * @brief Read page from card. 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 cc3433f7318..51c07faed22 100644 --- a/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller_i.c +++ b/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller_i.c @@ -62,11 +62,17 @@ MfUltralightError mf_ultralight_poller_auth_pwd( return ret; } -MfUltralightError mf_ultralight_poller_authenticate(MfUltralightPoller* instance) { +static MfUltralightError mf_ultralight_poller_send_authenticate_cmd( + MfUltralightPoller* instance, + const uint8_t* cmd, + const uint8_t length, + const bool initial_cmd, + uint8_t* response) { furi_check(instance); + furi_check(cmd); + furi_check(response); - uint8_t auth_cmd[2] = {MF_ULTRALIGHT_CMD_AUTH, 0x00}; - bit_buffer_copy_bytes(instance->tx_buffer, auth_cmd, sizeof(auth_cmd)); + bit_buffer_copy_bytes(instance->tx_buffer, cmd, length); MfUltralightError ret = MfUltralightErrorNone; Iso14443_3aError error = Iso14443_3aErrorNone; @@ -80,12 +86,111 @@ MfUltralightError mf_ultralight_poller_authenticate(MfUltralightPoller* instance ret = mf_ultralight_process_error(error); break; } - if((bit_buffer_get_size_bytes(instance->rx_buffer) != MF_ULTRALIGHT_AUTH_RESPONSE_SIZE) && - (bit_buffer_get_byte(instance->rx_buffer, 0) != 0xAF)) { + + const uint8_t expected_response_code = initial_cmd ? 0xAF : 0x00; + if((bit_buffer_get_byte(instance->rx_buffer, 0) != expected_response_code) || + (bit_buffer_get_size_bytes(instance->rx_buffer) != MF_ULTRALIGHT_AUTH_RESPONSE_SIZE)) { ret = MfUltralightErrorAuth; break; } - //Save encrypted PICC random number RndB here if needed + + memcpy( + response, + bit_buffer_get_data(instance->rx_buffer) + 1, + MF_ULTRALIGHT_AUTH_RESPONSE_SIZE - 1); + } while(false); + + return ret; +} + +MfUltralightError mf_ultralight_poller_authentication_test(MfUltralightPoller* instance) { + furi_check(instance); + + uint8_t auth_cmd[2] = {MF_ULTRALIGHT_CMD_AUTH, 0x00}; + uint8_t dummy[8]; + return mf_ultralight_poller_send_authenticate_cmd( + instance, auth_cmd, sizeof(auth_cmd), true, dummy); +} + +MfUltralightError mf_ultralight_poller_authenticate_start( + MfUltralightPoller* instance, + const uint8_t* RndA, + uint8_t* output) { + furi_check(instance); + furi_check(RndA); + furi_check(output); + + MfUltralightError ret = MfUltralightErrorNone; + do { + uint8_t encRndB[8] = {0}; + uint8_t auth_cmd[2] = {MF_ULTRALIGHT_CMD_AUTH, 0x00}; + ret = mf_ultralight_poller_send_authenticate_cmd( + instance, auth_cmd, sizeof(auth_cmd), true, encRndB /* instance->encRndB */); + + if(ret != MfUltralightErrorNone) break; + + uint8_t iv[8] = {0}; + uint8_t* RndB = output + 8; + mf_ultralight_3des_decrypt( + &instance->des_context, + instance->mfu_event.data->auth_context._3des_key.data, + iv, + encRndB, + //instance->encRndB, + sizeof(encRndB), + RndB); + mf_ultralight_3des_shift_data(RndB); + + memcpy(output, /* instance->RndA */ RndA, 8); + + mf_ultralight_3des_encrypt( + &instance->des_context, + instance->mfu_event.data->auth_context._3des_key.data, + encRndB, + output, + 16, + output); + + } while(false); + + return ret; +} + +MfUltralightError mf_ultralight_poller_authenticate_end( + MfUltralightPoller* instance, + const uint8_t* RndB, + const uint8_t* request, + uint8_t* response) { + furi_check(instance); + furi_check(RndB); + furi_check(request); + furi_check(response); + + uint8_t auth_cmd[17] = {0xAF}; + memcpy(&auth_cmd[1], request, 16); + bit_buffer_copy_bytes(instance->tx_buffer, auth_cmd, sizeof(auth_cmd)); + + MfUltralightError ret = MfUltralightErrorNone; + do { + ret = mf_ultralight_poller_send_authenticate_cmd( + instance, auth_cmd, sizeof(auth_cmd), false, response); + + if(ret != MfUltralightErrorNone) break; + + // uint8_t decoded_shifted_RndA[8] = {0}; + mf_ultralight_3des_decrypt( + &instance->des_context, + instance->mfu_event.data->auth_context._3des_key.data, + RndB, + bit_buffer_get_data(instance->rx_buffer) + 1, + 8, + response); + + /* memcpy( + response, + bit_buffer_get_data(instance->rx_buffer) + 1, + MF_ULTRALIGHT_AUTH_RESPONSE_SIZE - 1); */ + } while(false); return ret; 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 3f8645fe73a..be269f899ca 100644 --- a/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller_i.h +++ b/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller_i.h @@ -58,6 +58,7 @@ typedef enum { MfUltralightPollerStateReadCounters, MfUltralightPollerStateReadTearingFlags, MfUltralightPollerStateAuth, + MfUltralightPollerStateAuthMfulC, MfUltralightPollerStateReadPages, MfUltralightPollerStateTryDefaultPass, MfUltralightPollerStateReadFailed, @@ -87,6 +88,7 @@ struct MfUltralightPoller { uint8_t tearing_flag_total; uint16_t current_page; MfUltralightError error; + mbedtls_des3_context des_context; NfcGenericEvent general_event; MfUltralightPollerEvent mfu_event; @@ -110,6 +112,8 @@ bool mf_ultralight_poller_ntag_i2c_addr_lin_to_tag( uint8_t* tag, uint8_t* pages_left); +MfUltralightError mf_ultralight_poller_authentication_test(MfUltralightPoller* instance); + #ifdef __cplusplus } #endif From 80c57e8b4b65d6f375e55c0f362fbc6cae82e50e Mon Sep 17 00:00:00 2001 From: RebornedBrain Date: Mon, 17 Jun 2024 16:13:28 +0300 Subject: [PATCH 11/25] Added ultralight c des key to application --- applications/main/nfc/helpers/mf_ultralight_auth.c | 1 + applications/main/nfc/helpers/mf_ultralight_auth.h | 1 + .../nfc/helpers/protocol_support/mf_ultralight/mf_ultralight.c | 1 + 3 files changed, 3 insertions(+) diff --git a/applications/main/nfc/helpers/mf_ultralight_auth.c b/applications/main/nfc/helpers/mf_ultralight_auth.c index d954c1f7e91..93138712dea 100644 --- a/applications/main/nfc/helpers/mf_ultralight_auth.c +++ b/applications/main/nfc/helpers/mf_ultralight_auth.c @@ -20,6 +20,7 @@ void mf_ultralight_auth_reset(MfUltralightAuth* instance) { instance->type = MfUltralightAuthTypeNone; memset(&instance->password, 0, sizeof(MfUltralightAuthPassword)); + memset(&instance->_3des_key, 0, sizeof(MfUltralightC3DesAuthKey)); memset(&instance->pack, 0, sizeof(MfUltralightAuthPack)); } diff --git a/applications/main/nfc/helpers/mf_ultralight_auth.h b/applications/main/nfc/helpers/mf_ultralight_auth.h index 51267b3eab3..f0715ff490a 100644 --- a/applications/main/nfc/helpers/mf_ultralight_auth.h +++ b/applications/main/nfc/helpers/mf_ultralight_auth.h @@ -17,6 +17,7 @@ typedef enum { typedef struct { MfUltralightAuthType type; MfUltralightAuthPassword password; + MfUltralightC3DesAuthKey _3des_key; MfUltralightAuthPack pack; } MfUltralightAuth; diff --git a/applications/main/nfc/helpers/protocol_support/mf_ultralight/mf_ultralight.c b/applications/main/nfc/helpers/protocol_support/mf_ultralight/mf_ultralight.c index a3028905fc1..20f582eaaeb 100644 --- a/applications/main/nfc/helpers/protocol_support/mf_ultralight/mf_ultralight.c +++ b/applications/main/nfc/helpers/protocol_support/mf_ultralight/mf_ultralight.c @@ -150,6 +150,7 @@ static NfcCommand } if(!mf_ultralight_event->data->auth_context.skip_auth) { mf_ultralight_event->data->auth_context.password = instance->mf_ul_auth->password; + mf_ultralight_event->data->auth_context._3des_key = instance->mf_ul_auth->_3des_key; } } else if(mf_ultralight_event->type == MfUltralightPollerEventTypeAuthSuccess) { instance->mf_ul_auth->pack = mf_ultralight_event->data->auth_context.pack; From bf5ce424fd008f5cce7e93f635911dfc91f888e4 Mon Sep 17 00:00:00 2001 From: RebornedBrain Date: Mon, 17 Jun 2024 17:18:17 +0300 Subject: [PATCH 12/25] Renamed felica unlock scenes to more generic des auth scenes, because they are now used also for ultralight c --- .../helpers/protocol_support/felica/felica.c | 4 +-- .../nfc_protocol_support_unlock_helper.c | 2 +- .../main/nfc/scenes/nfc_scene_config.h | 4 +-- ...input.c => nfc_scene_des_auth_key_input.c} | 27 +++++++++++++------ ...arn.c => nfc_scene_des_auth_unlock_warn.c} | 17 +++++++----- 5 files changed, 35 insertions(+), 19 deletions(-) rename applications/main/nfc/scenes/{nfc_scene_felica_key_input.c => nfc_scene_des_auth_key_input.c} (52%) rename applications/main/nfc/scenes/{nfc_scene_felica_unlock_warn.c => nfc_scene_des_auth_unlock_warn.c} (68%) diff --git a/applications/main/nfc/helpers/protocol_support/felica/felica.c b/applications/main/nfc/helpers/protocol_support/felica/felica.c index ceb18065369..561cd4d2e91 100644 --- a/applications/main/nfc/helpers/protocol_support/felica/felica.c +++ b/applications/main/nfc/helpers/protocol_support/felica/felica.c @@ -106,7 +106,7 @@ static void nfc_scene_read_success_on_enter_felica(NfcApp* instance) { FuriString* temp_str = furi_string_alloc(); - if(!scene_manager_has_previous_scene(instance->scene_manager, NfcSceneFelicaUnlockWarn)) { + if(!scene_manager_has_previous_scene(instance->scene_manager, NfcSceneDesAuthUnlockWarn)) { furi_string_cat_printf( temp_str, "\e#%s\n", nfc_device_get_name(device, NfcDeviceNameTypeFull)); nfc_render_felica_info(data, NfcProtocolFormatTypeShort, temp_str); @@ -163,7 +163,7 @@ static void nfc_scene_read_menu_on_enter_felica(NfcApp* instance) { static bool nfc_scene_read_menu_on_event_felica(NfcApp* instance, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeCustom) { if(event.event == SubmenuIndexUnlock) { - scene_manager_next_scene(instance->scene_manager, NfcSceneFelicaKeyInput); + scene_manager_next_scene(instance->scene_manager, NfcSceneDesAuthKeyInput); return true; } } diff --git a/applications/main/nfc/helpers/protocol_support/nfc_protocol_support_unlock_helper.c b/applications/main/nfc/helpers/protocol_support/nfc_protocol_support_unlock_helper.c index f1d504d2486..598cf7a7e1b 100644 --- a/applications/main/nfc/helpers/protocol_support/nfc_protocol_support_unlock_helper.c +++ b/applications/main/nfc/helpers/protocol_support/nfc_protocol_support_unlock_helper.c @@ -22,7 +22,7 @@ void nfc_unlock_helper_setup_from_state(NfcApp* instance) { bool unlocking = scene_manager_has_previous_scene( instance->scene_manager, NfcSceneMfUltralightUnlockWarn) || - scene_manager_has_previous_scene(instance->scene_manager, NfcSceneFelicaUnlockWarn); + scene_manager_has_previous_scene(instance->scene_manager, NfcSceneDesAuthUnlockWarn); uint32_t state = unlocking ? NfcSceneReadMenuStateCardSearch : NfcSceneReadMenuStateCardFound; diff --git a/applications/main/nfc/scenes/nfc_scene_config.h b/applications/main/nfc/scenes/nfc_scene_config.h index 3017d16a406..83c8ffeed3e 100644 --- a/applications/main/nfc/scenes/nfc_scene_config.h +++ b/applications/main/nfc/scenes/nfc_scene_config.h @@ -33,8 +33,8 @@ ADD_SCENE(nfc, mf_ultralight_unlock_menu, MfUltralightUnlockMenu) ADD_SCENE(nfc, mf_ultralight_unlock_warn, MfUltralightUnlockWarn) ADD_SCENE(nfc, mf_ultralight_key_input, MfUltralightKeyInput) ADD_SCENE(nfc, mf_ultralight_capture_pass, MfUltralightCapturePass) -ADD_SCENE(nfc, felica_key_input, FelicaKeyInput) -ADD_SCENE(nfc, felica_unlock_warn, FelicaUnlockWarn) +ADD_SCENE(nfc, des_auth_key_input, DesAuthKeyInput) +ADD_SCENE(nfc, des_auth_unlock_warn, DesAuthUnlockWarn) ADD_SCENE(nfc, mf_desfire_more_info, MfDesfireMoreInfo) ADD_SCENE(nfc, mf_desfire_app, MfDesfireApp) diff --git a/applications/main/nfc/scenes/nfc_scene_felica_key_input.c b/applications/main/nfc/scenes/nfc_scene_des_auth_key_input.c similarity index 52% rename from applications/main/nfc/scenes/nfc_scene_felica_key_input.c rename to applications/main/nfc/scenes/nfc_scene_des_auth_key_input.c index b04f12dae85..0c6a0ce5b91 100644 --- a/applications/main/nfc/scenes/nfc_scene_felica_key_input.c +++ b/applications/main/nfc/scenes/nfc_scene_des_auth_key_input.c @@ -1,43 +1,54 @@ #include "../nfc_app_i.h" -void nfc_scene_felica_key_input_byte_input_callback(void* context) { +void nfc_scene_des_auth_key_input_byte_input_callback(void* context) { NfcApp* nfc = context; view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventByteInputDone); } -void nfc_scene_felica_key_input_on_enter(void* context) { +void nfc_scene_des_auth_key_input_on_enter(void* context) { NfcApp* nfc = context; // Setup view + NfcProtocol protocol = nfc_device_get_protocol(nfc->nfc_device); + uint8_t* key = (protocol == NfcProtocolFelica) ? nfc->felica_auth->card_key.data : + nfc->mf_ul_auth->_3des_key.data; + ByteInput* byte_input = nfc->byte_input; byte_input_set_header_text(byte_input, "Enter key in hex"); byte_input_set_result_callback( byte_input, - nfc_scene_felica_key_input_byte_input_callback, + nfc_scene_des_auth_key_input_byte_input_callback, NULL, nfc, - nfc->felica_auth->card_key.data, + key, FELICA_DATA_BLOCK_SIZE); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewByteInput); } -bool nfc_scene_felica_key_input_on_event(void* context, SceneManagerEvent event) { +bool nfc_scene_des_auth_key_input_on_event(void* context, SceneManagerEvent event) { NfcApp* nfc = context; UNUSED(event); bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { if(event.event == NfcCustomEventByteInputDone) { - nfc->felica_auth->skip_auth = false; - scene_manager_next_scene(nfc->scene_manager, NfcSceneFelicaUnlockWarn); + NfcProtocol protocol = nfc_device_get_protocol(nfc->nfc_device); + + if(protocol == NfcProtocolFelica) { + nfc->felica_auth->skip_auth = false; + } else { + nfc->mf_ul_auth->type = MfUltralightAuthTypeManual; + } + + scene_manager_next_scene(nfc->scene_manager, NfcSceneDesAuthUnlockWarn); consumed = true; } } return consumed; } -void nfc_scene_felica_key_input_on_exit(void* context) { +void nfc_scene_des_auth_key_input_on_exit(void* context) { NfcApp* nfc = context; // Clear view diff --git a/applications/main/nfc/scenes/nfc_scene_felica_unlock_warn.c b/applications/main/nfc/scenes/nfc_scene_des_auth_unlock_warn.c similarity index 68% rename from applications/main/nfc/scenes/nfc_scene_felica_unlock_warn.c rename to applications/main/nfc/scenes/nfc_scene_des_auth_unlock_warn.c index 15b61dfa510..28b7f62f854 100644 --- a/applications/main/nfc/scenes/nfc_scene_felica_unlock_warn.c +++ b/applications/main/nfc/scenes/nfc_scene_des_auth_unlock_warn.c @@ -1,25 +1,30 @@ #include "../nfc_app_i.h" -void nfc_scene_felica_unlock_warn_dialog_callback(DialogExResult result, void* context) { +void nfc_scene_des_auth_unlock_warn_dialog_callback(DialogExResult result, void* context) { NfcApp* nfc = context; view_dispatcher_send_custom_event(nfc->view_dispatcher, result); } -void nfc_scene_felica_unlock_warn_on_enter(void* context) { +void nfc_scene_des_auth_unlock_warn_on_enter(void* context) { NfcApp* nfc = context; const char* message = "Risky Action!"; DialogEx* dialog_ex = nfc->dialog_ex; dialog_ex_set_context(dialog_ex, nfc); - dialog_ex_set_result_callback(dialog_ex, nfc_scene_felica_unlock_warn_dialog_callback); + dialog_ex_set_result_callback(dialog_ex, nfc_scene_des_auth_unlock_warn_dialog_callback); dialog_ex_set_header(dialog_ex, message, 64, 0, AlignCenter, AlignTop); FuriString* str = furi_string_alloc(); furi_string_cat_printf(str, "Unlock with key: "); + + NfcProtocol protocol = nfc_device_get_protocol(nfc->nfc_device); + uint8_t* key = (protocol == NfcProtocolFelica) ? nfc->felica_auth->card_key.data : + nfc->mf_ul_auth->_3des_key.data; + for(uint8_t i = 0; i < FELICA_DATA_BLOCK_SIZE; i++) - furi_string_cat_printf(str, "%02X ", nfc->felica_auth->card_key.data[i]); + furi_string_cat_printf(str, "%02X ", key[i]); furi_string_cat_printf(str, "?"); nfc_text_store_set(nfc, furi_string_get_cstr(str)); @@ -33,7 +38,7 @@ void nfc_scene_felica_unlock_warn_on_enter(void* context) { view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewDialogEx); } -bool nfc_scene_felica_unlock_warn_on_event(void* context, SceneManagerEvent event) { +bool nfc_scene_des_auth_unlock_warn_on_event(void* context, SceneManagerEvent event) { NfcApp* nfc = context; UNUSED(event); bool consumed = false; @@ -51,7 +56,7 @@ bool nfc_scene_felica_unlock_warn_on_event(void* context, SceneManagerEvent even return consumed; } -void nfc_scene_felica_unlock_warn_on_exit(void* context) { +void nfc_scene_des_auth_unlock_warn_on_exit(void* context) { NfcApp* nfc = context; dialog_ex_reset(nfc->dialog_ex); From bd9e1973cbba8b45955817fa58f2414d4781440b Mon Sep 17 00:00:00 2001 From: RebornedBrain Date: Mon, 17 Jun 2024 17:18:53 +0300 Subject: [PATCH 13/25] Show different menus for different ultralight card types --- .../protocol_support/mf_ultralight/mf_ultralight.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/applications/main/nfc/helpers/protocol_support/mf_ultralight/mf_ultralight.c b/applications/main/nfc/helpers/protocol_support/mf_ultralight/mf_ultralight.c index 20f582eaaeb..bf8311e98e1 100644 --- a/applications/main/nfc/helpers/protocol_support/mf_ultralight/mf_ultralight.c +++ b/applications/main/nfc/helpers/protocol_support/mf_ultralight/mf_ultralight.c @@ -244,7 +244,13 @@ static bool nfc_scene_read_and_saved_menu_on_event_mf_ultralight( if(event.type == SceneManagerEventTypeCustom) { if(event.event == SubmenuIndexUnlock) { - scene_manager_next_scene(instance->scene_manager, NfcSceneMfUltralightUnlockMenu); + const MfUltralightData* data = + nfc_device_get_data(instance->nfc_device, NfcProtocolMfUltralight); + + uint32_t next_scene = (data->type == MfUltralightTypeMfulC) ? + NfcSceneDesAuthKeyInput : + NfcSceneMfUltralightUnlockMenu; + scene_manager_next_scene(instance->scene_manager, next_scene); consumed = true; } else if(event.event == SubmenuIndexWrite) { scene_manager_next_scene(instance->scene_manager, NfcSceneMfUltralightWrite); From 876371cef24c7152c906cad897f7db60dd67f202 Mon Sep 17 00:00:00 2001 From: RebornedBrain Date: Mon, 17 Jun 2024 17:29:11 +0300 Subject: [PATCH 14/25] Update api_symbols.csv and api_symbols.csv --- targets/f18/api_symbols.csv | 2 +- targets/f7/api_symbols.csv | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/targets/f18/api_symbols.csv b/targets/f18/api_symbols.csv index 5ec647d33c0..efabf01ca5e 100644 --- a/targets/f18/api_symbols.csv +++ b/targets/f18/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,69.1,, +Version,+,72.0,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/bt/bt_service/bt_keys_storage.h,, Header,+,applications/services/cli/cli.h,, diff --git a/targets/f7/api_symbols.csv b/targets/f7/api_symbols.csv index 21c05ca7bf9..fea6345da69 100644 --- a/targets/f7/api_symbols.csv +++ b/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,69.1,, +Version,+,72.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,, @@ -2525,7 +2525,7 @@ Function,+,mf_desfire_send_chunks,MfDesfireError,"MfDesfirePoller*, const BitBuf Function,+,mf_desfire_set_uid,_Bool,"MfDesfireData*, const uint8_t*, size_t" Function,+,mf_desfire_verify,_Bool,"MfDesfireData*, const FuriString*" Function,+,mf_ultralight_3des_decrypt,void,"mbedtls_des3_context*, const uint8_t*, const uint8_t*, const uint8_t*, const uint8_t, uint8_t*" -Function,+,mf_ultralight_3des_encrypt,void,"mbedtls_des3_context*, const uint8_t*, const uint8_t*, const uint8_t*, uint8_t*" +Function,+,mf_ultralight_3des_encrypt,void,"mbedtls_des3_context*, const uint8_t*, const uint8_t*, const uint8_t*, const uint8_t, uint8_t*" Function,+,mf_ultralight_3des_get_key,const uint8_t*,const MfUltralightData* Function,+,mf_ultralight_3des_shift_data,void,uint8_t* Function,+,mf_ultralight_alloc,MfUltralightData*, @@ -2548,7 +2548,8 @@ 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_authenticate,MfUltralightError,MfUltralightPoller* +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*" Function,+,mf_ultralight_poller_read_page,MfUltralightError,"MfUltralightPoller*, uint8_t, MfUltralightPageReadCommandData*" Function,+,mf_ultralight_poller_read_page_from_sector,MfUltralightError,"MfUltralightPoller*, uint8_t, uint8_t, MfUltralightPageReadCommandData*" From fd4e3d025fcf9b13db1fc7caf7433506529d4b78 Mon Sep 17 00:00:00 2001 From: RebornedBrain Date: Tue, 18 Jun 2024 16:03:03 +0300 Subject: [PATCH 15/25] Some macro defines added --- .../protocols/mf_ultralight/mf_ultralight.h | 12 +++++-- .../mf_ultralight/mf_ultralight_listener.c | 20 ++++++------ .../mf_ultralight/mf_ultralight_listener_i.h | 4 +-- .../mf_ultralight/mf_ultralight_poller.c | 11 ++++--- .../mf_ultralight/mf_ultralight_poller_i.c | 31 +++++++------------ 5 files changed, 41 insertions(+), 37 deletions(-) diff --git a/lib/nfc/protocols/mf_ultralight/mf_ultralight.h b/lib/nfc/protocols/mf_ultralight/mf_ultralight.h index edc9e3975dd..8d30f15300d 100644 --- a/lib/nfc/protocols/mf_ultralight/mf_ultralight.h +++ b/lib/nfc/protocols/mf_ultralight/mf_ultralight.h @@ -38,7 +38,15 @@ extern "C" { #define MF_ULTRALIGHT_TEARING_FLAG_NUM (3) #define MF_ULTRALIGHT_AUTH_PASSWORD_SIZE (4) #define MF_ULTRALIGHT_AUTH_PACK_SIZE (2) -#define MF_ULTRALIGHT_AUTH_RESPONSE_SIZE (9) + +#define MF_ULTRALIGHT_C_AUTH_RESPONSE_SIZE (9) +#define MF_ULTRALIGHT_C_AUTH_DES_KEY_SIZE (16) +#define MF_ULTRALIGHT_C_AUTH_DATA_SIZE (MF_ULTRALIGHT_C_AUTH_DES_KEY_SIZE) +#define MF_ULTRALIGHT_C_AUTH_IV_BLOCK_SIZE (8) +#define MF_ULTRALIGHT_C_AUTH_RND_BLOCK_SIZE (8) +#define MF_ULTRALIGHT_C_AUTH_RND_A_BLOCK_OFFSET (0) +#define MF_ULTRALIGHT_C_AUTH_RND_B_BLOCK_OFFSET (8) +#define MF_ULTRALIGHT_C_ENCRYPTED_PACK_SIZE (MF_ULTRALIGHT_C_AUTH_DATA_SIZE + 1) typedef enum { MfUltralightErrorNone, @@ -121,7 +129,7 @@ typedef struct { } MfUltralightAuthPassword; typedef struct { - uint8_t data[16]; + uint8_t data[MF_ULTRALIGHT_C_AUTH_DES_KEY_SIZE]; } MfUltralightC3DesAuthKey; typedef struct { diff --git a/lib/nfc/protocols/mf_ultralight/mf_ultralight_listener.c b/lib/nfc/protocols/mf_ultralight/mf_ultralight_listener.c index f3ed8fd55b5..0446564e0f5 100644 --- a/lib/nfc/protocols/mf_ultralight/mf_ultralight_listener.c +++ b/lib/nfc/protocols/mf_ultralight/mf_ultralight_listener.c @@ -551,32 +551,34 @@ static MfUltralightCommand FURI_LOG_T(TAG, "CMD_ULC_AUTH_2"); UNUSED(instance); do { - if(bit_buffer_get_byte(buffer, 0) != 0xAF || bit_buffer_get_size_bytes(buffer) != 16 + 1) + if(bit_buffer_get_byte(buffer, 0) != 0xAF || + bit_buffer_get_size_bytes(buffer) != MF_ULTRALIGHT_C_ENCRYPTED_PACK_SIZE) break; const uint8_t* data = bit_buffer_get_data(buffer) + 1; - const uint8_t* iv = data + 8; + const uint8_t* iv = data + MF_ULTRALIGHT_C_AUTH_RND_B_BLOCK_OFFSET; - uint8_t out[16] = {0}; + uint8_t out[MF_ULTRALIGHT_C_AUTH_DATA_SIZE] = {0}; const uint8_t* ck = mf_ultralight_3des_get_key(instance->data); mf_ultralight_3des_decrypt( &instance->des_context, ck, instance->encB, data, sizeof(out), out); uint8_t* rndA = out; - const uint8_t* decoded_shifted_rndB = out + 8; + const uint8_t* decoded_shifted_rndB = out + MF_ULTRALIGHT_C_AUTH_RND_B_BLOCK_OFFSET; mf_ultralight_3des_shift_data(rndA); mf_ultralight_3des_shift_data(instance->rndB); - if(memcmp(decoded_shifted_rndB, instance->rndB, 8) == 0) { + if(memcmp(decoded_shifted_rndB, instance->rndB, sizeof(instance->rndB)) == 0) { instance->auth_state = MfUltralightListenerAuthStateSuccess; } - mf_ultralight_3des_encrypt(&instance->des_context, ck, iv, rndA, 8, rndA); + mf_ultralight_3des_encrypt( + &instance->des_context, ck, iv, rndA, MF_ULTRALIGHT_C_AUTH_RND_BLOCK_SIZE, rndA); bit_buffer_reset(instance->tx_buffer); bit_buffer_append_byte(instance->tx_buffer, 0x00); - bit_buffer_append_bytes(instance->tx_buffer, rndA, 8); + bit_buffer_append_bytes(instance->tx_buffer, rndA, MF_ULTRALIGHT_C_AUTH_RND_BLOCK_SIZE); iso14443_3a_listener_send_standard_frame( instance->iso14443_3a_listener, instance->tx_buffer); @@ -601,11 +603,11 @@ static MfUltralightCommand furi_hal_random_fill_buf(instance->rndB, sizeof(instance->rndB)); - const uint8_t iv[8] = {0}; + const uint8_t iv[MF_ULTRALIGHT_C_AUTH_IV_BLOCK_SIZE] = {0}; const uint8_t* ck = mf_ultralight_3des_get_key(instance->data); mf_ultralight_3des_encrypt( - &instance->des_context, ck, iv, instance->rndB, 8, instance->encB); + &instance->des_context, ck, iv, instance->rndB, sizeof(instance->rndB), instance->encB); bit_buffer_append_bytes(instance->tx_buffer, instance->encB, sizeof(instance->encB)); 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 d6efe02b478..c43658eddbb 100644 --- a/lib/nfc/protocols/mf_ultralight/mf_ultralight_listener_i.h +++ b/lib/nfc/protocols/mf_ultralight/mf_ultralight_listener_i.h @@ -69,8 +69,8 @@ struct MfUltralightListener { MfUltralightMirrorMode mirror; MfUltralightListenerCompositeCommandContext composite_cmd; mbedtls_des3_context des_context; - uint8_t rndB[8]; - uint8_t encB[8]; + uint8_t rndB[MF_ULTRALIGHT_C_AUTH_RND_BLOCK_SIZE]; + uint8_t encB[MF_ULTRALIGHT_C_AUTH_RND_BLOCK_SIZE]; void* context; }; diff --git a/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.c b/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.c index fa3690eb3f0..9558f96ca0b 100644 --- a/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.c +++ b/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.c @@ -458,18 +458,19 @@ 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"); - uint8_t output[16]; - uint8_t RndA[8] = {0}; + 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); - uint8_t decoded_shifted_RndA[8] = {0}; - const uint8_t* RndB = output + 8; + 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); mf_ultralight_3des_shift_data(RndA); - instance->auth_context.auth_success = (memcmp(RndA, decoded_shifted_RndA, 8) == 0); + instance->auth_context.auth_success = + (memcmp(RndA, decoded_shifted_RndA, sizeof(decoded_shifted_RndA)) == 0); } } instance->state = MfUltralightPollerStateReadPages; 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 51c07faed22..56166209adf 100644 --- a/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller_i.c +++ b/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller_i.c @@ -89,7 +89,8 @@ static MfUltralightError mf_ultralight_poller_send_authenticate_cmd( const uint8_t expected_response_code = initial_cmd ? 0xAF : 0x00; if((bit_buffer_get_byte(instance->rx_buffer, 0) != expected_response_code) || - (bit_buffer_get_size_bytes(instance->rx_buffer) != MF_ULTRALIGHT_AUTH_RESPONSE_SIZE)) { + (bit_buffer_get_size_bytes(instance->rx_buffer) != + MF_ULTRALIGHT_C_AUTH_RESPONSE_SIZE)) { ret = MfUltralightErrorAuth; break; } @@ -97,7 +98,7 @@ static MfUltralightError mf_ultralight_poller_send_authenticate_cmd( memcpy( response, bit_buffer_get_data(instance->rx_buffer) + 1, - MF_ULTRALIGHT_AUTH_RESPONSE_SIZE - 1); + MF_ULTRALIGHT_C_AUTH_RND_BLOCK_SIZE); } while(false); return ret; @@ -107,7 +108,7 @@ MfUltralightError mf_ultralight_poller_authentication_test(MfUltralightPoller* i furi_check(instance); uint8_t auth_cmd[2] = {MF_ULTRALIGHT_CMD_AUTH, 0x00}; - uint8_t dummy[8]; + uint8_t dummy[MF_ULTRALIGHT_C_AUTH_RND_BLOCK_SIZE]; return mf_ultralight_poller_send_authenticate_cmd( instance, auth_cmd, sizeof(auth_cmd), true, dummy); } @@ -122,33 +123,32 @@ MfUltralightError mf_ultralight_poller_authenticate_start( MfUltralightError ret = MfUltralightErrorNone; do { - uint8_t encRndB[8] = {0}; + uint8_t encRndB[MF_ULTRALIGHT_C_AUTH_RND_BLOCK_SIZE] = {0}; uint8_t auth_cmd[2] = {MF_ULTRALIGHT_CMD_AUTH, 0x00}; ret = mf_ultralight_poller_send_authenticate_cmd( instance, auth_cmd, sizeof(auth_cmd), true, encRndB /* instance->encRndB */); if(ret != MfUltralightErrorNone) break; - uint8_t iv[8] = {0}; - uint8_t* RndB = output + 8; + uint8_t iv[MF_ULTRALIGHT_C_AUTH_IV_BLOCK_SIZE] = {0}; + 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._3des_key.data, iv, encRndB, - //instance->encRndB, sizeof(encRndB), RndB); mf_ultralight_3des_shift_data(RndB); - memcpy(output, /* instance->RndA */ RndA, 8); + memcpy(output, RndA, MF_ULTRALIGHT_C_AUTH_RND_BLOCK_SIZE); mf_ultralight_3des_encrypt( &instance->des_context, instance->mfu_event.data->auth_context._3des_key.data, encRndB, output, - 16, + MF_ULTRALIGHT_C_AUTH_DATA_SIZE, output); } while(false); @@ -166,8 +166,8 @@ MfUltralightError mf_ultralight_poller_authenticate_end( furi_check(request); furi_check(response); - uint8_t auth_cmd[17] = {0xAF}; - memcpy(&auth_cmd[1], request, 16); + uint8_t auth_cmd[MF_ULTRALIGHT_C_ENCRYPTED_PACK_SIZE] = {0xAF}; + memcpy(&auth_cmd[1], request, MF_ULTRALIGHT_C_AUTH_DATA_SIZE); bit_buffer_copy_bytes(instance->tx_buffer, auth_cmd, sizeof(auth_cmd)); MfUltralightError ret = MfUltralightErrorNone; @@ -177,20 +177,13 @@ MfUltralightError mf_ultralight_poller_authenticate_end( if(ret != MfUltralightErrorNone) break; - // uint8_t decoded_shifted_RndA[8] = {0}; mf_ultralight_3des_decrypt( &instance->des_context, instance->mfu_event.data->auth_context._3des_key.data, RndB, bit_buffer_get_data(instance->rx_buffer) + 1, - 8, + MF_ULTRALIGHT_C_AUTH_RND_BLOCK_SIZE, response); - - /* memcpy( - response, - bit_buffer_get_data(instance->rx_buffer) + 1, - MF_ULTRALIGHT_AUTH_RESPONSE_SIZE - 1); */ - } while(false); return ret; From 636c143dddd9cd00f6e30374e3e608f854d77d38 Mon Sep 17 00:00:00 2001 From: RebornedBrain Date: Tue, 18 Jun 2024 20:25:38 +0300 Subject: [PATCH 16/25] Different amount of pages will be now read for ultralight C and others --- lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.c b/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.c index 9558f96ca0b..c73a1fe964f 100644 --- a/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.c +++ b/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.c @@ -497,8 +497,9 @@ static NfcCommand mf_ultralight_poller_handler_read_pages(MfUltralightPoller* in instance->error = mf_ultralight_poller_read_page(instance, start_page, &data); } + const uint8_t read_cnt = instance->data->type == MfUltralightTypeMfulC ? 1 : 4; if(instance->error == MfUltralightErrorNone) { - for(size_t i = 0; i < 4; i++) { + for(size_t i = 0; i < read_cnt; i++) { if(start_page + i < instance->pages_total) { FURI_LOG_D(TAG, "Read page %d success", start_page + i); instance->data->page[start_page + i] = data.page[i]; From 2f0787c341b5d943c45550a31da59ec03366797a Mon Sep 17 00:00:00 2001 From: RebornedBrain Date: Tue, 18 Jun 2024 20:43:41 +0300 Subject: [PATCH 17/25] New unit test for ultralight C --- .../resources/unit_tests/nfc/Ultralight_C.nfc | 71 +++++++++++++++++++ .../debug/unit_tests/tests/nfc/nfc_test.c | 5 ++ .../mf_ultralight/mf_ultralight_poller_sync.c | 6 ++ 3 files changed, 82 insertions(+) create mode 100644 applications/debug/unit_tests/resources/unit_tests/nfc/Ultralight_C.nfc diff --git a/applications/debug/unit_tests/resources/unit_tests/nfc/Ultralight_C.nfc b/applications/debug/unit_tests/resources/unit_tests/nfc/Ultralight_C.nfc new file mode 100644 index 00000000000..8c125865c35 --- /dev/null +++ b/applications/debug/unit_tests/resources/unit_tests/nfc/Ultralight_C.nfc @@ -0,0 +1,71 @@ +Filetype: Flipper NFC device +Version: 4 +# Device type can be ISO14443-3A, ISO14443-3B, ISO14443-4A, ISO14443-4B, ISO15693-3, FeliCa, NTAG/Ultralight, Mifare Classic, Mifare DESFire, SLIX, ST25TB +Device type: NTAG/Ultralight +# UID is common for all formats +UID: 04 BA FF CA 4D 5D 80 +# ISO14443-3A specific data +ATQA: 00 44 +SAK: 00 +# NTAG/Ultralight specific data +Data format version: 2 +NTAG/Ultralight type: Mifare Ultralight C +Signature: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +Mifare version: 00 00 00 00 00 00 00 00 +Counter 0: 0 +Tearing 0: 00 +Counter 1: 0 +Tearing 1: 00 +Counter 2: 0 +Tearing 2: 00 +Pages total: 48 +Pages read: 48 +Page 0: 04 BA FF C9 +Page 1: CA 4D 5D 80 +Page 2: 5A 48 00 00 +Page 3: E1 10 12 00 +Page 4: 01 03 A0 0C +Page 5: 34 03 00 FE +Page 6: 00 00 00 00 +Page 7: 00 00 00 00 +Page 8: 00 00 00 00 +Page 9: 00 00 00 00 +Page 10: 00 00 BE AF +Page 11: 00 00 00 00 +Page 12: 00 00 00 00 +Page 13: 00 00 00 00 +Page 14: 00 00 00 00 +Page 15: 00 00 00 00 +Page 16: 00 00 00 00 +Page 17: 00 00 00 00 +Page 18: 00 00 00 00 +Page 19: 00 00 00 00 +Page 20: 00 00 00 00 +Page 21: 00 00 00 00 +Page 22: 00 00 00 00 +Page 23: 00 00 00 00 +Page 24: 00 00 00 00 +Page 25: 00 00 00 00 +Page 26: 00 00 00 00 +Page 27: 00 00 00 00 +Page 28: 00 00 00 00 +Page 29: 00 00 00 00 +Page 30: 00 00 00 00 +Page 31: 00 00 00 00 +Page 32: 00 00 00 00 +Page 33: 00 00 00 00 +Page 34: 00 00 00 00 +Page 35: 00 00 00 00 +Page 36: 00 00 00 00 +Page 37: 00 00 00 00 +Page 38: 00 00 00 00 +Page 39: 00 00 00 00 +Page 40: 00 00 00 00 +Page 41: 00 00 00 00 +Page 42: 05 00 00 00 +Page 43: 00 00 00 00 +Page 44: 00 00 00 00 +Page 45: 00 00 00 00 +Page 46: 00 00 00 00 +Page 47: 00 00 00 00 +Failed authentication attempts: 0 diff --git a/applications/debug/unit_tests/tests/nfc/nfc_test.c b/applications/debug/unit_tests/tests/nfc/nfc_test.c index 1e440707643..5f172d0b5ce 100644 --- a/applications/debug/unit_tests/tests/nfc/nfc_test.c +++ b/applications/debug/unit_tests/tests/nfc/nfc_test.c @@ -286,6 +286,10 @@ MU_TEST(mf_ultralight_21_reader) { mf_ultralight_reader_test(EXT_PATH("unit_tests/nfc/Ultralight_21.nfc")); } +MU_TEST(mf_ultralight_c_reader) { + mf_ultralight_reader_test(EXT_PATH("unit_tests/nfc/Ultralight_C.nfc")); +} + MU_TEST(ntag_215_reader) { mf_ultralight_reader_test(EXT_PATH("unit_tests/nfc/Ntag215.nfc")); } @@ -828,6 +832,7 @@ MU_TEST_SUITE(nfc) { MU_RUN_TEST(ntag_215_reader); MU_RUN_TEST(ntag_216_reader); MU_RUN_TEST(ntag_213_locked_reader); + MU_RUN_TEST(mf_ultralight_c_reader); MU_RUN_TEST(mf_ultralight_write); diff --git a/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller_sync.c b/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller_sync.c index 157e2bdef7b..59128c97536 100644 --- a/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller_sync.c +++ b/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller_sync.c @@ -251,6 +251,12 @@ static NfcCommand mf_ultralight_poller_read_callback(NfcGenericEvent event, void command = NfcCommandStop; } else if(mfu_event->type == MfUltralightPollerEventTypeAuthRequest) { mfu_event->data->auth_context.skip_auth = true; + if(mf_ultralight_support_feature( + mfu_poller->feature_set, MfUltralightFeatureSupportAuthenticate)) { + mfu_event->data->auth_context.skip_auth = false; + memset( + mfu_poller->auth_context._3des_key.data, 0x00, MF_ULTRALIGHT_C_AUTH_DES_KEY_SIZE); + } } if(command == NfcCommandStop) { From 782799e3b8dce9d44bb9461a1a01ba30e0d34274 Mon Sep 17 00:00:00 2001 From: RebornedBrain Date: Wed, 19 Jun 2024 12:40:13 +0300 Subject: [PATCH 18/25] Some comments and macro replacements --- lib/nfc/protocols/mf_ultralight/mf_ultralight.c | 4 ++-- .../mf_ultralight/mf_ultralight_poller.h | 16 ++++++++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/lib/nfc/protocols/mf_ultralight/mf_ultralight.c b/lib/nfc/protocols/mf_ultralight/mf_ultralight.c index d9b0388d493..e9174670e8c 100644 --- a/lib/nfc/protocols/mf_ultralight/mf_ultralight.c +++ b/lib/nfc/protocols/mf_ultralight/mf_ultralight.c @@ -672,10 +672,10 @@ void mf_ultralight_3des_shift_data(uint8_t* const data) { furi_check(data); uint8_t buf = data[0]; - for(uint8_t i = 1; i < 8; i++) { + for(uint8_t i = 1; i < MF_ULTRALIGHT_C_AUTH_RND_BLOCK_SIZE; i++) { data[i - 1] = data[i]; } - data[7] = buf; + data[MF_ULTRALIGHT_C_AUTH_RND_BLOCK_SIZE - 1] = buf; } const uint8_t* mf_ultralight_3des_get_key(const MfUltralightData* data) { diff --git a/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.h b/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.h index 0ed39519042..a02cd403110 100644 --- a/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.h +++ b/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.h @@ -81,14 +81,16 @@ MfUltralightError mf_ultralight_poller_auth_pwd( MfUltralightPoller* instance, MfUltralightPollerAuthContext* data); -/** TODO:Adjust this comment +/** * @brief Start authentication procedure. * * Must ONLY be used inside the callback function. * - * This function now is used only to identify Mf Ultralight C cards. + * This function is used to start authentication process for Ultralight C cards. * * @param[in, out] instance pointer to the instance to be used in the transaction. + * @param[in] RndA Randomly generated block which is required for authentication process. + * @param[out] output Authentication encryption result. * @return MfUltralightErrorNone if card supports authentication command, an error code on otherwise. */ MfUltralightError mf_ultralight_poller_authenticate_start( @@ -96,6 +98,16 @@ MfUltralightError mf_ultralight_poller_authenticate_start( const uint8_t* RndA, uint8_t* output); +/** + * @brief End authentication procedure + * + * This function is used to end authentication process for Ultralight C cards. + * + * @param[in, out] instance pointer to the instance to be used in the transaction. + * @param[in] RndB Block received from the card (card generates it randomly) which is required for authentication process. + * @param[in] request Contains data of RndA + RndB', where RndB' is decoded and shifted RndB received from the card on previous step. + * @param[out] response Must return RndA' which an encrypted shifted RndA value received from the card and decrypted by this function. +*/ MfUltralightError mf_ultralight_poller_authenticate_end( MfUltralightPoller* instance, const uint8_t* RndB, From 3c117c6f5720f9f86f1458fc11fbeef1b6ff5119 Mon Sep 17 00:00:00 2001 From: RebornedBrain Date: Wed, 26 Jun 2024 00:21:44 +0300 Subject: [PATCH 19/25] New function added to api --- lib/nfc/protocols/mf_ultralight/mf_ultralight.c | 7 +++++++ lib/nfc/protocols/mf_ultralight/mf_ultralight.h | 2 ++ targets/f18/api_symbols.csv | 2 +- targets/f7/api_symbols.csv | 11 ++++++----- 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/lib/nfc/protocols/mf_ultralight/mf_ultralight.c b/lib/nfc/protocols/mf_ultralight/mf_ultralight.c index 054fbd2b909..fae4f6e05f0 100644 --- a/lib/nfc/protocols/mf_ultralight/mf_ultralight.c +++ b/lib/nfc/protocols/mf_ultralight/mf_ultralight.c @@ -680,6 +680,13 @@ void mf_ultralight_3des_shift_data(uint8_t* const data) { data[MF_ULTRALIGHT_C_AUTH_RND_BLOCK_SIZE - 1] = buf; } +bool mf_ultralight_3des_key_valid(const MfUltralightData* data) { + furi_check(data); + furi_check(data->type == MfUltralightTypeMfulC); + + return !(data->pages_read == data->pages_total - 4); +} + const uint8_t* mf_ultralight_3des_get_key(const MfUltralightData* data) { furi_check(data); furi_check(data->type == MfUltralightTypeMfulC); diff --git a/lib/nfc/protocols/mf_ultralight/mf_ultralight.h b/lib/nfc/protocols/mf_ultralight/mf_ultralight.h index e62bad023e9..f748f681376 100644 --- a/lib/nfc/protocols/mf_ultralight/mf_ultralight.h +++ b/lib/nfc/protocols/mf_ultralight/mf_ultralight.h @@ -241,6 +241,8 @@ bool mf_ultralight_is_counter_configured(const MfUltralightData* data); void mf_ultralight_3des_shift_data(uint8_t* const arr); +bool mf_ultralight_3des_key_valid(const MfUltralightData* data); + const uint8_t* mf_ultralight_3des_get_key(const MfUltralightData* data); void mf_ultralight_3des_encrypt( diff --git a/targets/f18/api_symbols.csv b/targets/f18/api_symbols.csv index d4c3462fe54..90a3cc81954 100644 --- a/targets/f18/api_symbols.csv +++ b/targets/f18/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,72.0,, +Version,+,72.1,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/bt/bt_service/bt_keys_storage.h,, Header,+,applications/services/cli/cli.h,, diff --git a/targets/f7/api_symbols.csv b/targets/f7/api_symbols.csv index 26b02db19e8..6e8554451c8 100644 --- a/targets/f7/api_symbols.csv +++ b/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,72.0,, +Version,+,72.1,, 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,, @@ -2540,10 +2540,6 @@ Function,+,mf_desfire_save,_Bool,"const MfDesfireData*, FlipperFormat*" Function,+,mf_desfire_send_chunks,MfDesfireError,"MfDesfirePoller*, const BitBuffer*, BitBuffer*" Function,+,mf_desfire_set_uid,_Bool,"MfDesfireData*, const uint8_t*, size_t" Function,+,mf_desfire_verify,_Bool,"MfDesfireData*, const FuriString*" -Function,+,mf_ultralight_3des_decrypt,void,"mbedtls_des3_context*, const uint8_t*, const uint8_t*, const uint8_t*, const uint8_t, uint8_t*" -Function,+,mf_ultralight_3des_encrypt,void,"mbedtls_des3_context*, const uint8_t*, const uint8_t*, const uint8_t*, const uint8_t, uint8_t*" -Function,+,mf_ultralight_3des_get_key,const uint8_t*,const MfUltralightData* -Function,+,mf_ultralight_3des_shift_data,void,uint8_t* Function,+,mf_plus_alloc,MfPlusData*, Function,+,mf_plus_copy,void,"MfPlusData*, const MfPlusData*" Function,+,mf_plus_free,void,MfPlusData* @@ -2557,6 +2553,11 @@ Function,+,mf_plus_reset,void,MfPlusData* Function,+,mf_plus_save,_Bool,"const MfPlusData*, FlipperFormat*" Function,+,mf_plus_set_uid,_Bool,"MfPlusData*, const uint8_t*, size_t" Function,+,mf_plus_verify,_Bool,"MfPlusData*, const FuriString*" +Function,+,mf_ultralight_3des_decrypt,void,"mbedtls_des3_context*, const uint8_t*, const uint8_t*, const uint8_t*, const uint8_t, uint8_t*" +Function,+,mf_ultralight_3des_encrypt,void,"mbedtls_des3_context*, const uint8_t*, const uint8_t*, const uint8_t*, const uint8_t, uint8_t*" +Function,+,mf_ultralight_3des_get_key,const uint8_t*,const MfUltralightData* +Function,+,mf_ultralight_3des_key_valid,_Bool,const MfUltralightData* +Function,+,mf_ultralight_3des_shift_data,void,uint8_t* Function,+,mf_ultralight_alloc,MfUltralightData*, Function,+,mf_ultralight_copy,void,"MfUltralightData*, const MfUltralightData*" Function,+,mf_ultralight_detect_protocol,_Bool,const Iso14443_3aData* From f1721a1cfefa6d0711cbd64e65a10bb7427f8a8e Mon Sep 17 00:00:00 2001 From: RebornedBrain Date: Wed, 26 Jun 2024 00:22:17 +0300 Subject: [PATCH 20/25] Now all data read checks mfulC separately --- lib/nfc/protocols/mf_ultralight/mf_ultralight.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/lib/nfc/protocols/mf_ultralight/mf_ultralight.c b/lib/nfc/protocols/mf_ultralight/mf_ultralight.c index fae4f6e05f0..b10ac40b65b 100644 --- a/lib/nfc/protocols/mf_ultralight/mf_ultralight.c +++ b/lib/nfc/protocols/mf_ultralight/mf_ultralight.c @@ -624,15 +624,19 @@ bool mf_ultralight_is_all_data_read(const MfUltralightData* data) { furi_check(data); bool all_read = false; - if(data->pages_read == data->pages_total || - (data->type == MfUltralightTypeMfulC && data->pages_read == data->pages_total - 4)) { - // Having read all the pages doesn't mean that we've got everything. - // By default PWD is 0xFFFFFFFF, but if read back it is always 0x00000000, - // so a default read on an auth-supported NTAG is never complete. + + if(data->pages_read == data->pages_total) { uint32_t feature_set = mf_ultralight_get_feature_support_set(data->type); - if(!mf_ultralight_support_feature(feature_set, MfUltralightFeatureSupportPasswordAuth)) { + if((data->type == MfUltralightTypeMfulC) && + mf_ultralight_support_feature(feature_set, MfUltralightFeatureSupportAuthenticate)) { + all_read = true; + } else if(!mf_ultralight_support_feature( + feature_set, MfUltralightFeatureSupportPasswordAuth)) { all_read = true; } else { + // Having read all the pages doesn't mean that we've got everything. + // By default PWD is 0xFFFFFFFF, but if read back it is always 0x00000000, + // so a default read on an auth-supported NTAG is never complete. MfUltralightConfigPages* config = NULL; if(mf_ultralight_get_config_page(data, &config)) { uint32_t pass = bit_lib_bytes_to_num_be( From 009a829f0225850657057c37ae2442e74e3d9136 Mon Sep 17 00:00:00 2001 From: RebornedBrain Date: Wed, 26 Jun 2024 00:22:52 +0300 Subject: [PATCH 21/25] Adjusted listener to handle missing 3des_key properly --- lib/nfc/protocols/mf_ultralight/mf_ultralight_listener.c | 3 ++- lib/nfc/protocols/mf_ultralight/mf_ultralight_listener_i.c | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/nfc/protocols/mf_ultralight/mf_ultralight_listener.c b/lib/nfc/protocols/mf_ultralight/mf_ultralight_listener.c index 0446564e0f5..b5980b3882c 100644 --- a/lib/nfc/protocols/mf_ultralight/mf_ultralight_listener.c +++ b/lib/nfc/protocols/mf_ultralight/mf_ultralight_listener.c @@ -552,7 +552,8 @@ static MfUltralightCommand UNUSED(instance); do { if(bit_buffer_get_byte(buffer, 0) != 0xAF || - bit_buffer_get_size_bytes(buffer) != MF_ULTRALIGHT_C_ENCRYPTED_PACK_SIZE) + bit_buffer_get_size_bytes(buffer) != MF_ULTRALIGHT_C_ENCRYPTED_PACK_SIZE || + !mf_ultralight_3des_key_valid(instance->data)) break; const uint8_t* data = bit_buffer_get_data(buffer) + 1; 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 c09958ddd09..c954aa75e5b 100644 --- a/lib/nfc/protocols/mf_ultralight/mf_ultralight_listener_i.c +++ b/lib/nfc/protocols/mf_ultralight/mf_ultralight_listener_i.c @@ -615,6 +615,8 @@ bool mf_ultralight_c_check_access( bool is_write_op = (access_type == MfUltralightListenerAccessTypeWrite); do { + if(start_page >= 44) break; + const uint8_t auth0 = data->page[42].data[0]; const uint8_t auth1 = data->page[43].data[0] & 0x01; From 44d2a0a35f5cfb4a2bcc56cdaabbed2ab0bad9ed Mon Sep 17 00:00:00 2001 From: RebornedBrain Date: Wed, 26 Jun 2024 00:23:32 +0300 Subject: [PATCH 22/25] Now poller populates 3des_key after reading with auth to card data --- .../mf_ultralight/mf_ultralight_poller.c | 81 ++++++++++++++----- .../mf_ultralight/mf_ultralight_poller_i.h | 1 + 2 files changed, 64 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 80c672fb505..8869aef5c93 100644 --- a/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.c +++ b/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.c @@ -452,20 +452,33 @@ static NfcCommand mf_ultralight_poller_handler_auth_ultralight_c(MfUltralightPol 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"); - - 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); - - 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); - - mf_ultralight_3des_shift_data(RndA); - instance->auth_context.auth_success = - (memcmp(RndA, decoded_shifted_RndA, sizeof(decoded_shifted_RndA)) == 0); + instance->auth_context._3des_key = instance->mfu_event.data->auth_context._3des_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; + + 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) { + FURI_LOG_D(TAG, "Auth failed"); + iso14443_3a_poller_halt(instance->iso14443_3a_poller); + } } } instance->state = MfUltralightPollerStateReadPages; @@ -506,11 +519,16 @@ static NfcCommand mf_ultralight_poller_handler_read_pages(MfUltralightPoller* in instance->state = MfUltralightPollerStateReadCounters; } } else { - FURI_LOG_D(TAG, "Read page %d failed", instance->pages_read); - if(instance->pages_read) { - instance->state = MfUltralightPollerStateReadCounters; + if(instance->data->type == MfUltralightTypeMfulC && + !mf_ultralight_3des_key_valid(instance->data)) { + instance->state = MfUltralightPollerStateCheckMfulCAuthStatus; } else { - instance->state = MfUltralightPollerStateReadFailed; + FURI_LOG_D(TAG, "Read page %d failed", instance->pages_read); + if(instance->pages_read) { + instance->state = MfUltralightPollerStateReadCounters; + } else { + instance->state = MfUltralightPollerStateReadFailed; + } } } @@ -562,6 +580,31 @@ static NfcCommand mf_ultralight_poller_handler_try_default_pass(MfUltralightPoll return NfcCommandContinue; } +static NfcCommand + mf_ultralight_poller_handler_check_mfuc_auth_status(MfUltralightPoller* instance) { + instance->state = MfUltralightPollerStateReadSuccess; + + do { + if(!mf_ultralight_support_feature( + instance->feature_set, MfUltralightFeatureSupportAuthenticate)) + break; + + if(!instance->auth_context.auth_success) { + FURI_LOG_D(TAG, "Skip 3des key populating"); + break; + } + + memcpy( + &instance->data->page[44], + instance->auth_context._3des_key.data, + MF_ULTRALIGHT_C_AUTH_DES_KEY_SIZE); + instance->data->pages_read = instance->pages_total; + instance->pages_read = instance->pages_total; + } while(false); + + return NfcCommandContinue; +} + static NfcCommand mf_ultralight_poller_handler_read_fail(MfUltralightPoller* instance) { FURI_LOG_D(TAG, "Read Failed"); iso14443_3a_poller_halt(instance->iso14443_3a_poller); @@ -701,6 +744,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, + [MfUltralightPollerStateCheckMfulCAuthStatus] = + mf_ultralight_poller_handler_check_mfuc_auth_status, [MfUltralightPollerStateAuthMfulC] = mf_ultralight_poller_handler_auth_ultralight_c, [MfUltralightPollerStateReadPages] = mf_ultralight_poller_handler_read_pages, [MfUltralightPollerStateReadFailed] = mf_ultralight_poller_handler_read_fail, 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 be269f899ca..1f395ddd200 100644 --- a/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller_i.h +++ b/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller_i.h @@ -61,6 +61,7 @@ typedef enum { MfUltralightPollerStateAuthMfulC, MfUltralightPollerStateReadPages, MfUltralightPollerStateTryDefaultPass, + MfUltralightPollerStateCheckMfulCAuthStatus, MfUltralightPollerStateReadFailed, MfUltralightPollerStateReadSuccess, MfUltralightPollerStateRequestWriteData, From 4b657a836428d0e6ad966fa647c88d4d24bfea44 Mon Sep 17 00:00:00 2001 From: Aleksandr Kutuzov Date: Tue, 2 Jul 2024 18:51:41 +0100 Subject: [PATCH 23/25] Nfc: rename _3des_key to tdes_key --- applications/main/nfc/helpers/mf_ultralight_auth.c | 2 +- applications/main/nfc/helpers/mf_ultralight_auth.h | 2 +- .../helpers/protocol_support/mf_ultralight/mf_ultralight.c | 2 +- applications/main/nfc/scenes/nfc_scene_des_auth_key_input.c | 2 +- .../main/nfc/scenes/nfc_scene_des_auth_unlock_warn.c | 2 +- lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.c | 4 ++-- lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.h | 2 +- lib/nfc/protocols/mf_ultralight/mf_ultralight_poller_i.c | 6 +++--- lib/nfc/protocols/mf_ultralight/mf_ultralight_poller_sync.c | 2 +- 9 files changed, 12 insertions(+), 12 deletions(-) diff --git a/applications/main/nfc/helpers/mf_ultralight_auth.c b/applications/main/nfc/helpers/mf_ultralight_auth.c index 93138712dea..e97649cb3ed 100644 --- a/applications/main/nfc/helpers/mf_ultralight_auth.c +++ b/applications/main/nfc/helpers/mf_ultralight_auth.c @@ -20,7 +20,7 @@ void mf_ultralight_auth_reset(MfUltralightAuth* instance) { instance->type = MfUltralightAuthTypeNone; memset(&instance->password, 0, sizeof(MfUltralightAuthPassword)); - memset(&instance->_3des_key, 0, sizeof(MfUltralightC3DesAuthKey)); + memset(&instance->tdes_key, 0, sizeof(MfUltralightC3DesAuthKey)); memset(&instance->pack, 0, sizeof(MfUltralightAuthPack)); } diff --git a/applications/main/nfc/helpers/mf_ultralight_auth.h b/applications/main/nfc/helpers/mf_ultralight_auth.h index f0715ff490a..c9e80765fb5 100644 --- a/applications/main/nfc/helpers/mf_ultralight_auth.h +++ b/applications/main/nfc/helpers/mf_ultralight_auth.h @@ -17,7 +17,7 @@ typedef enum { typedef struct { MfUltralightAuthType type; MfUltralightAuthPassword password; - MfUltralightC3DesAuthKey _3des_key; + MfUltralightC3DesAuthKey tdes_key; MfUltralightAuthPack pack; } MfUltralightAuth; diff --git a/applications/main/nfc/helpers/protocol_support/mf_ultralight/mf_ultralight.c b/applications/main/nfc/helpers/protocol_support/mf_ultralight/mf_ultralight.c index 975be2ae629..3adf2a1f5c3 100644 --- a/applications/main/nfc/helpers/protocol_support/mf_ultralight/mf_ultralight.c +++ b/applications/main/nfc/helpers/protocol_support/mf_ultralight/mf_ultralight.c @@ -150,7 +150,7 @@ static NfcCommand } if(!mf_ultralight_event->data->auth_context.skip_auth) { mf_ultralight_event->data->auth_context.password = instance->mf_ul_auth->password; - mf_ultralight_event->data->auth_context._3des_key = instance->mf_ul_auth->_3des_key; + mf_ultralight_event->data->auth_context.tdes_key = instance->mf_ul_auth->tdes_key; } } else if(mf_ultralight_event->type == MfUltralightPollerEventTypeAuthSuccess) { instance->mf_ul_auth->pack = mf_ultralight_event->data->auth_context.pack; diff --git a/applications/main/nfc/scenes/nfc_scene_des_auth_key_input.c b/applications/main/nfc/scenes/nfc_scene_des_auth_key_input.c index 0c6a0ce5b91..f3a6ecb328e 100644 --- a/applications/main/nfc/scenes/nfc_scene_des_auth_key_input.c +++ b/applications/main/nfc/scenes/nfc_scene_des_auth_key_input.c @@ -12,7 +12,7 @@ void nfc_scene_des_auth_key_input_on_enter(void* context) { // Setup view NfcProtocol protocol = nfc_device_get_protocol(nfc->nfc_device); uint8_t* key = (protocol == NfcProtocolFelica) ? nfc->felica_auth->card_key.data : - nfc->mf_ul_auth->_3des_key.data; + nfc->mf_ul_auth->tdes_key.data; ByteInput* byte_input = nfc->byte_input; byte_input_set_header_text(byte_input, "Enter key in hex"); diff --git a/applications/main/nfc/scenes/nfc_scene_des_auth_unlock_warn.c b/applications/main/nfc/scenes/nfc_scene_des_auth_unlock_warn.c index 28b7f62f854..80c735c9ca1 100644 --- a/applications/main/nfc/scenes/nfc_scene_des_auth_unlock_warn.c +++ b/applications/main/nfc/scenes/nfc_scene_des_auth_unlock_warn.c @@ -21,7 +21,7 @@ void nfc_scene_des_auth_unlock_warn_on_enter(void* context) { NfcProtocol protocol = nfc_device_get_protocol(nfc->nfc_device); uint8_t* key = (protocol == NfcProtocolFelica) ? nfc->felica_auth->card_key.data : - nfc->mf_ul_auth->_3des_key.data; + nfc->mf_ul_auth->tdes_key.data; for(uint8_t i = 0; i < FELICA_DATA_BLOCK_SIZE; i++) furi_string_cat_printf(str, "%02X ", key[i]); diff --git a/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.c b/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.c index 8869aef5c93..0e5ff001162 100644 --- a/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.c +++ b/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.c @@ -452,7 +452,7 @@ static NfcCommand mf_ultralight_poller_handler_auth_ultralight_c(MfUltralightPol 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._3des_key = instance->mfu_event.data->auth_context._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}; @@ -596,7 +596,7 @@ static NfcCommand memcpy( &instance->data->page[44], - instance->auth_context._3des_key.data, + instance->auth_context.tdes_key.data, MF_ULTRALIGHT_C_AUTH_DES_KEY_SIZE); instance->data->pages_read = instance->pages_total; instance->pages_read = instance->pages_total; diff --git a/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.h b/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.h index a02cd403110..e5001732446 100644 --- a/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.h +++ b/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.h @@ -42,7 +42,7 @@ typedef enum { */ typedef struct { MfUltralightAuthPassword password; /**< Password to be used for authentication. */ - MfUltralightC3DesAuthKey _3des_key; + MfUltralightC3DesAuthKey tdes_key; MfUltralightAuthPack pack; /**< Pack received on successfull authentication. */ bool auth_success; /**< Set to true if authentication succeeded, false otherwise. */ bool skip_auth; /**< Set to true if authentication should be skipped, false otherwise. */ 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 56166209adf..e78b4a9b8b3 100644 --- a/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller_i.c +++ b/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller_i.c @@ -134,7 +134,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._3des_key.data, + instance->mfu_event.data->auth_context.tdes_key.data, iv, encRndB, sizeof(encRndB), @@ -145,7 +145,7 @@ MfUltralightError mf_ultralight_poller_authenticate_start( mf_ultralight_3des_encrypt( &instance->des_context, - instance->mfu_event.data->auth_context._3des_key.data, + instance->mfu_event.data->auth_context.tdes_key.data, encRndB, output, MF_ULTRALIGHT_C_AUTH_DATA_SIZE, @@ -179,7 +179,7 @@ MfUltralightError mf_ultralight_poller_authenticate_end( mf_ultralight_3des_decrypt( &instance->des_context, - instance->mfu_event.data->auth_context._3des_key.data, + instance->mfu_event.data->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_sync.c b/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller_sync.c index 59128c97536..9958dc50de5 100644 --- a/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller_sync.c +++ b/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller_sync.c @@ -255,7 +255,7 @@ static NfcCommand mf_ultralight_poller_read_callback(NfcGenericEvent event, void mfu_poller->feature_set, MfUltralightFeatureSupportAuthenticate)) { mfu_event->data->auth_context.skip_auth = false; memset( - mfu_poller->auth_context._3des_key.data, 0x00, MF_ULTRALIGHT_C_AUTH_DES_KEY_SIZE); + mfu_poller->auth_context.tdes_key.data, 0x00, MF_ULTRALIGHT_C_AUTH_DES_KEY_SIZE); } } From a26498f56e4116ab48682eb8332182f32d4fe636 Mon Sep 17 00:00:00 2001 From: Aleksandr Kutuzov Date: Tue, 2 Jul 2024 18:56:32 +0100 Subject: [PATCH 24/25] Bump API Symbols --- targets/f18/api_symbols.csv | 2 +- targets/f7/api_symbols.csv | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/targets/f18/api_symbols.csv b/targets/f18/api_symbols.csv index 48c1ab0ab64..23e098a91de 100644 --- a/targets/f18/api_symbols.csv +++ b/targets/f18/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,67.2,, +Version,+,68.0,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/bt/bt_service/bt_keys_storage.h,, Header,+,applications/services/cli/cli.h,, diff --git a/targets/f7/api_symbols.csv b/targets/f7/api_symbols.csv index 4f1d5e9314d..6cccce1e6dc 100644 --- a/targets/f7/api_symbols.csv +++ b/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,67.2,, +Version,+,68.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,, From 693ab5f03cdaf08116a7ceba13043abb589a9c0d Mon Sep 17 00:00:00 2001 From: Aleksandr Kutuzov Date: Wed, 3 Jul 2024 12:26:47 +0100 Subject: [PATCH 25/25] Mute PVS Warnings --- lib/nfc/protocols/mf_ultralight/mf_ultralight_listener_i.c | 2 +- lib/nfc/protocols/mf_ultralight/mf_ultralight_poller_i.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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 c954aa75e5b..3a9b893aa5d 100644 --- a/lib/nfc/protocols/mf_ultralight/mf_ultralight_listener_i.c +++ b/lib/nfc/protocols/mf_ultralight/mf_ultralight_listener_i.c @@ -625,7 +625,7 @@ bool mf_ultralight_c_check_access( break; } - if((auth0 <= start_page) && ((auth1 == 0) || (auth1 == 1 || is_write_op))) { + if((auth0 <= start_page) && ((auth1 == 0) || (auth1 == 1 || is_write_op))) { //-V560 break; } 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 e78b4a9b8b3..141ab6c46d0 100644 --- a/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller_i.c +++ b/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller_i.c @@ -166,7 +166,7 @@ MfUltralightError mf_ultralight_poller_authenticate_end( furi_check(request); furi_check(response); - uint8_t auth_cmd[MF_ULTRALIGHT_C_ENCRYPTED_PACK_SIZE] = {0xAF}; + uint8_t auth_cmd[MF_ULTRALIGHT_C_ENCRYPTED_PACK_SIZE] = {0xAF}; //-V1009 memcpy(&auth_cmd[1], request, MF_ULTRALIGHT_C_AUTH_DATA_SIZE); bit_buffer_copy_bytes(instance->tx_buffer, auth_cmd, sizeof(auth_cmd));