diff --git a/lib/nfc/nfc_worker.c b/lib/nfc/nfc_worker.c index aa63b0d6d..321de5b2c 100644 --- a/lib/nfc/nfc_worker.c +++ b/lib/nfc/nfc_worker.c @@ -223,6 +223,8 @@ static bool nfc_worker_read_mrtd(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* t do { // Read passport if(!furi_hal_nfc_detect(&nfc_worker->dev_data->nfc_data, 300)) break; + mrtd_select_efcardaccess(tx_rx, &mrtd_app); + mrtd_select_efdir(tx_rx, &mrtd_app); if(!mrtd_select_lds1(tx_rx, &mrtd_app)) break; /* diff --git a/lib/nfc/protocols/mrtd.c b/lib/nfc/protocols/mrtd.c index f70ed69d4..a70e86c22 100644 --- a/lib/nfc/protocols/mrtd.c +++ b/lib/nfc/protocols/mrtd.c @@ -4,6 +4,12 @@ //TODO: Check EF.DIR first? Before LDS1 //TODO: ICAO 9303 p11 §4.2 steps +//- Read EF.CardAccess (REQUIRED) +// If not available or does not contain PACE params, try BAC +//- Read EF.DIR (OPTIONAL) +// Check list of applications present +//- PACE (CONDITIONAL) +//- BAC (CONDITIONAL) static void mrtd_trace(FuriHalNfcTxRxContext* tx_rx, const char* message) { if(furi_log_get_level() == FuriLogLevelTrace) { @@ -29,14 +35,87 @@ uint16_t mrtd_decode_response(uint8_t* buffer, size_t len) { return (buffer[0] << 8) | buffer[1]; } +bool mrtd_select_efcardaccess(FuriHalNfcTxRxContext* tx_rx, MrtdApplication* mrtd_app) { + UNUSED(mrtd_app); + + // Chris: short: 0x6700, long: yes (0x9000) + // Anna: short: 0x6700, long: yes (0x9000) + + // ICAO 9303 p10 §3.6.2 + uint8_t select_efcardaccess_cmd[] = { + 0x00, // CLA + 0xA4, // INS + 0x02, // P1 + 0x0C, // P2 + 0x02, // Lc: Data length + 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(tx_rx, "Select EF.CardAccess:"); + 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(FuriHalNfcTxRxContext* tx_rx, MrtdApplication* mrtd_app) { + UNUSED(mrtd_app); + + // 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(tx_rx, "Select EF.DIR:"); + 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(FuriHalNfcTxRxContext* tx_rx, MrtdApplication* mrtd_app) { UNUSED(mrtd_app); uint8_t select_emrtd_cmd[] = { - 0x00, - 0xa4, // SELECT - 0x04, - 0x0C, // P1,P2: DF + 0x00, // CLA + 0xA4, // INS + 0x04, // P1 + 0x0C, // P2: DF 0x07, // Lc: Data length 0xa0, 0x00, diff --git a/lib/nfc/protocols/mrtd.h b/lib/nfc/protocols/mrtd.h index 87f856b08..972d427bb 100644 --- a/lib/nfc/protocols/mrtd.h +++ b/lib/nfc/protocols/mrtd.h @@ -38,6 +38,10 @@ typedef struct { MrtdAuthData auth; } MrtdData; +//TODO: description +bool mrtd_select_efcardaccess(FuriHalNfcTxRxContext* tx_rx, MrtdApplication* mrtd_app); +bool mrtd_select_efdir(FuriHalNfcTxRxContext* tx_rx, MrtdApplication* mrtd_app); + /** Select the LDS1 eMRTD application * @note Can be used to detect presence of Passport/ID-card *