Eric Betts 8 месяцев назад
Родитель
Сommit
15261b8fa4
7 измененных файлов с 66 добавлено и 91 удалено
  1. 5 12
      seos_central.c
  2. 9 12
      seos_characteristic.c
  3. 1 0
      seos_credential.c
  4. 1 0
      seos_credential.h
  5. 40 44
      seos_emulator.c
  6. 3 1
      seos_emulator.h
  7. 7 22
      seos_native_peripheral.c

+ 5 - 12
seos_central.c

@@ -77,20 +77,13 @@ void seos_central_notify(void* context, const uint8_t* buffer, size_t buffer_len
             bit_buffer_append_bytes(response, (uint8_t*)file_not_found, sizeof(file_not_found));
         }
     } else if(memcmp(apdu, select_adf_header, sizeof(select_adf_header)) == 0) {
-        // is our adf in the list?
-        // +1 to skip APDU length byte
-        void* p = memmem(
-            apdu + sizeof(select_adf_header) + 1,
-            apdu[sizeof(select_adf_header)],
-            SEOS_ADF_OID,
-            SEOS_ADF_OID_LEN);
-        if(p) {
-            seos_log_buffer(TAG, "Matched ADF", p, SEOS_ADF_OID_LEN);
+        const uint8_t* oid_list = apdu + sizeof(select_adf_header) + 1;
+        size_t oid_list_len = apdu[sizeof(select_adf_header)];
 
-            bit_buffer_append_byte(response, BLE_START);
-
-            seos_emulator_select_adf(&seos_central->params, seos_central->credential, response);
+        bit_buffer_append_byte(response, BLE_START);
 
+        if(seos_emulator_select_adf(
+               oid_list, oid_list_len, &seos_central->params, seos_central->credential, response)) {
             bit_buffer_append_bytes(response, (uint8_t*)success, sizeof(success));
             seos_central->phase = GENERAL_AUTHENTICATION_1;
         } else {

+ 9 - 12
seos_characteristic.c

@@ -196,18 +196,15 @@ void seos_characteristic_cred_flow(
             bit_buffer_append_bytes(payload, (uint8_t*)file_not_found, sizeof(file_not_found));
         }
     } else if(memcmp(apdu, select_adf_header, sizeof(select_adf_header)) == 0) {
-        // is our adf in the list?
-        // +1 to skip APDU length byte
-        void* p = memmem(
-            apdu + sizeof(select_adf_header) + 1,
-            apdu[sizeof(select_adf_header)],
-            SEOS_ADF_OID,
-            SEOS_ADF_OID_LEN);
-        if(p) {
-            seos_log_buffer(TAG, "Matched ADF", p, SEOS_ADF_OID_LEN);
-
-            seos_emulator_select_adf(
-                &seos_characteristic->params, seos_characteristic->credential, payload);
+        const uint8_t* oid_list = apdu + sizeof(select_adf_header) + 1;
+        size_t oid_list_len = apdu[sizeof(select_adf_header)];
+
+        if(seos_emulator_select_adf(
+               oid_list,
+               oid_list_len,
+               &seos_characteristic->params,
+               seos_characteristic->credential,
+               payload)) {
             bit_buffer_append_bytes(payload, (uint8_t*)success, sizeof(success));
         } else {
             FURI_LOG_W(TAG, "Failed to match any ADF OID");

+ 1 - 0
seos_credential.c

@@ -15,6 +15,7 @@ SeosCredential* seos_credential_alloc() {
     seos_credential->load_path = furi_string_alloc();
     seos_credential->storage = furi_record_open(RECORD_STORAGE);
     seos_credential->dialogs = furi_record_open(RECORD_DIALOGS);
+    seos_credential->use_hardcoded = false;
 
     return seos_credential;
 }

+ 1 - 0
seos_credential.h

@@ -24,6 +24,7 @@ typedef struct {
     size_t adf_oid_len;
     uint8_t adf_oid[32];
     uint8_t adf_response[80];
+    bool use_hardcoded;
 
     char name[SEOS_FILE_NAME_MAX_LENGTH + 1];
     FuriString* load_path;

+ 40 - 44
seos_emulator.c

@@ -23,8 +23,6 @@ static uint8_t general_authenticate_1[] =
 static uint8_t general_authenticate_1_response_header[] = {0x7c, 0x0a, 0x81, 0x08};
 static uint8_t general_authenticate_2_header[] = {0x00, 0x87, 0x00, 0x01};
 static uint8_t secure_messaging_header[] = {0x0c, 0xcb, 0x3f, 0xff};
-static uint8_t empty[16] =
-    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
 
 SeosEmulator* seos_emulator_alloc(SeosCredential* credential) {
     SeosEmulator* seos_emulator = malloc(sizeof(SeosEmulator));
@@ -87,7 +85,10 @@ bool seos_emulator_general_authenticate_2(
 
     params->key_no = rx_data[3];
 
-    if(memcmp(credential->priv_key, empty, sizeof(empty)) == 0) {
+    if(credential->use_hardcoded) {
+        memcpy(params->priv_key, credential->priv_key, sizeof(params->priv_key));
+        memcpy(params->auth_key, credential->auth_key, sizeof(params->auth_key));
+    } else {
         seos_worker_diversify_key(
             SEOS_ADF1_READ,
             credential->diversifier,
@@ -99,10 +100,6 @@ bool seos_emulator_general_authenticate_2(
             params->key_no,
             true,
             params->priv_key);
-    } else {
-        memcpy(params->priv_key, credential->priv_key, sizeof(params->priv_key));
-    }
-    if(memcmp(credential->auth_key, empty, sizeof(empty)) == 0) {
         seos_worker_diversify_key(
             SEOS_ADF1_READ,
             credential->diversifier,
@@ -114,8 +111,6 @@ bool seos_emulator_general_authenticate_2(
             params->key_no,
             false,
             params->auth_key);
-    } else {
-        memcpy(params->auth_key, credential->auth_key, sizeof(params->auth_key));
     }
 
     uint8_t cmac[16];
@@ -257,21 +252,38 @@ void seos_emulator_aes_adf_payload(SeosCredential* credential, uint8_t* buffer)
     mbedtls_aes_free(&ctx);
 }
 
-void seos_emulator_select_adf(
+bool seos_emulator_select_adf(
+    const uint8_t* oid_list,
+    size_t oid_list_len,
     AuthParameters* params,
     SeosCredential* credential,
     BitBuffer* tx_buffer) {
     FURI_LOG_D(TAG, "Select ADF");
-    // Shortcut if the credential file contained the hardcoded response
-    // TODO: check that the ADF for the hardcoded response is the one requested
-    if(credential->adf_response[0] == 0xCD) {
-        FURI_LOG_I(TAG, "Using hardcoded ADF Response");
-        bit_buffer_append_bytes(
-            tx_buffer, credential->adf_response, sizeof(credential->adf_response));
-
-        params->cipher = credential->adf_response[2];
-        params->hash = credential->adf_response[3];
-        return;
+
+    void* p = NULL;
+    if(credential->adf_oid_len > 0) {
+        p = memmem(oid_list, oid_list_len, credential->adf_oid, credential->adf_oid_len);
+        if(p) {
+            seos_log_buffer(TAG, "Select ADF OID(credential)", p, credential->adf_oid_len);
+
+            if(credential->adf_response[0] == 0xCD) {
+                FURI_LOG_I(TAG, "Using hardcoded ADF Response");
+                bit_buffer_append_bytes(
+                    tx_buffer, credential->adf_response, sizeof(credential->adf_response));
+
+                params->cipher = credential->adf_response[2];
+                params->hash = credential->adf_response[3];
+                credential->use_hardcoded = true;
+                return true;
+            }
+        }
+    }
+    // Next we try to match the ADF OID from the keys file
+    p = memmem(oid_list, oid_list_len, SEOS_ADF_OID, SEOS_ADF_OID_LEN);
+    if(p) {
+        seos_log_buffer(TAG, "Select ADF OID(keys)", p, SEOS_ADF_OID_LEN);
+    } else {
+        return false;
     }
 
     size_t prefix_len = bit_buffer_get_size_bytes(tx_buffer);
@@ -317,6 +329,7 @@ void seos_emulator_select_adf(
     uint8_t cmac_prefix[] = {0x8e, 0x08};
     bit_buffer_append_bytes(tx_buffer, cmac_prefix, sizeof(cmac_prefix));
     bit_buffer_append_bytes(tx_buffer, cmac, SEOS_WORKER_CMAC_SIZE);
+    return true;
 }
 
 NfcCommand seos_worker_listener_inspect_reader(Seos* seos) {
@@ -364,6 +377,7 @@ NfcCommand seos_worker_listener_process_message(Seos* seos) {
     const uint8_t* apdu = rx_data + offset;
 
     if(memcmp(apdu, select_header, sizeof(select_header)) == 0) {
+        seos_emulator->credential->use_hardcoded = false;
         if(memcmp(apdu + sizeof(select_header) + 1, standard_seos_aid, sizeof(standard_seos_aid)) ==
            0) {
             seos_emulator_select_aid(seos_emulator->tx_buffer);
@@ -399,35 +413,17 @@ NfcCommand seos_worker_listener_process_message(Seos* seos) {
                 seos_emulator->tx_buffer, (uint8_t*)FILE_NOT_FOUND, sizeof(FILE_NOT_FOUND));
         }
     } else if(memcmp(apdu, select_adf_header, sizeof(select_adf_header)) == 0) {
-        void* p = NULL;
         // +1 to skip APDU length byte
         const uint8_t* oid_list = apdu + sizeof(select_adf_header) + 1;
         size_t oid_list_len = apdu[sizeof(select_adf_header)];
-        // First we try to match the credential ADF OID
-        SeosCredential* credential = seos_emulator->credential;
-        if(credential->adf_oid_len > 0) {
-            p = memmem(oid_list, oid_list_len, credential->adf_oid, credential->adf_oid_len);
-            if(p) {
-                seos_log_buffer(TAG, "Select ADF OID(credential)", p, credential->adf_oid_len);
-
-                view_dispatcher_send_custom_event(
-                    seos->view_dispatcher, SeosCustomEventADFMatched);
-
-                seos_emulator_select_adf(
-                    &seos_emulator->params, seos_emulator->credential, seos_emulator->tx_buffer);
-
-                return ret;
-            }
-        }
-        // Next we try to match the ADF OID from the keys file
-        p = memmem(oid_list, oid_list_len, SEOS_ADF_OID, SEOS_ADF_OID_LEN);
-        if(p) {
-            seos_log_buffer(TAG, "Select ADF OID(keys)", p, SEOS_ADF_OID_LEN);
 
+        if(seos_emulator_select_adf(
+               oid_list,
+               oid_list_len,
+               &seos_emulator->params,
+               seos_emulator->credential,
+               seos_emulator->tx_buffer)) {
             view_dispatcher_send_custom_event(seos->view_dispatcher, SeosCustomEventADFMatched);
-
-            seos_emulator_select_adf(
-                &seos_emulator->params, seos_emulator->credential, seos_emulator->tx_buffer);
         } else {
             FURI_LOG_W(TAG, "Failed to match any ADF OID");
         }

+ 3 - 1
seos_emulator.h

@@ -36,7 +36,9 @@ bool seos_emulator_general_authenticate_2(
     BitBuffer* tx_buffer);
 
 void seos_emulator_select_aid(BitBuffer* tx_buffer);
-void seos_emulator_select_adf(
+bool seos_emulator_select_adf(
+    const uint8_t* oid_list,
+    size_t oid_list_len,
     AuthParameters* params,
     SeosCredential* credential,
     BitBuffer* tx_buffer);

+ 7 - 22
seos_native_peripheral.c

@@ -192,32 +192,17 @@ void seos_native_peripheral_process_message_cred(
             bit_buffer_append_bytes(response, (uint8_t*)file_not_found, sizeof(file_not_found));
         }
     } else if(memcmp(apdu, select_adf_header, sizeof(select_adf_header)) == 0) {
-        void* p = NULL;
         // +1 to skip APDU length byte
         const uint8_t* oid_list = apdu + sizeof(select_adf_header) + 1;
         size_t oid_list_len = apdu[sizeof(select_adf_header)];
-        // First we try to match the credential ADF OID
-        SeosCredential* credential = seos_native_peripheral->credential;
-        if(credential->adf_oid_len > 0) {
-            p = memmem(oid_list, oid_list_len, credential->adf_oid, credential->adf_oid_len);
-            if(p) {
-                seos_log_buffer(TAG, "Select ADF OID(credential)", p, credential->adf_oid_len);
-
-                view_dispatcher_send_custom_event(
-                    seos->view_dispatcher, SeosCustomEventADFMatched);
-
-                seos_emulator_select_adf(&seos_native_peripheral->params, credential, response);
-                return;
-            }
-        }
-
-        p = memmem(oid_list, oid_list_len, SEOS_ADF_OID, SEOS_ADF_OID_LEN);
-        if(p) {
-            seos_log_buffer(TAG, "Matched ADF", p, SEOS_ADF_OID_LEN);
 
-            seos_emulator_select_adf(
-                &seos_native_peripheral->params, seos_native_peripheral->credential, response);
-            bit_buffer_append_bytes(response, (uint8_t*)success, sizeof(success));
+        if(seos_emulator_select_adf(
+               oid_list,
+               oid_list_len,
+               &seos_native_peripheral->params,
+               seos_native_peripheral->credential,
+               response)) {
+            view_dispatcher_send_custom_event(seos->view_dispatcher, SeosCustomEventADFMatched);
         } else {
             FURI_LOG_W(TAG, "Failed to match any ADF OID");
         }