Hardware, IoT & Embedded · IoT Security

IoT Security Basics: Provisioning, Keys, and Trust

Stop shipping devices that are easy to hijack.

Reading time: ~8–12 min
Level: All levels
Updated:

Stop shipping devices that are easy to hijack. Most IoT breaches aren’t “advanced crypto failures” — they’re basic identity mistakes: shared secrets, default credentials, unverified updates, and no clear chain of trust. This guide walks through the practical foundation: provisioning, device keys, and the trust model that keeps your fleet sane.


Quickstart

If you only do a few things, do these. They’re the highest-leverage moves for IoT security basics: they reduce the blast radius of a compromise, prevent fleet-wide takeovers, and make incident response possible.

1) Give every device a unique identity

Never ship shared credentials. Each device should have its own cryptographic identity (ideally a private key that never leaves the device).

  • Generate a unique keypair per device (preferably inside the device or secure element)
  • Bind identity to a stable device ID/serial in manufacturing records
  • Use mTLS or signed challenges for authentication (not “device says it’s device-123”)

2) Establish a real chain of trust

Trust should be rooted in hardware and verified at every hop: boot, firmware, and cloud connection.

  • Enable secure boot (signed firmware verification)
  • Lock debug ports for production (or gate them with authorization)
  • Use signed OTA updates with rollback protection

3) Split “bootstrap” from “operational” credentials

Provisioning credentials should do one job: safely introduce a device to your system. After that, rotate to scoped, least-privilege creds.

  • Bootstrap identity proves “this is a real device”
  • Operational creds are tenant-/product-scoped and rotateable
  • Be able to revoke a single device without touching the fleet

4) Plan for revocation on day one

If you can’t revoke, you can’t respond. Revocation is what turns a compromise into an incident (not a catastrophe).

  • Maintain a device registry (state: active / quarantined / revoked)
  • Support cert/key rotation and “deny list” checks
  • Log authentication + update events with device identity
A simple rule that saves fleets

If one stolen device can be used to impersonate other devices, your provisioning model is broken. Design the system so compromises are per-device, not per-fleet.

Overview

“IoT security” can feel huge: radio links, firmware, cloud, apps, manufacturing, and end users. But the foundation is surprisingly small: identity, keys, and trust decisions. If you get those right, everything else becomes easier to reason about.

What this post covers

  • Provisioning: how devices get initial credentials and become “known” to your backend
  • Keys: what keys you need, where they live, and how to rotate/revoke them
  • Trust: the chain of trust from bootloader → firmware → network → cloud policies
  • Practical steps: a step-by-step workflow you can apply to real products

We’ll use a lifecycle lens. Most bugs happen at transitions: factory → customer, onboarding → normal operation, update → rollback, and decommission → reuse/resale.

Lifecycle stage What can go wrong What “good” looks like
Manufacturing Shared secrets, untracked serials, leaked keys Per-device identity + auditable provisioning records
Onboarding Impersonation, MITM, “claiming” someone else’s device Mutual auth + claim flow bound to identity
Normal operation Overbroad permissions, replay, weak telemetry integrity Least-privilege topics/APIs + rotation + logging
Updates Malicious firmware, downgrade attacks Signed OTA + version/rollback protection
End-of-life Keys left on device, reused credentials Secure wipe + revoke + re-provision as new identity
Design goal

Your system should be able to answer quickly: “Who is this device?” and “What is it allowed to do?” — even years after you ship it.

Core concepts

Let’s align on a few terms. Most teams don’t fail because they don’t know crypto; they fail because they don’t have a consistent model of what is trusted, when, and why.

Provisioning vs onboarding vs enrollment

Provisioning (factory-time or first-boot)

Provisioning is how a device receives (or generates) its initial credentials and becomes uniquely identifiable. Think: “give the device a passport.”

  • Key material is created or injected
  • Device identity is recorded in a registry
  • Root/intermediate trust anchors are installed

Onboarding (customer-time)

Onboarding is how a real customer/tenant claims the device and grants it the correct permissions. Think: “assign this passport to an account.”

  • Device proves identity (mTLS / attestation)
  • Customer claims device (QR / code / ownership proof)
  • Operational credentials + policies are issued

Root of trust and the chain of trust

A root of trust is the smallest component you assume is trustworthy. Everything else is verified against it. In embedded systems, this is typically a ROM bootloader, a hardware secure element/TPM, or a verified first-stage bootloader.

A mental model: “trust only what you can verify”

  • Boot verifies firmware signature (secure boot)
  • Firmware uses device identity to authenticate to cloud (mTLS or signed challenge)
  • Cloud authorizes actions based on identity + policy (least privilege)
  • OTA verifies update signatures before install (and prevents downgrade)

Key types you’ll actually use

You don’t need ten keys to be secure, but you do need the right separation. The simplest robust approach is: one device identity key + one update verification key (public) + derived session keys during communication.

Key / artifact Used for Where it should live
Device private key Authentication (mTLS) / signing challenges Secure element/TPM/TEE if possible; otherwise protected flash + hardening
Device certificate Proving identity (public, signed by your CA) Device filesystem/flash (OK to be readable; not secret)
Trust anchor (CA cert) Verifying servers or provisioning endpoints Device firmware/flash (immutable preferred)
Firmware signing public key Verifying OTA images Bootloader/ROM/immutable region
Operational tokens App-level access (topics/APIs) Device secure storage; short-lived; rotateable
What not to do

Avoid “one symmetric key for the entire fleet.” If that key leaks once, an attacker can impersonate every device you’ve ever shipped. Unique per-device identity is the baseline for safe IoT provisioning.

Step-by-step

Below is a practical, “works in production” flow. It’s vendor-neutral and scales from hobby deployments to real manufacturing. The details change per cloud/provider, but the security decisions are the same.

Step 1 — Write a threat model (small, specific)

You don’t need a 40-page document. You need a list of what you’re protecting, from whom, and what happens if you’re wrong.

  • Assets: device identity, customer data, update channel, backend credentials
  • Attackers: internet attackers, local attackers with device access, malicious resellers
  • Constraints: power, CPU, storage, offline time, manufacturing process
  • Failure cost: annoyance vs safety-critical vs financial loss

Step 2 — Choose an identity strategy

For most connected IoT devices, a per-device asymmetric keypair is the cleanest choice. It supports strong authentication, secure provisioning, and per-device revocation.

Recommended default: X.509 + mTLS

  • Device has a private key + certificate
  • Backend validates certificate chain
  • Policies bind permissions to device identity
  • Revocation/quarantine is feasible per device

When PSKs are acceptable

Symmetric keys can work for very constrained devices, but only if they are unique per device and stored/handled carefully.

  • Device has enough entropy to avoid predictable keys
  • You can rotate keys safely
  • Your backend can isolate damage per device

Step 3 — Provision credentials (factory or first boot)

There are two common patterns: (1) generate keys inside the device and have the factory sign a CSR, or (2) inject keys during manufacturing (more risk; requires stronger handling controls). Prefer generating keys on the device when possible.

Factory reality

Provisioning is a manufacturing problem as much as a software problem. The best crypto plan fails if your factory workflow can’t track which identity belongs to which physical unit.

# Demo: create a small CA and sign a device certificate (for learning/testing).
# In production, your CA should be protected (HSM), audited, and separated by environment.

# 1) Create a root CA key + certificate
openssl genrsa -out ca.key 4096
openssl req -x509 -new -nodes -key ca.key -sha256 -days 3650 \
  -subj "/CN=unilab-demo-root" -out ca.crt

# 2) Generate a device keypair (ECDSA P-256) and CSR
openssl ecparam -name prime256v1 -genkey -noout -out device.key
openssl req -new -key device.key \
  -subj "/CN=device-000123/O=unilab-demo" -out device.csr

# 3) Sign the CSR with the CA
openssl x509 -req -in device.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
  -out device.crt -days 365 -sha256

Provisioning checklist (what to record)

  • Serial/device ID ↔ certificate fingerprint (or public key hash)
  • Manufacturing batch/line metadata (helps trace incidents)
  • Firmware version at ship time
  • Device state: manufactured → shipped → claimed → active → quarantined → revoked

Step 4 — Onboard devices with a safe claim flow

Onboarding answers: “which customer owns this device?” The most common mistake is letting a device be claimed using only a serial number (easy to guess) or a barcode that never expires (easy to copy).

A safe pattern

  • Device authenticates to backend using mTLS (certificate)
  • User proves physical possession (QR code / short code printed on device)
  • Backend binds device identity to tenant/account
  • Backend issues operational permissions scoped to that tenant

Hard rules

  • Claim codes must expire and be single-use
  • Claim should require proof-of-possession (not just “enter serial”)
  • Never accept unauthenticated “I am device-123” messages

Step 5 — Enforce least privilege in cloud policies

The cloud side is where you prevent “device A publishes commands to device B.” Bind authorization to device identity and keep topic/API permissions tight.

{
  "version": "2026-01-09",
  "statement": [
    {
      "effect": "allow",
      "action": ["connect"],
      "resource": ["device:${deviceId}"]
    },
    {
      "effect": "allow",
      "action": ["publish"],
      "resource": [
        "topic:devices/${deviceId}/telemetry",
        "topic:devices/${deviceId}/status"
      ]
    },
    {
      "effect": "allow",
      "action": ["subscribe"],
      "resource": ["topicfilter:devices/${deviceId}/commands/#"]
    },
    {
      "effect": "deny",
      "action": ["publish", "subscribe"],
      "resource": ["topic:devices/*/commands/#"]
    }
  ]
}
Why explicit deny matters

Many policy engines are “allow if any rule matches.” Adding explicit deny rules can prevent surprising escalation paths when you later expand the policy set.

Step 6 — Implement mTLS on the device (and rotate operational creds)

A typical flow is: use the device certificate to establish a secure connection, then request short-lived operational credentials (tokens) for app-specific access. This gives you a clean rotation story without touching the hardware identity often.

# Example: connect to an MQTT broker using mutual TLS (mTLS) and publish telemetry.
# You can adapt this pattern to your platform/language; the important part is:
# device cert + private key authenticate the device, and the broker verifies the CA chain.

import ssl
import time

import paho.mqtt.client as mqtt  # pip install paho-mqtt

BROKER_HOST = "mqtt.example.com"
BROKER_PORT = 8883

DEVICE_ID = "device-000123"
CA_CERT = "ca.crt"
DEVICE_CERT = "device.crt"
DEVICE_KEY = "device.key"

client = mqtt.Client(client_id=DEVICE_ID, clean_session=True)

tls_ctx = ssl.create_default_context(cafile=CA_CERT)
tls_ctx.load_cert_chain(certfile=DEVICE_CERT, keyfile=DEVICE_KEY)
tls_ctx.check_hostname = True
tls_ctx.verify_mode = ssl.CERT_REQUIRED

client.tls_set_context(tls_ctx)
client.connect(BROKER_HOST, BROKER_PORT, keepalive=30)
client.loop_start()

for i in range(3):
  payload = {"deviceId": DEVICE_ID, "tempC": 23.4 + i, "ts": int(time.time())}
  client.publish(f"devices/{DEVICE_ID}/telemetry", str(payload), qos=1)
  time.sleep(2)

client.loop_stop()
client.disconnect()

Operational hygiene checklist

  • Use short-lived tokens for app-level access where possible
  • Rotate tokens automatically; handle clock/time issues explicitly
  • Pin the trust anchor (CA) you expect; don’t trust “any public CA” by default
  • Log auth failures and unexpected topic/API access attempts

Step 7 — Secure OTA updates (signed, versioned, rollback-safe)

OTA is where attackers go when they can’t break your crypto directly. If an attacker can trick devices into installing malicious firmware (or downgrading to a vulnerable version), your fleet becomes a botnet.

OTA must-haves

  • Firmware images are signed; device verifies before install
  • Rollback protection (monotonic version counter or anti-rollback policy)
  • A/B partitions or safe recovery path
  • Update keys separated from device identity keys

Practical extras

  • Staged rollouts (canary groups) and health checks
  • Device-side update integrity logs
  • Emergency “quarantine mode” if update verification fails repeatedly

Common mistakes

These mistakes show up in real fleets (not just tutorials). The fixes are usually cheaper than a breach response and dramatically improve reliability.

Mistake 1 — Shared secrets (fleet-wide keys)

One leaked key turns a single compromised device into a fleet compromise.

  • Fix: per-device keypairs/certs or per-device PSKs (never shared)
  • Fix: bind policies to device identity and support per-device revocation

Mistake 2 — “Serial number = identity”

Identifiers aren’t authenticators. Anyone can claim to be “device-123.”

  • Fix: use cryptographic proof (mTLS or challenge signing)
  • Fix: require a claim flow with proof-of-possession for ownership

Mistake 3 — Leaving debug interfaces open

UART/JTAG/SWD in production can bypass higher-level security entirely.

  • Fix: disable or lock debug in production builds; document exceptions
  • Fix: if you must keep it, gate with authorization + logging + physical controls

Mistake 4 — Storing private keys in easy-to-read flash

If keys are extractable, an attacker can clone devices or impersonate them.

  • Fix: use secure element/TPM/TEE when feasible
  • Fix: harden storage (encryption-at-rest, readout protection, secure boot) and assume some physical attacks succeed

Mistake 5 — OTA without signature verification (or no anti-rollback)

Attackers love updates because they scale and persist.

  • Fix: signed firmware + verification in bootloader or trusted code
  • Fix: prevent downgrades to known-vulnerable versions

Mistake 6 — No revocation / no incident response hooks

If you can’t quarantine a device, every compromise is a slow-motion disaster.

  • Fix: device registry states (active/quarantine/revoked) enforced by policy
  • Fix: rotate operational tokens and support cert/key replacement where possible
The “test vs prod” trap

Don’t reuse certificates/keys between environments. Separate roots (or intermediates) for dev/stage/prod so a test leak can’t reach production.

FAQ

What is device provisioning in IoT security?

Provisioning is the process of giving a device its initial security identity and trust anchors — typically generating or injecting a unique key, installing a certificate (or PSK), and registering that identity in your backend so the device can authenticate later.

Should IoT devices use certificates or pre-shared keys?

Certificates (with per-device asymmetric keys) are usually the safer default because they support strong authentication, least privilege, and per-device revocation. PSKs can work for constrained devices, but only if they are unique per device and you have a solid rotation plan.

Where should the private key live on an embedded device?

Ideally in a secure element/TPM/TEE so it’s non-exportable. If that’s not possible, store it in protected flash with readout protections enabled, rely on secure boot to reduce malware extraction, and assume sophisticated physical attackers may still extract keys.

What does “chain of trust” mean for IoT?

It means each stage verifies the next: a trusted boot component verifies firmware signatures, firmware uses a protected identity to authenticate to the cloud, and the cloud authorizes actions based on that verified identity. No single “I promise I’m legit” step should be trusted without verification.

How do you revoke a compromised IoT device?

You revoke at the identity layer: mark the device as quarantined/revoked in your registry and enforce that state in your authorization policies (e.g., deny connect/publish/subscribe). If you use certificates, you can also rotate or invalidate certs and re-provision the device only after remediation.

How do I secure OTA updates without overengineering?

Start with signed firmware images verified on-device before installation, keep update verification keys separate from identity keys, and prevent downgrade to vulnerable versions. If you can, use A/B partitions and staged rollouts to avoid bricking fleets.

What’s the minimum “must have” for IoT security basics?

Unique per-device identity, mutual authentication to backend, least-privilege authorization, signed OTA updates, and a revocation/quarantine mechanism. Those five cover the majority of preventable fleet compromises.

Cheatsheet

A scan-fast checklist you can use during design reviews, manufacturing prep, and release sign-off.

Provisioning (factory / first boot)

  • Per-device keypair (prefer generated on-device)
  • Device certificate issued (or unique PSK) and recorded in registry
  • Trust anchors installed (CA / server cert pinning strategy)
  • Manufacturing records: serial ↔ key/cert fingerprint
  • Dev/stage/prod roots separated

Onboarding (customer claim)

  • Device proves identity (mTLS / signed challenge)
  • Claim requires proof-of-possession (QR/short code)
  • Claim codes expire + single-use
  • Operational permissions are tenant-scoped
  • Audit trail: who claimed, when, from where

Runtime security

  • Least-privilege topics/APIs (device can access only its namespace)
  • Short-lived operational tokens (where feasible) + rotation
  • Rate limits + basic anomaly detection (failed auth spikes)
  • Logs include device identity (not just IP)
  • Secure time strategy (handle clock drift/offline)

Updates & incident response

  • Signed OTA images, verified pre-install
  • Anti-rollback policy (no downgrades)
  • Device registry states: active / quarantine / revoked
  • Ability to revoke a single device without impacting others
  • Secure wipe + revoke at end-of-life
Review question

Ask during reviews: “If an attacker owns one device, what else can they do?” Your answer should be “almost nothing beyond that device.”

Wrap-up

IoT security basics are not about fancy algorithms. They’re about eliminating the “easy wins” attackers rely on: shared secrets, unverifiable identity, and updates you can’t trust. If you build a clean provisioning story and a clear chain of trust, you get a fleet that’s easier to operate, easier to debug, and dramatically harder to hijack.

What to do next (in order)

  1. Audit identity: confirm every device has unique credentials and a registry entry.
  2. Lock trust: verify secure boot + signed OTA are enforced on-device.
  3. Tighten policies: least privilege for topics/APIs (per-device namespace).
  4. Add revocation: quarantine/revoke workflow that works under pressure.

Want to go deeper on the practical side of scaling provisioning and keeping embedded systems safe? Continue with the related posts below.

Quiz

Quick self-check (demo). This quiz is auto-generated for hardware / iot / embedded.

1) Which approach best prevents a single compromise from becoming a fleet-wide compromise?
2) What is the primary purpose of secure boot in an IoT device?
3) What’s the safest way to design a device claim (onboarding) flow?
4) Which is the best reason to separate bootstrap credentials from operational credentials?