esp32FOTA

repository·master·Indexed 19 days ago

https://github.com/chrisjoyce911/esp32fota

An Arduino library for ESP32 devices that enables Over-The-Air (OTA) firmware updates by polling a remote JSON configuration file. It supports HTTP and HTTPS, semantic versioning, RSA signature verification for security, and compressed firmware via Zlib or gzip. The library also allows for simultaneous updates of firmware and filesystem partitions such as SPIFFS, LittleFS, and SD.

Tokens
4.2K
Snippets
9
Records
17
Agent score
15%

What's inside esp32fota

  1. Key features of esp32FOTA

    master

    The library provides several advanced OTA features, including:

    • Compression Support: Handles Zlib or gzip compressed firmware.
    • Filesystem Support: Supports SPIFFS, LittleFS, and SD for storing certificates and signatures.
    • Protocol Support: Seamlessly handles both HTTP and HTTPS.
    • Security: Includes signature verification and signature checking of downloaded firmware images.
    • Update Logic: Supports semantic versioning, batch firmware sync, force updates, and web-based updates (when a web server is present).
    • Partition Updates: Supports updating SPIFFS/LittleFS partitions.
  2. Configure the Hosted JSON Manifest

    master

    The esp32FOTA library uses a JSON manifest hosted on a webserver to determine if an update is available. You can define firmware updates using two different strategies. You cannot mix these strategies in a single manifest entry.

    1. Complete URL (Firmware Only)

    Use the url field to provide a direct link to the .bin file. This method does not support filesystem updates (SPIFFS, LittleFS, etc.).

    2. Component-based URLs (Firmware + Filesystem)

    Use host, port, and bin to construct the firmware URL, and optional spiffs, littlefs, or fatfs keys for filesystem updates. This method allows updating both the firmware and the filesystem in one cycle.

    Important: If the url field is present, all other URL-related fields (like host, port, bin, or filesystem keys) will be ignored.

    {
        "type": "esp32-fota-http",
        "version": "1.0.0",
        "host": "example.com",
        "port": 443,
        "bin": "/firmware.bin",
        "littlefs": "/filesystem.bin"
    }
  3. Handle Multiple Firmware Types or Versions in JSON

    master

    A single JSON manifest can contain an array of objects to support multiple hardware types or multiple version entries for the same type. The library selects the entry where the type matches the string passed to the esp32FOTA constructor.

    Multiple Hardware Types

    [
       {
          "type":"esp32-fota-http",
          "version":"0.0.2",
          "url":"http://192.168.0.100/fota/esp32-fota-http-2.bin"
       },
       {
          "type":"esp32-other-hardware",
          "version":"0.0.3",
          "url":"http://192.168.0.100/fota/esp32-other-hardware.bin"
       }
    ]

    Multiple Versions for One Type

    [
       {
          "type":"esp32-fota-http",
          "version":"0.0.2",
          "url":"http://192.168.0.100/fota/esp32-fota-0.0.2.bin"
       },
       {
          "type":"esp32-fota-http",
          "version":"0.0.3",
          "url":"http://192.168.0.100/fota/esp32-fota-0.0.3.bin",
          "spiffs":"http://192.168.0.100/fota/esp32-fota-0.0.3.spiffs.bin"
       }
    ]
  4. How esp32FOTA works

    master

    The update process follows this workflow:

    1. JSON Check: The library accesses a JSON file hosted on your webserver.
    2. Decision Logic: It reviews the JSON content to determine if a newer firmware version is available.
    3. Download & Install: If an update is required, the library downloads the firmware and installs it to the device.

    Requirements for successful updates:

    • Webserver: Must host a JSON file containing firmware metadata.
    • JSON Metadata: Must include Firmware version, Firmware type, and the Firmware bin URL (the bin can optionally be compressed with zlib or gzip).
    • HTTPS/Security Requirements: If using HTTPS or signature verification, you must store root_ca.pem (for HTTPS) and rsa_key.pem (for signature checking) in your SPIFFS partition.
  5. Configure HTTP vs HTTPS in esp32FOTA

    master

    The library determines whether to use plain HTTP or HTTPS based on the port specified in the URL:

    • HTTPS: Use port 443 or 4433. Note that for HTTPS to work, you must have the root_ca.pem file stored in your SPIFFS partition.
    • HTTP: Use any other port (defaulting to plain HTTP).
  6. Secure firmware updates with RSA signatures

    master

    To ensure firmware integrity, you can sign your firmware binary using a private key. The ESP32 will verify the signature using a public key stored in a dedicated SPIFFS partition before applying the update.

    1. Generate the signature

    Use OpenSSL to create a signature file from your firmware binary and private key:

    openssl dgst -sign priv_key.pem -keyform PEM -sha256 -out firmware.sign -binary firmware.bin

    2. Create the signed image

    Concatenate the signature and the firmware binary into a single .img file. The library expects the signature to be the first 512 bytes of the file:

    cat firmware.sign firmware.bin > firmware.img

    3. Deploy and Verify

    1. Upload firmware.img to your OTA server.
    2. Update your firmware.json to point to the new firmware.img URL.
    3. Ensure your ESP32 has a SPIFFS partition containing your rsa_key.pub. This partition is only distributed once and is not touched during subsequent OTA updates.

    During the update check, the ESP32 downloads firmware.img, extracts the first 512 bytes (the signature), and validates it against the remaining image using the public key. If valid, the device resets into the new firmware.

    openssl dgst -sign priv_key.pem -keyform PEM -sha256 -out firmware.sign -binary firmware.bin
    cat firmware.sign firmware.bin > firmware.img
  7. Initialize esp32FOTA with Early or Late Configuration

    master

    You can initialize the library using a simple constructor for basic use cases, or use FOTAConfig_t for advanced configurations like signature verification and custom certificates.

    Early Initialization (Simple)

    Best for standard HTTP updates with a known name and version.

    Late Initialization (Advanced)

    Use getConfig() and setConfig() to set parameters like semantic versioning, signature checking, and custom root certificates.

    Note: If you are using a filesystem (like SPIFFS) to store certificates, include the filesystem header (e.g., #include <SPIFFS.h>) before including esp32FOTA.hpp.

    ### Early Init
    ```cpp
    #include <esp32FOTA.hpp>
    
    esp32FOTA esp32FOTA("esp32-fota-http", "1.0.0");
    
    void setup() {
      // ...
      esp32FOTA.setManifestURL("http://server/fota/fota.json");
    }

    Late Init

    #include <SPIFFS.h>
    #include <esp32FOTA.hpp>
    
    esp32FOTA FOTA;
    
    void setup() {
      auto cfg = FOTA.getConfig();
      cfg.name          = "esp32-fota-http";
      cfg.manifest_url  = "http://server/fota/fota.json";
      cfg.sem           = SemverClass(1, 0, 0);
      cfg.check_sig     = false;
      cfg.unsafe        = true; // Disable cert check for TLS
      FOTA.setConfig(cfg);
    }
  8. Use Zlib/Gzip Compressed Firmware

    master

    You can use compressed firmware images to save bandwidth. Note: This feature cannot be used with signature verification.

    Gzip (.gz)

    Requires the ESP32-targz library. The file extension in the JSON manifest must be .gz.

    Zlib/Pigz (.zz)

    Requires the flashz library. The file extension in the JSON manifest must be .zz.

    Compression Commands:

    # For .zz
    $ pigz -9kzc esp32-fota-http-2.bin > esp32-fota-http-2.bin.zz
    
    # For .gz
    $ gzip -c esp32-fota-http-2.bin > esp32-fota-http-2.bin.gz
    {
        "type": "esp32-fota-http",
        "version": "2.5.1",
        "url": "http://192.168.0.100/fota/esp32-fota-http-2.bin.gz"
    }
  9. Verify Firmware via RSA Signature

    master

    To ensure firmware integrity, you can sign your .bin files with an RSA private key and have the ESP32 verify them using a public key before applying the update.

    1. Generate Key Pair

    openssl genrsa -out priv_key.pem 4096
    openssl rsa -in priv_key.pem -pubout > rsa_key.pub

    2. Enable Verification in Code

    Set check_sig = true in your FOTAConfig_t and provide the public key using setPubKey().

    3. Sign the Firmware

    (Note: The specific command to sign the binary is implied to follow the key generation step in the documentation).

    auto cfg = FOTA.getConfig();
    cfg.check_sig = true;
    FOTA.setConfig(cfg);
    
    // Load public key from SD
    CryptoFileAsset *MyPubKey = new CryptoFileAsset("/rsa_key.pub", &SD);
    esp32FOTA.setPubKey(MyPubKey);
  10. Manage Root Certificates and TLS

    master

    To use HTTPS, you must provide root certificates.

    Bundled Certificates (Arduino 3.x)

    If using Arduino 3.x, you can use built-in certificates by calling: esp32FOTA.useBundledCerts();

    If using PlatformIO, you must manually embed the ca_cert_bundle file in your platformio.ini: board_build.embed_txtfiles=ca_cert_bundle

    Custom Certificates

    Certificates can be loaded from a filesystem (SPIFFS, LittleFS, SD) using CryptoFileAsset or from memory using CryptoMemAsset.

    Example: Loading from SD and Memory

    CryptoFileAsset *MyRootCA = new CryptoFileAsset("/root_ca.pem", &SD);
    const char* root_ca = "-----BEGIN CERTIFICATE-----\n...";
    CryptoMemAsset *MyRootCA_Mem = new CryptoMemAsset("Root CA", root_ca, strlen(root_ca)+1);
    
    // Apply in setup()
    esp32FOTA.setRootCA(MyRootCA);