1. Today's topic

The identity lifecycle:

text
device produced
→ unique device_id
→ key pair
→ CSR
→ client certificate
→ mTLS
→ certificate rotation
→ revocation
→ decommission

The main idea: every device must have its own cryptographic identity. A production station must not write one shared password or private key across the entire fleet.

2. Why this matters

The username=device/password=common scheme is dangerous:

text
a leak from one device -> compromise of all devices.

The correct approach:

text
TC-0001842 -> unique private key -> unique client certificate -> mTLS

If a device is compromised, one certificate is revoked. Device identity must link:

c
device_id;
ESP32 MAC;
EC25 IMEI;
hardware revision;
client certificate fingerprint;
firmware release;
HIL result.

3. Theory

A serial number is not a cryptographic identity

device_id, MAC, IMEI and STM32 UID are inventory attributes. A private key proves possession of an identity.

Key pair

text
private key: secret, never leaves the device;
public key: included in the certificate; the server verifies the signature.

ECC P-256 is often convenient for embedded systems.

CSR

The device generates a key pair, creates a CSR and sends the public key plus proof to the CA. The CA issues a certificate and does not receive the private key.

Provisioning models

Poor approach:

text
one shared key/cert for the entire fleet.

Better approach:

text
the station generates a unique key and writes it to the device.

Even better:

text
a key pair is generated on the device or secure element;
the station receives only a CSR.

A/B credential slots

Rotation must not overwrite active credentials:

text
identity_a ACTIVE
identity_b PENDING

The new identity is activated only after proof-of-possession/a TLS probe.

Where to store an ESP32 private key

Options:

text
embedded in firmware: for laboratory use only;
NVS Encryption + Flash Encryption: better;
secure element ATECC608A: stronger;
new ESP32 SoC hardware with hardware-backed crypto: depends on the target.

For the classic ESP32-WROOM-32U, an external secure element is a good option if the private key must not be extractable by software.

STM32

On STM32, a private key can be stored in protected internal Flash/TrustZone/Secure Storage or in STSAFE. STSAFE-A110 supports on-chip key generation and ECDSA operations without exposing the private key to the MCU.

4. Common mistakes

  • One certificate for every device.
  • Treating MAC/IMEI as proof of identity.
  • Generating private keys in a shared CI job.
  • Storing a private key in Git.
  • Sending a private key to the backend instead of a CSR.
  • Overwriting the active certificate without A/B slots.
  • Deleting the old certificate before checking the new one.
  • Disabling server verification because a client certificate is present.
  • Storing a key in plaintext NVS.
  • Writing a PEM key to a debug log.
  • Not monitoring certificate expiry.
  • Using one bootstrap token for an entire batch.
  • Having no recovery path after credentials are lost.

5. A practical task for 30–60 minutes

Create DEVICE_IDENTITY_POLICY.md:

markdown
# Device identity policy
1. Every production device has a unique key pair.
2. A private key is never shared by multiple devices.
3. The backend receives CSR, never a device private key.
4. MAC, UID and IMEI are inventory attributes, not credentials.
5. Server certificate verification is always enabled.
6. Operational credentials are stored in A/B slots.
7. New credentials are tested before activation.
8. Old credentials are retained during a grace period.
9. Every credential has a generation and fingerprint.
10. Production private keys are never stored in Git or CI artifacts.
11. Lost credentials do not fall back to a common password.
12. Provisioning produces an auditable device record.

Create a development CA and device certificate using OpenSSL:

sh
# Editorial addition: development CA only; not a production provisioning workflow.
cat > device.ext <<'EOF'
basicConstraints=critical,CA:FALSE
keyUsage=critical,digitalSignature
extendedKeyUsage=clientAuth
subjectAltName=URI:urn:traffic-controller:device:TC-DEV-0001
EOF
openssl x509 -req -in TC-DEV-0001.csr -CA dev-ca.crt -CAkey dev-ca.key \
  -CAcreateserial -out TC-DEV-0001.crt -days 365 -sha256 -extfile device.ext
openssl verify -purpose sslclient -CAfile dev-ca.crt TC-DEV-0001.crt

OpenSSL x509: CSR signing and certificate extensions

text
openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -out dev-ca.key
openssl req -x509 -new -key dev-ca.key -sha256 -days 3650 \
  -subj "/CN=Embedded Development CA" -out dev-ca.crt
openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -out TC-DEV-0001.key
openssl req -new -key TC-DEV-0001.key -subj "/CN=TC-DEV-0001" -out TC-DEV-0001.csr

Add a SAN:

text
subjectAltName=URI:urn:traffic-controller:device:TC-DEV-0001
keyUsage=critical,digitalSignature
extendedKeyUsage=clientAuth

Check:

text
openssl verify -CAfile dev-ca.crt TC-DEV-0001.crt

Add a CLI identity info command that displays fingerprint, issuer, SAN, generation and backend, but not the private key.

6. What to read or try next

  • ESP-TLS client certificates, NVS Encryption and ATECC608A integration.
  • STSAFE-A110 / X-CUBE-STSE01.
  • Device provisioning audit records and CSR enrollment.
What should a CA receive during device enrollment according to the lesson?

Criteria: Keep the private-key boundary explicit.

Exercise

Describe safe A/B credential rotation when identity_a is ACTIVE and identity_b is PENDING. State when the new identity becomes active and what must not be deleted prematurely.

Self-check criteria: Separate writing, testing and activation; retain distinct generations/fingerprints and do not expose a private key in diagnostics.

Show the supplied answer

Write the new credentials to the inactive/PENDING slot, validate proof-of-possession and a TLS probe, then activate the new identity. Do not overwrite the current active credentials or remove the old certificate before the new identity is checked; preserve the planned grace/recovery path.