Przeglądaj źródła

Capture SIO of Desfire EV1

Eric Betts 2 lat temu
rodzic
commit
d4b72caee7

+ 31 - 8
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);

+ 1 - 0
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);

+ 1 - 0
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);
 

+ 1 - 0
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,