Zelta/Documentation

Firmware Signing

Zelta uses ECDSA P-256 digital signatures to ensure firmware authenticity and integrity.

Why Sign Firmware?

Without signatures, attackers could:

  • Man-in-the-middle attacks: Intercept downloads and inject malicious firmware
  • Server compromise: Upload unauthorized firmware if server is breached
  • Replay attacks: Deliver old, vulnerable firmware versions

Signatures ensure that:

  1. Firmware was created by an authorized party (authenticity)
  2. Firmware hasn't been modified (integrity)
  3. Only your private key can sign valid updates

How It Works

Signing Flow (Dashboard)

┌─────────────┐     ┌──────────────┐     ┌─────────────┐
│  Firmware   │────▶│  SHA-256     │────▶│   ECDSA     │
│   Binary    │     │    Hash      │     │    Sign     │
└─────────────┘     └──────────────┘     └─────────────┘
                                                │
                           Private Key ────────┘
                                                │
                                                ▼
                                         ┌─────────────┐
                                         │  Signature  │
                                         │  (Base64)   │
                                         └─────────────┘

Verification Flow (Device)

┌─────────────┐     ┌──────────────┐     ┌─────────────┐
│  Downloaded │────▶│  SHA-256     │────▶│   ECDSA     │
│  Firmware   │     │    Hash      │     │   Verify    │
└─────────────┘     └──────────────┘     └─────────────┘
                                                │
                           Public Key ─────────┘
                           Signature ──────────┘
                                                │
                                                ▼
                                         ┌─────────────┐
                                         │  Valid /    │
                                         │  Invalid    │
                                         └─────────────┘

Algorithm Details

| Property | Value | |----------|-------| | Algorithm | ECDSA | | Curve | P-256 (secp256r1) | | Hash | SHA-256 | | Signature Format | DER, Base64-encoded | | Key Format | SPKI (public), PKCS#8 (private) |

Generating Keys

In Dashboard (Recommended)

  1. Go to Firmware page
  2. Click Generate Keypair in the Signing Key section
  3. A new ECDSA P-256 keypair is generated in your browser
  4. Download the private key immediately and store securely
  5. Click Save Public Key to Org

Using OpenSSL

# Generate private key
openssl ecparam -genkey -name prime256v1 -noout -out private_key.pem

# Extract public key
openssl ec -in private_key.pem -pubout -out public_key.pem

# Convert to DER for embedding
openssl ec -pubin -in public_key.pem -outform DER -out public_key.der

Embedding Public Key

Export the public key for your firmware:

  1. In Key Manager, select format (C, C++, or Rust)
  2. Click Copy Code
  3. Paste into your firmware source

C Format

static const uint8_t public_key_der[91] = {
    0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86,
    0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a,
    // ... rest of key
};

C++ Format

constexpr std::array<uint8_t, 91> public_key_der = {{
    0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86,
    // ... rest of key
}};

Rust Format

const PUBLIC_KEY_DER: [u8; 91] = [
    0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86,
    // ... rest of key
];

Verification on Device

The SDK handles verification automatically:

// In zelta_download_and_apply():
// 1. Download firmware and compute hash
// 2. Verify hash matches server-provided hash
// 3. Verify signature using embedded public key
// 4. Only then apply the update

For manual verification:

#include <zelta/verify.h>

// After downloading firmware
uint8_t hash[32];
zelta_compute_hash(firmware_data, firmware_size, hash);

// Verify signature
int ret = zelta_verify_signature(
    hash, sizeof(hash),
    update_info.signature,
    public_key_der, sizeof(public_key_der)
);

if (ret != ZELTA_OK) {
    LOG_ERR("Signature verification failed!");
    return ret;
}

Security Considerations

Private Key Protection

  • Never upload private key to server
  • Store in secure location (hardware security module, encrypted storage)
  • Use separate keys for development and production
  • Rotate keys periodically

Key Rotation

When rotating keys:

  1. Generate new keypair
  2. Update embedded public key in firmware
  3. Deploy firmware update with OLD key (devices still have old public key)
  4. Once all devices updated, switch to new key for signing
  5. Key fingerprint in dashboard shows which key signed each firmware

Compromise Response

If private key is compromised:

  1. Generate new keypair immediately
  2. Push emergency update signed with old key containing new public key
  3. Mark old key as revoked
  4. Sign all future updates with new key

Troubleshooting

"Signature verification failed"

  • Ensure public key in firmware matches key used for signing
  • Check if firmware was modified during download (hash mismatch)
  • Verify signature format is Base64-encoded DER

"Invalid public key"

  • Key must be in SPKI DER format
  • Check key length (should be 91 bytes for P-256)
  • Ensure key wasn't truncated

Next Steps