Zero-Trust Security for Embedded IoT: Why Your Devices Are Probably Vulnerable
We've audited a lot of IoT systems. The pattern is almost always the same: security was treated as a final step, bolted on after the core functionality was working. By then, the architecture made proper security nearly impossible without a rewrite.
This guide is about doing it right from day one.
The Zero-Trust Model for IoT
Zero-trust means: never trust, always verify. For IoT:
Step 1: Device Identity — The Foundation
The most common mistake: using the same password/API key on every device.
X.509 Certificate-Based Identity
Each device gets a unique certificate signed by your Certificate Authority:
Generate device-specific certificate
openssl genrsa -out device-001.key 2048
openssl req -new -key device-001.key -out device-001.csr \
-subj "/CN=device-001/O=CodeCaracal/OU=IoT Fleet"Sign with your CA (or AWS IoT CA)
openssl x509 -req -in device-001.csr \
-CA ca.crt -CAkey ca.key \
-CAcreateserial -out device-001.crt \
-days 365
Embed at flash time, not at runtime. The certificate is part of the build artifact for that specific device.
Step 2: mTLS — Mutual Authentication
Standard TLS authenticates the server. mTLS authenticates both sides.
// ESP32: configure mTLS
WiFiClientSecure client;
client.setCACert(rootCA); // Trust this CA
client.setCertificate(devCert); // Our identity
client.setPrivateKey(devKey); // Prove it// The broker now verifies BOTH sides
// A fake device without a valid cert gets rejected at the TLS layer
On the broker side (AWS IoT Core, Mosquitto with TLS):
mosquitto.conf
listener 8883
cafile /etc/mqtt/ca.crt
certfile /etc/mqtt/server.crt
keyfile /etc/mqtt/server.key
require_certificate true # Enforce mTLS
use_identity_as_username true
Step 3: Least-Privilege MQTT Policies
Devices should only publish to their own topic, and only subscribe to their own command topic.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "iot:Publish",
"Resource": "arn:aws:iot:us-east-1:*:topic/devices/${iot:ClientId}/telemetry"
},
{
"Effect": "Allow",
"Action": "iot:Subscribe",
"Resource": "arn:aws:iot:us-east-1:*:topicfilter/devices/${iot:ClientId}/commands"
}
]
}
The ${iot:ClientId} variable ensures device-001 can't publish to device-002's topic.
Step 4: Secure OTA — Don't Ship Untrusted Code
OTA without signature verification is a remote code execution vulnerability.
bool verifyFirmwareSignature(const uint8_t* firmware, size_t len, const uint8_t* sig) {
// Verify ECDSA signature using your public key
mbedtls_ecdsa_context ctx;
mbedtls_ecdsa_init(&ctx); // Load your OTA signing public key (embedded at compile time)
mbedtls_ecp_point_read_binary(&ctx.grp, &ctx.Q, OTA_PUBLIC_KEY, sizeof(OTA_PUBLIC_KEY));
uint8_t hash[32];
mbedtls_sha256(firmware, len, hash, 0);
int result = mbedtls_ecdsa_read_signature(&ctx, hash, 32, sig, sigLen);
mbedtls_ecdsa_free(&ctx);
return result == 0;
}
Never flash firmware that fails signature verification.
Step 5: Certificate Rotation
Certificates expire. Build rotation into your architecture from the start.
Automated rotation with AWS IoT
// Lambda function triggered 30 days before cert expiry
async function rotateCertificate(deviceId) {
// Issue new cert
const newCert = await iot.createKeysAndCertificate({ setAsActive: true }).promise() // Attach policy
await iot.attachPolicy({
policyName: 'IoTDevicePolicy',
target: newCert.certificateArn
}).promise()
// Deliver new cert via shadow (device will pick up on next connection)
await iotData.updateThingShadow({
thingName: deviceId,
payload: JSON.stringify({
state: {
desired: {
newCertificate: newCert.certificatePem,
newPrivateKey: newCert.keyPair.PrivateKey,
rotateBy: new Date(Date.now() + 7 * 86400000).toISOString()
}
}
})
}).promise()
}
Security Audit Checklist
Before shipping any IoT system:
The Cost of Getting This Wrong
Mirai botnet. Verkada breach. Ubiquiti. These aren't abstract risks — they're documented incidents where basic IoT security failures led to device compromise at scale.
The cost of doing this right at design time? A few days of architecture work.
The cost of retrofitting security into 10,000 deployed devices? Potentially a full product recall.
Need help auditing or architecting your IoT security? [Talk to our team](/contact) — we've built zero-trust IoT systems for clients across 15+ countries.