From d4b72caee755e49ace63bc39c483088bad8f2f85 Mon Sep 17 00:00:00 2001 From: Eric Betts Date: Mon, 1 Jan 2024 10:48:11 -0800 Subject: [PATCH] Capture SIO of Desfire EV1 --- sam_api.c | 39 +++++++++++++++++++++++------ scenes/seader_scene_read_14a.c | 1 + scenes/seader_scene_read_picopass.c | 1 + seader_credential.c | 1 + 4 files changed, 34 insertions(+), 8 deletions(-) diff --git a/sam_api.c b/sam_api.c index c032f6d..ac59b1e 100644 --- a/sam_api.c +++ b/sam_api.c @@ -475,14 +475,26 @@ void seader_capture_sio(BitBuffer* tx_buffer, BitBuffer* rx_buffer, SeaderCreden size_t len = bit_buffer_get_size_bytes(tx_buffer); const uint8_t* rxBuffer = bit_buffer_get_data(rx_buffer); - if(memcmp(buffer, read4Block6, len) == 0 && rxBuffer[0] == 0x30) { - memcpy(credential->sio, rxBuffer, 32); - } else if(memcmp(buffer, read4Block10, len) == 0 && rxBuffer[0] == 0x30) { - memcpy(credential->sio, rxBuffer, 32); - } else if(memcmp(buffer, read4Block9, len) == 0) { - memcpy(credential->sio + 32, rxBuffer + 8, 24); - } else if(memcmp(buffer, read4Block13, len) == 0) { - memcpy(credential->sio + 32, rxBuffer + 8, 24); + if(credential->type == SeaderCredentialTypePicopass) { + if(memcmp(buffer, read4Block6, len) == 0 && rxBuffer[0] == 0x30) { + memcpy(credential->sio, rxBuffer, 32); + } else if(memcmp(buffer, read4Block10, len) == 0 && rxBuffer[0] == 0x30) { + memcpy(credential->sio, rxBuffer, 32); + } else if(memcmp(buffer, read4Block9, len) == 0) { + memcpy(credential->sio + 32, rxBuffer + 8, 24); + } else if(memcmp(buffer, read4Block13, len) == 0) { + memcpy(credential->sio + 32, rxBuffer + 8, 24); + } + } else if(credential->type == SeaderCredentialType14A) { + // Desfire EV1 passes SIO in the clear + uint8_t desfire_read[] = { + 0x90, 0xbd, 0x00, 0x00, 0x07, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + if(memcmp(buffer, desfire_read, len) == 0 && rxBuffer[0] == 0x30) { + memcpy( + credential->sio, + rxBuffer, + bit_buffer_get_size_bytes(rx_buffer) - 2); // -2 for the APDU response bytes + } } } @@ -564,6 +576,7 @@ void seader_iso14443a_transmit( break; } + seader_capture_sio(tx_buffer, rx_buffer, seader->credential); seader_send_nfc_rx( seader_uart, (uint8_t*)bit_buffer_get_data(rx_buffer), @@ -725,6 +738,10 @@ bool seader_process_success_response_i( return processed; } +bool seader_mf_df_check_card_type(uint8_t ATQA0, uint8_t ATQA1, uint8_t SAK) { + return ATQA0 == 0x44 && ATQA1 == 0x03 && SAK == 0x20; +} + NfcCommand seader_worker_card_detect( Seader* seader, uint8_t sak, @@ -741,6 +758,8 @@ NfcCommand seader_worker_card_detect( SeaderWorker* seader_worker = seader->worker; SeaderUartBridge* seader_uart = seader_worker->uart; + SeaderCredential* credential = seader->credential; + CardDetails_t* cardDetails = 0; cardDetails = calloc(1, sizeof *cardDetails); assert(cardDetails); @@ -754,6 +773,7 @@ NfcCommand seader_worker_card_detect( protocol_bytes[1] = FrameProtocol_iclass; OCTET_STRING_fromBuf( &cardDetails->protocol, (const char*)protocol_bytes, sizeof(protocol_bytes)); + memcpy(credential->diversifier, uid, uid_len); } else { protocol_bytes[1] = FrameProtocol_nfc; OCTET_STRING_fromBuf( @@ -761,6 +781,9 @@ NfcCommand seader_worker_card_detect( cardDetails->sak = &sak_string; cardDetails->atqa = &atqa_string; + if(seader_mf_df_check_card_type(atqa[0], atqa[1], sak)) { + memcpy(credential->diversifier, uid, uid_len); + } } seader_send_card_detected(seader_uart, cardDetails); diff --git a/scenes/seader_scene_read_14a.c b/scenes/seader_scene_read_14a.c index 6538fce..10786ed 100644 --- a/scenes/seader_scene_read_14a.c +++ b/scenes/seader_scene_read_14a.c @@ -17,6 +17,7 @@ void seader_scene_read_14a_on_enter(void* context) { seader->worker->stage = SeaderPollerEventTypeCardDetect; seader_credential_clear(seader->credential); + seader->credential->type = SeaderCredentialType14A; nfc_poller_start(seader->poller, seader_worker_poller_callback_iso14443_4a, seader); seader_blink_start(seader); diff --git a/scenes/seader_scene_read_picopass.c b/scenes/seader_scene_read_picopass.c index e1faa0e..7ea653b 100644 --- a/scenes/seader_scene_read_picopass.c +++ b/scenes/seader_scene_read_picopass.c @@ -15,6 +15,7 @@ void seader_scene_read_picopass_on_enter(void* context) { seader->worker->stage = SeaderPollerEventTypeCardDetect; seader_credential_clear(seader->credential); + seader->credential->type = SeaderCredentialTypePicopass; seader->picopass_poller = picopass_poller_alloc(seader->nfc); picopass_poller_start(seader->picopass_poller, seader_worker_poller_callback_picopass, seader); diff --git a/seader_credential.c b/seader_credential.c index 87527a7..aa0f7d4 100644 --- a/seader_credential.c +++ b/seader_credential.c @@ -418,6 +418,7 @@ bool seader_credential_save_picopass(SeaderCredential* cred, const char* name) { furi_string_printf(temp_str, "Block %d", i); switch(i) { case CSN_INDEX: + // TODO: Is there any practical difference here? If so, document. if(withSIO) { if(!flipper_format_write_hex( file,