[FL-3835] Ultralight C authentication with des key (#3720)

* Update api_symbols.csv
* Ultralight C 3des implementation added
* Access check for Ultralight cards is now splitted into 2 functions one for ULC card and another for common
* Ultralight C authentication command handlers added
* Update api_symbols.csv and api_symbols.csv
* Length added to ultralight encrypt function
* New structure for storing 3des key added
* Reseting of 3des_key added
* des_context init/deinit added to poller
* New poller step for ultralight c auth added
* Added ultralight c des key to application
* Renamed felica unlock scenes to more generic des auth scenes, because they are now used also for ultralight c
* Show different menus for different ultralight card types
* Update api_symbols.csv and api_symbols.csv
* Some macro defines added
* Different amount of pages will be now read for ultralight C and others
* New unit test for ultralight C
* Some comments and macro replacements
* New function added to api
* Now all data read checks mfulC separately
* Adjusted listener to handle missing 3des_key properly
* Now poller populates 3des_key after reading with auth to card data
* Nfc: rename _3des_key to tdes_key
* Bump API Symbols
* Mute PVS Warnings

Co-authored-by: hedger <hedger@users.noreply.github.com>
Co-authored-by: gornekich <n.gorbadey@gmail.com>
Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
This commit is contained in:
RebornedBrain
2024-07-03 14:38:30 +03:00
committed by GitHub
parent 95658063af
commit 3224401479
22 changed files with 632 additions and 75 deletions

View File

@@ -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(
@@ -669,3 +673,61 @@ 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 < MF_ULTRALIGHT_C_AUTH_RND_BLOCK_SIZE; i++) {
data[i - 1] = data[i];
}
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);
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,
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_enc(ctx, ck);
mbedtls_des3_crypt_cbc(ctx, MBEDTLS_DES_ENCRYPT, length, (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);
}