Jelajahi Sumber

implement eFuse for locking out firmware updates

Andrew Tridgell 3 tahun lalu
induk
melakukan
8c953ed513
4 mengubah file dengan 80 tambahan dan 0 penghapusan
  1. 14 0
      README.md
  2. 3 0
      RemoteIDModule/RemoteIDModule.ino
  3. 59 0
      RemoteIDModule/efuse.cpp
  4. 4 0
      RemoteIDModule/efuse.h

+ 14 - 0
README.md

@@ -160,6 +160,20 @@ IDs for your board.
 
 Once signed you can upload the firmware via the web server.
 
+## LOCK_LEVEL Parameter
+
+The LOCK_LEVEL parameter is the way a vendor can lock down the
+RemoteID board so that it is tamper resistant. if any valid public
+keys have been set then setting LOCK_LEVEL=1 will prevent any
+parameter changes using the DroneCAN or MAVLink interfaces. All
+parameter changes will need to be made via the SecureCommand
+signed interface.
+
+Setting LOCK_LEVEL=2 will also cause the ESP32 eFuses to be set to
+prevent firmware updates except via the signed web interface. This is
+a permanent change and cannot be undone even if the LOCK_LEVEL is
+changed back to 0 or 1 via SecureCommand.
+
 ## ArduPilot Support
 
 Support for OpenDroneID is in ArduPilot master and is also in the

+ 3 - 0
RemoteIDModule/RemoteIDModule.ino

@@ -20,6 +20,7 @@
 #include "webinterface.h"
 #include "check_firmware.h"
 #include <esp_ota_ops.h>
+#include "efuse.h"
 
 #if AP_DRONECAN_ENABLED
 static DroneCAN dronecan;
@@ -70,6 +71,8 @@ void setup()
     dronecan.init();
 #endif
 
+    set_efuses();
+
     CheckFirmware::check_OTA_running();
 
 #if defined(PIN_CAN_EN)

+ 59 - 0
RemoteIDModule/efuse.cpp

@@ -0,0 +1,59 @@
+#include <Arduino.h>
+#include "efuse.h"
+#include <soc/efuse_reg.h>
+#include <esp_efuse.h>
+#include <esp_efuse_table.h>
+#include "parameters.h"
+
+static const struct {
+    const esp_efuse_desc_t **desc;
+    const char *name;
+} fuses[] = {
+    { ESP_EFUSE_DIS_DOWNLOAD_MODE, "DIS_DOWNLOAD_MODE" },
+    { ESP_EFUSE_DIS_USB_JTAG, "DIS_USB_JTAG" },
+#ifdef ESP_EFUSE_DIS_PAD_JTAG
+    { ESP_EFUSE_DIS_PAD_JTAG, "DIS_PAD_JTAG" },
+#endif
+#ifdef ESP_EFUSE_DIS_USB_SERIAL_JTAG
+    { ESP_EFUSE_DIS_USB_SERIAL_JTAG, "DIS_USB_SERIAL_JTAG" },
+#endif
+#ifdef ESP_EFUSE_DIS_USB_DOWNLOAD_MODE
+    { ESP_EFUSE_DIS_USB_DOWNLOAD_MODE, "DIS_USB_DOWNLOAD_MODE" },
+#endif
+#ifdef ESP_EFUSE_DIS_FORCE_DOWNLOAD
+    { ESP_EFUSE_DIS_FORCE_DOWNLOAD, "DIS_FORCE_DOWNLOAD" },
+#endif
+#ifdef ESP_EFUSE_DIS_LEGACY_SPI_BOOT
+    { ESP_EFUSE_DIS_LEGACY_SPI_BOOT, "DIS_LEGACY_SPI_BOOT" },
+#endif
+};
+
+/*
+  set efuses to prevent firmware upload except via signed web
+  interface
+ */
+void set_efuses(void)
+{
+    bool some_unset = false;
+    for (const auto &f : fuses) {
+        const bool v = esp_efuse_read_field_bit(f.desc);
+        Serial.printf("%s = %u\n", f.name, unsigned(v));
+        some_unset |= !v;
+    }
+    if (g.lock_level >= 2 && some_unset) {
+        Serial.printf("Burning efuses\n");
+        esp_efuse_batch_write_begin();
+        for (const auto &f : fuses) {
+            const bool v = esp_efuse_read_field_bit(f.desc);
+            if (!v) {
+                Serial.printf("%s -> 1\n", f.name);
+                auto ret = esp_efuse_write_field_bit(f.desc);
+                if (ret != ESP_OK) {
+                    Serial.printf("%s change failed\n", f.name);
+                }
+            }
+        }
+        esp_efuse_batch_write_commit();
+    }
+}
+

+ 4 - 0
RemoteIDModule/efuse.h

@@ -0,0 +1,4 @@
+#pragma once
+
+void set_efuses(void);
+