Overview
Generating a private key and certificate signing request is easy:
openssl req -new ...
The harder problem for system administrators is everything that happens afterward.
How does the server securely submit the request to the certificate authority?
How does the CA authenticate the requesting system?
How does the client retrieve the issued certificate and chain?
How does that certificate get renewed before expiration?
How does the system request revocation if the private key is compromised?
The Certificate Management Protocol (CMP) was designed to handle those certificate lifecycle operations.
OpenSSL includes a CMP client:
openssl cmp
It can communicate directly with a CMP-enabled certificate authority to:
- enroll a system for its first certificate;
- request additional certificates;
- renew or re-key an existing certificate;
- submit PKCS#10 certificate requests;
- request certificate revocation;
- retrieve CA information;
- save issued certificates and certificate chains.
OpenSSL’s CMP client was introduced in OpenSSL 3.0 and implements CMP certificate-management transactions over HTTP or HTTPS. Current OpenSSL 3.5 documentation describes the protocol according to RFC 9810 and its HTTP(S) transport according to RFC 9811.
This tutorial uses a practical system-administration scenario:
A new internal application server needs a TLS certificate from an organization’s CMP-enabled certificate authority. Instead of manually creating a CSR, submitting it through a web portal, downloading the resulting certificate, and repeating the process at renewal time, we will enroll the system directly with
openssl cmp.
We will cover:
- checking CMP support;
- understanding the CMP request types;
- generating the server key;
- performing initial enrollment;
- adding Subject Alternative Names;
- validating the CMP server;
- using shared-secret authentication;
- saving the issued certificate and chain;
- validating the certificate;
- converting an existing CSR into a CMP request;
- renewing or re-keying a certificate;
- revoking a certificate;
- using a configuration file for automation;
- troubleshooting common CMP failures.
What is OpenSSL CMP?
CMP stands for Certificate Management Protocol.
It provides a standardized protocol between a certificate requester and a certificate authority.
The OpenSSL CMP client supports several request types:
ir
cr
kur
p10cr
rr
genm
These correspond to different certificate lifecycle operations. OpenSSL documents these through the -cmd option.
| CMP command | Purpose |
|---|---|
ir | Initialization Request |
cr | Certificate Request |
kur | Key Update Request |
p10cr | PKCS#10 certificate request |
rr | Revocation Request |
genm | General Message |
The basic command structure is:
openssl cmp \
-cmd REQUEST_TYPE \
-server CMP_SERVER \
[authentication options] \[certificate options]
For example:
openssl cmp \
-cmd ir \
-server https://pki.example.net/cmp
A real enrollment requires additional information, particularly authentication and trust configuration.
OpenSSL version compatibility
This article covers:
- OpenSSL 3.0;
- OpenSSL 3.1;
- OpenSSL 3.2;
- OpenSSL 3.3;
- OpenSSL 3.4;
- OpenSSL 3.5 LTS;
- OpenSSL 4.0.
Check your version:
openssl version
For complete build information:
openssl version -a
CMP itself was added in OpenSSL 3.0, making it a natural fit for this OpenSSL 3-and-later series.
OpenSSL 3.0
OpenSSL 3.0 introduced:
openssl cmp
with support for certificate enrollment, updates, revocation requests, general CMP messages, HTTP transfer, CMP authentication, TLS transport, and test/mock-server operation.
The -engine option was already deprecated when CMP was introduced.
OpenSSL 3.2
OpenSSL 3.2 added CMP capabilities including:
-serialfor identifying certificates during revocation;-srvcertout;- several CA-certificate update options;
- expanded
-cacertsoutbehavior.
The -issuer option could also be used when identifying certificates for revocation.
OpenSSL 3.3
OpenSSL 3.3 added:
-profile
-no_cache_extracerts
along with improved handling of delayed CMP responses.
The -profile option is particularly useful in enterprise environments where the CA exposes named certificate profiles such as:
WebServer
ClientAuthentication
NetworkDevice
OpenSSL 3.4
OpenSSL 3.4 added options including:
-template
-crlcert
-oldcrl
-crlout
-crlform
providing additional capabilities around certificate request templates and CRL retrieval.
OpenSSL 3.5 LTS
OpenSSL 3.5 added central key generation:
-centralkeygen
-newkeyout
along with corresponding mock-server options.
This allows a CMP server to generate the private key centrally and return it to the client when the CA supports that workflow.
For most server TLS certificates, locally generating the private key is preferable because the private key never leaves the machine that will use it.
OpenSSL 4.0
CMP remains available in OpenSSL 4.0.
The deprecated:
-engine
option was removed in OpenSSL 4.0. Provider-based cryptographic integration should be used instead.
OpenSSL 4.0 also adds a CMP interoperability quirk option named:
-ta_in_ip_extracerts
for specific compatibility situations.
For normal enrollment, renewal, and revocation, the primary workflow remains the same.
Real-world scenario
Assume we are provisioning:
app01.example.internal
The organization’s certificate authority exposes a CMP endpoint at:
https://pki.example.net/cmp
The CA administrator has provided:
CMP endpoint
Enrollment reference
Enrollment shared secret
CA trust certificate
Certificate profile name
For this example:
CMP server: https://pki.example.net/cmp
Enrollment ID: app01-enrollment
Certificate: app01.example.internal
Profile: WebServer
We will intentionally use generic placeholders rather than real internal infrastructure values.
Step 1: Confirm that CMP is available
Run:
openssl list -1 -commands | grep '^cmp$'
Expected:
cmp
Display CMP help:
openssl cmp -help
Because CMP contains many options, the help output is extensive.
You can search for a particular feature:
openssl cmp -help 2>&1 | grep certout
Or:
openssl cmp -help 2>&1 | grep server
For more command-discovery techniques, see How to List OpenSSL Commands and Get Command Help.
Step 2: Create a secure working directory
Create:
mkdir -p ~/cmp-enrollment
cd ~/cmp-enrollment
Restrict permissions:
chmod 700 ~/cmp-enrollment
Set a restrictive umask:
umask 077
This directory may eventually contain:
app01.key
app01.crt
app01-chain.pem
ca-root.crt
The private key requires significantly stronger protection than the public certificate files.
Step 3: Generate the private key locally
Generate an RSA private key:
openssl genpkey \
-algorithm RSA \
-pkeyopt rsa_keygen_bits:2048 \
-out app01.key
Protect it:
chmod 600 app01.key
Validate it:
openssl pkey \
-in app01.key \
-check \
-noout
For certificate enrollment, CMP can use the key through:
-newkey
The public portion is placed into the certificate request. For the normal signature-based proof-of-possession method, OpenSSL also needs access to the private key.
Why proof of possession matters
A certificate authority should not normally issue a certificate merely because someone submits a public key.
The requester should demonstrate possession of the corresponding private key.
CMP calls this Proof of Possession, commonly abbreviated:
POPO
OpenSSL supports several methods through:
-popo
The default for normal enrollment is signature-based proof of possession.
That means OpenSSL signs information from the certificate request using:
app01.key
The CA can then verify that the requesting system controls the private key associated with the requested public key.
For ordinary server enrollment, leaving the default POPO behavior is generally appropriate.
Step 4: Obtain the CA trust certificate
Before trusting responses from the CMP server, obtain the appropriate CA or CMP server trust certificate through an authenticated channel.
For example:
cmp-trust.pem
Inspect it:
openssl x509 \
-in cmp-trust.pem \
-noout \
-subject \
-issuer \
-dates \
-fingerprint \
-sha256
Verify the fingerprint against an independent source supplied by the PKI administrator.
Do not download an unknown CA certificate from the same untrusted connection you are attempting to authenticate and then automatically trust it.
Step 5: Perform an initial certificate enrollment
The CMP operation for enrolling an entity for its first certificate is:
ir
which means Initialization Request. OpenSSL distinguishes this from cr, which requests an additional certificate for an entity already initialized in the PKI.
A simplified enrollment might look like:
openssl cmp \
-cmd ir \
-server https://pki.example.net/cmp \
-ref app01-enrollment \
-secret pass:ENROLLMENT_SECRET \
-newkey app01.key \
-subject "/CN=app01.example.internal" \
-sans "app01.example.internal" \
-trusted cmp-trust.pem \
-certout app01.crt
Do not place a real production enrollment secret directly on the command line in automation.
We will improve secret handling later in this article.
The important pieces are:
-cmd ir
Requests initial enrollment.
-server
Specifies the CMP endpoint.
-ref
Provides the reference value used for shared-secret CMP authentication.
-secret
Provides the corresponding enrollment secret.
-newkey
Identifies the key being certified.
-subject
Requests the certificate subject.
-sans
Requests Subject Alternative Names.
-trusted
Provides certificate trust for validating CMP message protection.
-certout
Saves the issued certificate.
OpenSSL supports HTTP and HTTPS CMP servers. Supplying an https:// URL automatically enables TLS transport.
Step 6: Request Subject Alternative Names
For server certificates, the SAN is generally more important than the Common Name for hostname verification.
Use:
-sans "app01.example.internal"
Multiple SANs can be supplied:
-sans "app01.example.internal,app.example.internal"
OpenSSL permits DNS names, IP addresses, email addresses, and URIs in this option.
For example:
openssl cmp \
-cmd ir \
-server https://pki.example.net/cmp \
-ref app01-enrollment \
-secret pass:ENROLLMENT_SECRET \
-newkey app01.key \
-subject "/CN=app01.example.internal" \
-sans "app01.example.internal,app.example.internal" \
-trusted cmp-trust.pem \
-certout app01.crt
The CA ultimately decides whether the requested SAN values are allowed.
A properly configured enterprise CA should apply authorization rules rather than blindly issue every DNS name requested by a client.
Step 7: Save the certificate chain
Add:
-chainout
to save the chain returned for the new certificate:
openssl cmp \
-cmd ir \
-server https://pki.example.net/cmp \
-ref app01-enrollment \
-secret pass:ENROLLMENT_SECRET \
-newkey app01.key \
-subject "/CN=app01.example.internal" \
-sans "app01.example.internal" \
-trusted cmp-trust.pem \
-certout app01.crt \
-chainout app01-chain.pem
OpenSSL documents -chainout as saving the chain for the newly enrolled certificate while excluding both the leaf certificate itself and the root trust anchor.
You might therefore receive:
app01.crt
app01-chain.pem
where:
app01.crt
contains the new server certificate and:
app01-chain.pem
contains one or more intermediate certificates.
Step 8: Inspect the issued certificate
Check the result:
openssl x509 \
-in app01.crt \
-noout \
-subject \
-issuer \
-serial \
-dates
Inspect SANs:
openssl x509 \
-in app01.crt \
-noout \
-ext subjectAltName
Inspect certificate purposes:
openssl x509 \
-in app01.crt \
-noout \
-purpose
Review the complete certificate when troubleshooting:
openssl x509 \
-in app01.crt \
-text \
-noout
For more certificate-inspection examples, see Create and Inspect Certificates with OpenSSL.
Step 9: Verify the issued certificate
Do not assume successful enrollment means the certificate is correct for the intended application.
Verify the chain:
openssl verify \
-CAfile cmp-trust.pem \
-untrusted app01-chain.pem \
app01.crt
Expected result:
app01.crt: OK
Then verify the hostname:
openssl verify \
-CAfile cmp-trust.pem \
-untrusted app01-chain.pem \
-verify_hostname app01.example.internal \
app01.crt
For more complex chain troubleshooting, see the OpenSSL verify guide.
Step 10: Validate the private key matches the certificate
Compare their public keys.
Certificate:
openssl x509 \
-in app01.crt \
-pubkey \
-noout \
> certificate-public.pem
Private key:
openssl pkey \
-in app01.key \
-pubout \
> key-public.pem
Compare:
cmp certificate-public.pem key-public.pem
No output indicates that the public keys match.
Clean up:
rm certificate-public.pem key-public.pem
This is particularly important after automated enrollment because deploying a certificate with the wrong private key will cause the service to fail.
Step 11: Understand CMP authentication versus HTTPS
CMP can involve two separate security layers.
HTTPS transport security
If your server is:
https://pki.example.net/cmp
TLS protects the network connection.
OpenSSL exposes TLS-specific CMP options including:
-tls_used
-tls_trusted
-tls_cert
-tls_key
-tls_host
CMP message protection
CMP messages themselves also support authentication and integrity protection.
OpenSSL can use methods such as:
- shared-secret authentication;
- certificate-based signatures.
This means HTTPS transport alone does not necessarily replace CMP message authentication.
The protocol message and the HTTP transport are separate layers.
Step 12: Verify the HTTPS server
When using HTTPS, provide the appropriate TLS trust certificate when necessary:
-tls_trusted tls-ca.pem
And explicitly specify the expected host when needed:
-tls_host pki.example.net
A command may therefore include both:
-trusted cmp-message-trust.pem
and:
-tls_trusted tls-ca.pem
These can represent different trust decisions:
- trust for the CMP message signer;
- trust for the HTTPS server.
In some deployments the same PKI hierarchy may provide both, but do not assume this.
Step 13: Test the CMP server’s TLS endpoint separately
Before debugging CMP itself, test HTTPS connectivity:
openssl s_client \
-connect pki.example.net:443 \
-servername pki.example.net
Check:
- certificate chain;
- hostname;
- protocol;
- negotiated cipher;
- trust errors.
If the TLS connection itself fails, fix that problem before spending time troubleshooting CMP request syntax.
See OpenSSL s_client Commands and Examples for a complete TLS troubleshooting workflow.
Step 14: Avoid exposing the shared secret
This is convenient:
-secret pass:ENROLLMENT_SECRET
but undesirable on many systems because command-line arguments may be exposed through:
process listings
shell history
debug output
job logs
OpenSSL supports its standard passphrase-source syntax for secret values.
For example, use a protected file:
printf '%s\n' 'ENROLLMENT_SECRET' > cmp-secret.txt
chmod 600 cmp-secret.txt
Then:
-secret file:cmp-secret.txt
A better production design may retrieve the secret from:
- a secrets manager;
- a protected file provisioned at runtime;
- a restricted file descriptor;
- another approved credential-management system.
Do not embed enrollment secrets in:
- source code;
- Git repositories;
- Dockerfiles;
- public CI variables;
- documentation;
- screenshots.
For OpenSSL’s supported credential-source forms, see the official passphrase options documentation.
Step 15: Use certificate-based CMP authentication
Once a system already has a certificate recognized by the PKI, CMP messages can be authenticated with certificate-based signatures.
Relevant options include:
-cert
-key
For example:
openssl cmp \
-cmd cr \
-server https://pki.example.net/cmp \
-cert existing-client.crt \
-key existing-client.key \
-newkey app01.key \
-subject "/CN=app01.example.internal" \
-sans "app01.example.internal" \
-trusted cmp-trust.pem \
-certout app01.crt
This model may be preferable after initial bootstrap because the existing certificate acts as the client’s CMP credential.
The exact authentication model is determined by the CA’s CMP configuration.
Initialization Request versus Certificate Request
These two are easy to confuse.
Initialization Request
Use:
-cmd ir
when initializing an end entity into the PKI and requesting its first certificate.
Certificate Request
Use:
-cmd cr
when the entity is already initialized and is requesting an additional certificate.
OpenSSL explicitly distinguishes these operations.
Your CA may impose different authentication or policy requirements for each.
Step 16: Use an existing PKCS#10 CSR
Many administrators already have an established CSR-generation workflow.
For example:
openssl req \
-new \
-key app01.key \
-out app01.csr \
-subj "/CN=app01.example.internal" \
-addext "subjectAltName=DNS:app01.example.internal"
You can submit a PKCS#10 request through CMP using:
p10cr
Example:
openssl cmp \
-cmd p10cr \
-server https://pki.example.net/cmp \
-ref app01-enrollment \
-secret file:cmp-secret.txt \
-csr app01.csr \
-trusted cmp-trust.pem \
-certout app01.crt
p10cr is the CMP operation specifically intended for legacy PKCS#10-style enrollment.
This can provide an easier migration path when you already have:
key generation
↓
PKCS#10 CSR
↓
existing automation
and only want to replace the manual CA-submission step.
For CSR generation examples, see Create a CSR with OpenSSL.
Using -csr with regular CMP requests
The -csr option can also be used with:
ir
cr
kur
OpenSSL can transform information from a PKCS#10 CSR into the corresponding regular CMP request. In those cases, a private key is normally still required to provide proof of possession.
This distinction matters:
-cmd p10cr
sends a PKCS#10-style request through CMP.
Whereas:
-cmd cr -csr request.csr
uses information from the CSR to construct a regular CMP certificate request.
Step 17: Renew or re-key an existing certificate
CMP provides:
kur
which means Key Update Request.
This is designed to update an existing certificate.
Assume:
app01-old.crt
app01-old.key
represent the existing certificate and key.
Generate a new private key:
openssl genpkey \
-algorithm RSA \
-pkeyopt rsa_keygen_bits:2048 \
-out app01-new.key
Then submit a key update:
openssl cmp \
-cmd kur \
-server https://pki.example.net/cmp \
-cert app01-old.crt \
-key app01-old.key \
-oldcert app01-old.crt \
-newkey app01-new.key \
-trusted cmp-trust.pem \
-certout app01-new.crt \
-chainout app01-new-chain.pem
The exact authentication and certificate-profile requirements depend on the CMP server.
OpenSSL uses the reference certificate during KUR processing and can derive defaults such as subject name and SANs from it.
Renewal versus re-keying
These terms are often used loosely.
Renewal
The CA issues a replacement certificate while continuing to use the same key.
Re-keying
A new key pair is generated and the replacement certificate contains the new public key.
From a security perspective, periodically generating a new key is often preferable to keeping the same private key indefinitely.
CMP’s Key Update Request supports certificate replacement workflows and can use a new key through:
-newkey
Step 18: Prevent SANs from being copied automatically
During certificate updates, OpenSSL can copy Subject Alternative Names from the reference certificate when no new SANs are explicitly supplied.
Disable this behavior with:
-san_nodefault
OpenSSL documents this as preventing SANs from being copied automatically from the reference certificate.
This is useful when:
- old DNS aliases are being retired;
- certificate identity is intentionally changing;
- you want every SAN explicitly stated in automation.
Example:
openssl cmp \
-cmd kur \
... \
-san_nodefault \
-sans "app01.example.internal"
Step 19: Request a named certificate profile
OpenSSL 3.3 and later support:
-profile
Example:
openssl cmp \
-cmd ir \
-server https://pki.example.net/cmp \
-profile WebServer \
...
The CA must recognize the profile.
A PKI administrator might expose profiles such as:
WebServer
ClientAuthentication
VPNClient
NetworkDevice
Profiles are useful because the CA can centrally control:
- key usage;
- extended key usage;
- certificate validity;
- certificate policy;
- permitted SAN types;
- permitted key algorithms.
The requester asks for the profile, but the CA remains responsible for enforcing its policy.
Step 20: Request a specific validity period
Use:
-days
to request certificate validity:
-days 90
For example:
openssl cmp \
-cmd ir \
... \
-days 90
This is a request.
The CA may issue a certificate with a different validity period according to its policy.
Always inspect the resulting certificate:
openssl x509 \
-in app01.crt \
-noout \
-dates
Do not assume the CA honored the requested lifetime.
Step 21: Revoke a certificate with CMP
CMP supports:
rr
which means Revocation Request.
If:
app01.crt
must be revoked:
openssl cmp \
-cmd rr \
-server https://pki.example.net/cmp \
-cert cmp-client.crt \
-key cmp-client.key \
-oldcert app01.crt \
-trusted cmp-trust.pem
The authenticated requester must have permission to revoke the target certificate.
Step 22: Specify the revocation reason
Use:
-revreason
OpenSSL maps the values to the RFC 5280 CRLReason values.
Examples include:
| Value | Reason |
|---|---|
0 | unspecified |
1 | keyCompromise |
2 | cACompromise |
3 | affiliationChanged |
4 | superseded |
5 | cessationOfOperation |
6 | certificateHold |
8 | removeFromCRL |
9 | privilegeWithdrawn |
10 | aACompromise |
For a compromised server key:
-revreason 1
Example:
openssl cmp \
-cmd rr \
-server https://pki.example.net/cmp \
-cert cmp-client.crt \
-key cmp-client.key \
-oldcert app01.crt \
-revreason 1 \
-trusted cmp-trust.pem
Step 23: Revoke by issuer and serial number
OpenSSL 3.2 and later can identify a certificate using:
-issuer
-serial
Example:
openssl cmp \
-cmd rr \
-server https://pki.example.net/cmp \
-issuer "/CN=Example Issuing CA" \
-serial 0x1234 \
-revreason 1 \
...
This can be useful when the certificate file itself is not available but authoritative issuer and serial information are known.
Step 24: Request CA information
CMP supports general messages:
genm
Use:
openssl cmp \
-cmd genm \
-server https://pki.example.net/cmp \
...
You can request specific information with:
-infotype
OpenSSL 3.5 includes explicit support for information types such as:
caCerts
rootCaCert
certReqTemplate
crlStatusList
among others.
For example, a CMP environment may allow a client to retrieve current CA certificates rather than distributing them manually.
The availability of each information type depends on the server.
Step 25: Retrieve a certificate request template
OpenSSL 3.4 and later provide:
-template
for saving a certificate request template received through CMP.
This can help clients discover certificate-request requirements from the CA.
For example:
openssl cmp \
-cmd genm \
-infotype certReqTemplate \
-server https://pki.example.net/cmp \
-template cert-template.der \
...
The returned template can describe parameters the CA expects for enrollment.
This is more flexible than permanently hard-coding every certificate requirement into a provisioning script.
Step 26: Central key generation in OpenSSL 3.5
OpenSSL 3.5 introduced:
-centralkeygen
and:
-newkeyout
for CMP servers that support centralized key generation.
A conceptual command looks like:
openssl cmp \
-cmd ir \
-centralkeygen \
-newkeyout app01.key \
-server https://pki.example.net/cmp \
...
With central key generation, the key originates at the CMP server rather than on the requesting host.
This may be appropriate for specialized PKI workflows, but understand the security tradeoff.
For ordinary TLS servers, locally generating:
app01.key
means the private key never needs to be transported from the CA to the server.
Central key generation should therefore be used only when it matches the organization’s key-management architecture and security requirements.
Step 27: Use a CMP configuration file
Long CMP commands quickly become difficult to maintain.
Instead of:
openssl cmp \
-cmd ir \
-server ... \
-trusted ... \
-ref ... \
-secret ... \
-newkey ... \
-subject ... \
-sans ... \
-profile ... \
-certout ... \
-chainout ...
create a configuration file.
For example:
[cmp]
server = https://pki.example.net/cmp
cmd = ir
trusted = cmp-trust.pem
ref = app01-enrollment
newkey = app01.key
subject = /CN=app01.example.internal
sans = app01.example.internal
profile = WebServer
certout = app01.crt
chainout = app01-chain.pem
Then run:
openssl cmp \
-config cmp.cnf
By default, OpenSSL uses the:
[cmp]
section for CMP configuration.
A different section can be selected:
openssl cmp \
-config cmp.cnf \
-section production
Step 28: Keep secrets out of the configuration file
The configuration file may contain server addresses and certificate paths.
Avoid putting the enrollment secret directly in a file that is:
- world-readable;
- stored in Git;
- included in system images;
- captured in support bundles.
Instead, override the secret securely at runtime:
openssl cmp \
-config cmp.cnf \
-secret file:/run/secrets/cmp-enrollment
Protect:
/run/secrets/cmp-enrollment
with restrictive permissions.
This makes the configuration reusable without embedding credentials.
Step 29: Increase CMP logging
CMP transactions can involve:
DNS
TCP
HTTP
TLS
certificate validation
CMP authentication
certificate policy
proof of possession
CA authorization
When troubleshooting, increase verbosity:
openssl cmp \
-verbosity 7 \
...
OpenSSL defines verbosity values from:
0 = EMERG
...
6 = INFO
7 = DEBUG
8 = TRACE
with INFO as the normal default.
For deeper troubleshooting:
-verbosity 8
Be cautious when publishing verbose logs.
They may expose:
- internal hostnames;
- certificate subjects;
- CMP identities;
- certificate serial numbers;
- URLs;
- PKI architecture;
- other environment-specific information.
Review logs before sharing them externally.
Step 30: Capture CMP requests and responses
OpenSSL provides debugging options such as:
-reqout
-rspout
These allow CMP messages to be written to files for troubleshooting.
For example:
openssl cmp \
... \
-reqout request.der \
-rspout response.der
This is useful when working with:
- a CA vendor;
- application support;
- PKI interoperability testing;
- protocol debugging.
Treat these files as potentially sensitive.
A CMP message may disclose information about:
- requested identities;
- internal DNS names;
- certificate profiles;
- PKI hierarchy;
- enrollment metadata.
Do not upload real production messages publicly without reviewing their contents.
Step 31: Test without a production CMP server
OpenSSL includes CMP debugging and mock-server capabilities.
Options include:
-use_mock_srv
-port
-srv_cert
-srv_key
-srv_secret
among many others.
These capabilities are valuable for:
- learning CMP;
- developing enrollment automation;
- testing client behavior;
- reproducing CA interoperability problems;
- CI testing.
A mock CMP server is not a substitute for a production CA.
Use it to validate workflow and client behavior without issuing certificates from the organization’s actual PKI.
Common OpenSSL CMP errors
Unknown option
Check:
openssl version
Then:
openssl cmp -help
Some CMP options were added after OpenSSL 3.0.
For example:
-centralkeygen
requires OpenSSL 3.5 or later.
Connection refused
Test basic connectivity:
nc -vz pki.example.net 443
Then test TLS:
openssl s_client \
-connect pki.example.net:443 \
-servername pki.example.net
Confirm:
- hostname;
- port;
- firewall rules;
- proxy configuration;
- CMP endpoint path.
HTTP 404 or wrong endpoint
CMP often uses a specific HTTP path.
For example:
/cmp
or a CA-specific alias.
OpenSSL supports specifying the path either as part of:
-server
or through:
-path
The default path is / when none is supplied.
Confirm the exact endpoint with your CA administrator.
Certificate verification failed
Determine whether the failure relates to:
- HTTPS server validation;
- CMP message signer validation;
- issued-certificate validation.
These are different checks.
Inspect:
-trusted
-tls_trusted
-out_trusted
and confirm you supplied the correct trust anchors for the intended operation.
Invalid shared secret
Verify that:
-ref
matches the enrollment reference expected by the CA and:
-secret
contains the correct associated secret.
Do not repeatedly expose the secret in terminal commands while troubleshooting.
Proof-of-possession failure
Confirm that the private key corresponding to the requested public key is available:
openssl pkey \
-in app01.key \
-check \
-noout
OpenSSL requires the private key for the normal signature-based POPO method.
Requested SAN is missing
Inspect the resulting certificate:
openssl x509 \
-in app01.crt \
-noout \
-ext subjectAltName
The CA may:
- reject the requested SAN;
- modify it;
- apply certificate-profile rules;
- require SANs in another format.
CMP can request certificate attributes; the CA retains authority over what it actually issues.
Enrollment succeeds but certificate validation fails
Inspect:
openssl x509 \
-in app01.crt \
-noout \
-subject \
-issuer \
-dates
Then:
openssl verify \
-CAfile root-ca.pem \
-untrusted app01-chain.pem \
app01.crt
Check whether the proper chain was returned and whether your chosen trust anchor belongs to that hierarchy.
HTTPS works but CMP fails
If:
openssl s_client
works, transport-level TLS is probably not the problem.
Investigate:
- CMP message authentication;
- shared-secret credentials;
- certificate-based client authentication;
- profile name;
- CMP endpoint path;
- CA authorization;
- proof of possession.
TLS success proves only that you can establish the HTTPS connection.
Important openssl cmp options
| Option | Purpose |
|---|---|
-cmd | Selects the CMP operation |
-server | Specifies the CMP HTTP/HTTPS server |
-path | Specifies the remote CMP path |
-profile | Requests a named certificate profile |
-newkey | Specifies the key for the requested certificate |
-newkeypass | Supplies the new-key password |
-subject | Specifies the requested subject DN |
-sans | Requests Subject Alternative Names |
-days | Requests certificate validity |
-csr | Supplies a PKCS#10 CSR |
-oldcert | Specifies a certificate to update or revoke |
-cert | Supplies the CMP client certificate |
-key | Supplies the CMP client private key |
-ref | Supplies a shared-secret reference value |
-secret | Supplies the CMP shared secret |
-trusted | Supplies trust for CMP message validation |
-certout | Saves an issued certificate |
-chainout | Saves its certificate chain |
-issuer | Specifies issuer information |
-serial | Identifies a certificate by serial |
-revreason | Specifies revocation reason |
-tls_used | Enables TLS for CMP transport |
-tls_trusted | Supplies HTTPS trust |
-verbosity | Controls logging detail |
-reqout | Saves CMP request messages |
-rspout | Saves CMP response messages |
-centralkeygen | Requests central key generation in OpenSSL 3.5+ |
-newkeyout | Saves a centrally generated private key |
The CMP command has substantially more options than can reasonably be covered in one administrator tutorial. Use the official OpenSSL CMP documentation when implementing advanced CMP profiles or authentication modes.
CMP versus manual CSR enrollment
A traditional administrator workflow often looks like:
Generate key
↓
Generate CSR
↓
Open CA web portal
↓
Paste/upload CSR
↓
Wait for approval
↓
Download certificate
↓
Download chain
↓
Install certificate
↓
Repeat at renewal
CMP can reduce that to:
Generate key
↓
Authenticate to CMP
↓
Request certificate
↓
Receive certificate + chain
↓
Validate
↓
Deploy
This is where CMP becomes particularly useful for infrastructure automation.
CMP versus ACME
CMP and ACME both automate certificate enrollment, but they were designed with different PKI environments in mind.
ACME is widely associated with automated TLS certificate issuance and domain validation.
CMP supports a broader PKI-management model including:
- initial enrollment;
- additional certificate requests;
- certificate updates;
- certificate revocation requests;
- CA information retrieval;
- multiple authentication models;
- enterprise certificate profiles.
Which protocol is appropriate depends on the CA platform and PKI architecture.
Do not replace a functioning ACME workflow with CMP merely because OpenSSL supports it.
Use the enrollment protocol designed for your CA and operational requirements.
Security recommendations
When automating CMP enrollment:
- Generate private keys locally unless centralized generation is intentionally required.
- Protect enrollment shared secrets.
- Do not put secrets directly into scripts or Git.
- Validate the CMP server or message signer.
- Validate HTTPS independently when HTTPS transport is used.
- Review requested SANs and profiles.
- Verify the issued certificate before deployment.
- Confirm the certificate matches the private key.
- Store certificate chains separately when useful.
- Protect client authentication certificates and keys.
- Restrict access to verbose CMP logs.
- Treat captured CMP request and response files as potentially sensitive.
- Use short-lived bootstrap credentials when supported.
- Migrate from shared-secret bootstrap to certificate-based authentication where appropriate.
- Test renewal before the first certificate approaches expiration.
Certificate enrollment is security-sensitive automation. A script capable of requesting trusted certificates should receive the same scrutiny as other privileged infrastructure automation.
Frequently asked questions
What is OpenSSL CMP?
openssl cmp is OpenSSL’s client implementation of the Certificate Management Protocol. It can request, update, and revoke certificates and perform other CMP operations against a compatible CA server.
When was openssl cmp added?
The CMP application was added in OpenSSL 3.0.
How do I request my first certificate?
Use:
openssl cmp \
-cmd ir \
...
ir means Initialization Request.
What is the difference between ir and cr?
ir initializes an entity in the PKI with its first certificate.
cr requests an additional certificate for an entity that is already initialized.
What is p10cr?
p10cr sends a PKCS#10 certificate request using CMP.
It is useful when you already have a traditional CSR-generation workflow.
How do I renew a certificate with CMP?
Use a Key Update Request:
openssl cmp \
-cmd kur \
...
Provide the existing reference certificate and the key information required by your CMP server.
How do I revoke a certificate?
Use:
openssl cmp \
-cmd rr \
...
Optionally add:
-revreason 1
for key compromise.
Does CMP require HTTPS?
Not necessarily.
CMP can use HTTP or HTTPS transport. If the https:// scheme is supplied to -server, OpenSSL automatically enables TLS.
CMP message protection and HTTPS transport security are related but separate concepts.
Can OpenSSL CMP use a shared secret?
Yes.
OpenSSL supports:
-ref
-secret
for shared-secret CMP authentication.
Can CMP use client certificates?
Yes.
Use options such as:
-cert
-key
for certificate-based client authentication and CMP message protection.
Can CMP request SAN certificates?
Yes.
Use:
-sans "app01.example.internal,app.example.internal"
subject to the CA’s certificate policy.
Can OpenSSL CMP request centrally generated keys?
Yes, starting with OpenSSL 3.5:
-centralkeygen
-newkeyout
The CMP server must support central key generation.
Does openssl cmp work with OpenSSL 4.0?
Yes.
The CMP command remains available in OpenSSL 4.0. The old -engine option was removed; modern integrations should use providers.
Practical enrollment summary
Generate the key:
openssl genpkey \
-algorithm RSA \
-pkeyopt rsa_keygen_bits:2048 \
-out app01.key
Protect it:
chmod 600 app01.key
Enroll:
openssl cmp \
-cmd ir \
-server https://pki.example.net/cmp \
-ref app01-enrollment \
-secret file:cmp-secret.txt \
-newkey app01.key \
-subject "/CN=app01.example.internal" \
-sans "app01.example.internal" \
-trusted cmp-trust.pem \
-certout app01.crt \
-chainout app01-chain.pem
Inspect:
openssl x509 \
-in app01.crt \
-noout \
-subject \
-issuer \
-dates \
-ext subjectAltName
Verify:
openssl verify \
-CAfile cmp-trust.pem \
-untrusted app01-chain.pem \
-verify_hostname app01.example.internal \
app01.crt
Later, re-key:
openssl cmp \
-cmd kur \
...
Or revoke:
openssl cmp \
-cmd rr \
-oldcert app01.crt \
-revreason 1 \
...
Related OpenSSL guides
- Browse the complete OpenSSL Commands Guide.
- Build traditional PKCS#10 requests with Create a CSR with OpenSSL.
- Validate certificates and chains with OpenSSL verify.
- Troubleshoot the HTTPS layer with OpenSSL s_client.
- Manage a small manual CA with OpenSSL ca.
- Inspect certificate structures with OpenSSL asn1parse.
- Learn how OpenSSL discovers commands and features in How to List OpenSSL Commands and Get Command Help.
External references
- OpenSSL 3.5 CMP documentation
- OpenSSL 3.0 CMP documentation
- OpenSSL 4.0 CMP documentation
- OpenSSL passphrase options
- OpenSSL certificate verification options
- OpenSSL req documentation
Conclusion
The openssl cmp command brings certificate lifecycle automation directly into the OpenSSL command line.
Instead of relying on a manual workflow:
Generate CSR
Upload CSR
Wait
Download certificate
Install certificate
Repeat
a CMP-enabled environment can support:
Authenticate
↓
Enroll
↓
Receive certificate
↓
Validate
↓
Deploy
↓
Renew or re-key
↓
Revoke when necessary
For system administrators, the most useful CMP operations are:
ir Initial enrollment
cr Additional certificate
p10cr Existing PKCS#10 CSR
kur Renewal or key update
rr Revocation request
genm Retrieve PKI information
OpenSSL 3.0 provides the baseline CMP client, while later OpenSSL 3.x releases expanded certificate profiles, CRL and CA update support, and other enterprise enrollment capabilities. OpenSSL 3.5 adds central key generation, while OpenSSL 4.0 continues the CMP client using the modern provider architecture.
The most important operational point is that certificate enrollment is not just certificate generation.
A secure CMP deployment must also address:
client authentication
server authentication
proof of possession
certificate policy
private-key protection
certificate validation
renewal
revocation
When those controls are in place, CMP can turn a manual certificate-management process into a repeatable PKI workflow suitable for infrastructure automation.
Leave a Reply