Skip to content

Commit

Permalink
Capture SIO of Desfire EV1
Browse files Browse the repository at this point in the history
  • Loading branch information
bettse committed Jan 1, 2024
1 parent 7c0ff50 commit d4b72ca
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 8 deletions.
39 changes: 31 additions & 8 deletions sam_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
}

Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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,
Expand All @@ -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);
Expand All @@ -754,13 +773,17 @@ 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(
&cardDetails->protocol, (const char*)protocol_bytes, sizeof(protocol_bytes));

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);
Expand Down
1 change: 1 addition & 0 deletions scenes/seader_scene_read_14a.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions scenes/seader_scene_read_picopass.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
1 change: 1 addition & 0 deletions seader_credential.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down

0 comments on commit d4b72ca

Please sign in to comment.