E ESTRFC 7030

Standards-track · RFC 7030 · updated by RFC 8951

Enrollment overSecure Transport

EST is the IETF way for a device to ask a certificate authority for an identity certificate over ordinary HTTPS: one well-known URL, a PKCS#10 request, and a certificate back. No vendor agent, no PKCS#7 envelope gymnastics, no custom port.

6 endpoints PKCS#10 → PKCS#7 TLS 1.1+ (1.2/1.3 today) .well-known/est
3 of 6endpoints every server must implement
2layers that carry auth: TLS and HTTP
200 / 202“done” and “accepted, poll later”
0new crypto primitives invented

Orientation

What EST actually is — and where it sits

EST is a profile, not a product: it says how to move certificate management messages (CMC / PKCS#10) over HTTPS, and what the client is allowed to assume about the server. Architecturally the EST service plays the Registration Authority role, sitting between the client and the CA.

End entity

The client

A device, server, or agent that needs a certificate and holds the private key.

  • Generates the key pair (usually locally)
  • Signs the PKCS#10 request → proof-of-possession
  • Validates the EST server against a pinned trust anchor
RA / protocol front end

The EST server

Terminates HTTPS, authenticates the client, applies policy, and brokers the request.

  • Publishes /.well-known/est/…
  • Decides whether to forward, hold, or reject
  • May require HTTP auth on top of TLS auth
Issuer · out of scope

The CA (and its chain)

Signs the certificate. In practice an intermediate signer does the signing, chained to an offline root.

  • Holds CA keys and issuance policy
  • Intermediate signs leaves; root signs intermediates
  • Link could be CMP, an API, a database, a queue…

The signing chain, concretely

“The CA” is rarely a single machine. A typical deployment keeps the root offline and lets an intermediate — the intermediary signer — do the actual signing.

Root CAoffline · self-signed · trust anchor
Intermediate / issuing CAthe intermediary signer · HSM · path-length constrained
EST server TLS certserverAuth
Client certificatesclientAuth · issued via EST

Clients receive the intermediate, and any chain above it, from /cacerts; the root is the anchor they already pinned. Keep the root key offline, keep the intermediate revocable, and remember /simpleenroll returns only the leaf.

The detail people miss

RFC 7030 defines only the client↔EST-server leg. The server→CA protocol, revocation publishing, key archival, and identity proofing are left to the deployment. That is why two “EST servers” can behave very differently while both being compliant.

One protocol, four layers

Each layer has a narrow job. Most production bugs come from confusing them — for example, blaming the CSR when the real failure is TLS client authentication, or chasing a certificate problem that is actually an HTTP 401 challenge.

APPLICATION

PKCS#10 / CMS

The request and the certificate bag. Base64 text over HTTP. This is the only layer EST really “adds” semantics to.

HTTP

Routes & status

Path selects the operation, Content-Type selects the message type, status codes carry control flow.

TLS

Identity & secrecy

Server auth is mandatory; client auth is the recommended path. Also supplies the tls-unique channel binding.

POLICY

Who gets what

CA policy decides issuance. EST only proves who is asking and what key they hold.

“Birth certificate” and “bootstrap certificate”

Both terms are used constantly in device PKI, and neither appears in RFC 7030. They describe roles, not protocol messages — so always ask what the other person means. Here is the mapping that makes the enrollment flow make sense.

Informal · IEEE 802.1AR

Birth certificate

= IDevID · Initial Device Identifier

The device's first identity, installed at manufacturing. Issued by the manufacturer's CA, with the private key generated in the factory and usually locked into a secure element.

In EST: this is the “previously installed certificate issued by a third party” from §2.2.1, presented as the TLS client certificate on the very first /simpleenroll. The EST server must trust the manufacturer's CA.

Ambiguous · always clarify

Bootstrap certificate

no single standards meaning

Usually just another name for the birth certificate — but vendors also use it for:

  1. a throwaway self-signed certificate, generated on the device so it has a TLS identity before any CA is configured;
  2. the CA trust anchors downloaded from /cacerts — RFC 7030 calls that “Bootstrap Distribution of CA Certificates” (§4.1.1), and it is not a client certificate at all.
Informal · IEEE 802.1AR

Operational certificate

= LDevID · Locally Significant Device Identifier

What the device actually uses in production: 802.1X, mutual TLS, IPsec. Bound to a key generated on the device and issued by your CA, not the manufacturer's.

In EST: the result of /simpleenroll, later renewed or rekeyed with /simplereenroll. This is the certificate that expires on a schedule.

Why the distinction matters

Birth certificate = “who built me”. Operational certificate = “what this network lets me be”. The birth certificate is a long-lived skeleton key whose only job is to authorise enrollment, so scope it: which CA may it enroll with, which names may it request, and is every use logged? A stolen birth certificate lets an attacker mint operational identities until someone notices and revokes it.

It also normally cannot stand in for /simplereenroll, because that request must carry the same subject and SAN as the certificate being renewed. Keep it — plus a fallback auth path — for recovery when the operational certificate has expired.

What EST is good at

Small clients, no user in the loop, long-lived devices, and environments where you already have PKI. It is deliberately boring: HTTPS plus two standard object types.

What EST is not

Not a discovery protocol, not a CA API, not a revocation protocol, and not a substitute for identity proofing. A /simpleenroll that is open to the internet will happily issue certificates to anyone who asks.

Roles & authority

Who decides what — including the policy authority

EST is a conversation between two systems, but a certificate is a governance artifact. Before anything is signed, someone has to decide who may enrol, what they may ask for, and who is allowed to say no. Those are different jobs, held by different roles — and only some of them appear in the protocol.

Decides
Policy authority
Rules, profiles, naming, eligibility
Approves
RA · EST server
Proves identity, applies the rules
Signs
CA
Issues, publishes, revokes
Trusts
Relying party
Validates and enforces use
Role What it decides / owns Where you see it in EST
Policy authoritygovernance role, not a system The rules. Certificate profiles (key type, curve, validity, EKU), which identities may enrol, which names and SANs are legitimate, renewal windows, revocation triggers, and who accepts the residual risk. Owns the certificate policy and CPS. Nowhere directly. RFC 7030 never uses the term — it talks about “local CA policy” instead (§3.7). You meet the PA's decisions as /csrattrs hints, 4xx rejections, and the profile the CA will actually sign.
Registration authorityoften the EST server itself Individual requests. Proves that the requester is who it claims to be, decides whether this key may be bound to this identity, and approves, holds or denies. Can be fully automated, a human queue, or an RA client acting for others. Built in. RFC 7030 says the EST service performs “functions traditionally allocated to the Registration Authority role”. A human approver shows up as 202 + Retry-After; an RA client presents a certificate with the id-kp-cmcRA EKU and may use /fullcmc.
Certification authorityroot + intermediate signer Issuance mechanics. The root is an offline anchor; the intermediate (issuing) CA is the intermediary signer that actually signs leaf certificates. It assigns serial numbers and validity, enforces the profile, publishes CRL/OCSP, and manages rollover. Behind the curtain. The server↔CA protocol is explicitly out of scope. /cacerts publishes the CA chain and rollover certificates; everything else is an implementation detail.
End entitydevice, workload, or person Its own key. Generates and protects the private key, signs the CSR, renews before expiry, and reports compromise. It does not get to decide what it is allowed to be. The client. Authenticates with an existing certificate, HTTP credentials or TLS-SRP; its CSR signature is the proof-of-possession; renewing means /simplereenroll.
Relying partyevery service that trusts the CA Acceptance. Validates the chain to a trust anchor, checks revocation and name/policy constraints, and decides what the certificate is good for. After the fact. Not part of enrollment at all — but the reason enrollment exists. EST says nothing about revocation, so CRL/OCSP and trust-store hygiene are still yours.
PKI operationsplatform / on-call Keeping it running. Deploys and monitors the servers, works the approval queue, restores service, executes revocations, and rehearses renewal and CA rollover. The control plane. Operates the EST server and its CA connector, watches error rates and the 202 backlog, and owns the pager when enrollment breaks.
Auditorindependent of all of the above Evidence. Checks that what was issued matches policy and that approvals happened — not that the cryptography is correct. Logs. Needs a chain joining authenticated identity → request → decision → issued serial, retained long enough to answer “who got what, and who said yes”.
Where policy actually surfaces

There is no “policy” message in EST. Policy is expressed as configuration and enforced as rejection: advisory hints in /csrattrs, eligibility checked at /simpleenroll, a human in the loop via 202, and the CA profile as the final arbiter.

The only role marker on the wire is the id-kp-cmcRA EKU on a client certificate — everything else about authority is deployment convention.

The collapse to avoid

One team writing the profile, approving its own exceptions, and holding unattended CA keys is how “any valid certificate can request any name” becomes policy. Keep approval separate from profile authorship, and keep both away from unattended CA key custody (HSM, dual control, split knowledge).

Practical test: can the person who approves an enrollment also change what the CA will sign? If yes, the separation is decorative.

Interactive walkthrough

The enrollment exchange, step by step

Click any step — or use ← → while the diagram has focus — to see what is sent, why it exists, and which part of the spec governs it. Rows are ordered the way a well-behaved client behaves, including the two optional branches that confuse people: the 401 retry and the 202 hold.

1 / 14

The CA lane is dashed on purpose: RFC 7030 does not define what happens between the EST server and the CA. In practice it is an intermediate signer, not the root.

Reference

Six endpoints, three of them mandatory

Everything hangs off https://<host>/.well-known/est. The path suffix selects the function; the HTTP method and Content-Type identify the message. A server may insert an extra path segment to select between CAs (/.well-known/est/label1/cacerts), and must still serve the unlabelled form.

On the wire

What the bytes actually look like

EST bodies are DER, base64-encoded, with no PEM armour and — since RFC 8951 — no meaningful Content-Transfer-Encoding. These are illustrative exchanges; the request and response bodies are shortened.


    

Status codes you must handle

200
Success. Body is the expected media type. Anything else means the operation failed.
202
Accepted, not ready. Retry-After is mandatory. Re-send the same request after the interval; the server keeps the state.
204 / 404
Only for /csrattrs: no attributes to offer. Treat as “empty”.
400 / 403
Policy or malformed request. Often a plaintext, human-readable reason in the body.
401
HTTP auth challenge (WWW-Authenticate). Retry with credentials — but only over TLS.
501 / 404
Optional endpoint (/fullcmc, /serverkeygen) not implemented.

Format rules worth memorising

  • Bodies are base64 of DER, not PEM. No -----BEGIN lines.
  • Whitespace and line wrapping are not significant; clients MUST tolerate variation (RFC 8951 §3.1).
  • Content-Transfer-Encoding is deprecated. Do not require it, do not break when it is absent.
  • application/pkcs7-mime responses carry smime-type=certs-only.
  • The certificate response contains only the issued certificate — not the chain.
  • /cacerts is the opposite: root plus every intermediate needed to build a path, plus optional rollover certs.

Decode a real CSR-attributes response

This is the actual base64 body from RFC 7030 Appendix A.2, decoded in your browser. Click a node to see which bytes it occupies. The CA is asking for challengePassword (identity/POP linking), a P-256 key, SHA-256 signatures — plus two made-up attributes (2.999.x) that a client must ignore.

selected node raw bytes

The heart of it

The CSR: proof-of-possession, and proof-of-which session

A certificate request proves you hold the private key. EST adds an optional twist: you can bind that proof to the TLS session you are currently using, so the server knows the key was exercised inside the authenticated tunnel — not replayed from somewhere else.

How the binding works

The client pulls the tls-unique channel binding (RFC 5929) from its TLS stack, base64-encodes it, and puts it in the PKCS#9 challengePassword attribute of the CSR. Because that attribute is inside the signed request, it cannot be altered without breaking the signature.

Presence of the attribute is the signal. If it is there, the server must verify it against the live session. If it is absent, the client chose not to link.

One wrinkle: tls-unique is defined for TLS 1.2 and earlier. TLS 1.3 has no such value — RFC 9266 defines tls-exporter instead — so estates that insist on POP linking tend to pin TLS 1.2, or accept enrollment without the binding.

The trap

Any TLS-terminating middlebox — a load balancer, reverse proxy, or inspection appliance — breaks the binding, because the server sees a different session than the client signed. Same thing if the client tears down and rebuilds the connection between CSR generation and POST.

Fix: rebuild the CSR (not the key) on the same connection, or have the server accept POP without linking. Retries after a 202 are exactly where this bites.

The three challenge-password dialects

challengePassword is overloaded across PKI history. RFC 7894 added distinct attributes so a server can tell them apart — worth knowing when you see a CSR rejected for “wrong password” when no password was ever configured.

  • challengePassword 1.2.840.113549.1.9.7 — in EST, carries the base64 tls-unique value; classically also a shared enrollment secret.
  • id-aa-estIdentityLinking 1.2.840.113549.1.9.16.2.58 — explicit, unambiguous identity-linking value (RFC 7894).
  • id-aa-otpChallenge / id-aa-revocationChallenge …2.56 / …2.57 — one-time passwords and revocation passphrases, kept separate on purpose.

Context

EST next to SCEP, CMP, and ACME

All four get a certificate onto a device. They disagree about transport, encoding, authentication, and how much state the server keeps. None of them is universally better — the choice is usually dictated by what the device already speaks.

Property EST RFC 7030 SCEP legacy CMP / CMPv2 RFC 4210 ACME RFC 8555
Transport HTTPS only, GET/POST to fixed paths HTTP or HTTPS, GET with base64 in the query, plus POST Usually HTTPS; also TCP, or in-message transport HTTPS with JSON
Message format PKCS#10 + CMS/PKCS#7 certs-only, base64 CMS enveloped PKCS#7, base64 in URLs (size limits) CMS PKI messages, richer controls JSON + JWS, PEM output
Client auth TLS client cert (recommended), HTTP Basic/Digest, TLS-SRP Shared secret in challengePassword (weak) Certificate, shared secret, or MAC Account key + JWS; domain validation
Proof-of-possession CSR signature, optionally bound to TLS session CSR signature inside CMS CSR signature, or central key generation CSR signature
Server-generated keys yes /serverkeygen, optional yes yes, common in telco no
Async / approval 202 + Retry-After, replay same request Poll with CertPoll Polling, ir/ip, or push Authorization polling
Renewal /simplereenroll, subject/SAN must match RenewalReq Same message with new keys Re-order; new cert
Client complexity low — HTTPS + two encoders low, but many dialect quirks high — large ASN.1 surface medium — JSON/JWS stack
Typical home Network gear, IoT, utilities (IEC 62351), BRSKI, industrial Legacy MDM, Windows estates, older appliances Telco, large enterprise PKI, 3GPP Web servers, public TLS, ACME-capable appliances
Reach for EST when

The device is small and PKI-literate

You control the firmware, you can ship a trust anchor, and you want standards-based enrollment with no proprietary agent.

Reach for SCEP when

You are meeting devices where they are

An existing fleet only speaks SCEP. It is everywhere, but treat the shared secret as a weakness and plan a migration.

Reach for ACME when

The identity is a domain name

Automated web TLS with domain validation. ACME is not designed for device identity or private-key escrow.

Two descendants worth knowing

BRSKI (RFC 8995) bootstraps trust for brand-new devices using manufacturer-installed certificates and a voucher, then hands off to EST for the actual enrollment. EST-coaps (RFC 9148) carries the same payloads over CoAP/DTLS for constrained networks. Both reuse the endpoint model described on this page.

Production reality

When it doesn’t work

EST failures are rarely cryptographic. They are almost always trust, session, or policy mismatches — and the error message is usually a single status code with no explanation.

Symptom → cause → fix

TLS handshake fails on the very first enrollment

Cause: the client has no trust anchor for the CA that signed the EST server certificate, so validation fails before HTTP is even reached.

Fix: use bootstrap distribution — fetch /cacerts over a provisional connection and have a human confirm the CA fingerprint out-of-band (SHA-256 of the whole cert), then install it as an explicit trust anchor and reconnect.

Don’t: leave the client permanently in “trust anything” mode. RFC 7030 requires the ability to disable implicit anchors.

HTTP 401 on every request, forever

Cause: the server wants HTTP Basic/Digest and the client never answers the challenge, or the client certificate is not being sent (wrong keystore, missing intermediate, server not requesting it).

Fix: check WWW-Authenticate, configure credentials, and verify the client chain the server actually receives. The server may require both a client cert and a password.

400 with a plaintext body like “CSR attributes incomplete”

Cause: policy rejection. When there is no Content-Type, RFC 7030 says the body is human-readable text — read it, it is the only diagnostic you get.

Fix: call /csrattrs and honour it: required curve, hash, SAN, or extra attributes. A missing challengePassword is a common one when the CA requires POP linking.

202 Accepted that never becomes 200

Cause: the request is queued for manual approval, or waiting on an upstream CA. The server is holding state; the client just needs to keep asking.

Fix: wait at least Retry-After, then re-send the identical request. Do not regenerate the key on each attempt. If the TLS session was closed and you used tls-unique, rebuild the CSR but keep the key pair.

“POP verification failed” / tls-unique mismatch

Cause: the CSR was signed over a different TLS session than the one that delivered it. Load balancers, TLS inspection, connection reuse across hosts, and retry loops all cause this.

Fix: generate and submit the CSR on a single connection; terminate TLS on the EST server itself (or forward session info); disable renegotiation-style optimisations between those two points.

Certificate issued, but clients reject it

Cause: the issued cert is fine; the chain is incomplete. /simpleenroll returns only the leaf, and the client usually lacks the intermediate that signed it.

Fix: fetch and distribute the chain from /cacerts, and make sure your trust store has the root, not just an intermediate.

Works with curl, fails on the device

Cause: embedded clients often lack TLS client auth, a real clock, or the ability to hold more than one trust anchor.

Fix: check time sync first (a wrong clock breaks both validation and signatures), then fall back to HTTP auth or certificate-less TLS (SRP) if policy allows, and confirm the device can parse base64 bodies without PEM headers.

Renewal rejected because “subject does not match”

Cause: /simplereenroll requires the subject and SubjectAltName to be identical to the certificate being renewed. Any drift — a new hostname, a reordered RDN, a different SAN encoding — is a mismatch.

Fix: copy the identity from the existing certificate byte-for-byte, or use the CMC ChangeSubjectName attribute if a rename is genuinely intended.

Some clients choke on missing Content-Transfer-Encoding

Cause: RFC 7030 used MIME headers; RFC 8951 deprecated Content-Transfer-Encoding because real implementations omit or ignore it.

Fix: emit base64 bodies without relying on the header, and on the client side accept bodies with or without it. Whitespace handling should be equally lenient.

Hardening checklist

  • Pin the anchor. Explicit trust anchor, fingerprint verified out of band.
  • Kill implicit trust once enrollment succeeds.
  • Require client auth for enroll and re-enroll; keep /cacerts open only if you must.
  • Authorise, don’t authenticate. A valid certificate is not permission to enroll for any name.
  • Validate SANs against inventory before issuance.
  • Rate limit and log per-identity, not per-IP.
  • Keep /serverkeygen off unless there is a hard requirement; if on, require CMS encryption of the key.
  • Renew early. Leave room for retries and a 202 hold.
  • Publish revocation. EST says nothing about CRL/OCSP; you still need it.
  • Plan CA rollover. Serve the CMP old/new rollover certs from /cacerts.
  • Time sync on every client, with drift alarms.
  • TLS 1.2+ in practice; drop NULL and anonymous suites.
The one that gets exploited

An enrollment endpoint that authenticates but does not authorise. If any valid client certificate can request any subject name, one compromised device can mint identities for the whole fleet. Bind the requested identity to the authenticated one, every time.

Check yourself

Eight questions that separate “read the RFC” from “operated it”

Instant feedback, with the reasoning. No score is stored anywhere.

0 / 7 correct

Reference

Cheat sheet and further reading

The bits you end up looking up twice.

Wire-format cheat sheet

Base path
/.well-known/est
Enroll request
application/pkcs10, base64 DER
Enroll response
application/pkcs7-mime + smime-type=certs-only
Attributes
application/csrattrs, base64 DER CsrAttrs
Full CMC
application/pkcs7-mime + smime-type=CMC-request|CMC-response
Server keys
multipart/mixed: pkcs7-mime + application/pkcs8
POP binding
challengePassword = base64(tls-unique), ≤ 255 bytes
Pending
202 + Retry-After
Server EKU
URI check per RFC 6125 or id-kp-cmcRA
RA EKU
id-kp-cmcRA on a client cert means RA privileges

Glossary

CSR / PKCS#10
Signed request binding a public key to a subject.
certs-only
CMS structure carrying certificates and nothing else.
Trust anchor
CA cert you trust a priori. Explicit = configured; implicit = shipped.
Intermediate CA
The issuing signer between the root and the leaves; what /cacerts must hand out.
Path validation
Building and checking the chain: leaf → intermediate(s) → trusted root.
POP
Proof you hold the private key — here, the CSR signature.
tls-unique
Channel binding from the TLS handshake (RFC 5929).
RA
Registration Authority: approves and forwards requests.
Policy authority
Governance role that sets the rules the RA and CA enforce; not an EST message or system.
Relying party
Service that accepts the issued certificate and checks revocation.
Birth certificate
Informal: the manufacturer-installed device identity, i.e. IDevID (802.1AR).
Bootstrap certificate
Informal and ambiguous: the birth certificate, a throwaway self-signed cert, or the CA anchors from /cacerts.
IDevID / LDevID
Factory and operational device certificates in 802.1AR terms.
Rekey vs renew
New key vs same key, new validity.