Safeguard
Supply Chain Security•

EST and SCEP Explained: Device Certificate Enrollment and Security

EST (RFC 7030) and SCEP (RFC 8894) let devices without DNS names get certificates. How each works, where CMP and ACME fit, and how to lock them down.

Safeguard Security Team
40 min read

EST and SCEP are the two protocols most devices use to get an X.509 certificate from a private certificate authority. SCEP (RFC 8894) wraps a PKCS #10 request in CMS envelopes over plain HTTP and authenticates it with a shared challenge password. EST (RFC 7030) sends the same kind of request over TLS and can use the device's existing certificate, a password or both. To secure either one, make every enrollment credential single use, restrict what each profile can issue, keep lifetimes short and keep an inventory of everything issued.

ACME gets most of the attention because public web certificates run on it, and our ACME protocol explainer covers it in depth. But a managed laptop that needs a Wi-Fi certificate, a router that needs an IPsec identity or a sensor on a factory floor has no public DNS name and no web server to answer a challenge. Those devices enroll with SCEP or EST, and increasingly with CMP. This post explains how each protocol works on the wire, what changed in the RFCs between 2013 and 2026, where the weak points are, and how to run a safe lab deployment with open source software.

Key takeaways

  • SCEP spent over twenty years as a draft before RFC 8894 (September 2020). It makes AES128-CBC and SHA-256 mandatory and forbids single DES and MD5, because the unauthenticated GetCACaps response allows downgrade.
  • EST (RFC 7030, October 2013) runs over HTTPS and can bind each request to its TLS session.
  • RFC 8951 (2020) and RFC 9908 (January 2026) clarified EST, the latter adding a server-supplied CSR template, and RFC 9148 (2022) carries EST over CoAP and DTLS.
  • CMP is the third option. RFC 9810 (July 2025) obsoletes RFC 4210 and RFC 9480, adds support for KEM public keys, and RFC 9483 profiles it for industrial and IoT use.
  • ACME is moving toward devices through the device attestation draft, now at revision 10, and Apple already documents an ACME payload that uses its device-attest-01 challenge.
  • Most real failures are operational: one challenge for the whole fleet, multi-year certificates, profiles that sign any requested name, and no inventory.

Why devices need something other than ACME

ACME, defined in RFC 8555 in March 2019, proves control of an identifier. For public web certificates that identifier is a DNS name, and the proof is an HTTP file, a DNS record or a TLS ALPN response that the CA can check from the internet. The challenge types post walks through them.

Device certificates break most of those assumptions:

  • No public name. A laptop's Wi-Fi certificate identifies a device or a user, not a host name. Its subject might be a serial number, a directory identifier or an email address.
  • No listening service. A phone or a battery-powered sensor does not run a web server the CA can reach, and it often sits behind NAT.
  • The question is different. The CA does not need to know whether you control a name. It needs to know whether this request comes from a device the organisation owns or manages, and which identity that device should get. That is an authorisation decision, usually made by a management system or a registration authority (RA), not a domain validation.
  • Constrained hardware. Some devices have tens of kilobytes of RAM, talk over lossy radio links and use CoAP rather than HTTP. They need small messages and DTLS.
  • Installed base. Network gear, VPN clients and mobile device management (MDM) platforms have shipped SCEP clients for two decades. Apple documents a SCEP payload for iOS, macOS, tvOS, visionOS and watchOS, and Microsoft Intune supports SCEP certificate profiles alongside PKCS and imported PKCS certificates.

So device enrollment turns on one question: how does the RA know this request is legitimate? SCEP answers with a shared secret, EST with TLS client authentication or a password inside TLS, CMP with signatures or a MAC, and the ACME device attestation draft with a hardware attestation statement.

A short history and timeline

DateDocumentWhat it did
September 2005RFC 4210Certificate Management Protocol (CMP) version 2, obsoleting RFC 2510
October 2013RFC 7030Enrollment over Secure Transport (EST), a profile of CMC over HTTPS
2015SCEP draft rebootPer RFC 8894's background notes, the long-stalled SCEP draft was restarted and cleaned up
January 2018RFC 8295EST extensions: extra path components for firmware, trust anchors and keys, plus a Package Availability List
March 2019RFC 8555ACME
June 2020NIST SP 1800-16NCCoE practice guide on TLS server certificate management
September 2020RFC 8894SCEP published as an Informational RFC
November 2020RFC 8951EST clarification: deprecates Content-Transfer-Encoding, fixes ASN.1
April 2022RFC 9148EST-coaps: EST over CoAP and DTLS
July 2022RFC 9266tls-exporter channel binding for TLS 1.3
November 2023RFC 9480, 9482, 9483CMP updates, CMP over CoAP, Lightweight CMP Profile
July 2025RFC 9810, 9811CMP (version 3 syntax) obsoletes RFC 4210 and RFC 9480; new HTTP transfer document
January 2026RFC 9908EST CSR attributes clarification and CSR template
August 2026ACME device attestation draft, revision 10device-attest-01 challenge and hardware identifiers for ACME

SCEP's history is unusual. RFC 8894's own background notes say the specification "spent over twenty years in the draft stage." It began as a network equipment vendor's protocol for provisioning IPsec routers, drifted into general device and IoT use, and accumulated conflicting appendices. Its original sponsors more or less abandoned it, and it was rebooted in 2015 because so much of the industry depended on it. The authors note that before the update, the lowest common denominator for interoperability was single DES and MD5.

How SCEP works

RFC 8894 lists five general operations: CA public key distribution, certificate enrolment and issue, certificate renewal, certificate query and CRL query. It builds them out of two older standards, CMS (formerly PKCS #7) for signing and encrypting, and PKCS #10 for the certificate request itself.

The transport

SCEP runs over HTTP, not HTTPS. Every message goes to one path with an operation query parameter. The RFC says clients should use the fixed path /cgi-bin/pkiclient.exe unless told otherwise, a relic of the protocol's early server software:

GET  /cgi-bin/pkiclient.exe?operation=GetCACaps   HTTP/1.1
GET  /cgi-bin/pkiclient.exe?operation=GetCACert   HTTP/1.1
POST /cgi-bin/pkiclient.exe?operation=PKIOperation HTTP/1.1

Early drafts sent everything with GET, base64 encoded into the URL. RFC 8894 makes POST mandatory to implement and keeps GET only "for historical reasons." Confidentiality and integrity come from the CMS layer, not from TLS.

Step 1: GetCACaps and GetCACert

The client first asks the server what it supports. GetCACaps returns a plain text list of keywords such as AES, SHA-256, POSTPKIOperation, Renewal, GetNextCACert and SCEPStandard. The SCEPStandard keyword is new in RFC 8894 and implies AES, POSTPKIOperation and SHA-256.

Then the client fetches the CA certificate (or the CA and RA certificates) with GetCACert. The response is not authenticated by anything the client already trusts, so the RFC requires the client to check it out of band. The usual method is a fingerprint: a SHA-256 hash over the whole CA certificate, configured on the device in advance. Apple's SCEP payload has a CAFingerprint key for exactly this purpose.

Step 2: build the request

The client generates a key pair and a PKCS #10 certificate signing request. If it has no certificate yet, it creates a temporary self-signed certificate with the same subject and key, and uses it to sign the SCEP message. That is a PKCSReq. If it already holds a certificate from this CA and the CA supports renewal, it signs with the existing certificate instead. That is a RenewalReq.

The authorisation secret goes inside the PKCS #10 request as the PKCS #9 challengePassword attribute. The RFC recommends including it, and recommends that it be a one-time value.

Step 3: wrap it twice

The request is placed in a CMS EnvelopedData structure encrypted to the CA (or RA) certificate, so the challenge password and the request are not readable in transit. That envelope is then placed inside a CMS SignedData structure signed with the client's self-signed or existing certificate. The signed attributes carry the SCEP fields:

AttributePurpose
transactionIDUnique ID for the transaction, used to match polls and responses
messageType19 PKCSReq, 17 RenewalReq, 20 CertPoll, 21 GetCert, 22 GetCRL, 3 CertRep
pkiStatusIn a response: success, failure or 3 for PENDING
failInfo and failInfoTextWhy a request failed; failInfoText is new in RFC 8894
senderNonce and recipientNonce16 byte random values to tie a response to its request

Step 4: CertRep, or PENDING and polling

The CA answers with a CertRep. If it issues immediately, the response carries the certificate in an envelope encrypted to the client. If the request needs manual approval, the status is PENDING and the client repeats a CertPoll message (called GetCertInitial in older drafts) until the CA issues or rejects. Apple's payload exposes Retries and RetryDelay keys to control that polling.

Manual approval is the RFC's fallback when a request has neither a challenge password nor a trusted certificate. Most deployments rely on the challenge password instead.

What RFC 8894 actually standardised

RFC 8894 kept the wire format and consolidated fifteen years of appendices. The changes that matter for security are:

  1. Mandatory to implement: GetCACaps, GetCACert, PKCSReq with its responses, HTTP POST, AES128-CBC and SHA-256.
  2. Allowed for compatibility: HTTP GET, triple DES and SHA-1.
  3. Forbidden: single DES and MD5. The RFC explains that as of 2017 a DES key could be recovered with rainbow tables in under a minute because SCEP messages contain large amounts of predictable plaintext, and that MD5 chosen prefix collisions cost very little compute.
  4. Two optional additions: the SCEPStandard capability and the failInfoText attribute. Older implementations simply ignore both.

It is Informational, not Standards Track, reflecting its history as a documented industry protocol.

How EST works

RFC 7030 defines EST as a Standards Track profile of Certificate Management over CMS (CMC) messages over a secure transport, in practice HTTPS. Where SCEP builds security out of CMS envelopes, EST relies on TLS.

URIs and operations

All EST operations live under a well-known prefix, /.well-known/est, optionally followed by an arbitrary label so one server can host several CAs or profiles:

https://ca.example.internal/.well-known/est/cacerts
https://ca.example.internal/.well-known/est/wifi-devices/simpleenroll
OperationPathStatus in RFC 7030What it does
Distribution of CA certificates/cacertsMUSTReturns the current CA certificates as a certs-only CMS message
Enrollment/simpleenrollMUSTClient POSTs a PKCS #10 request, server returns the certificate
Re-enrollment/simplereenrollMUSTRenew or rekey, authenticated with the current certificate
Full CMC/fullcmcOPTIONALFull CMC requests and responses for advanced cases
Server-side key generation/serverkeygenOPTIONALServer generates the private key and returns it with the certificate
CSR attributes/csrattrsOPTIONALServer tells the client what to put in the CSR

RFC 8295 (January 2018) added paths for firmware, trust anchors and keys, plus a Package Availability List. Check server support before relying on them.

Trust anchors and bootstrapping

RFC 7030 separates two trust anchor databases on the client. The Explicit TA database holds the CA certificates you configured for this PKI. The Implicit TA database is something like the operating system's public web roots. An Implicit TA lets the client confirm the server holds a certificate for the URL, but not that it is authorised to act as an RA for your PKI. The RFC requires that clients can disable the Implicit TA database, and recommends that clients using it rely only on TLS client certificates and channel binding so their passwords are not exposed to the wrong server.

When a device has no trust anchors at all, the RFC allows a bootstrap distribution of CA certificates. The client may complete an unauthenticated TLS handshake only to fetch /cacerts, and must then have a human approve the result using out-of-band data such as a SHA-256 fingerprint. It must not answer HTTP authentication requests on that unauthenticated connection, and must open a new, properly authenticated TLS session before doing anything else.

Client authentication

EST gives the server several ways to decide whether to issue:

  • TLS client certificate. The device presents an existing certificate. That could be a manufacturer installed device certificate (often called an IDevID), a certificate from another PKI, or the certificate it is renewing.
  • HTTP Basic or Digest authentication. RFC 7030 allows these only inside TLS. Its security considerations warn that Basic hands the server a cleartext password and recommend that clients use such credentials only once, to obtain a certificate they will use from then on.
  • Certificate-less TLS. Cipher suites built on a shared secret are allowed, but the RFC requires that they resist offline guessing and that the secret is never shared beyond the client and server.

Deciding what an authenticated client may receive is left to local policy, which is where profiles and subject rules come in.

Linking identity and proof of possession

A signed PKCS #10 request already proves the client holds the private key. EST adds an optional link between that proof and the TLS session. The client takes the tls-unique channel binding value from its TLS stack, base64 encodes it and puts it in the request's challengePassword attribute before signing. The server checks that the value matches its own view of the session.

This stops an attacker relaying a request through a different authenticated session. Clients SHOULD do it, servers MUST verify it when present and MAY refuse requests without it.

One gap is worth knowing. tls-unique is defined for TLS 1.2 and earlier. RFC 9266 (July 2022) says it "is not defined for TLS 1.3" and defines a replacement binding called tls-exporter. If your EST server and clients negotiate TLS 1.3, test whether your implementations support channel binding at all before you make it a policy requirement.

Server-side key generation, carefully

/serverkeygen exists for devices that cannot generate good keys themselves. RFC 7030 is blunt about the cost: the private key travels to the client protected only by TLS unless the optional CMS encryption is used. It recommends that servers not offer the operation by default, that clients not request it without a compelling reason, that the Implicit TA database not be used with it, and that the encrypted CMS response be used. If you enable it, you have created a copy of every device key on the server side, which then needs the same protection as the CA.

RFC 8951 and RFC 9908: making EST interoperable

RFC 7030 told servers to send base64 bodies with a MIME style Content-Transfer-Encoding header, which HTTP does not use. Implementations disagreed, and RFC 8951 (November 2020) resolved it: payloads are base64 (RFC 4648) of the DER encoding, and the header is deprecated. It also fixed ASN.1 errors in the original.

The CSR attributes response was also ambiguous about whether it listed attribute types or values. RFC 9908 (January 2026) clarifies the encoding and adds a template: the server sends a partly filled CSR, including a subject name, for the client to complete. That lets the CA, not the device, decide the identity.

EST over CoAP: RFC 9148

RFC 9148 (April 2022) maps EST onto CoAP over DTLS for constrained devices. Our CoAP explainer covers the transport itself. The EST-specific changes are:

  • Shorter paths. URIs are part of every packet, so EST-coaps uses short names under the same well-known prefix.
EST over HTTPSEST-coaps
/cacerts/crts
/simpleenroll/sen
/simplereenroll/sren
/serverkeygen/skg (PKCS #7) or /skc (single certificate)
/csrattrs/att
  • A fixed cipher suite. The mandatory DTLS cipher suite is TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 with curve secp256r1 (NIST P-256), following the IoT TLS profile in RFC 7925. DTLS 1.3 is also covered.
  • Client certificates required. EST-coaps client authentication MUST use a client certificate. There is no password option, which suits devices that ship with a manufacturer certificate.
  • Block-wise transfer. Certificates and CMS structures are larger than a single small packet, so EST-coaps uses CoAP block-wise transfer (RFC 7959).
  • Connection reuse. Unlike the original EST, a /crts request followed by /sen can share one authenticated DTLS session, saving a handshake on a device that is bootstrapping.
  • A registrar at the edge. An HTTPS to CoAPS registrar at the network boundary relays to an ordinary EST server. It is effectively an RA and needs the same hardening.

Where CMP fits

CMP predates both EST and the SCEP RFC. RFC 4210 (September 2005) defined CMP version 2 for the full certificate lifecycle: initial registration, certification requests, key update, revocation requests, cross certification, key recovery and confirmation messages. It authenticates messages with signatures or with a MAC based on a shared secret, and it can run over HTTP or other transports.

RFC 9480 (November 2023) updated CMP to use EnvelopedData, clarified PKCS #10 handling and improved crypto agility. In July 2025, RFC 9810 obsoleted both RFC 4210 and RFC 9480. It adds support for certificates containing a Key Encapsulation Mechanism (KEM) public key, which matters for post-quantum algorithms, and uses protocol version cmp2021(3). RFC 9811 replaced the HTTP transfer document. RFC 9482 defined CMP over CoAP, and RFC 9483, the Lightweight CMP Profile narrows CMP to what industrial and IoT scenarios need.

CMP is heavier than EST but has an explicit certificate confirmation message and a richer revocation flow. For an industrial or automotive PKI, read RFC 9483 before defaulting to EST.

ACME for devices: the attestation draft

The IETF ACME working group's device attestation draft (revision 10, last revised 9 August 2026) adapts ACME for devices. The draft adds permanent-identifier and hardware-module identifier types, a device-attest-01 challenge whose response contains a WebAuthn attestation statement, and the use of ACME external account binding to pre-authenticate requests to an enterprise CA. It is still an Internet-Draft, not an RFC.

Apple already documents an ACME certificate payload (com.apple.security.acme) built on this approach. According to Apple's documentation, the device generates a key pair, requests an order using a ClientIdentifier as the permanent identifier, receives a device-attest-01 challenge, and if Attest is true answers with an attestation of the key and device properties. With HardwareBound set, the Secure Enclave generates the key and the system cannot export it; hardware bound keys must be P-256 or P-384. Apple lists attestation support for iPhone and iPad from A11 Bionic, Apple silicon Macs on macOS 14 and later, Apple TV from A12, Apple Watch from S4 and Vision Pro. Apple also notes that the ClientIdentifier alone is "a relatively weak indication" because it can be intercepted.

That is the argument for attestation: a secret proves the device saw it, while an attestation gives the CA evidence that the key lives in specific hardware.

Comparison: SCEP, EST, CMP and ACME

SCEP (RFC 8894)EST (RFC 7030 and updates)CMP (RFC 9810, 9483)ACME (RFC 8555, device draft)
StatusInformational RFC, 2020Standards Track, 2013, clarified 2020 and 2026Standards Track, 2005, rewritten 2025Standards Track, 2019; device attestation is a draft
TransportHTTP; security from CMS envelopesHTTPS; CoAP and DTLS via RFC 9148HTTP, CoAP, othersHTTPS with JWS signed requests
Initial authenticationChallenge password in the CSR, or manual approvalTLS client certificate, HTTP Basic or Digest in TLS, or certificate-less TLSSignature with an existing key, or MAC with a shared secretAccount key plus a challenge; external account binding; device attestation in the draft
Server authenticationCA fingerprint checked out of bandTLS with explicit trust anchors; fingerprint for bootstrapSigned responsesTLS to the directory URL
Proof of possessionSigned CSR on first enrollment; not on renewalSigned CSR, optionally bound to the TLS sessionSignature or other POP methodsCSR signature at finalization
RenewalRenewalReq signed with the current certificate/simplereenroll with the current certificateKey update requestNew order, often with ACME Renewal Information
Server key generationNoOptional /serverkeygenSupportedNo
Issue confirmationNoneNoneYes, certificate confirmationOrder status
Typical useMDM profiles, network gear, legacy VPN clientsNetwork gear, IoT, newer MDM and industrialIndustrial, telecom, automotive PKIWeb servers; devices through attestation

The weaknesses, at concept level

None of these protocols is broken when deployed as their RFCs recommend. The problems come from how they are commonly deployed.

Shared and static challenge passwords

In SCEP, the challenge password is the only thing standing between "anyone who can reach the URL" and "a certificate from your CA." RFC 8894 says it should not be a conventional password but a high-entropy value, ideally single use, with a limited lifetime, and stored on the CA as a salted iterated hash or a keyed MAC. It points out a useful side effect: if a single use value arrives twice, that is evidence of a breach.

Many deployments bake one static challenge into an MDM profile, image or router template. Anyone who extracts it can enroll as many devices as they like.

Intune's documentation shows the alternative. When it delivers a SCEP profile, Intune generates an encrypted and signed challenge blob per device that the device cannot read. A policy module on the SCEP server compares the device's CSR to the blob, including the expected subject and subject alternative name, and only issues to requests that match. A direct request to the published SCEP URL gets a 403.

No proof of who the device is

A challenge password proves the requester knows a secret, not which device is asking or that the key is in protected hardware. EST with a manufacturer certificate, CMP with an existing key, or ACME with attestation give stronger evidence.

Weak legacy cryptography and downgrade

SCEP's GetCACaps response is unauthenticated. RFC 8894 explains that if a server still supports single DES and MD5, an on-path attacker can strip the stronger keywords from the response and roll the exchange down. It suggests that a client which expects SCEPStandard and does not see it should treat that as a security issue. Client tools may also fall back on their own: the documentation of sscep, a long-standing open source SCEP client, says its default signature and encryption algorithms are "the best from getcacaps, or md5." Pin algorithms explicitly.

RFC 8894 lists other structural issues: the CA private key is used to sign and possibly decrypt transport messages, not just certificates; there is no issue confirmation; and renewal requests do not prove possession of the new key, because they are signed with the old one.

Unrestricted subject names and extensions

The most damaging misconfiguration is a profile that copies whatever subject and subject alternative names the CSR contains. A device enrolled for Wi-Fi could ask for a name that a VPN gateway or an internal web service trusts, or for a user principal name that maps to an administrator. The fix is to have the RA or CA decide the identity from its own records (or from the RFC 9908 template it hands the device), restrict which name types each profile accepts, and fix the extended key usage. Our post on name constraints for private CAs covers the CA-side limit that backs this up.

Intune's documentation gives a concrete example of why mapping matters: for certificate authentication against Active Directory, the KDC requires strong mapping, with a security identifier extension in the subject alternative name that matches the user or device.

The RA and the server key store

An RA that can approve requests is as sensitive as the CA for the profiles it serves. So is any server that keeps generated private keys. Intune's guidance not to host the SCEP service on the issuing CA server, because that is a risk when the CA serves internet requests, applies to any design: put the internet-facing enrollment front end on a separate host from the CA key.

Step by step: a lab EST and SCEP deployment with open source tools

This walkthrough uses OpenXPKI, an open source CA released under the Apache License whose project page lists SCEP, EST, SimpleCMC and ACME enrollment interfaces, with OpenSSL and curl as the EST client and sscep as the SCEP client. Dogtag PKI, another open source CA, also supports SCEP. Use a disposable lab machine. The OpenXPKI Docker repository states its images are for demonstration and testing and "should not be used in a production environment."

Step 1: start a lab CA

From the OpenXPKI Docker repository's README, clone the community configuration into the compose directory, prepare the CLI key and crypto secrets as the README describes, then start the stack and generate a demo two-tier hierarchy:

git clone https://github.com/openxpki/openxpki-config.git \
  --single-branch --branch=community
# follow the README to create config/client.key and set secrets in
# openxpki-config/config.d/system/crypto.yaml before starting
docker compose up -d web
docker compose exec -u pkiadm server /bin/bash /etc/openxpki/contrib/sampleconfig.sh

The web UI comes up at https://localhost:8443/webui/index/. The project's sample Apache configuration exposes SCEP on port 80 and the RPC and EST APIs on port 443 over HTTPS. The README warns that if you do not supply real TLS certificates, dummy ones are generated and TLS client authentication, and therefore EST re-enrollment, will not work. Put a real server certificate from your lab CA in place before Step 5. For a production layout with an offline root, see our private CA explainer.

Step 2: fetch and verify the CA certificates over EST

The first /cacerts call is the bootstrap case from RFC 7030 section 4.1.1, so you must verify the result out of band before trusting it. Replace the host and label with the ones your configuration exposes.

EST=https://localhost:8443/.well-known/est
# Bootstrap only: -k because no trust anchor exists yet
curl -sk "$EST/cacerts" -o cacerts.b64
base64 -d cacerts.b64 > cacerts.p7b
openssl pkcs7 -inform DER -in cacerts.p7b -print_certs -out cacerts.pem
openssl x509 -in cacerts.pem -noout -subject -fingerprint -sha256

Compare the SHA-256 fingerprint with the one shown on the CA itself (from the web UI or openssl x509 -fingerprint -sha256 on the CA host). Only then keep cacerts.pem and drop -k from every later command.

Step 3: create a device key and CSR

Generate the key on the device. P-256 keeps the request small and matches the EST-coaps mandatory curve.

openssl req -new -newkey ec -pkeyopt ec_paramgen_curve:P-256 -noenc \
  -keyout device.key -out device.csr \
  -subj "/CN=lab-sensor-0042" \
  -addext "subjectAltName=DNS:lab-sensor-0042.devices.example.internal"
openssl req -in device.csr -noout -text | grep -A1 "Subject Alternative"

-noenc is the OpenSSL 3 spelling of the older -nodes. On a real device the key would live in a TPM or secure element instead of a file.

Step 4: enroll with /simpleenroll

EST expects the CSR as base64 of the DER encoding (RFC 8951), with content type application/pkcs10. This example uses HTTP Basic inside TLS with a one-time enrollment secret, which is how RFC 7030 suggests passwords be used:

openssl req -in device.csr -outform DER | base64 > device.csr.b64
curl -s --cacert cacerts.pem \
  --user "lab-sensor-0042:ONE-TIME-SECRET" \
  -H "Content-Type: application/pkcs10" \
  --data-binary @device.csr.b64 \
  "$EST/simpleenroll" -o device.p7.b64
base64 -d device.p7.b64 > device.p7b
openssl pkcs7 -inform DER -in device.p7b -print_certs -out device.pem
openssl x509 -in device.pem -noout -subject -issuer -enddate -ext subjectAltName,extendedKeyUsage

Check that the subject alternative name is the one the CA should assign, the extended key usage is only client authentication, and the end date matches your short lifetime. If the CA accepted an extra name you added to the CSR, the profile is too permissive. The OpenSSL certificate reading guide explains each field.

Step 5: renew with /simplereenroll

Re-enrollment authenticates with the current certificate over TLS, so no password is needed:

curl -s --cacert cacerts.pem --cert device.pem --key device.key \
  -H "Content-Type: application/pkcs10" \
  --data-binary @device.csr.b64 \
  "$EST/simplereenroll" -o renewed.p7.b64

The same CSR renews the same key. Rekeying with a fresh key on each renewal limits how long a leaked key stays useful.

Step 6: ask the server what it wants

curl -s --cacert cacerts.pem "$EST/csrattrs" | base64 -d | openssl asn1parse -inform DER

An empty response is allowed. A populated one lists attributes or, under RFC 9908, a template with the expected subject.

Step 7: enroll a second device over SCEP

SCEP puts the challenge password inside the CSR, so it needs an OpenSSL config section. Treat the file as a secret and delete it after use.

# scep-req.cnf
[req]
prompt = no
distinguished_name = dn
attributes = req_attributes
[dn]
CN = lab-laptop-0107
[req_attributes]
challengePassword = ONE-TIME-CHALLENGE
SCEP_URL="http://localhost/scep/your-endpoint"   # from your server config
sscep getcaps -u "$SCEP_URL"
sscep getca -u "$SCEP_URL" -c ca.crt
openssl x509 -in ca.crt-0 -noout -fingerprint -sha256   # compare out of band
openssl req -new -newkey rsa:3072 -noenc -keyout laptop.key \
  -config scep-req.cnf -out laptop.csr
sscep enroll -u "$SCEP_URL" -c ca.crt-0 -k laptop.key -r laptop.csr \
  -l laptop.crt -E aes -S sha256
shred -u scep-req.cnf 2>/dev/null || rm -f scep-req.cnf

getca may write several files with -0, -1 suffixes when the server returns CA and RA certificates; pick the right one for -c. The -E aes -S sha256 flags pin the algorithms so the client does not fall back to its defaults if GetCACaps is missing or tampered with. Check the getcaps output for SCEPStandard or at least AES and SHA-256; if the server advertises DES without DES3, or MD5, fix the server.

Step 8: restrict profiles and subject names

CAs separate enrollment endpoints from certificate profiles; in OpenXPKI both live in YAML files in the configuration you cloned. Set these rules per endpoint:

  • One profile per purpose. A Wi-Fi endpoint issues only client authentication certificates for the Wi-Fi profile. It cannot issue server certificates or anything with CA:TRUE.
  • Server-chosen identity. The subject and subject alternative names come from your inventory or MDM record, or are checked against it, never accepted from the CSR as is.
  • Allowed name types and patterns. For example, DNS names only under devices.example.internal, or a UPN only for the device's own enrolled user.
  • Fixed key usage and extended key usage, with requested extensions ignored.
  • Minimum key sizes and allowed algorithms, matching what your clients and RADIUS or VPN servers support.
  • Authentication per endpoint. Single use secrets for initial SCEP enrollment; TLS client certificates for EST renewal; manual approval for anything unusual.

Step 9: short lifetimes and automatic renewal

Shorter lifetimes reduce how long a stolen key or a mistaken issue stays useful, and make revocation less critical. Intune allows a validity period of up to 24 months for SCEP certificates; nothing requires you to use it. For lab devices, try 30 to 90 days and renew at about two thirds of the lifetime. A minimal renewal check for a Linux device:

#!/bin/sh
# renew-if-due.sh: renew when fewer than 20 days remain
if ! openssl x509 -in /etc/device/device.pem -noout -checkend $((20*86400)); then
  openssl req -new -key /etc/device/device.key -subj "/CN=$(hostname)" -outform DER \
    | base64 > /tmp/renew.csr.b64
  curl -sf --cacert /etc/device/cacerts.pem \
    --cert /etc/device/device.pem --key /etc/device/device.key \
    -H "Content-Type: application/pkcs10" --data-binary @/tmp/renew.csr.b64 \
    "$EST/simplereenroll" | base64 -d \
    | openssl pkcs7 -inform DER -print_certs -out /etc/device/device.new.pem \
    && mv /etc/device/device.new.pem /etc/device/device.pem
fi

Run it from a systemd timer or cron daily. Make sure the device alerts somewhere when renewal fails; a quiet failure becomes an outage on the expiry date. Our certificate lifecycle post covers renewal monitoring in more depth.

Step 10: keep an inventory

Export the issued certificate list from the CA regularly (OpenXPKI exposes search in the UI and API) and record serial, subject, names, profile, requester, issue and expiry dates. From any PEM file you can extract the same fields:

openssl x509 -in device.pem -noout -serial -subject -enddate -ext subjectAltName

Reconcile the list against your device inventory or MDM. A certificate with no matching device is either a decommissioned device you forgot to revoke or something you did not issue on purpose. NIST's NCCoE practice guide SP 1800-16 treats an inventory of certificates and their owners as the foundation of certificate management, and that advice applies to device certificates as much as to TLS server certificates.

How enrollment fits with 802.1X Wi-Fi and VPN

Most device certificates exist to get onto a network. In 802.1X with EAP-TLS, the device presents its certificate to a RADIUS server through the access point or switch, and the RADIUS server decides whether to let it in. Our 802.1X and EAP explainer and the post on Wi-Fi certificates versus shared passwords cover the network side. The enrollment side needs to line up with it:

  1. Deploy the trust chain first. Intune requires a trusted certificate profile with the root or issuing CA before SCEP or PKCS profiles. Devices should also validate the RADIUS server's certificate by name and issuer.
  2. Give network certificates their own issuing CA or profile, and have the RADIUS server trust only that, so certificates issued for other purposes cannot get on the network.
  3. Make identity mapping deliberate. Decide whether the RADIUS policy keys on the subject, a SAN value, a device ID extension or a directory lookup, and make the enrollment profile write exactly that field.
  4. Match key usage. Issue client authentication EKU for device and user certificates, and check that the RADIUS or VPN server enforces it.
  5. For VPN, the same rules apply: trust only the VPN issuing CA and map identities explicitly.

How to revoke at scale

Revocation is where device PKIs most often fail quietly. Some practical rules:

  • Tie revocation to lifecycle events. When a device is retired, wiped, lost or removed from MDM, revoke its certificates by serial number from the inventory. Make that a step in your offboarding runbook.
  • Make sure relying parties check. A RADIUS server or VPN gateway that never fetches the CRL or queries OCSP ignores revocation entirely. Configure and test it. Our post on why a revocation is not effective until the cache agrees explains cache timing.
  • Plan for mass revocation. If a challenge password or an RA credential leaks, you need to find every certificate issued through that endpoint during the exposure window and revoke them. That requires an inventory that records the endpoint and authentication method for each issue.
  • Lean on short lifetimes for devices you cannot reach. If a device cannot check revocation status, a 30 day certificate limits the damage more than any CRL.
  • Rotate the CA without breaking the fleet. SCEP's GetNextCACert and EST's /cacerts both let you distribute the next CA certificate before the rollover. Push it well ahead of time.

Common mistakes

  • One static challenge for the whole fleet. It ends up in profiles, scripts and backups, and anyone who finds it can enroll. Use single use, short-lived values, or a dynamic challenge that binds to the expected subject, as Intune's challenge blob does.
  • Trusting the CSR's names. If the device chooses its own subject and SANs, a compromised or cloned device can ask for someone else's identity.
  • Long-lived certificates. Multi-year device certificates make every leaked key and every mistaken issue last for years, and make revocation the only defence.
  • No inventory of issued certificates. You cannot find what a leaked secret issued, spot orphans or predict expiries.
  • Allowing legacy SCEP algorithms. Leaving single DES or MD5 enabled on the server invites downgrade. Remove them and pin AES and SHA-256 on clients.
  • Skipping CA fingerprint checks. Without them, an on-path attacker can substitute their own CA during GetCACert or EST bootstrap.
  • Running the enrollment front end on the CA host. Put the internet-facing SCEP or EST service on a separate machine from the CA key.
  • Enabling server-side key generation by default. RFC 7030 recommends against it. If you need it, encrypt the key response and protect the server like the CA.
  • One issuing CA for everything. A RADIUS server that trusts a general internal CA will accept certificates that were never meant for network access.
  • Silent renewal failures. If renewal fails and nobody is told, the device drops off Wi-Fi or VPN on the expiry date.

FAQ

What is the difference between EST and SCEP?

SCEP sends CMS wrapped PKCS #10 requests over plain HTTP, authenticated by a challenge password. EST sends them over HTTPS, authenticated by a TLS client certificate or a password inside TLS, and can bind the request to the session. EST is Standards Track; SCEP is Informational.

Is SCEP still secure in 2026?

It can be, if run as RFC 8894 recommends: AES and SHA-256 only, single use challenges, CA fingerprint checks, strict profiles and short lifetimes. Its lack of issue confirmation and renewal proof of possession remain.

What does RFC 8894 change compared to older SCEP drafts?

The wire protocol is the same. RFC 8894 consolidates the appendices, makes AES128-CBC, SHA-256 and HTTP POST mandatory to implement, forbids single DES and MD5, and adds the optional SCEPStandard capability and failInfoText attribute.

Does EST work with TLS 1.3?

EST runs over any TLS version the client and server support; RFC 7030 required TLS 1.1 or later. The optional channel binding uses tls-unique, which RFC 9266 says is not defined for TLS 1.3 and replaces with tls-exporter. Check whether your EST implementations support binding under TLS 1.3.

What are /simpleenroll and /simplereenroll?

EST's enrollment and renewal operations. A device POSTs a base64 DER PKCS #10 request to the first, then to the second, authenticated by its current certificate, to renew.

What is EST over CoAP?

RFC 9148 defines EST-coaps, which runs EST over CoAP and DTLS for constrained devices. It uses short paths such as /crts and /sen, a mandatory ECDSA and AES-CCM cipher suite, block-wise transfer, and client certificate authentication only.

Should I use CMP instead of EST?

Consider CMP for explicit certificate confirmation, richer revocation or an industrial profile (RFC 9810, RFC 9483). EST is simpler and more widely implemented.

Can ACME issue certificates to devices?

Not with the standard DNS challenges. The ACME device attestation draft adds hardware identifier types and a device-attest-01 challenge using a WebAuthn attestation statement. It is still a draft, though Apple documents an ACME payload that uses it.

How do I stop SCEP issuing certificates for arbitrary names?

Do not let the profile copy names from the CSR. Derive or validate names against your MDM or inventory, restrict SAN types per endpoint and fix the extended key usage. A dynamic challenge that encodes the expected subject, as Intune's does, enforces this at the server.

How long should device certificates be valid?

As short as your renewal automation reliably handles. Intune allows up to 24 months for SCEP certificates, but shorter lifetimes limit leaked keys and reduce reliance on revocation.

Why software supply chain hygiene still matters here

Enrollment security is mostly PKI configuration, and the fix for a leaked challenge or a loose profile comes from your CA and MDM, not from a dependency update. But the software doing the enrolling is software you build and ship: the CA and RA containers, SCEP and EST client libraries, CoAP and DTLS stacks and the TLS libraries inside device firmware are all open source components that need tracking and patching like any other.

Safeguard does not issue certificates, manage devices or protect CA keys. Where it does help is inventory and patching of those components: safeguard scan --dir . on a firmware or agent repository, --image on the container image that runs your CA or registrar, or --sbom on an SBOM a device vendor gives you, then matching the components against vulnerability databases and showing which projects contain a given version.

Fix it without waiting for upstream

Whatever the vulnerability, most of the risk sits in two gaps. The first is the time between a fix being published and that fix actually running in your production builds. The second, and worse, is the time before any fix exists at all, while a maintainer works out a patch and a release schedule. Waiting through both gaps is a habit, not a requirement. Safeguard gives teams three ways to close them.

1. Autonomous remediation: pull requests, not tickets

When a fixed version exists, Safeguard's Griffin models open a tested, policy gated pull request that moves the affected dependency to the safe version. You can run it on one repository or in bulk across every project that carries the vulnerable version. Remediation categories include dependencies, licenses, security posture and findings, and each one is set separately. Reachability analysis ranks the vulnerable code paths your application actually calls first, so the first pull requests you merge are the ones that matter most. Autonomous remediation ships switched off, with every category set to Manual, so your team decides how much runs on its own and what still needs a human approval.

2. Gold Open Source: the safe version in seconds, free

gold.safeguard.sh is free and needs no login. Search any CVE or package to see affected and fixed versions, CVSS, EPSS, CISA KEV status and a recommended safe version, or use the "Am I affected?" checker. The same data is available through a free read API, README status badges and RSS threat feeds.

3. Gold Registry: start from components that are already fixed

Gold Registry provides hardened, drop in replacements for upstream packages and container images. Every Gold artifact is held continuously to zero exploitable critical or high CVEs and a completed license check, with signed build provenance (signed with Safeguard's key and verifiable with cosign, SLSA Build Level 3 as the design target) and a public evidence page you can hand to an auditor. An artifact loses its Gold badge if it regresses. Teams can point their own package directory at the registry so hardened equivalents resolve without changing how developers install anything.

When upstream has no fix yet, or will not ship one, Safeguard first works to get the fix accepted upstream. If the issue is severe or upstream will not move, Safeguard builds a fork, fixes the vulnerability there and publishes a hardened Gold build, so you are not stuck on a maintainer's release schedule. You can also request a hardened, compatibility tested build of a specific package. Ask which packages it covers before you plan around it.

Your situationWhat to use
A fixed version existsAutonomous remediation opens the upgrade pull request; Gold Open Source confirms the safe version
You need to know today whether you are affectedGold Open Source lookup and "Am I affected?" checker, free and without login
You want vulnerable versions to stop shippingSafeguard policies and gates in CI
Upstream has no fix yet, or will not ship oneA custom Gold request; fork and patch
You want to start clean on new projectsPull hardened components and images from Gold Registry

One honest limit: when the vulnerable code lives in a vendor appliance, a hosted service or an operating system runtime you do not build yourself, the fix still has to come from that vendor or distribution. The steps above apply to the open source dependencies and container images you build and ship, which is where most teams carry the largest and least tracked share of their exposure.

See how Safeguard would help

The first demo is a real Safeguard CLI session. It opens the interactive terminal, is asked to fix a lodash CVE in a repository, reads the finding and advisory, asks before any command that changes something, edits package.json, runs npm install and npm test with approval, prints a summary and pushes nothing. The same flow applies to the enrollment agent or RA service you maintain: find the vulnerable library, apply the upgrade and run the tests before anything ships.

Click through it at your own pace, or open it full screen.

The second demo sets up the local runner on your own machine, approves it with its device code and scans from the terminal. That suits device firmware and CA images that are built on internal machines and never leave the build network.

Click through it at your own pace, or open it full screen.

The third demo connects Claude to the Safeguard MCP server with OAuth and lets you choose which tools Claude can use. A PKI team working in Claude could ask which of its projects carry a particular TLS or CoAP library version, with tool permissions the team sets.

Click through it at your own pace, or open it full screen.

To try the CLI, download Safeguard and follow the CLI documentation.

Quick check

Why does RFC 8894 forbid single DES and MD5 even though stronger algorithms are available?

Because GetCACaps is not authenticated. If a server still accepts single DES and MD5, an on-path attacker can remove the stronger options from the GetCACaps response and push the client down to them, and both are practical to break.

An EST client has no trust anchors yet. What must happen before it trusts the /cacerts response?

A human (or pre-configured data) must verify the CA certificate out of band, for example by its SHA-256 fingerprint. The client must not send HTTP credentials on the unauthenticated connection, and must open a new authenticated TLS session afterwards.

Sources

Last reviewed: 25 October 2026. Check the IETF Datatracker for the current status of the ACME device attestation draft and any further EST or CMP updates.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.