A comprehensive solution for securing over-the-air (OTA) firmware updates on IoT devices, with special support for legacy hardware.
- RSA-PSS Cryptographic Signing - Firmware signed with 2048-bit RSA keys
- SHA-256 Integrity Verification - File integrity checks
- HMAC-based Data Authentication - Additional integrity verification layer
- Public Key Infrastructure - Separate keys for signing and verification
- Version Control - Semantic versioning with update checks
- Rollback Protection - Prevents downgrade attacks
- Manifest-based Delivery - Structured firmware metadata
- Firmware Repository - Centralized storage for multiple versions
- Legacy Device Compatibility - Minimal resource requirements
- Stateless Architecture - Works on resource-constrained devices
- Flexible Storage - Configurable firmware storage paths
- Progress Tracking - Callbacks for update progress monitoring
secure-ota-system/
├── security_tools/ # Cryptographic utilities
│ ├── crypto.py # RSA signing and verification
│ └── manifest.py # Firmware manifests and versioning
├── ota_server/ # Server-side OTA management
│ └── server.py # Firmware repository and distribution
├── firmware_client/ # Client-side firmware update
│ └── client.py # Legacy device update client
├── tests/ # Test suite
│ └── test_ota_system.py # Unit tests
├── ota_firmware_tool.py # Command-line tool
├── requirements.txt # Python dependencies
└── README.md # Documentation
pip install -r requirements.txtpython ota_firmware_tool.py sign firmware.bin --key-out private_key.pempython ota_firmware_tool.py manifest firmware.bin \
--device-type sensor_v1 \
--version 2.1.0 \
--release-notes "Security patch for CVE-2024-XXXX"python ota_firmware_tool.py verify firmware.bin \
--public-key public_key.pem \
--signature firmware.bin.sigfrom ota_server.server import UpdateServer, FirmwareRepository
# Initialize server
server = UpdateServer("/var/firmware_repo")
# Add firmware
server.firmware_repo.add_firmware("device_type", "1.0.0", "firmware.bin", metadata)
# Check for updates
updates = server.check_for_updates("device_type", "0.9.0")from firmware_client.client import LegacyFirmwareClient
# Initialize client
client = LegacyFirmwareClient(
device_id="DEVICE001",
device_type="sensor",
current_version="1.0.0"
)
# Verify firmware before installation
client.verify_firmware_integrity("firmware.bin", expected_hash)
# Install firmware
client.install_firmware("firmware.bin")from security_tools.crypto import SigningKey, FirmwareSigner
# Create signing key
key = SigningKey()
key.generate()
key.save_private_key("private.pem")
# Sign firmware
signer = FirmwareSigner(key)
signature, hash = signer.sign_firmware("firmware.bin")- Algorithm: RSA with PSS padding
- Key Size: 2048-bit
- Hash: SHA-256
- Padding: Probabilistic Signature Scheme (PSS)
- File Hash: SHA-256
- HMAC: Support for additional authentication
- Rollback Prevention: Version history tracking
- Version History: Tracks all firmware updates
- Minimum Version Check: Prevents rollback below security threshold
- Downgrade Detection: Identifies downgrade attempts
- Controlled Rollback: Explicit approval for downgrades
Run the test suite:
python -m pytest tests/
# or
python tests/test_ota_system.pyTests cover:
- Cryptographic key generation and management
- Firmware signing and verification
- Manifest creation and validation
- Version management and comparison
- Rollback protection logic
- Firmware repository operations
- Client device functionality
- ARM Cortex-M (STM32, nRF52, etc.)
- RISC-V devices
- ESP8266/ESP32
- Raspberry Pi / Linux-based IoT
- Custom embedded systems
- Python 3.7+ (for tools)
- C/C++ compiler (for embedded client)
- Cryptographic library (mbedTLS, OpenSSL, or equivalent)
- Minimal storage (KBs for version history)
- Network connectivity (for update checks)
client = LegacyFirmwareClient(
device_id="DEVICE001",
device_type="sensor",
current_version="1.0.0",
storage_path="/custom/firmware/path"
)def progress_callback(status):
print(f"Status: {status['status']}, Progress: {status['progress']}%")
client.set_progress_callback(progress_callback)
client.install_firmware("firmware.bin")from security_tools.manifest import RollbackProtection
rb = RollbackProtection()
rb.record_version_update("1.0.0")
rb.record_version_update("2.0.0")
# Allow rollback to 1.5.0 if needed
rb.allow_rollback_to("1.5.0")-
Key Management
- Store private keys securely
- Use different keys for different device types
- Rotate keys periodically
-
Firmware Signing
- Sign all firmware releases
- Include release notes
- Document security patches
-
Version Control
- Use semantic versioning
- Document minimum versions
- Track rollback windows
-
Server Security
- Use HTTPS for firmware downloads
- Implement rate limiting
- Log all update attempts
-
Device Security
- Verify signatures on device
- Check version compatibility
- Maintain version history
- Implement watchdog timers
- Check that public key matches the private key used for signing
- Ensure firmware file hasn't been modified
- Verify signature file integrity
- Ensure version strings follow semantic versioning (x.y.z)
- Check rollback protection settings
- Review version history
- Verify storage path exists and is writable
- Check available disk space
- Ensure file permissions are correct
generate()- Generate new RSA key pairload_private_key(path)- Load key from filesave_private_key(path)- Save key to file
sign_firmware(path)- Sign firmware and return signatureverify_firmware(path, signature)- Verify signature
verify_firmware_integrity(path, hash)- Check file integrityverify_firmware_signature(path, sig, pubkey)- Verify signatureinstall_firmware(path)- Install firmwarerollback_firmware(version)- Rollback to previous versionget_device_info()- Get device status
check_for_updates(device_type, version)- Check available updatesget_firmware_download(type, version)- Stream firmwarerecord_update(device_id, type, old, new, status)- Log update
MIT License