From grimoire
Designs firmware update mechanisms for IoT devices: implementing code signing, verified secure boot chains, and rollback protection to prevent malicious firmware execution.
How this skill is triggered — by the user, by Claude, or both
Slash command
/grimoire:design-iot-secure-bootThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Implement cryptographic code signing for firmware, verified boot chain from ROM to application, and rollback prevention — ensuring only authorized firmware runs on IoT devices even after physical access.
Implement cryptographic code signing for firmware, verified boot chain from ROM to application, and rollback prevention — ensuring only authorized firmware runs on IoT devices even after physical access.
Adopted by: OWASP IoT Top 10 I4 (Lack of Secure Update Mechanism). NIST SP 800-193 (Platform Firmware Resiliency) is the US federal standard for firmware integrity. The IETF SUIT (Software Updates for Internet of Things) manifest standard (RFC 9019) defines the protocol. Arm TrustZone secure boot is implemented in the majority of modern IoT SoCs (STM32H5, NXP i.MX RT, Nordic nRF9161). AWS IoT Jobs, Azure Device Update, and Mbed TLS all implement SUIT-compatible update pipelines. Impact: Mirai botnet (2016, 600,000+ devices compromised) and its variants exploited devices with no firmware verification — malicious firmware was flashed over default credentials and telnet. VPNFilter (2018, 500,000 routers compromised) survived factory resets because it persisted in flash memory beyond the OS partition. NIST SP 800-193 states that "the ability to detect and recover from corrupt or maliciously modified firmware is a foundational security control" — without it, physical access equals full device compromise. Why best: OTA updates without signature verification allow any attacker who intercepts the update channel (or the update server itself) to push malicious firmware to the entire device fleet. Code signing ensures the device verifies the firmware author before executing it. Secure boot ties the trust chain to hardware (ROM key, OTP fuses) so no software-level attack can bypass it.
Sources: OWASP IoT Top 10 I4; NIST SP 800-193; IETF RFC 9019 (SUIT Manifest); Arm Platform Security Architecture (PSA) documentation
Sign firmware images before distribution:
# Generate signing key (keep private key in HSM for production)
openssl ecparam -name prime256v1 -genkey -noout -out firmware-signing-key.pem
openssl ec -in firmware-signing-key.pem -pubout -out firmware-signing-key-pub.pem
# Sign firmware binary
openssl dgst -sha256 -sign firmware-signing-key.pem \
-out firmware-v1.2.3.bin.sig firmware-v1.2.3.bin
# Verify (device does this)
openssl dgst -sha256 -verify firmware-signing-key-pub.pem \
-signature firmware-v1.2.3.bin.sig firmware-v1.2.3.bin
Implement ECDSA signature verification in the bootloader:
#include "mbedtls/ecdsa.h"
#include "mbedtls/sha256.h"
/* Public key burned into OTP fuses or stored in secure storage */
static const uint8_t SIGNING_PUBLIC_KEY[] = {
0x04, /* uncompressed point marker */
/* 64-byte public key X and Y coordinates */
};
int verify_firmware(const uint8_t *firmware, size_t firmware_len,
const uint8_t *signature, size_t sig_len) {
uint8_t hash[32];
mbedtls_sha256(firmware, firmware_len, hash, 0);
mbedtls_ecdsa_context ecdsa;
mbedtls_ecdsa_init(&ecdsa);
int ret = mbedtls_ecp_point_read_binary(
&ecdsa.private_grp, &ecdsa.private_Q,
SIGNING_PUBLIC_KEY, sizeof(SIGNING_PUBLIC_KEY)
);
if (ret != 0) return VERIFY_FAILED;
ret = mbedtls_ecdsa_read_signature(&ecdsa, hash, sizeof(hash),
signature, sig_len);
mbedtls_ecdsa_free(&ecdsa);
return (ret == 0) ? VERIFY_OK : VERIFY_FAILED;
}
Implement rollback protection using a monotonic counter:
/* Store anti-rollback counter in OTP fuses — cannot be decremented */
typedef struct {
uint32_t version; /* firmware semantic version */
uint32_t anti_rollback; /* must be >= current OTP counter */
} FirmwareHeader;
int check_rollback(const FirmwareHeader *header) {
uint32_t otp_counter = read_otp_anti_rollback_counter();
/* New firmware must have counter >= current value */
if (header->anti_rollback < otp_counter) {
return ROLLBACK_DETECTED; /* reject downgrade */
}
/* After successful boot, advance OTP counter to new firmware's value */
if (header->anti_rollback > otp_counter) {
/* Only write OTP after successful boot, not at verification time */
schedule_otp_update(header->anti_rollback);
}
return ROLLBACK_OK;
}
Implement A/B partition update with revert capability:
/* Dual-bank flash layout:
* Bank A: active firmware (currently running)
* Bank B: update target (download here before activating)
*/
typedef enum { BANK_A = 0, BANK_B = 1 } FlashBank;
UpdateResult apply_update(const uint8_t *firmware, size_t len,
const uint8_t *signature, size_t sig_len) {
/* Step 1: verify before touching active partition */
if (verify_firmware(firmware, len, signature, sig_len) != VERIFY_OK) {
return UPDATE_SIGNATURE_INVALID;
}
FlashBank inactive = get_inactive_bank();
/* Step 2: erase and write to inactive bank only */
flash_erase_bank(inactive);
flash_write(get_bank_address(inactive), firmware, len);
/* Step 3: verify what was written */
if (!verify_bank_contents(inactive, firmware, len)) {
return UPDATE_WRITE_ERROR;
}
/* Step 4: set boot flag — reverts to A if B fails to boot 3 times */
set_pending_boot_bank(inactive, max_boot_attempts=3);
return UPDATE_PENDING_REBOOT;
}
OTA update client with transport security:
/* Use TLS 1.2+ with certificate pinning for update server */
#include "mbedtls/ssl.h"
#define UPDATE_SERVER_CERT_FINGERPRINT \
"\xAB\xCD\xEF..." /* SHA-256 of server certificate */
int download_update(const char *url, uint8_t *buffer, size_t *len) {
/* Pin server certificate — prevent MitM from serving malicious firmware */
ssl_config.verify_mode = MBEDTLS_SSL_VERIFY_REQUIRED;
ssl_config.ca_chain = &server_cert_chain;
/* Verify fingerprint after TLS handshake */
const mbedtls_x509_crt *peer_cert = mbedtls_ssl_get_peer_cert(&ssl);
uint8_t fingerprint[32];
mbedtls_sha256(peer_cert->raw.p, peer_cert->raw.len, fingerprint, 0);
if (memcmp(fingerprint, UPDATE_SERVER_CERT_FINGERPRINT, 32) != 0) {
return ERROR_CERT_MISMATCH;
}
/* ... download proceeds ... */
}
npx claudepluginhub jeffreytse/grimoire --plugin grimoireProvides IoT security practices for resource-constrained devices: X.509/secure element identity, secure boot chains, TLS/DTLS comms, firmware signing, network segmentation, device attestation, and vuln management.
Produce a complete OTA update system design — partition layout, update flow, rollback conditions, validation checks, fleet management approach, failure modes and recovery. Use when asked about "OTA updates", "firmware updates over the air", "how do I update devices in the field", "OTA strategy", or "remote firmware update design".
Produces complete OTA update system designs for embedded/IoT devices including partition layouts, update flows, rollback conditions, validations, fleet management, and failure recovery paths.