> Markdown version of https://docs.laavat.io/solutions/trusted-device-identities/ from the LAAVAT PKI and Signing Platform documentation. All pages: https://docs.laavat.io/llms.txt

# Trusted device identities for CRA-ready devices

Cryptographic device identity is a key enabler for the EU Cyber Resilience
Act's Annex I essential requirements and its secure-by-design principles.
LAAVAT is the platform on which you operate your own PKI to issue two
identities per device: a **birth certificate** (IDevID) provisioned at
manufacturing, and an **operational certificate** (LDevID) issued after
deployment. The same platform issues enterprise TLS and OPC UA application
certificates from the same pattern.

## Why device identity matters

The CRA requires products with digital elements sold in the EU to incorporate
security by design across the product lifecycle. Cryptographic device identity
is one of the enablers those obligations rest on: it is what lets a product be
individually authenticated, which underpins both the "protection against
unauthorized access" property in Annex I Part I and the auditability expected
of vulnerability handling in Part II.

Two certificates cover most of the device lifecycle:

- **Birth certificate (IDevID)** — issued once at the factory, immutable, and
  the root of trust the operator relies on to accept the device into its
  network. Defined by IEEE 802.1AR.
- **Operational certificate (LDevID)** — issued in the field, carrying the
  operator's identity assignment for the device, used for all day-to-day
  communication. Also defined by IEEE 802.1AR.

Together, these let a device attest to its manufacturer of origin, its
deploying operator, and its authorised capabilities — the foundation of any
CRA-aligned security posture.

## The ecosystem

A device passes through two lifecycle phases, each with its counterpart
system. During manufacturing, a **manufacturing station** provisions the birth
certificate. In the field, **device management** takes over certificate
lifecycle events, beginning with the issuance of an operational certificate on
first connection. The manufacturer's and the operator's certificate authorities
are separate entities; both can run on the LAAVAT platform, with the same
operation and approval model.

```mermaid
graph LR
    subgraph factory["Factory"]
        D1["<b>Device (birth)</b><br/>generates its keypair on-chip"]
        MS["<b>Manufacturing station</b><br/>requests an IDevID per device"]
    end
    subgraph ops["Operational network"]
        D2["<b>Deployed device</b><br/>presents IDevID · uses LDevID"]
        DM["<b>Device management</b><br/>enrols an LDevID per device"]
    end
    subgraph laavat["LAAVAT platform"]
        MP["<b>Manufacturer PKI</b><br/>issues IDevID · REST"]
        OP["<b>Operator PKI</b><br/>issues LDevID · EST"]
    end
    D1 --- MS
    MS -->|"CSR"| MP
    MP -->|"IDevID"| MS
    D2 --- DM
    DM -->|"CSR"| OP
    OP -->|"LDevID"| DM
```

In this example, manufacturing calls LAAVAT over **REST** with a bearer token,
and device management calls LAAVAT over **EST** with HTTP Basic. Enterprise
TLS and OT/OPC UA PKIs sit alongside on the same platform.

> **Note: Auth on each interface is a choice, not a fixed characteristic**
> This example uses bearer tokens on REST and HTTP Basic on EST for
> simplicity. Both interfaces also support mTLS as the client
> authentication mechanism; **REST + mTLS** and **EST + mTLS** are equally
> available on the platform.

> **Abstract: Core property — the private key never leaves the device**
> The device generates its own keypair on-chip. Only the certificate
> signing request — the public key and identity claims — travels
> off-device. LAAVAT returns a signed certificate, the public artefact,
> which the manufacturing station or device management then installs. The
> private key stays where it was created. The CA keys, likewise, stay in
> the HSM — see [key custody](https://docs.laavat.io/security/#key-custody-and-export).

## IDevID: the manufacturer PKI

The IDevID is the device's immutable, factory-provisioned identity. It is
issued once from a PKI under manufacturer control and persists on the device
for its operational lifetime. Every device leaving the factory carries one; it
is the trust anchor from which the operator later derives its acceptance
decision when admitting the device to its network.

### Hierarchy

A two-layer hierarchy — a Root CA and an Issuing Sub CA — is the minimum viable
configuration. Production deployments may add intermediate CAs.

<div class="grid cards stages" markdown>

-   __Manufacturer Root CA__

    ---

    *ECDSA P-256 · self-signed*

    Created once. Signs the Issuing CA and is otherwise untouched.

    **Issues** — the IDevID Issuing CA, under two-person approval

-   __IDevID Issuing CA__

    ---

    *ECDSA P-256 · Sub CA*

    Issues leaves only (`pathLenConstraint = 0`).

    **Issues** — one IDevID per device, unattended, at manufacturing volume

-   __IDevID__

    ---

    *ECDSA P-256 · leaf*

    The device's birth certificate. Subject and SAN from the device's CSR;
    `O` and `C` templated by the profile.

    **Held by** — the device, for its lifetime

</div>

> **Note: Validity values in the profiles below are examples**
> Choose values appropriate to your policy. CRL settings are left empty in
> these example profiles; a production deployment should configure CRL
> expiry, issue interval and distribution points to support revocation.

#### Profile: Manufacturer Root CA

| Field | Value |
| --- | --- |
| Profile type | Root CA |
| Key algorithm | ECDSA P-256 (`secp256r1`) |
| Signature algorithm | ECDSA with SHA-256 (self-signed) |
| Validity | 30 years |
| Subject | `CN = Manufacturer Root CA; O = Manufacturer` |
| Basic Constraints | `CA:TRUE`, `pathLenConstraint = 1` (permits one sub-CA layer below) |
| Key Usage | keyCertSign, cRLSign |
| Approval | Manual (one-time at initial setup) |

#### Profile: IDevID Issuing CA (Sub CA)

| Field | Value |
| --- | --- |
| Profile type | Sub CA |
| Key algorithm | ECDSA P-256 (`secp256r1`) |
| Signature algorithm | ECDSA with SHA-256 |
| Validity | 25 years |
| Subject | `CN = IDevID Issuing CA; O = Manufacturer` |
| Basic Constraints | `CA:TRUE`, `pathLenConstraint = 0` (issues leaves only, no further sub-CAs) |
| Key Usage | keyCertSign, cRLSign |
| Approval | Manual (one-time at setup) |

#### Profile: IDevID leaf

| Field | Value |
| --- | --- |
| Standard | IEEE 802.1AR-2018 (baseline in-suite: ECDSA P-256 / SHA-256) |
| Key algorithm | ECDSA P-256 (`secp256r1`) |
| Signature algorithm | ECDSA with SHA-256 (uniform with the CA chain) |
| Validity | 20 years |
| Subject template | Fixed manufacturer DN (`O`, `C`); caller supplies `CN` and `serialNumber` via CSR |
| SAN | Caller-supplied via CSR; typically `hardwareModuleName` otherName (OID `1.3.6.1.5.5.7.8.4`) carrying `hwType` + `hwSerialNum`. The profile permits SAN types to pass through; it does not itself supply SAN values |
| Key Usage | digitalSignature, keyAgreement |
| Extended Key Usage | id-kp-clientAuth |
| Basic Constraints | `CA:FALSE` |
| Uniqueness | Unique DN + unique public key — the profile's `EnforceUniqueDN` and `EnforceUniquePublicKey` flags |
| Approval | Automated (manufacturing volume) |

The profile YAML fields behind these tables are documented in
[Certificate profiles](https://docs.laavat.io/usage/productguide/pki/); example profile files are
in [Certificate templates](https://docs.laavat.io/certtemplates/templates/).

### Creating the PKI in the console

The PKI is built in four stages in the console: design the profiles, create
the Root CA, create the Sub CA, and sign the Sub CA and mark it Active. The
dialogs are documented in [CA hierarchy](https://docs.laavat.io/gui/pki/ca-hierarchy/) and
[Profiles](https://docs.laavat.io/gui/pki/profiles/); this section covers what each stage does.

#### Stage 1: design the profiles

All three profiles — Root CA, Sub CA and End Entity — are created through the
same *Create Profile* dialog. Only the *Profile type* selector and the field
values differ per layer.

#### Stage 2: create the Manufacturer Root CA

With the profiles in place, instantiate the actual CAs. When the Root CA
creation request is approved, LAAVAT:

- generates the Root CA's keypair inside the HSM — the private key never
  leaves
- self-signs the Manufacturer Root CA certificate per the profile
- publishes the Root CA in the console
- activates the `IssueSubCA` operation on this Root, gated by its approval
  rule

#### Stage 3: create the IDevID Issuing CA

Same wizard as the Root CA, with one additional early step: picking the
parent, which is the Root CA just created.

The Sub CA request goes to the Root's `IssueSubCA` operation and stays Pending
until a member of the Root's approval group approves it. Issuing a Sub CA is
the one step in this hierarchy that always needs a second person; leaf
issuance later runs unattended.

#### Stage 4: sign the Sub CA and mark it Active

Once approved, LAAVAT signs the Sub CA certificate with the Root CA and returns
it as a PKCS#7 blob. The signed certificate is picked up from the certificate
list, converted to PEM and uploaded to the pending Sub CA.

The chain is complete. *CA Overview* now shows the IDevID Issuing CA nested
under the Manufacturer Root CA, both Active. Manufacturing stations can call
the Sub CA's *IssueCertificate* operation with a device-generated CSR; the
operation is automated for volume by its blanket-groups rule.

## Issuing IDevID certificates

With the hierarchy in place, the manufacturing station issues an IDevID for
each device by presenting the device-generated CSR to the Sub CA's
*IssueCertificate* operation. Three things govern this: the structure of the
CSR, the mechanics of submission, and the expected structure and validation
criteria of the issued certificate.

### The CSR

The device generates its own ECDSA P-256 keypair on-chip; the private key
never leaves the device. The CSR is a standard PKCS#10 structure carrying:

- **Subject DN** — the caller supplies `CN` and `serialNumber`. The profile
  templates `O=Manufacturer` and `C=FI` onto the issued certificate regardless
  of what the CSR contains.
- **Public key** — the ECDSA P-256 point the device just generated.
- **Subject Alternative Name** — `hardwareModuleName` otherName (OID
  `1.3.6.1.5.5.7.8.4`, defined in RFC 4108) carrying the device's hardware
  type OID (`hwType`) and hardware serial number (`hwSerialNum`).
- **Self-signature** — over all of the above, using the device's private key.
  This proves the device holds the private key corresponding to the CSR's
  public key.

A minimal CSR configuration for the IDevID leaf profile:

```ini
[req]
distinguished_name = dn
req_extensions     = ext
prompt             = no

[dn]
CN           = device-01
serialNumber = HW-0000000001

[ext]
subjectAltName = otherName:1.3.6.1.5.5.7.8.4;SEQ:hmod

[hmod]
field1 = OID:1.3.6.1.4.1.99999.1.7
# hwSerialNum as hex-encoded OCTET STRING
field2 = FORMAT:HEX,OCTETSTRING:48572d30303030303030303031
```

Generate the keypair and CSR:

```bash
openssl ecparam -name prime256v1 -genkey -noout -out device.key
openssl req -new -nodes -key device.key -config csr.cnf \
    -outform DER -out device.csr.der

# Inspect what the CSR contains:
openssl req -in device.csr.der -inform DER -noout -text
```

### Submission over REST

The manufacturing station authenticates to the LAAVAT API with a bearer token
— see [API authentication](https://docs.laavat.io/api/authentication/). Issuance is two calls:
**POST** the CSR to the Sub CA's *IssueCertificate* operation, then **GET**
the resulting request to read the issued certificate. Because the operation's
approval rule puts the manufacturing group in blanket groups, with no approval
group, the request completes immediately.

#### POST — submit the CSR

```bash
curl -sS -X POST "${API}/cas/${CA}/certificaterequests" \
    -H "Authorization: Bearer ${TOKEN}" \
    -H "Content-Type: application/json" \
    -d "{\"csr\":\"$(base64 -w0 device.csr.der)\",\"operationId\":\"${OP}\"}"
```

Returns **HTTP 202 Accepted** — the request is queued, not yet complete. The
response body contains the request `id` (a UUID) and the initial `state`.
Capture the `id` for the next call.

**State values**: `1` Created, `2` ApprovalRequired, `4` Approved (about to
issue), `8` InProcess, `16` Ready, `32` Rejected, `64` Failed. Terminal states
are `16`, `32` and `64`. For a blanket-group operation like this one, the state
usually goes `4 → 8 → 16` within a second or two.

#### GET — read the issued certificate

```bash
curl -sS -X GET "${API}/certificaterequests/${REQ_ID}" \
    -H "Authorization: Bearer ${TOKEN}"
```

Poll this endpoint — or call it once for automated leaf issuance, which is
already Ready by return time. Response fields when `state = 16`:

- `certificate` — the issued leaf, base64-encoded
- `chain` — array of base64-encoded certificates from the Issuing Sub CA up to
  the Root

Decode and save:

```bash
jq -r '.certificate' response.json | base64 -d > device.crt
jq -r '.chain[]' response.json | base64 -d > chain.pem
```

The same flow through `signing-tool` — `production add` and `production get`
— is shown in the [device certificate example](https://docs.laavat.io/exampleflows/devicecertificate/).

#### Inspect the issued certificate

Two commands cover everything worth reading:

```bash
# Full text dump of the leaf
openssl x509 -in device.crt -noout -text

# Verify the leaf against the returned chain
openssl verify -CAfile chain.pem device.crt
```

The full-text output covers issuer, subject, validity, public key, key usage,
extended key usage, basic constraints, and both key identifiers. The one
exception is the `hardwareModuleName` otherName. OpenSSL renders it as
`othername: 1.3.6.1.5.5.7.8.4::<unsupported>` because the otherName inner
structure is application-specific. Decode it separately with
`asn1parse -strparse`:

```bash
OFF=$(openssl asn1parse -in device.crt \
    | awk '/X509v3 Subject Alternative Name/{getline; print}' \
    | cut -d: -f1 | tr -d ' ')
openssl asn1parse -in device.crt -strparse $OFF
```

You should see the `hwType` OID and `hwSerialNum` `OCTET STRING` byte-for-byte
matching what was in the CSR.

### Validation: what makes a correct IDevID

Cross-check the inspected certificate against these properties. All are
verifiable from the two `openssl` commands above; no special tooling required.

| Property | Expected value |
| --- | --- |
| **Chain trust** | Verifies against the Manufacturer Root CA (returned chain has Issuing Sub CA + Root) |
| **Subject: templated fields** | `O=Manufacturer, C=FI` (regardless of what the CSR requested) |
| **Subject: pass-through fields** | `CN` and `serialNumber` match the values sent in the CSR |
| **SAN** | `hardwareModuleName` otherName present, with `hwType` and `hwSerialNum` byte-for-byte matching the CSR |
| **Key algorithm** | ECDSA on `prime256v1` (P-256) |
| **Signature algorithm** | `ecdsa-with-SHA256` |
| **Basic Constraints** | `CA:FALSE` |
| **Key Usage** | `digitalSignature, keyAgreement` — only these two |
| **Extended Key Usage** | `id-kp-clientAuth` — only this, never serverAuth on an IDevID |
| **Validity** | Matches the profile setting. Bounds always: `notBefore` ≤ now, `notAfter` ≥ now, ≤ Issuing CA's `notAfter` |
| **Uniqueness** | Subject DN and public key are unique across the fleet (enforced by LAAVAT at issuance time) |
| **Key binding** | The public key in the certificate matches the device's private key (SHA-256 of the DER-encoded public key matches) |

## LDevID: the operator PKI

Following deployment, the device enrols for an LDevID issued by the operator's
PKI. The LDevID conveys the operator-assigned identity for the device, which
may differ from the manufacturer-assigned identity carried in the IDevID, and
governs all subsequent communication within the operator's network. This is
the trust hand-off at the core of IEEE 802.1AR: manufacturer-anchored trust
yields to operator-anchored trust.

### Operator hierarchy

```mermaid
graph TD
    R["<b>Operator Root CA</b><br/>ECDSA P-256"]
    S["<b>LDevID Issuing CA</b><br/>ECDSA P-256"]
    L["<b>LDevID</b><br/>ECDSA P-256 · leaf"]
    R -->|issues| S
    S -->|issues| L
```

Only the End-Entity profile is shown; the Operator Root CA and LDevID Issuing
CA profiles follow the Manufacturer Root CA and IDevID Issuing CA profiles
above, with the operator's subject names.

#### Profile: LDevID leaf

| Field | Value |
| --- | --- |
| Standard | IEEE 802.1AR-2018 (LDevID) |
| Key algorithm | ECDSA P-256 |
| Validity | 1 to 2 years |
| Subject template | Operator-defined; may differ from the IDevID |
| SAN | DNS/IP as needed for the operator's network |
| Key Usage | digitalSignature, keyAgreement |
| Extended Key Usage | id-kp-clientAuth, id-kp-serverAuth (per role) |
| Basic Constraints | `CA:FALSE` |
| Uniqueness | Not enforced |
| Approval | Automated (fleet enrolment volume) |

PKI creation follows the same four stages as the manufacturer PKI above:
profiles first, then Root CA and Sub CA instantiation in the console.

### Issuance over EST

The device — or device management enrolling on its behalf — uses the standard
Enrollment over Secure Transport flow (RFC 7030) against the operator's LDevID
Issuing Sub CA. One-time platform setup: enable EST on the Sub CA. Per
enrolment: fetch the CA chain, submit a CSR, receive the LDevID.

The endpoint shape is `https://<est-host>/.well-known/est/<tenant>.<caId>/`:
the CA is addressed by a URL label following the RFC 7030 `<label>` convention
(§3.2.2). Client authentication uses HTTP Basic over TLS in this example; mTLS
is a supported alternative.

#### 1. Enable EST on the Sub CA (one-time)

Before any enrolment can happen, the Sub CA has to be added to the EST service
configuration. This is done in the console — *Admin → Est Service*, pick the
CA from the transfer list and send for approval, as described in
[EST service configuration](https://docs.laavat.io/gui/est/configuration/) — or with one REST
call:

```bash
curl -sS -X POST "${API}/estservice/groups" \
    -H "Authorization: Bearer ${TOKEN}" \
    -H "Content-Type: application/json" \
    -d '{
      "items": [
        { "ca":   "LDevID Issuing CA (EST-enabled)",
          "caID": "<sub-ca-uuid>" }
      ]
    }'
```

The request is approved in the console. Once approved, the CA's EST endpoint
is reachable and accepts enrolments. Only CAs with the Device CA use case are
eligible for EST; an approved request replaces the whole EST configuration,
so include every CA that should stay published.

#### 2. Fetch the CA chain — `cacerts`

RFC 7030 §4.1 requires the `cacerts` endpoint to accept anonymous requests.
This lets a device fetch the operator's trust anchor before it has credentials
of its own. Two equivalent calls:

```bash
# Anonymous (RFC 7030 §4.1)
curl -sS "https://${EST_HOST}/.well-known/est/${LABEL}/cacerts"

# Authenticated — libest example
estclient -g -v -s ${EST_HOST} -p 443 --path-seg ${LABEL} \
    -u ${EST_USER} -h ${EST_PASS} -o work/ --pem-output
```

#### 3. Generate keypair and CSR

Same pattern as the IDevID case: the device generates its own ECDSA P-256
keypair, and the private key never leaves the device. The CSR carries the
operator's identity assignment for this device.

```bash
openssl ecparam -name prime256v1 -genkey -noout -out device.key
openssl req -new -nodes -key device.key \
    -subj "/C=FI/O=Operator/CN=device-01.op.example.com" \
    -out device.csr.pem
```

#### 4. Enrol — `simpleenroll`

```bash
estclient -e -v -s ${EST_HOST} -p 443 --path-seg ${LABEL} \
    -u ${EST_USER} -h ${EST_PASS} \
    -y device.csr.pem -o work/ --pem-output

# Result: the issued LDevID lands at work/cert-0-0.pem
openssl x509 -in work/cert-0-0.pem -noout -subject -issuer -dates
```

#### 5. Renew — `simplereenroll`

When the LDevID nears expiry, the device presents its existing LDevID (client
certificate) and private key to prove possession, and requests a fresh
certificate from the same Sub CA:

```bash
estclient -r -v -s ${EST_HOST} -p 443 --path-seg ${LABEL} \
    -c cert-original.pem -k device.key \
    -u ${EST_USER} -h ${EST_PASS} \
    -o work/ --pem-output
```

> **Note: The EST client is illustrative**
> The examples above use Cisco's libest (`estclient`) as the EST client;
> any RFC 7030-compliant client works — openssl-scripted flows, curl-based
> clients, vendor tooling, or an embedded EST client in the device's own
> stack. The endpoints, request bodies and response formats are the
> standard-defined ones.

Once the LDevID is installed, the device holds two certificates: the
manufacturer-issued IDevID, proof of identity to any operator that trusts the
manufacturer root, and the operator-issued LDevID, used for all operational
communication within the operator's network.

## Other supported use cases

Beyond device identity, the same platform issues certificates for enterprise
TLS and for OPC UA applications on the plant floor. They are included because
a deployment rarely stops at device identity, and the hierarchy pattern and the
operation model are the same as for IDevID and LDevID; only the profile
differs. As above, only the End-Entity profiles are shown.

### Enterprise TLS

Certificates for internal services and users. The hierarchy follows the same
Root CA + Issuing Sub CA structure; the distinguishing element is at the leaf
layer, where the server and client profiles differ.

#### Profile: TLS server leaf

| Field | Value |
| --- | --- |
| Key algorithm | ECDSA P-256 |
| Validity | 90 days to 1 year |
| Subject | `CN` = primary DNS name |
| SAN | **Required.** DNS/IP entries (RFC 6125) |
| Key Usage | digitalSignature, keyEncipherment or keyAgreement |
| Extended Key Usage | id-kp-serverAuth |

#### Profile: TLS client leaf

| Field | Value |
| --- | --- |
| Key algorithm | ECDSA P-256 |
| Validity | 1 year |
| Subject | `CN` = user or service principal name |
| SAN | rfc822Name or URI |
| Key Usage | digitalSignature |
| Extended Key Usage | id-kp-clientAuth |

### OPC UA in OT networks

OPC UA is the dominant open protocol on plant floors for machine-to-machine
communication. Its security model requires each application — server or
client — to hold a certificate, and the protocol's certificate validator is
prescriptive about the certificate's contents. Certificates that fail its
checks are rejected at connect time with specific `BadCertificate*` error
codes; this makes OPC UA the one use case where correctness is enforced by the
protocol itself rather than by trust policy.

Three characteristics distinguish an OPC UA application certificate from a
generic TLS certificate:

- **Application URI in SAN (required).** The Subject Alternative Name must
  include a URI entry (for example `urn:manufacturer:LineController-01`) that
  matches the `ApplicationUri` declared in the application's
  `ApplicationDescription`. If the URI is missing or does not match, the
  client rejects with `BadCertificateUriInvalid`.
- **Both server and client EKU.** Applications typically act as both server
  and client in OPC UA, so the Extended Key Usage carries both
  `id-kp-serverAuth` and `id-kp-clientAuth`.
- **Full Key Usage bit set.** The Key Usage extension must include
  digitalSignature, contentCommitment, keyEncipherment and dataEncipherment.
  This is broader than a typical TLS certificate.

```mermaid
graph TD
    R["<b>OT Root CA</b><br/>ECDSA P-256"]
    S["<b>OPC UA Issuing CA</b><br/>ECDSA P-256"]
    L["<b>OPC UA application certificate</b><br/>ECDSA P-256 · leaf"]
    R -->|issues| S
    S -->|issues| L
```

#### Profile: OPC UA application leaf

| Field | Value |
| --- | --- |
| Standard | OPC UA Part 6 (Mappings) |
| Key algorithm | ECDSA P-256 |
| Validity | 1 to 5 years |
| Subject | `CN` = application name |
| SAN | **Application URI (required)** plus DNS/IP entries |
| Key Usage | digitalSignature, contentCommitment, keyEncipherment, dataEncipherment |
| Extended Key Usage | id-kp-serverAuth *and* id-kp-clientAuth |
| Basic Constraints | `CA:FALSE` |

For both use cases, PKI creation and issuance follow the same profile-driven,
operation-based pattern as the device identity example above.

## Related

- [CRA compliance](https://docs.laavat.io/cra-compliance/) — how device identity supports
  the Annex I requirements, and the
  [Annex I mapping](https://docs.laavat.io/cra-compliance/annex-i-mapping/)
- [Device certificate example](https://docs.laavat.io/exampleflows/devicecertificate/) — the
  same issuance flow through `signing-tool`, from product creation to a
  certificate
- [Advanced PKI example flow](https://docs.laavat.io/exampleflows/advancedpki/) — multi-level
  hierarchies and externally rooted Sub CAs
- [EST service configuration](https://docs.laavat.io/gui/est/configuration/) — publishing a CA
  through the EST endpoint
- [CA hierarchy](https://docs.laavat.io/gui/pki/ca-hierarchy/) and
  [Profiles](https://docs.laavat.io/gui/pki/profiles/) — the console dialogs behind the four
  stages
- [CRA-ready i.MX8M gateways](https://docs.laavat.io/solutions/cra-ready-imx8m/) — the companion design for
  the boot chain and update bundles
- [Encrypted RAUC updates](https://docs.laavat.io/solutions/encrypted-rauc-per-device-keys/) — a separate
  Sub CA issuing per-device encryption certificates, kept apart from IDevID
- [Exportable tokens example](https://docs.laavat.io/exampleflows/exportabletoken/) — one
  shared fleet key instead, and when that is and is not enough
- [Security and architecture](https://docs.laavat.io/security/) — where the CA keys live
  and who can reach them

## References

- [IEEE 802.1AR-2018](https://standards.ieee.org/ieee/802.1AR/6995/) — Secure
  Device Identity: the definition of IDevID and LDevID
- [RFC 5280](https://datatracker.ietf.org/doc/html/rfc5280) — X.509v3
  certificate profile
- [RFC 4108](https://datatracker.ietf.org/doc/html/rfc4108) — the
  `hardwareModuleName` otherName carried in the IDevID SAN
- [RFC 6125](https://datatracker.ietf.org/doc/html/rfc6125) — server identity
  verification in TLS
- [RFC 7030](https://datatracker.ietf.org/doc/html/rfc7030) — Enrollment over
  Secure Transport (EST)
- [OPC UA Part 6](https://reference.opcfoundation.org/Core/Part6/v104/docs/) —
  Mappings (security, transport, encoding), and the
  [OPC Foundation's OPC UA overview](https://opcfoundation.org/about/opc-technologies/opc-ua/)
