diff --git a/lib/nfc/nfc_worker.c b/lib/nfc/nfc_worker.c index efbeafa94..3012f121e 100644 --- a/lib/nfc/nfc_worker.c +++ b/lib/nfc/nfc_worker.c @@ -228,7 +228,10 @@ static bool nfc_worker_read_mrtd(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* t //mrtd_select_efcardaccess(mrtd_app); //mrtd_select_efdir(mrtd_app); mrtd_test(mrtd_app); - if(!mrtd_select_lds1(mrtd_app)) break; + if(!mrtd_select_app(mrtd_app, AID.eMRTDApplication)) break; + + //TODO: read general informatie + //TODO: after auth scene, do auth (BAC / PACE) /* // Copy data diff --git a/lib/nfc/protocols/mrtd.c b/lib/nfc/protocols/mrtd.c index 63ffcbc8e..eefaa15d9 100644 --- a/lib/nfc/protocols/mrtd.c +++ b/lib/nfc/protocols/mrtd.c @@ -1,3 +1,5 @@ +#include + #include "mrtd.h" #define TAG "Mrtd" @@ -56,6 +58,13 @@ struct EFFormat EF = { .DG16 = {.file_id = 0X0110, .short_id = 0X10 }, }; +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}, + .AdditionalBiometrics = {0xA0, 0x00, 0x00, 0x02, 0x47, 0x20, 0x03}, +}; + /*bool mrtd_send_apdu(MrtdApplication* app, uint8_t* buffer, size_t length) { FuriHalNfcTxRxContext* tx_rx = app->tx_rx; @@ -114,7 +123,17 @@ bool mrtd_send_apdu(MrtdApplication* app, uint8_t cla, uint8_t ins, uint8_t p1, return false; } -bool mrtd_select(MrtdApplication* app, EFFile file) { +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]); + if(!mrtd_send_apdu(app, 0x00, 0xA4, 0x04, 0x0C, 0x07, aid, -1)) { + FURI_LOG_E(TAG, "Failed select App"); + return false; + } + return true; +} + +bool mrtd_select_file(MrtdApplication* app, EFFile file) { uint8_t data[] = {file.file_id >> 8, file.file_id & 0xff}; FURI_LOG_D(TAG, "Send select EF: 0x%04X", file.file_id); if(!mrtd_send_apdu(app, 0x00, 0xA4, 0x02, 0x0C, 0x02, data, -1)) { @@ -143,7 +162,7 @@ size_t mrtd_read_binary(MrtdApplication* app, uint8_t* buffer, size_t bufsize, s void mrtd_read_dump(MrtdApplication* app, EFFile file, const char* descr) { FURI_LOG_D(TAG, "Read and dump %s:", descr); - if(!mrtd_select(app, file)) { + if(!mrtd_select_file(app, file)) { return; } uint8_t data[2048]; @@ -174,145 +193,21 @@ void mrtd_free(MrtdApplication* app) { free(app); } -/* -size_t mrtd_read_data(MrtdApplication* app, uint8_t* buffer, size_t bufsize) { - //TODO: fill buffer with data from file - - //TODO: use protected APDU if authenticated - - - - return read; -} -*/ - -bool mrtd_select_efcardaccess(MrtdApplication* app) { - FuriHalNfcTxRxContext* tx_rx = app->tx_rx; - - // Chris: short: 0x6700, long: yes (0x9000) - // Anna: short: 0x6700, long: yes (0x9000) - - EFFile file = EF.CardAccess; - - // ICAO 9303 p10 ยง3.6.2 - uint8_t select_efcardaccess_cmd[] = { - 0x00, // CLA - 0xA4, // INS - 0x02, // P1 - 0x0C, // P2 - 0x02, // Lc: Data length - file.file_id >> 8 | (file.file_id & 0xFF), - //0x01, 0x1C, // Data: EF.CardAccess File ID - 0x00, // Le - }; - - memcpy(tx_rx->tx_data, select_efcardaccess_cmd, sizeof(select_efcardaccess_cmd)); - tx_rx->tx_bits = sizeof(select_efcardaccess_cmd) * 8; - tx_rx->tx_rx_type = FuriHalNfcTxRxTypeDefault; - - bool efcardaccess_success = false; - - FURI_LOG_D(TAG, "Send select EF.CardAccess"); - if(furi_hal_nfc_tx_rx(tx_rx, 300)) { - mrtd_trace(app); - if(mrtd_decode_response(tx_rx->rx_data, tx_rx->rx_bits / 8) == 0x9000) { - efcardaccess_success = true; - } else { - FURI_LOG_D(TAG, "Select EF.CardAccess response is not 0x9000"); - } - } else { - FURI_LOG_E(TAG, "Failed select EF.CardAccess"); - } - return efcardaccess_success; -} - -bool mrtd_select_efdir(MrtdApplication* app) { - FuriHalNfcTxRxContext* tx_rx = app->tx_rx; - - // Chris: short: no, long: no (0x6A82) - // Anna: short: no, long: yes (0x9000) - - uint8_t select_efdir_cmd[] = { - 0x00, // CLA - 0xA4, // INS - 0x02, // P1 - 0x0C, // P2 - 0x02, // Lc: Data length - 0x2F, 0x00, // Data: EF.DIR File ID - 0x00, // Le - }; - - memcpy(tx_rx->tx_data, select_efdir_cmd, sizeof(select_efdir_cmd)); - tx_rx->tx_bits = sizeof(select_efdir_cmd) * 8; - tx_rx->tx_rx_type = FuriHalNfcTxRxTypeDefault; - - bool efdir_success = false; - - FURI_LOG_D(TAG, "Send select EF.DIR"); - if(furi_hal_nfc_tx_rx(tx_rx, 300)) { - mrtd_trace(app); - if(mrtd_decode_response(tx_rx->rx_data, tx_rx->rx_bits / 8) == 0x9000) { - efdir_success = true; - } else { - FURI_LOG_D(TAG, "Select EF.DIR response is not 0x9000"); - } - } else { - FURI_LOG_E(TAG, "Failed select EF.DIR"); - } - return efdir_success; -} - -bool mrtd_select_lds1(MrtdApplication* app) { - FuriHalNfcTxRxContext* tx_rx = app->tx_rx; - - uint8_t select_emrtd_cmd[] = { - 0x00, // CLA - 0xA4, // INS - 0x04, // P1 - 0x0C, // P2: DF - 0x07, // Lc: Data length - 0xa0, - 0x00, - 0x00, - 0x02, - 0x47, - 0x10, - 0x01, // Data: LDS1 eMRTD Application - 0x00, // Le - }; - - memcpy(tx_rx->tx_data, select_emrtd_cmd, sizeof(select_emrtd_cmd)); - tx_rx->tx_bits = sizeof(select_emrtd_cmd) * 8; - tx_rx->tx_rx_type = FuriHalNfcTxRxTypeDefault; - - bool lds1_success = false; - - FURI_LOG_D(TAG, "Send select LDS1 eMRTD"); - if(furi_hal_nfc_tx_rx(tx_rx, 300)) { - mrtd_trace(app); - if(mrtd_decode_response(tx_rx->rx_data, tx_rx->rx_bits / 8) == 0x9000) { - lds1_success = true; - } else { - FURI_LOG_D(TAG, "Select LDS1 eMRTD response is not 0x9000"); - } - } else { - FURI_LOG_E(TAG, "Failed select LDS1"); - } - - return lds1_success; -} - -int mrtd_bac_keyhandshake(MrtdApplication* app) { +bool mrtd_bac(MrtdApplication* app) { UNUSED(app); - return 0; -} - -bool mrtd_read(MrtdApplication* app) { - bool mrtd_read = false; - - memset(app, 0, sizeof(MrtdApplication)); - - mrtd_read = mrtd_bac_keyhandshake(app); - return mrtd_read; + static bool rand_generator_inited = false; + uint8_t rnd_ifd[8]; + uint8_t k_ifd[16]; + + if(!rand_generator_inited) { + // TODO: should this maybe be system wide? + srand(DWT->CYCCNT); + rand_generator_inited = true; + } + + furi_hal_random_fill_buf(rnd_ifd, 8); + furi_hal_random_fill_buf(k_ifd, 16); + + return false; //TODO: return true } diff --git a/lib/nfc/protocols/mrtd.h b/lib/nfc/protocols/mrtd.h index 1e775f436..7d8c19bf9 100644 --- a/lib/nfc/protocols/mrtd.h +++ b/lib/nfc/protocols/mrtd.h @@ -51,18 +51,19 @@ struct EFFormat { extern struct EFFormat EF; +typedef uint8_t AIDValue[7]; + +struct AIDSet { + AIDValue eMRTDApplication; + AIDValue TravelRecords; + AIDValue VisaRecords; + AIDValue AdditionalBiometrics; +}; + +extern struct AIDSet AID; + //TODO: description MrtdApplication* mrtd_alloc_init(FuriHalNfcTxRxContext* tx_rx); -bool mrtd_select(MrtdApplication* app, EFFile file); -bool mrtd_select_efcardaccess(MrtdApplication* mrtd_app); -bool mrtd_select_efdir(MrtdApplication* mrtd_app); +bool mrtd_select_app(MrtdApplication* app, AIDValue aid); +bool mrtd_select_file(MrtdApplication* app, EFFile file); void mrtd_test(MrtdApplication* app); - -/** Select the LDS1 eMRTD application - * @note Can be used to detect presence of Passport/ID-card - * - * @param emv_app MrtdApplication instance - * - * @return true on success - */ -bool mrtd_select_lds1(MrtdApplication* mrtd_app); diff --git a/lib/nfc/protocols/mrtd_helpers.c b/lib/nfc/protocols/mrtd_helpers.c index fd6f201ae..f8adb0cf7 100644 --- a/lib/nfc/protocols/mrtd_helpers.c +++ b/lib/nfc/protocols/mrtd_helpers.c @@ -3,6 +3,8 @@ #include #include +static inline unsigned char *ucstr(const char *str) { return (unsigned char *)str; } + uint8_t mrtd_bac_check_digit(const uint8_t* input, const uint8_t length) { const uint8_t num_weights = 3; uint8_t weights[] = {7, 3, 1}; @@ -75,7 +77,7 @@ bool mrtd_bac_keys(const uint8_t kseed[16], uint8_t ksenc[16], uint8_t ksmac[16] 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, "\x00\x00\x00", 3)) break; + if(mbedtls_sha1_update(&ctx, ucstr("\x00\x00\x00"), 3)) break; if(mbedtls_sha1_update(&ctx, &i, 1)) break; if(mbedtls_sha1_finish(&ctx, hash)) break;