SCEP API Documentation¶
Simple Certificate Enrollment Protocol (SCEP) is a PKI enrollment protocol specified in RFC 8894. Trustpoint exposes SCEP endpoints for initial certificate enrollment and certificate renewal in industrial and other device environments.
Overview¶
Trustpoint’s SCEP server supports:
Discovery of server capabilities (
GetCACaps).Retrieval of the SCEP server certificate and CA chain (
GetCACert).Initial enrollment using
PKCSReq(messageType = 19) and a device-specificchallengePassword.Certificate-based renewal using
RenewalReq(messageType = 17).Transaction retry handling that returns the previously issued certificate for the same request.
RSA-based enrollment and supported elliptic-curve client keys, subject to the implementation’s cryptographic constraints.
Client compatibility: Some sscep versions send a certificate-authenticated
PKCSReq instead of RenewalReq when renewing with -K and -O. The current
handler routes a PKCSReq whose signer is not self-signed through renewal
authentication. That path checks the registered signer credential, its status,
domain, and requested identity. Test the intended client version against the
deployed Trustpoint release; message type alone does not establish authorization.
Base URL¶
SCEP endpoints are available under:
http://<trustpoint-host>/.well-known/scep/
SCEP uses CMS message protection, but HTTPS is recommended in production, particularly for discovery and integrity of server/CA certificate distribution. Confirm the applicable proxy and TLS configuration before deploying.
URL Structure¶
Domain endpoint¶
GET /.well-known/scep/<domain>/?operation=GetCACaps
GET /.well-known/scep/<domain>/?operation=GetCACert
POST /.well-known/scep/<domain>/?operation=PKIOperation
For POST, operation=PKIOperation is optional; omitting it defaults to PKIOperation in the current Django view.
Domain and certificate profile¶
POST /.well-known/scep/<domain>/<cert_profile>/?operation=PKIOperation
A certificate profile in the URL is required for initial enrollment. During certificate-authenticated renewal, Trustpoint resolves the profile associated with the previously issued credential. Discovery requests may use the domain URL without a profile.
Example:
http://127.0.0.1/.well-known/scep/arburg/bacnet_sc/
Path and query parameters¶
Parameter |
Location |
Description |
Example |
|---|---|---|---|
|
Path |
Trustpoint domain identifier; required |
|
|
Path |
Certificate profile allowed for the domain; required for initial enrollment |
|
|
Query |
SCEP operation, or implicit |
|
Supported Operations¶
Operation |
HTTP method |
Function |
Status |
|---|---|---|---|
|
GET |
Returns advertised capabilities as newline-separated text |
Supported |
|
GET |
Returns SCEP server certificate and certificate chain |
Supported |
|
POST |
Processes initial enrollment and renewal requests |
Supported |
|
GET |
Retrieves next CA certificates |
Not implemented ( |
|
GET |
Fetches an issued certificate by identifier |
Not implemented ( |
|
GET |
Retrieves a CRL |
Not implemented ( |
|
GET |
Polling operation |
Not implemented ( |
GET ...?operation=PKIOperation returns 405 Method Not Allowed; use POST.
Discovery¶
GetCACaps¶
curl -s 'http://127.0.0.1/.well-known/scep/arburg/?operation=GetCACaps'
The current server advertises:
AES
POSTPKIOperation
Renewal
SCEPStandard
SHA-256
Response content type: text/plain.
GetCACert¶
curl -s 'http://127.0.0.1/.well-known/scep/arburg/?operation=GetCACert' \
-o ca-certs.p7b
The current implementation returns a DER-encoded certificates-only CMS structure with content type application/x-x509-ca-ra-cert.
Extract the certificates:
openssl pkcs7 -inform DER -in ca-certs.p7b -print_certs -out ca-certs.pem
Security: Do not trust CA certificates solely because they were downloaded from the endpoint. Establish their authenticity using a trusted fingerprint or other out-of-band mechanism.
PKIOperation Request Format¶
HTTP method and headers¶
POST /.well-known/scep/arburg/tls_server/?operation=PKIOperation
Content-Type: application/x-pki-message
Body: binary DER-encoded CMS SignedData containing SCEP signed attributes and an encrypted PKCS#10 certificate request (pkcsPKIEnvelope). Do not send the CSR PEM directly to this endpoint.
The server rejects oversized requests (currently more than 128 KiB).
Supported SCEP message types¶
Message type |
Value |
Purpose |
|---|---|---|
|
|
Initial enrollment using a self-signed signer and a challenge |
|
|
Certificate-based renewal using an existing Trustpoint-issued certificate |
|
|
Server response to enrollment/renewal |
The server does not currently implement CertPoll, GetCert, or GetCRL through the PKIOperation handler.
Response Format¶
Successful or rejected PKIOperation¶
HTTP/1.1 200 OK
Content-Type: application/x-pki-message
A valid protocol-level request receives a CMS-encoded SCEP CertRep, with pkiStatus describing the outcome. HTTP 200 does not necessarily mean certificate issuance succeeded.
|
Meaning |
|---|---|
|
|
|
|
|
|
On success, Trustpoint returns the issued certificate inside the encrypted response. CA certificates can be obtained separately using GetCACert.
HTTP errors¶
HTTP status |
Example reason |
|---|---|
|
Unknown operation, malformed SCEP message, or invalid POST operation |
|
Domain unavailable or no usable SCEP serving credential |
|
|
|
Request exceeds the configured size limit |
|
Unexpected server failure |
|
Recognized but unsupported discovery operation |
Examples¶
Example 1: Prepare the CA certificates¶
curl -s 'http://127.0.0.1/.well-known/scep/arburg/?operation=GetCACert' \
-o ca-certs.p7b
openssl pkcs7 -inform DER -in ca-certs.p7b -print_certs \
-out ca-certs.pem
Example 2: Create a key and CSR for initial enrollment¶
Download the device-specific scep.cnf from the Trustpoint SCEP help page. It contains the device identity and the current challengePassword.
Example structure (placeholder only; do not use a real secret in documentation):
[req]
distinguished_name = dn
attributes = attrs
prompt = no
[dn]
CN = example-device
[attrs]
challengePassword = REPLACE_WITH_DEVICE_CHALLENGE
Generate the key and CSR:
openssl req -new -newkey rsa:2048 -noenc \
-keyout key.pem -out req.pem -config scep.cnf -sha256
Verify that the CSR includes challengePassword:
openssl req -in req.pem -noout -text
openssl req -in req.pem -noout -verify
The attribute list must not show Attributes: (none).
Example 3: Enroll a TLS server certificate with sscep¶
sscep enroll \
-u http://127.0.0.1/.well-known/scep/arburg/tls_server/ \
-c ca-certs.pem -e ca-certs.pem \
-k key.pem -r req.pem -l cert.pem \
-S sha256 -E aes
After success, check the certificate identity and public key:
openssl x509 -in cert.pem -noout -subject -issuer -serial
openssl x509 -in cert.pem -noout -ext basicConstraints
openssl pkey -in key.pem -pubout -outform DER | openssl dgst -sha256
openssl x509 -in cert.pem -pubkey -noout | \
openssl pkey -pubin -outform DER | openssl dgst -sha256
The public-key digests must match. If sscep reports a subject mismatch, compare the CSR subject with the issued certificate; a profile may add or modify subject attributes.
Example 4: Enroll a BACnet/SC certificate¶
Use a CSR generated for the appropriate device and profile:
sscep enroll \
-u http://127.0.0.1/.well-known/scep/arburg/bacnet_sc/ \
-c ca-certs.pem -e ca-certs.pem \
-k key.pem -r req.pem -l bacnet-cert.pem \
-S sha256 -E aes
Certificate profiles may inject subject fields and SANs. Ensure the resulting subject is compatible with your SCEP client and the profile’s intended identity policy.
Example 5: Renew using an existing certificate (sscep)¶
Generate a new key and CSR. The requested identity must match the currently issued certificate, including any required SANs:
openssl req -new -newkey rsa:2048 -noenc \
-keyout newkey.pem -out newreq.pem \
-subj '/CN=example-device' -sha256
The example assumes a CN-only certificate. If the existing certificate has additional subject attributes or SANs, reproduce those in the CSR according to the configured profile.
sscep enroll \
-u http://127.0.0.1/.well-known/scep/arburg/tls_server/ \
-c ca-certs.pem -e ca-certs.pem \
-k newkey.pem -r newreq.pem \
-K key.pem -O cert.pem \
-l cert-renewed.pem \
-S sha256 -E aes
Compatibility note: In sscep 0.10.0, this is an enroll command, not sscep renew. Check your Trustpoint version for certificate-authenticated PKCSReq compatibility before relying on this flow.
Error Handling¶
SCEP protocol failures are returned as CertRep messages with pkiStatus = FAILURE and a failInfo value.
|
Value |
Meaning / common causes |
|---|---|---|
|
|
Unsupported signature, hash, or key algorithm |
|
|
CMS integrity/signature failure, decryption problem, or invalid initial signer |
|
|
Unsupported message type, invalid challenge, profile or enrollment policy rejection |
|
|
Signer certificate time validity failure |
|
|
Unknown or invalid signer certificate identity |
Typical sscep output:
sscep: valid response from server
sscep: pkistatus: FAILURE
sscep: reason: Integrity check failed
The client-side reason may be generic. Check the corresponding Trustpoint SCEP_REJECTED audit record (transaction ID, fail_info, reason) and server logs for the exact rejection cause. Do not log enrollment challenges or private keys.
Transaction Retries¶
Trustpoint records successful SCEP transaction IDs with a digest of the original request and a reference to the issued certificate. Replaying the same request can return the already issued certificate. Reusing the same transaction ID for a different request is rejected.
A request with a new transaction ID is a new operation—not a retry of the previous transaction.
Security Considerations¶
Protect the enrollment challenge: Downloaded
scep.cnffiles contain a credential capable of authorizing initial enrollment. Limit access, avoid shell history/logging, and remove unnecessary copies.Authenticate the CA: Verify downloaded CA certificates and SCEP server identity against an independently trusted source.
Protect private keys: Keep device private keys local, encrypted or hardware-backed where possible. Never upload them to the SCEP endpoint.
Enforce device/domain ownership: Renewal requests must validate the existing signer certificate against Trustpoint’s issued credential and domain records.
Avoid accidental credential replacement: Separate new issuance from renewal; do not identify the credential to replace solely by common name. Verify the intended renewal/replacement behavior in the shared credential lifecycle for your release.
Use TLS where available: CMS protects protocol messages, but HTTPS adds transport protections and helps reduce deployment risks.
Observe supported algorithms and limits: The current implementation advertises AES, SHA-256, and POST PKIOperation; request processing is bounded by limits including a 128 KiB body size.
Integration with Trustpoint Workflows¶
SCEP uses Trustpoint’s shared certificate profile validation and issuance pipeline. Authorization is checked before issuance. The current handler does not invoke the workflow enrollment orchestrator and has no built-in SCEP approval/pending trigger. Do not configure a workflow expecting it to gate SCEP issuance. Asynchronous SCEP polling is not implemented.
Current Limitations¶
GetNextCACert,GetCert,GetCRL, andCertPollare not implemented.SCEP
PENDINGresponses and certificate polling are not currently supported.Certificate-authenticated
PKCSReqrenewal is implemented, but interoperability must be checked with the intended client version.Certificate profiles that alter the subject can cause client-side subject mismatch errors.
Correct separation of independently issued credentials and renewal replacement is a shared credential lifecycle concern and is not guaranteed by SCEP alone.