diff --git a/applications/main/fap_loader/fap_loader_app.c b/applications/main/fap_loader/fap_loader_app.c index ffbf87c7a..bffb0899f 100644 --- a/applications/main/fap_loader/fap_loader_app.c +++ b/applications/main/fap_loader/fap_loader_app.c @@ -104,31 +104,27 @@ static bool fap_loader_run_selected_app(FapLoader* loader) { FURI_LOG_I(TAG, "Loaded in %ums", (size_t)(furi_get_tick() - start)); FURI_LOG_I(TAG, "FAP Loader is starting app"); - - if(strcmp(furi_string_get_cstr(loader->fap_args), "false") == 0) - { - FuriThread* thread = - flipper_application_spawn(loader->app, NULL); - furi_thread_start(thread); - furi_thread_join(thread); - show_error = false; - int ret = furi_thread_get_return_code(thread); + if(strcmp(furi_string_get_cstr(loader->fap_args), "false") == 0) { + FuriThread* thread = flipper_application_spawn(loader->app, NULL); + furi_thread_start(thread); + furi_thread_join(thread); - FURI_LOG_I(TAG, "FAP app returned: %i", ret); - } - else - { - FuriThread* thread = - flipper_application_spawn(loader->app, (void*)furi_string_get_cstr(loader->fap_args)); - furi_thread_start(thread); - furi_thread_join(thread); + show_error = false; + int ret = furi_thread_get_return_code(thread); - show_error = false; - int ret = furi_thread_get_return_code(thread); + FURI_LOG_I(TAG, "FAP app returned: %i", ret); + } else { + FuriThread* thread = flipper_application_spawn( + loader->app, (void*)furi_string_get_cstr(loader->fap_args)); + furi_thread_start(thread); + furi_thread_join(thread); - FURI_LOG_I(TAG, "FAP app returned: %i", ret); - } + show_error = false; + int ret = furi_thread_get_return_code(thread); + + FURI_LOG_I(TAG, "FAP app returned: %i", ret); + } } while(0); if(show_error) { diff --git a/applications/main/nfc/scenes/nfc_scene_passport_read.c b/applications/main/nfc/scenes/nfc_scene_passport_read.c index 3f5ce66f8..23ada2a11 100644 --- a/applications/main/nfc/scenes/nfc_scene_passport_read.c +++ b/applications/main/nfc/scenes/nfc_scene_passport_read.c @@ -21,19 +21,19 @@ void nfc_scene_passport_read_on_enter(void* context) { temp_str = furi_string_alloc(); furi_string_set(temp_str, "\e#Passport\n"); char iso_type = FURI_BIT(data->sak, 5) ? '4' : '3'; - - char nfc_type; - switch(data->type) { - case FuriHalNfcTypeA: - nfc_type = 'A'; - break; - case FuriHalNfcTypeB: - nfc_type = 'B'; - break; - default: - nfc_type = '?'; - break; - } + + char nfc_type; + switch(data->type) { + case FuriHalNfcTypeA: + nfc_type = 'A'; + break; + case FuriHalNfcTypeB: + nfc_type = 'B'; + break; + default: + nfc_type = '?'; + break; + } furi_string_cat_printf(temp_str, "ISO 14443-%c (NFC-%c)\n", iso_type, nfc_type); furi_string_cat_printf(temp_str, "UID:"); for(size_t i = 0; i < data->uid_len; i++) { diff --git a/applications/plugins/subbrute/scenes/subbrute_scene_start.c b/applications/plugins/subbrute/scenes/subbrute_scene_start.c index b993b922c..fb01a3339 100644 --- a/applications/plugins/subbrute/scenes/subbrute_scene_start.c +++ b/applications/plugins/subbrute/scenes/subbrute_scene_start.c @@ -52,7 +52,8 @@ bool subbrute_scene_start_on_event(void* context, SceneManagerEvent event) { SubBruteAttacks attack = subbrute_main_view_get_index(instance->view_main); uint8_t extra_repeats = subbrute_main_view_get_extra_repeats(instance->view_main); - if(subbrute_device_attack_set(instance->device, attack, extra_repeats) != SubBruteFileResultOk || + if(subbrute_device_attack_set(instance->device, attack, extra_repeats) != + SubBruteFileResultOk || !subbrute_worker_init_default_attack( instance->worker, attack, diff --git a/applications/services/desktop/scenes/desktop_scene_main.c b/applications/services/desktop/scenes/desktop_scene_main.c index 7847e784a..cb60579f5 100644 --- a/applications/services/desktop/scenes/desktop_scene_main.c +++ b/applications/services/desktop/scenes/desktop_scene_main.c @@ -229,20 +229,20 @@ bool desktop_scene_main_on_event(void* context, SceneManagerEvent event) { break; } case DesktopMainEventOpenArkanoid: { - LoaderStatus status = - loader_start(desktop->loader, "Applications", EXT_PATH("/apps/Games/Arkanoid.fap")); + LoaderStatus status = loader_start( + desktop->loader, "Applications", EXT_PATH("/apps/Games/Arkanoid.fap")); consumed = true; break; } case DesktopMainEventOpenHeap: { - LoaderStatus status = - loader_start(desktop->loader, "Applications", EXT_PATH("/apps/Games/Heap_Defence.fap")); + LoaderStatus status = loader_start( + desktop->loader, "Applications", EXT_PATH("/apps/Games/Heap_Defence.fap")); consumed = true; break; } case DesktopMainEventOpenSubRemote: { - LoaderStatus status = - loader_start(desktop->loader, "Applications", EXT_PATH("/apps/Main/SubGHz_Remote.fap")); + LoaderStatus status = loader_start( + desktop->loader, "Applications", EXT_PATH("/apps/Main/SubGHz_Remote.fap")); consumed = true; break; } diff --git a/applications/services/desktop/views/desktop_view_main.c b/applications/services/desktop/views/desktop_view_main.c index 3ee3d7f61..a4b6025e5 100644 --- a/applications/services/desktop/views/desktop_view_main.c +++ b/applications/services/desktop/views/desktop_view_main.c @@ -84,7 +84,8 @@ bool desktop_main_input_callback(InputEvent* event, void* context) { } else if(event->key == InputKeyDown) { main_view->callback(DesktopMainEventOpenFavoriteSecondary, main_view->context); } else if(event->key == InputKeyLeft) { - main_view->callback(DesktopMainEventOpenSubRemote, main_view->context); // OPENS SUBGHZ REMOTE + main_view->callback( + DesktopMainEventOpenSubRemote, main_view->context); // OPENS SUBGHZ REMOTE } } } else if(main_view->is_gamemode == true) { @@ -97,7 +98,8 @@ bool desktop_main_input_callback(InputEvent* event, void* context) { // PREFER TO OPEN GAMES MENU main_view->callback(DesktopMainEventOpen2048, main_view->context); // OPENS 2048 } else if(event->key == InputKeyLeft) { - main_view->callback(DesktopMainEventOpenTetris, main_view->context); // OPENS TETRIS + main_view->callback( + DesktopMainEventOpenTetris, main_view->context); // OPENS TETRIS } } else if(event->type == InputTypeLong) { if(event->key == InputKeyOk) { @@ -105,7 +107,8 @@ bool desktop_main_input_callback(InputEvent* event, void* context) { } else if(event->key == InputKeyUp) { main_view->callback(DesktopMainEventOpenDOOM, main_view->context); // OPENS DOOM } else if(event->key == InputKeyDown) { - main_view->callback(DesktopMainEventOpenZombiez, main_view->context); // OPENS Zombiez + main_view->callback( + DesktopMainEventOpenZombiez, main_view->context); // OPENS Zombiez } else if(event->key == InputKeyLeft) { main_view->callback(DesktopMainEventOpenClock, main_view->context); // OPENS CLOCK } @@ -117,9 +120,11 @@ bool desktop_main_input_callback(InputEvent* event, void* context) { } else if(event->key == InputKeyUp) { main_view->callback(DesktopMainEventOpenLockMenu, main_view->context); } else if(event->key == InputKeyDown) { - main_view->callback(DesktopMainEventOpenTetris, main_view->context); // OPENS Tetris + main_view->callback( + DesktopMainEventOpenTetris, main_view->context); // OPENS Tetris } else if(event->key == InputKeyLeft) { - main_view->callback(DesktopMainEventOpenArkanoid, main_view->context); // OPENS Arkanoid + main_view->callback( + DesktopMainEventOpenArkanoid, main_view->context); // OPENS Arkanoid } } else if(event->type == InputTypeLong) { if(event->key == InputKeyOk) { @@ -127,9 +132,11 @@ bool desktop_main_input_callback(InputEvent* event, void* context) { } else if(event->key == InputKeyUp) { main_view->callback(DesktopMainEventOpenDOOM, main_view->context); // OPENS DOOM } else if(event->key == InputKeyDown) { - main_view->callback(DesktopMainEventOpenZombiez, main_view->context); // OPENS Zombiez + main_view->callback( + DesktopMainEventOpenZombiez, main_view->context); // OPENS Zombiez } else if(event->key == InputKeyLeft) { - main_view->callback(DesktopMainEventOpenHeap, main_view->context); // OPENS Heap Defence + main_view->callback( + DesktopMainEventOpenHeap, main_view->context); // OPENS Heap Defence } } } diff --git a/firmware/targets/f7/furi_hal/furi_hal_subghz.c b/firmware/targets/f7/furi_hal/furi_hal_subghz.c index 581351b07..5b59aa44e 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_subghz.c +++ b/firmware/targets/f7/furi_hal/furi_hal_subghz.c @@ -19,7 +19,6 @@ #define TAG "FuriHalSubGhz" - /* * Uncomment define to enable duplication of * IO GO0 CC1101 to an external comb. @@ -35,7 +34,7 @@ * Attention this setting switches pin to output. * Make sure it is not connected directly to power or ground */ - + //#define SUBGHZ_DEBUG_CC1101_PIN gpio_ext_pa7 #ifdef SUBGHZ_DEBUG_CC1101_PIN uint32_t subghz_debug_gpio_buff[2]; diff --git a/lib/nfc/helpers/iso7816.c b/lib/nfc/helpers/iso7816.c index cab78bcb7..e06a98fc4 100644 --- a/lib/nfc/helpers/iso7816.c +++ b/lib/nfc/helpers/iso7816.c @@ -15,7 +15,7 @@ TlvInfo iso7816_tlv_parse(const uint8_t* data) { tlv.tag = *(data++); tlv.ber.constructed = ((tlv.tag & 0x20) != 0); tlv.ber.class = (tlv.tag >> 6) & 0x03; - if ((tlv.tag & 0x1f) == 0x1f) { + if((tlv.tag & 0x1f) == 0x1f) { // BER-TLV, multi byte tag tlv.tag <<= 8; tlv.tag |= *(data++); @@ -33,19 +33,19 @@ TlvInfo iso7816_tlv_parse(const uint8_t* data) { //TODO: check for invalid 'indefinite length' tlv.length = *(data++); - if (tlv.length == 0xff) { + if(tlv.length == 0xff) { // Simple-TLV 2 byte length tlv.length = *(data++) << 8; tlv.length += *(data++); } else if(tlv.length > 0x7f) { uint8_t length_bytes = tlv.length & 0x7f; //printf("BER length of %d bytes\n", length_bytes); - if (length_bytes < 1 || length_bytes > 4) { + if(length_bytes < 1 || length_bytes > 4) { //TODO: error: ISO7816 doesn't support more than 4 length bytes return (TlvInfo){.tag = 0}; } tlv.length = 0; - for(uint8_t i=0; iinterface == FuriHalNfcInterfaceIsoDep) { + if(nfc_data->interface == FuriHalNfcInterfaceIsoDep) { FURI_LOG_I(TAG, "ISO14443-4B card detected"); //TODO: thoughts on improving logic/readability here? do { @@ -451,15 +451,15 @@ void nfc_worker_read(NfcWorker* nfc_worker) { } } } else if(nfc_data->type == FuriHalNfcTypeB) { - if(nfc_worker_read_nfcb(nfc_worker, &tx_rx)) { - if(dev_data->protocol == NfcDeviceProtocolMRTD) { - event = NfcWorkerEventReadPassport; - break; - } - } - - event = NfcWorkerEventReadUidNfcB; - break; + if(nfc_worker_read_nfcb(nfc_worker, &tx_rx)) { + if(dev_data->protocol == NfcDeviceProtocolMRTD) { + event = NfcWorkerEventReadPassport; + break; + } + } + + event = NfcWorkerEventReadUidNfcB; + break; } else if(nfc_data->type == FuriHalNfcTypeF) { event = NfcWorkerEventReadUidNfcF; break; diff --git a/lib/nfc/protocols/mrtd.c b/lib/nfc/protocols/mrtd.c index 2f10584ce..612b03127 100644 --- a/lib/nfc/protocols/mrtd.c +++ b/lib/nfc/protocols/mrtd.c @@ -17,7 +17,7 @@ //TODO: idea - generalize ISO7816 reading. List available apps -#define num_elements(A) (sizeof(A)/sizeof(A[0])) +#define num_elements(A) (sizeof(A) / sizeof(A[0])) static void hexdump(FuriLogLevel level, char* prefix, void* data, size_t length) { if(furi_log_get_level() >= level) { @@ -46,12 +46,22 @@ static void mrtd_trace(MrtdApplication* app) { uint16_t mrtd_decode_response(uint8_t* buffer, size_t len) { // Last two bytes are return code - return (buffer[len-2] << 8) | buffer[len-1]; + return (buffer[len - 2] << 8) | buffer[len - 1]; } //TODO: rename to transceive? //TODO: PRIO output and output written writing seems to crash flipper, sometimes -bool mrtd_send_apdu(MrtdApplication* app, uint8_t cla, uint8_t ins, uint8_t p1, uint8_t p2, uint8_t lc, const void* data, int16_t le, uint8_t* output, size_t* output_written) { +bool mrtd_send_apdu( + MrtdApplication* app, + uint8_t cla, + uint8_t ins, + uint8_t p1, + uint8_t p2, + uint8_t lc, + const void* data, + int16_t le, + uint8_t* output, + size_t* output_written) { FuriHalNfcTxRxContext* tx_rx = app->tx_rx; size_t idx = 0; @@ -59,7 +69,8 @@ bool mrtd_send_apdu(MrtdApplication* app, uint8_t cla, uint8_t ins, uint8_t p1, if(app->secure_messaging) { app->ssc_long++; - idx = mrtd_protect_apdu(cla, ins, p1, p2, lc, data, le, app->ksenc, app->ksmac, app->ssc_long, tx_rx->tx_data); + idx = mrtd_protect_apdu( + cla, ins, p1, p2, lc, data, le, app->ksenc, app->ksmac, app->ssc_long, tx_rx->tx_data); } else { tx_rx->tx_data[idx++] = cla; tx_rx->tx_data[idx++] = ins; @@ -71,7 +82,7 @@ bool mrtd_send_apdu(MrtdApplication* app, uint8_t cla, uint8_t ins, uint8_t p1, idx += lc; } if(le >= 0) { - tx_rx->tx_data[idx++] = le&0xff; + tx_rx->tx_data[idx++] = le & 0xff; } } @@ -85,8 +96,14 @@ bool mrtd_send_apdu(MrtdApplication* app, uint8_t cla, uint8_t ins, uint8_t p1, if(app->secure_messaging && ret_code == 0x9000) { app->ssc_long++; - ret_code = mrtd_bac_decrypt_verify_sm(tx_rx->rx_data, tx_rx->rx_bits / 8 - 2, - app->ksenc, app->ksmac, app->ssc_long, output, output_written); + ret_code = mrtd_bac_decrypt_verify_sm( + tx_rx->rx_data, + tx_rx->rx_bits / 8 - 2, + app->ksenc, + app->ksmac, + app->ssc_long, + output, + output_written); //ret_code = 0x1337; //TODO: remove PRIO } @@ -101,22 +118,22 @@ bool mrtd_send_apdu(MrtdApplication* app, uint8_t cla, uint8_t ins, uint8_t p1, FURI_LOG_I(TAG, "APDU answer is not 0x9000, but 0x%04X", ret_code); switch(ret_code) { - case 0x6987: - FURI_LOG_I(TAG, "'expected secure messaging data objects are missing'"); - app->secure_messaging = false; - break; - case 0x6988: - FURI_LOG_I(TAG, "'secure messaging data objects are incorrect'"); - app->secure_messaging = false; - break; - case 0xff01: - //CUSTOM ERROR CODE from mrtd_helpers.c - FURI_LOG_I(TAG, "'invalid padding'"); - break; - case 0xff02: - //CUSTOM ERROR CODE from mrtd_helpers.c - FURI_LOG_I(TAG, "'verify failed'"); - break; + case 0x6987: + FURI_LOG_I(TAG, "'expected secure messaging data objects are missing'"); + app->secure_messaging = false; + break; + case 0x6988: + FURI_LOG_I(TAG, "'secure messaging data objects are incorrect'"); + app->secure_messaging = false; + break; + case 0xff01: + //CUSTOM ERROR CODE from mrtd_helpers.c + FURI_LOG_I(TAG, "'invalid padding'"); + break; + case 0xff02: + //CUSTOM ERROR CODE from mrtd_helpers.c + FURI_LOG_I(TAG, "'verify failed'"); + break; } return false; @@ -129,8 +146,16 @@ bool mrtd_send_apdu(MrtdApplication* app, uint8_t cla, uint8_t ins, uint8_t p1, //TODO: rename commands to "mrtd_cmd_..." bool mrtd_select_app(MrtdApplication* app, AIDValue aid) { - FURI_LOG_D(TAG, "Send select App: %02X %02X %02X %02X %02X %02X %02X", - aid[0], aid[1], aid[2], aid[3], aid[4], aid[5], aid[6]); + FURI_LOG_D( + TAG, + "Send select App: %02X %02X %02X %02X %02X %02X %02X", + aid[0], + aid[1], + aid[2], + aid[3], + aid[4], + aid[5], + aid[6]); if(!mrtd_send_apdu(app, 0x00, 0xA4, 0x04, 0x0C, 0x07, aid, -1, NULL, NULL)) { FURI_LOG_W(TAG, "Failed select App"); return false; @@ -149,12 +174,18 @@ bool mrtd_get_challenge(MrtdApplication* app, uint8_t challenge[8]) { return true; } -bool mrtd_external_authenticate(MrtdApplication* app, uint8_t* cmd_data, size_t cmd_size, uint8_t* out_data, size_t out_size) { +bool mrtd_external_authenticate( + MrtdApplication* app, + uint8_t* cmd_data, + size_t cmd_size, + uint8_t* out_data, + size_t out_size) { furi_assert(cmd_size == 0x28); furi_assert(out_size >= 0x28); FURI_LOG_D(TAG, "Send External Authenticate"); - if(!mrtd_send_apdu(app, 0x00, 0x82, 0x00, 0x00, cmd_size, cmd_data, 0x28, out_data, &out_size)) { + if(!mrtd_send_apdu( + app, 0x00, 0x82, 0x00, 0x00, cmd_size, cmd_data, 0x28, out_data, &out_size)) { FURI_LOG_W(TAG, "Failed External Authenticate"); return false; } @@ -184,7 +215,8 @@ size_t mrtd_read_binary(MrtdApplication* app, uint8_t* buffer, size_t bufsize, s //TODO: test with max_read = bufsize (value !0, > file size) int16_t max_read = 0; // 0 = 'everything', -1 = 'nothing', >0 = amount of bytes size_t buf_written = 0; - if(!mrtd_send_apdu(app, 0x00, 0xB0, offset>>8, offset&0xff, 0x00, NULL, max_read, buffer, &buf_written)) { + if(!mrtd_send_apdu( + app, 0x00, 0xB0, offset >> 8, offset & 0xff, 0x00, NULL, max_read, buffer, &buf_written)) { FURI_LOG_E(TAG, "Failed to read"); return 0; } @@ -225,13 +257,19 @@ bool parse_ef_dir(EF_DIR_contents* EF_DIR, const uint8_t* data, size_t length) { TlvInfo tlv = iso7816_tlv_parse(data + offset); if(tlv.tag != 0x61 || tlv.length != 0x09) { - FURI_LOG_E(TAG, "Invalid EF.DIR, tag at offset %d must be '61' and length 9. Got '%02X' and %d", offset, tlv.tag, tlv.length); + FURI_LOG_E( + TAG, + "Invalid EF.DIR, tag at offset %d must be '61' and length 9. Got '%02X' and %d", + offset, + tlv.tag, + tlv.length); return false; } tlv = iso7816_tlv_parse(tlv.value); if(tlv.tag != 0x4F || tlv.length != 0x07) { - FURI_LOG_E(TAG, "Invalid EF.DIR, subtag at offset %d must be '4F' and length 7", offset); + FURI_LOG_E( + TAG, "Invalid EF.DIR, subtag at offset %d must be '4F' and length 7", offset); return false; } @@ -244,9 +282,9 @@ bool parse_ef_dir(EF_DIR_contents* EF_DIR, const uint8_t* data, size_t length) { //TODO: remove testing block: FURI_LOG_D(TAG, "EF.DIR applications: %d", EF_DIR->applications_count); if(furi_log_get_level() >= FuriLogLevelDebug) { - for(uint8_t i=0; iapplications_count; ++i) { + for(uint8_t i = 0; i < EF_DIR->applications_count; ++i) { printf("- "); - for(uint8_t n=0; napplications[i][n]); } printf("\r\n"); @@ -261,7 +299,8 @@ bool parse_ef_com(EF_COM_contents* EF_COM, const uint8_t* data, size_t length) { uint16_t unicode_tag_path[] = {0x60, 0x5f36}; uint16_t tags_tag_path[] = {0x60, 0x5c}; - TlvInfo tlv_lds_version = iso7816_tlv_select(data, length, lds_tag_path, num_elements(lds_tag_path)); + TlvInfo tlv_lds_version = + iso7816_tlv_select(data, length, lds_tag_path, num_elements(lds_tag_path)); if(!tlv_lds_version.tag) { FURI_LOG_W(TAG, "EF.COM LDS version not found"); return false; @@ -269,7 +308,8 @@ bool parse_ef_com(EF_COM_contents* EF_COM, const uint8_t* data, size_t length) { EF_COM->lds_version = tlv_number(tlv_lds_version); - TlvInfo tlv_unicode_version = iso7816_tlv_select(data, length, unicode_tag_path, num_elements(unicode_tag_path)); + TlvInfo tlv_unicode_version = + iso7816_tlv_select(data, length, unicode_tag_path, num_elements(unicode_tag_path)); if(!tlv_unicode_version.tag) { FURI_LOG_W(TAG, "EF.COM Unicode info not found!"); return false; @@ -277,13 +317,14 @@ bool parse_ef_com(EF_COM_contents* EF_COM, const uint8_t* data, size_t length) { EF_COM->unicode_version = tlv_number(tlv_unicode_version); - TlvInfo tlv_tag_list = iso7816_tlv_select(data, length, tags_tag_path, num_elements(tags_tag_path)); + TlvInfo tlv_tag_list = + iso7816_tlv_select(data, length, tags_tag_path, num_elements(tags_tag_path)); if(!tlv_tag_list.tag) { FURI_LOG_W(TAG, "EF.CO Tag List not found!"); return false; } - for(size_t i=0; itag_list[i] = (i < tlv_tag_list.length) ? tlv_tag_list.value[i] : 0x00; } @@ -293,7 +334,7 @@ bool parse_ef_com(EF_COM_contents* EF_COM, const uint8_t* data, size_t length) { void mrzcpy(uint8_t* dest, const uint8_t* src, size_t* idx, size_t n) { //FURI_LOG_D(TAG, "mrzcpy %d: %.*s", n, n, src + *idx); //memcpy(dest, src + *idx, n); - for(size_t i=0; itype = MrtdTypeTD1; - mrzcpy(DG1->doctype, mrz, &idx, 2); - mrzcpy(DG1->issuing_state, mrz, &idx, 3); - mrzcpy(DG1->docnr, mrz, &idx, 9); - idx += 1; // docnr check digit - idx += 15; // optional data - mrtd_parse_date(&DG1->birth_date, mrz + idx); - idx += 6; // birth_date - idx += 1; // birth date check digit - mrzcpy(DG1->sex, mrz, &idx, 1); - mrtd_parse_date(&DG1->expiry_date, mrz + idx); - idx += 6; // expiry_date - idx += 1; // expiry date check digit - mrzcpy(DG1->nationality, mrz, &idx, 3); - idx += 11; // optional data - idx += 1; // check digit - mrzcpy(DG1->name, mrz, &idx, 30); - // 30 + 30 + 30 - break; - case 72: - DG1->type = MrtdTypeTD2; - mrzcpy(DG1->doctype, mrz, &idx, 2); - mrzcpy(DG1->issuing_state, mrz, &idx, 3); - mrzcpy(DG1->name, mrz, &idx, 31); - mrzcpy(DG1->docnr, mrz, &idx, 9); - idx += 1; // docnr check digit - mrzcpy(DG1->nationality, mrz, &idx, 3); - mrtd_parse_date(&DG1->birth_date, mrz + idx); - idx += 6; // birth_date - idx += 1; // birth date check digit - mrzcpy(DG1->sex, mrz, &idx, 1); - mrtd_parse_date(&DG1->expiry_date, mrz + idx); - idx += 6; // expiry_date - idx += 1; // expiry date check digit - idx += 7; // optional data - idx += 1; // check digit - // 36 + 36 - break; - case 88: - DG1->type = MrtdTypeTD3; - mrzcpy(DG1->doctype, mrz, &idx, 2); - mrzcpy(DG1->issuing_state, mrz, &idx, 3); - mrzcpy(DG1->name, mrz, &idx, 39); - mrzcpy(DG1->docnr, mrz, &idx, 9); - idx += 1; // docnr check digit - mrzcpy(DG1->nationality, mrz, &idx, 3); - mrtd_parse_date(&DG1->birth_date, mrz + idx); - idx += 1; // birth date check digit - idx += 6; // birth_date - mrzcpy(DG1->sex, mrz, &idx, 1); - mrtd_parse_date(&DG1->expiry_date, mrz + idx); - idx += 6; // expiry_date - idx += 1; // expiry date check digit - idx += 14; // optional data - idx += 1; // check digit - idx += 1; // check digit - // 44 + 44 - break; - default: - FURI_LOG_W(TAG, "Unexpected MRZ length in DG1: %d. TD1=90, TD2=72, TD3=88.", tlv_mrz.length); - return false; + case 90: + DG1->type = MrtdTypeTD1; + mrzcpy(DG1->doctype, mrz, &idx, 2); + mrzcpy(DG1->issuing_state, mrz, &idx, 3); + mrzcpy(DG1->docnr, mrz, &idx, 9); + idx += 1; // docnr check digit + idx += 15; // optional data + mrtd_parse_date(&DG1->birth_date, mrz + idx); + idx += 6; // birth_date + idx += 1; // birth date check digit + mrzcpy(DG1->sex, mrz, &idx, 1); + mrtd_parse_date(&DG1->expiry_date, mrz + idx); + idx += 6; // expiry_date + idx += 1; // expiry date check digit + mrzcpy(DG1->nationality, mrz, &idx, 3); + idx += 11; // optional data + idx += 1; // check digit + mrzcpy(DG1->name, mrz, &idx, 30); + // 30 + 30 + 30 + break; + case 72: + DG1->type = MrtdTypeTD2; + mrzcpy(DG1->doctype, mrz, &idx, 2); + mrzcpy(DG1->issuing_state, mrz, &idx, 3); + mrzcpy(DG1->name, mrz, &idx, 31); + mrzcpy(DG1->docnr, mrz, &idx, 9); + idx += 1; // docnr check digit + mrzcpy(DG1->nationality, mrz, &idx, 3); + mrtd_parse_date(&DG1->birth_date, mrz + idx); + idx += 6; // birth_date + idx += 1; // birth date check digit + mrzcpy(DG1->sex, mrz, &idx, 1); + mrtd_parse_date(&DG1->expiry_date, mrz + idx); + idx += 6; // expiry_date + idx += 1; // expiry date check digit + idx += 7; // optional data + idx += 1; // check digit + // 36 + 36 + break; + case 88: + DG1->type = MrtdTypeTD3; + mrzcpy(DG1->doctype, mrz, &idx, 2); + mrzcpy(DG1->issuing_state, mrz, &idx, 3); + mrzcpy(DG1->name, mrz, &idx, 39); + mrzcpy(DG1->docnr, mrz, &idx, 9); + idx += 1; // docnr check digit + mrzcpy(DG1->nationality, mrz, &idx, 3); + mrtd_parse_date(&DG1->birth_date, mrz + idx); + idx += 1; // birth date check digit + idx += 6; // birth_date + mrzcpy(DG1->sex, mrz, &idx, 1); + mrtd_parse_date(&DG1->expiry_date, mrz + idx); + idx += 6; // expiry_date + idx += 1; // expiry date check digit + idx += 14; // optional data + idx += 1; // check digit + idx += 1; // check digit + // 44 + 44 + break; + default: + FURI_LOG_W( + TAG, "Unexpected MRZ length in DG1: %d. TD1=90, TD2=72, TD3=88.", tlv_mrz.length); + return false; } return true; @@ -437,17 +479,17 @@ void mrtd_test(MrtdApplication* app, MrtdData* mrtd_data) { mrtd_data->auth_success = false; FURI_LOG_D(TAG, "Auth method: %d", method); switch(method) { - case MrtdAuthMethodAny: - //TODO: try PACE, then BAC - case MrtdAuthMethodBac: - mrtd_data->auth_success = mrtd_bac(app, &mrtd_data->auth); - break; - case MrtdAuthMethodPace: - FURI_LOG_E(TAG, "Auth method PACE not implemented"); - break; - case MrtdAuthMethodNone: - default: - break; + case MrtdAuthMethodAny: + //TODO: try PACE, then BAC + case MrtdAuthMethodBac: + mrtd_data->auth_success = mrtd_bac(app, &mrtd_data->auth); + break; + case MrtdAuthMethodPace: + FURI_LOG_E(TAG, "Auth method PACE not implemented"); + break; + case MrtdAuthMethodNone: + default: + break; } if(!mrtd_data->auth_success) { @@ -514,14 +556,14 @@ bool mrtd_bac(MrtdApplication* app, MrtdAuthData* auth) { uint8_t S[32]; memcpy(S, rnd_ifd, 8); - memcpy(S+8, rnd_ic, 8); - memcpy(S+16, k_ifd, 16); + memcpy(S + 8, rnd_ic, 8); + memcpy(S + 16, k_ifd, 16); hexdump(FuriLogLevelDebug, "S:", S, 32); uint8_t cmd_data[40]; - uint8_t *eifd = cmd_data; - uint8_t *mifd = cmd_data+32; + uint8_t* eifd = cmd_data; + uint8_t* mifd = cmd_data + 32; mrtd_bac_encrypt(S, 32, kenc, eifd); mrtd_bac_padded_mac(eifd, 32, kmac, mifd); @@ -536,8 +578,8 @@ bool mrtd_bac(MrtdApplication* app, MrtdAuthData* auth) { FURI_LOG_W(TAG, "BAC DecryptVerify failed"); } - uint8_t *rnd_ifd_recv = buffer + 8; - uint8_t *kic = buffer + 16; + uint8_t* rnd_ifd_recv = buffer + 8; + uint8_t* kic = buffer + 16; hexdump(FuriLogLevelDebug, "kic:", kic, 16); @@ -546,7 +588,7 @@ bool mrtd_bac(MrtdApplication* app, MrtdAuthData* auth) { } uint8_t kseed[16]; - for(uint8_t i=0; i<16; ++i) { + for(uint8_t i = 0; i < 16; ++i) { kseed[i] = k_ifd[i] ^ kic[i]; //printf("seed %2d = %02X ^ %02X = %02X\r\n", i, k_ifd[i], kic[i], kseed[i]); } diff --git a/lib/nfc/protocols/mrtd_helpers.c b/lib/nfc/protocols/mrtd_helpers.c index 7456830d1..b22c040f3 100644 --- a/lib/nfc/protocols/mrtd_helpers.c +++ b/lib/nfc/protocols/mrtd_helpers.c @@ -7,7 +7,9 @@ #include #include -static inline unsigned char *ucstr(const char *str) { return (unsigned char *)str; } +static inline unsigned char* ucstr(const char* str) { + return (unsigned char*)str; +} uint8_t mrtd_bac_check_digit(const char* input, const uint8_t length) { const uint8_t num_weights = 3; @@ -15,7 +17,7 @@ uint8_t mrtd_bac_check_digit(const char* input, const uint8_t length) { uint8_t check_digit = 0; uint8_t idx; - for(uint8_t i=0; i= 'A' && c <= 'Z') { idx = c - 'A' + 10; @@ -26,7 +28,7 @@ uint8_t mrtd_bac_check_digit(const char* input, const uint8_t length) { } else { idx = 0; } - check_digit = (check_digit + idx * weights[i%num_weights]) % 10; + check_digit = (check_digit + idx * weights[i % num_weights]) % 10; } return check_digit; } @@ -62,7 +64,7 @@ bool mrtd_bac_get_kmrz(MrtdAuthData* auth, char* output, uint8_t output_size) { } cd_idx = idx; - for(uint8_t i=0; idoc_number[i]; if(c >= 'a' && c <= 'z') { c = c - 'a' + 'A'; @@ -71,21 +73,21 @@ bool mrtd_bac_get_kmrz(MrtdAuthData* auth, char* output, uint8_t output_size) { } if(docnr_length < 9) { - memset(output+idx, '<', 9-docnr_length); - idx += 9-docnr_length; + memset(output + idx, '<', 9 - docnr_length); + idx += 9 - docnr_length; } - output[idx++] = mrtd_bac_check_digit(output+cd_idx, docnr_length) + '0'; + output[idx++] = mrtd_bac_check_digit(output + cd_idx, docnr_length) + '0'; cd_idx = idx; - mrtd_print_date(output+idx, &auth->birth_date); + mrtd_print_date(output + idx, &auth->birth_date); idx += 6; - output[idx++] = mrtd_bac_check_digit(output+cd_idx, 6) + '0'; + output[idx++] = mrtd_bac_check_digit(output + cd_idx, 6) + '0'; cd_idx = idx; - mrtd_print_date(output+idx, &auth->expiry_date); + mrtd_print_date(output + idx, &auth->expiry_date); idx += 6; - output[idx++] = mrtd_bac_check_digit(output+cd_idx, 6) + '0'; + output[idx++] = mrtd_bac_check_digit(output + cd_idx, 6) + '0'; output[idx++] = '\x00'; return true; @@ -97,7 +99,7 @@ bool mrtd_bac_keys_from_seed(const uint8_t kseed[16], uint8_t ksenc[16], uint8_t mbedtls_sha1_init(&ctx); do { - for(uint8_t i=1; i<=2; ++i) { + for(uint8_t i = 1; i <= 2; ++i) { if(mbedtls_sha1_starts(&ctx)) break; if(mbedtls_sha1_update(&ctx, kseed, 16)) break; if(mbedtls_sha1_update(&ctx, ucstr("\x00\x00\x00"), 3)) break; @@ -105,16 +107,16 @@ bool mrtd_bac_keys_from_seed(const uint8_t kseed[16], uint8_t ksenc[16], uint8_t if(mbedtls_sha1_finish(&ctx, hash)) break; switch(i) { - case 1: - memcpy(ksenc, hash, 16); - mbedtls_des_key_set_parity(ksenc); - mbedtls_des_key_set_parity(ksenc+8); - break; - case 2: - memcpy(ksmac, hash, 16); - mbedtls_des_key_set_parity(ksmac); - mbedtls_des_key_set_parity(ksmac+8); - break; + case 1: + memcpy(ksenc, hash, 16); + mbedtls_des_key_set_parity(ksenc); + mbedtls_des_key_set_parity(ksenc + 8); + break; + case 2: + memcpy(ksmac, hash, 16); + mbedtls_des_key_set_parity(ksmac); + mbedtls_des_key_set_parity(ksmac + 8); + break; } } } while(false); @@ -171,15 +173,20 @@ bool mrtd_bac_decrypt(const uint8_t* data, size_t data_length, uint8_t* key, uin return true; } -bool mrtd_bac_decrypt_verify(const uint8_t* data, size_t data_length, uint8_t* key_enc, uint8_t* key_mac, uint8_t* output) { +bool mrtd_bac_decrypt_verify( + const uint8_t* data, + size_t data_length, + uint8_t* key_enc, + uint8_t* key_mac, + uint8_t* output) { mrtd_bac_decrypt(data, data_length - 8, key_enc, output); uint8_t mac_calc[8]; mrtd_bac_padded_mac(data, data_length - 8, key_mac, mac_calc); if(memcmp(mac_calc, data + data_length - 8, 8)) { - printf( "MAC failed\r\n"); - for(uint8_t i=0; i<8; ++i) { + printf("MAC failed\r\n"); + for(uint8_t i = 0; i < 8; ++i) { printf("%02X <=> %02X\r\n", mac_calc[i], data[data_length - 8 + i]); } return false; @@ -191,12 +198,19 @@ bool mrtd_bac_decrypt_verify(const uint8_t* data, size_t data_length, uint8_t* k // Otherwise, and if DO'87 is present, data is written to *output // output should have enough room for additional padding (rounded up by 8 bytes) // output_written will be the length without padding -uint16_t mrtd_bac_decrypt_verify_sm(const uint8_t* data, size_t data_length, uint8_t* key_enc, uint8_t* key_mac, uint64_t ssc, uint8_t* output, size_t* output_written) { +uint16_t mrtd_bac_decrypt_verify_sm( + const uint8_t* data, + size_t data_length, + uint8_t* key_enc, + uint8_t* key_mac, + uint64_t ssc, + uint8_t* output, + size_t* output_written) { // Message: [DO'85 or DO'87] || [DO'99] || DO'8E // Lengths: Var 1+1+2=4 1+1+8=10 //TODO: check for DO'99 presence, instead of assuming - uint16_t ret_code = data[data_length - 10 - 2] <<8 | data[data_length - 10 - 1]; + uint16_t ret_code = data[data_length - 10 - 2] << 8 | data[data_length - 10 - 1]; //ntohs(data + data_length - 10 - 2); TlvInfo do87 = iso7816_tlv_select(data, data_length, (uint16_t[]){0x87}, 1); @@ -213,11 +227,13 @@ uint16_t mrtd_bac_decrypt_verify_sm(const uint8_t* data, size_t data_length, uin size_t enclength = do87.length - 1; mrtd_bac_decrypt(encdata, enclength, key_enc, output); - printf("Decrypted: "); for(uint8_t i=0; i=0; --padidx) { + for(padidx = enclength - 1; padidx >= 0; --padidx) { if(output[padidx] == 0x00) { continue; } else if(output[padidx] == 0x80) { @@ -228,13 +244,13 @@ uint16_t mrtd_bac_decrypt_verify_sm(const uint8_t* data, size_t data_length, uin } } printf(" "); - for(int i=0; i %02X\r\n", mac_calc[i], data[data_length - 8 + i]); } return 0xff02; @@ -284,18 +301,25 @@ bool mrtd_bac_mac_update(mrtd_bac_mac_ctx* ctx, const uint8_t* data, size_t data data_idx += buff_add; if(ctx->idx_in == 0) { // buffer_in filled - for(uint8_t j=0; j<8; ++j) { + for(uint8_t j = 0; j < 8; ++j) { ctx->xormac[j] = ctx->mac[j] ^ ctx->buffer_in[j]; } mbedtls_des_crypt_ecb(&ctx->des, ctx->xormac, ctx->mac); - printf("DES buf: %02X %02X %02X %02X %02X %02X %02X %02X\r\n", - ctx->buffer_in[0], ctx->buffer_in[1], ctx->buffer_in[2], ctx->buffer_in[3], - ctx->buffer_in[4], ctx->buffer_in[5], ctx->buffer_in[6], ctx->buffer_in[7]); + printf( + "DES buf: %02X %02X %02X %02X %02X %02X %02X %02X\r\n", + ctx->buffer_in[0], + ctx->buffer_in[1], + ctx->buffer_in[2], + ctx->buffer_in[3], + ctx->buffer_in[4], + ctx->buffer_in[5], + ctx->buffer_in[6], + ctx->buffer_in[7]); //printf("DES1: %02X %02X %02X %02X %02X %02X %02X %02X\n", - //xormac[0], xormac[1], xormac[2], xormac[3], - //xormac[4], xormac[5], xormac[6], xormac[7]); + //xormac[0], xormac[1], xormac[2], xormac[3], + //xormac[4], xormac[5], xormac[6], xormac[7]); } } @@ -304,18 +328,25 @@ bool mrtd_bac_mac_update(mrtd_bac_mac_ctx* ctx, const uint8_t* data, size_t data // Not a full block break; } - for(uint8_t j=0; j<8; ++j) { + for(uint8_t j = 0; j < 8; ++j) { ctx->xormac[j] = ctx->mac[j] ^ data[data_idx++]; } mbedtls_des_crypt_ecb(&ctx->des, ctx->xormac, ctx->mac); - printf("DES add: %02X %02X %02X %02X %02X %02X %02X %02X\r\n", - data[data_idx - 8 + 0], data[data_idx - 8 + 1], data[data_idx - 8 + 2], data[data_idx - 8 + 3], - data[data_idx - 8 + 4], data[data_idx - 8 + 5], data[data_idx - 8 + 6], data[data_idx - 8 + 7]); + printf( + "DES add: %02X %02X %02X %02X %02X %02X %02X %02X\r\n", + data[data_idx - 8 + 0], + data[data_idx - 8 + 1], + data[data_idx - 8 + 2], + data[data_idx - 8 + 3], + data[data_idx - 8 + 4], + data[data_idx - 8 + 5], + data[data_idx - 8 + 6], + data[data_idx - 8 + 7]); //printf("DES1: %02X %02X %02X %02X %02X %02X %02X %02X\n", - //xormac[0], xormac[1], xormac[2], xormac[3], - //xormac[4], xormac[5], xormac[6], xormac[7]); + //xormac[0], xormac[1], xormac[2], xormac[3], + //xormac[4], xormac[5], xormac[6], xormac[7]); } if(data_idx < data_length) { @@ -340,7 +371,7 @@ bool mrtd_bac_mac_finalize(mrtd_bac_mac_ctx* ctx, uint8_t output[8]) { uint8_t tmp[8]; mbedtls_des_init(&ctx->des); - mbedtls_des_setkey_dec(&ctx->des, ctx->key+8); + mbedtls_des_setkey_dec(&ctx->des, ctx->key + 8); mbedtls_des_crypt_ecb(&ctx->des, ctx->mac, tmp); mbedtls_des_init(&ctx->des); @@ -362,19 +393,26 @@ bool mrtd_bac_mac(const uint8_t* data, size_t data_length, const uint8_t* key, u mbedtls_des_setkey_enc(&ctx, key); memset(mac, 0, 8); - for(size_t i=0; i 0) { - size_t newlength = ((lc+8)/8)*8; + size_t newlength = ((lc + 8) / 8) * 8; uint8_t padded[newlength]; output[idx++] = 0x87; // Header - output[idx++] = newlength + 1; // Length + output[idx++] = newlength + 1; // Length output[idx++] = 0x01; //TODO: check this value memset(padded, 0, newlength); @@ -464,7 +513,7 @@ size_t mrtd_protect_apdu(uint8_t cla, uint8_t ins, uint8_t p1, uint8_t p2, uint8 idx += 8; printf("MAC: "); - for(uint8_t i=0; i<8; ++i) { + for(uint8_t i = 0; i < 8; ++i) { printf("%02X ", output[idx - 8 + i]); } printf("\r\n"); @@ -477,63 +526,81 @@ size_t mrtd_protect_apdu(uint8_t cla, uint8_t ins, uint8_t p1, uint8_t p2, uint8 return idx; } -EFFile EFNone = {.name = NULL, .file_id = 0x0000, .short_id = 0x00, .tag = 0x00 }; +EFFile EFNone = {.name = NULL, .file_id = 0x0000, .short_id = 0x00, .tag = 0x00}; const struct EFFormat EF = { - .ATR = {.name = "ATR", .file_id = 0x2F01, .short_id = 0x01 }, - .DIR = {.name = "DIR", .file_id = 0x2F00, .short_id = 0x1E }, - .CardAccess = {.name = "CardAccess", .file_id = 0x011C, .short_id = 0x1C }, - .CardSecurity = {.name = "CardSecurity", .file_id = 0x011D, .short_id = 0x1D }, - .COM = {.name = "COM", .file_id = 0x011E, .short_id = 0x1E, .tag = 0x60 }, - .SOD = {.name = "SOD", .file_id = 0X011D, .short_id = 0X1D, .tag = 0x77 }, - .DG1 = {.name = "DG1", .file_id = 0X0101, .short_id = 0X01, .tag = 0x61 }, - .DG2 = {.name = "DG2", .file_id = 0X0102, .short_id = 0X02, .tag = 0x75 }, - .DG3 = {.name = "DG3", .file_id = 0X0103, .short_id = 0X03, .tag = 0x63 }, - .DG4 = {.name = "DG4", .file_id = 0X0104, .short_id = 0X04, .tag = 0x76 }, - .DG5 = {.name = "DG5", .file_id = 0X0105, .short_id = 0X05, .tag = 0x65 }, - .DG6 = {.name = "DG6", .file_id = 0X0106, .short_id = 0X06, .tag = 0x66 }, - .DG7 = {.name = "DG7", .file_id = 0X0107, .short_id = 0X07, .tag = 0x67 }, - .DG8 = {.name = "DG8", .file_id = 0X0108, .short_id = 0X08, .tag = 0x68 }, - .DG9 = {.name = "DG9", .file_id = 0X0109, .short_id = 0X09, .tag = 0x69 }, - .DG10 = {.name = "DG10", .file_id = 0X010A, .short_id = 0X0A, .tag = 0x6a }, - .DG11 = {.name = "DG11", .file_id = 0X010B, .short_id = 0X0B, .tag = 0x6b }, - .DG12 = {.name = "DG12", .file_id = 0X010C, .short_id = 0X0C, .tag = 0x6c }, - .DG13 = {.name = "DG13", .file_id = 0X010D, .short_id = 0X0D, .tag = 0x6d }, - .DG14 = {.name = "DG14", .file_id = 0X010E, .short_id = 0X0E, .tag = 0x6e }, - .DG15 = {.name = "DG15", .file_id = 0X010F, .short_id = 0X0F, .tag = 0x6f }, - .DG16 = {.name = "DG16", .file_id = 0X0110, .short_id = 0X10, .tag = 0x70 }, + .ATR = {.name = "ATR", .file_id = 0x2F01, .short_id = 0x01}, + .DIR = {.name = "DIR", .file_id = 0x2F00, .short_id = 0x1E}, + .CardAccess = {.name = "CardAccess", .file_id = 0x011C, .short_id = 0x1C}, + .CardSecurity = {.name = "CardSecurity", .file_id = 0x011D, .short_id = 0x1D}, + .COM = {.name = "COM", .file_id = 0x011E, .short_id = 0x1E, .tag = 0x60}, + .SOD = {.name = "SOD", .file_id = 0X011D, .short_id = 0X1D, .tag = 0x77}, + .DG1 = {.name = "DG1", .file_id = 0X0101, .short_id = 0X01, .tag = 0x61}, + .DG2 = {.name = "DG2", .file_id = 0X0102, .short_id = 0X02, .tag = 0x75}, + .DG3 = {.name = "DG3", .file_id = 0X0103, .short_id = 0X03, .tag = 0x63}, + .DG4 = {.name = "DG4", .file_id = 0X0104, .short_id = 0X04, .tag = 0x76}, + .DG5 = {.name = "DG5", .file_id = 0X0105, .short_id = 0X05, .tag = 0x65}, + .DG6 = {.name = "DG6", .file_id = 0X0106, .short_id = 0X06, .tag = 0x66}, + .DG7 = {.name = "DG7", .file_id = 0X0107, .short_id = 0X07, .tag = 0x67}, + .DG8 = {.name = "DG8", .file_id = 0X0108, .short_id = 0X08, .tag = 0x68}, + .DG9 = {.name = "DG9", .file_id = 0X0109, .short_id = 0X09, .tag = 0x69}, + .DG10 = {.name = "DG10", .file_id = 0X010A, .short_id = 0X0A, .tag = 0x6a}, + .DG11 = {.name = "DG11", .file_id = 0X010B, .short_id = 0X0B, .tag = 0x6b}, + .DG12 = {.name = "DG12", .file_id = 0X010C, .short_id = 0X0C, .tag = 0x6c}, + .DG13 = {.name = "DG13", .file_id = 0X010D, .short_id = 0X0D, .tag = 0x6d}, + .DG14 = {.name = "DG14", .file_id = 0X010E, .short_id = 0X0E, .tag = 0x6e}, + .DG15 = {.name = "DG15", .file_id = 0X010F, .short_id = 0X0F, .tag = 0x6f}, + .DG16 = {.name = "DG16", .file_id = 0X0110, .short_id = 0X10, .tag = 0x70}, }; struct AIDSet AID = { - .eMRTDApplication = {0xA0, 0x00, 0x00, 0x02, 0x47, 0x10, 0x01}, - .TravelRecords = {0xA0, 0x00, 0x00, 0x02, 0x47, 0x20, 0x01}, - .VisaRecords = {0xA0, 0x00, 0x00, 0x02, 0x47, 0x20, 0x02}, + .eMRTDApplication = {0xA0, 0x00, 0x00, 0x02, 0x47, 0x10, 0x01}, + .TravelRecords = {0xA0, 0x00, 0x00, 0x02, 0x47, 0x20, 0x01}, + .VisaRecords = {0xA0, 0x00, 0x00, 0x02, 0x47, 0x20, 0x02}, .AdditionalBiometrics = {0xA0, 0x00, 0x00, 0x02, 0x47, 0x20, 0x03}, }; const EFFile* mrtd_tag_to_file(uint8_t tag) { //TODO: generate this code with macros? switch(tag) { - case 0x60: return &EF.COM; - case 0x77: return &EF.SOD; - case 0x61: return &EF.DG1; - case 0x75: return &EF.DG2; - case 0x63: return &EF.DG3; - case 0x76: return &EF.DG4; - case 0x65: return &EF.DG5; - case 0x66: return &EF.DG6; - case 0x67: return &EF.DG7; - case 0x68: return &EF.DG8; - case 0x69: return &EF.DG9; - case 0x6a: return &EF.DG10; - case 0x6b: return &EF.DG11; - case 0x6c: return &EF.DG12; - case 0x6d: return &EF.DG13; - case 0x6e: return &EF.DG14; - case 0x6f: return &EF.DG15; - case 0x70: return &EF.DG16; - default: - return &EFNone; + case 0x60: + return &EF.COM; + case 0x77: + return &EF.SOD; + case 0x61: + return &EF.DG1; + case 0x75: + return &EF.DG2; + case 0x63: + return &EF.DG3; + case 0x76: + return &EF.DG4; + case 0x65: + return &EF.DG5; + case 0x66: + return &EF.DG6; + case 0x67: + return &EF.DG7; + case 0x68: + return &EF.DG8; + case 0x69: + return &EF.DG9; + case 0x6a: + return &EF.DG10; + case 0x6b: + return &EF.DG11; + case 0x6c: + return &EF.DG12; + case 0x6d: + return &EF.DG13; + case 0x6e: + return &EF.DG14; + case 0x6f: + return &EF.DG15; + case 0x70: + return &EF.DG16; + default: + return &EFNone; } }; diff --git a/lib/nfc/protocols/mrtd_helpers.h b/lib/nfc/protocols/mrtd_helpers.h index 83197d95e..e1bca39e9 100644 --- a/lib/nfc/protocols/mrtd_helpers.h +++ b/lib/nfc/protocols/mrtd_helpers.h @@ -158,33 +158,54 @@ bool mrtd_bac_padded_mac(const uint8_t* data, size_t data_length, uint8_t* key, bool mrtd_bac_decrypt(const uint8_t* data, size_t data_length, uint8_t* key, uint8_t* output); -bool mrtd_bac_decrypt_verify(const uint8_t* data, size_t data_length, uint8_t* key_enc, uint8_t* key_mac, uint8_t* output); +bool mrtd_bac_decrypt_verify( + const uint8_t* data, + size_t data_length, + uint8_t* key_enc, + uint8_t* key_mac, + uint8_t* output); //TODO: add some consts -uint16_t mrtd_bac_decrypt_verify_sm(const uint8_t* data, size_t data_length, uint8_t* key_enc, uint8_t* key_mac, uint64_t ssc, uint8_t* output, size_t* output_written); +uint16_t mrtd_bac_decrypt_verify_sm( + const uint8_t* data, + size_t data_length, + uint8_t* key_enc, + uint8_t* key_mac, + uint64_t ssc, + uint8_t* output, + size_t* output_written); #include #define htonll(x) ((((uint64_t)__htonl(x)) << 32) + __htonl((x) >> 32)) static __inline uint64_t mrtd_ssc_from_data(const uint8_t* rnd_ic, const uint8_t* rnd_ifd) { #if _BYTE_ORDER == _LITTLE_ENDIAN - return - (((uint64_t)rnd_ic[4] << 56) & 0xff00000000000000) | - (((uint64_t)rnd_ic[5] << 48) & 0x00ff000000000000) | - (((uint64_t)rnd_ic[6] << 40) & 0x0000ff0000000000) | - (((uint64_t)rnd_ic[7] << 32) & 0x000000ff00000000) | - (((uint64_t)rnd_ifd[4] << 24) & 0x00000000ff000000) | - (((uint64_t)rnd_ifd[5] << 16) & 0x0000000000ff0000) | - (((uint64_t)rnd_ifd[6] << 8) & 0x000000000000ff00) | - (((uint64_t)rnd_ifd[7]) & 0x00000000000000ff); + return (((uint64_t)rnd_ic[4] << 56) & 0xff00000000000000) | + (((uint64_t)rnd_ic[5] << 48) & 0x00ff000000000000) | + (((uint64_t)rnd_ic[6] << 40) & 0x0000ff0000000000) | + (((uint64_t)rnd_ic[7] << 32) & 0x000000ff00000000) | + (((uint64_t)rnd_ifd[4] << 24) & 0x00000000ff000000) | + (((uint64_t)rnd_ifd[5] << 16) & 0x0000000000ff0000) | + (((uint64_t)rnd_ifd[6] << 8) & 0x000000000000ff00) | + (((uint64_t)rnd_ifd[7]) & 0x00000000000000ff); #else #error Using untested code, please verify first! - return (*((uint64_t*)(rnd_ic + 4)) & 0xffffffff) + - (*((uint64_t*)(rnd_ifd + 4)) * 0x100000000); + return (*((uint64_t*)(rnd_ic + 4)) & 0xffffffff) + (*((uint64_t*)(rnd_ifd + 4)) * 0x100000000); #endif } -size_t mrtd_protect_apdu(uint8_t cla, uint8_t ins, uint8_t p1, uint8_t p2, uint8_t lc, const void* data, int16_t le, const uint8_t* key_enc, const uint8_t* key_mac, uint64_t ssc, uint8_t* output); +size_t mrtd_protect_apdu( + uint8_t cla, + uint8_t ins, + uint8_t p1, + uint8_t p2, + uint8_t lc, + const void* data, + int16_t le, + const uint8_t* key_enc, + const uint8_t* key_mac, + uint64_t ssc, + uint8_t* output); int tlv_number(TlvInfo tlv);