• Skip to primary navigation
  • Skip to main content
  • Skip to primary sidebar
  • Skip to footer

Mister PKI

SSL Certificates * SSL Tools * Certificate Decoder

  • Home
  • OpenSSL
  • Keytool
  • SSL Tools
  • Donate
  • Cookie Policy (EU)
  • Contribute to Mister PKI (Cybersecurity Guest Posts)
  • PKI for DevOps Engineers (Free Training)
  • SSL Certificate Consulting & TLS Troubleshooting
  • Apereo CAS Consulting

OpenSSL CMP: Automate Certificate Enrollment and Renewal

August 14, 2026 by Mister PKI Leave a Comment

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:

  1. checking CMP support;
  2. understanding the CMP request types;
  3. generating the server key;
  4. performing initial enrollment;
  5. adding Subject Alternative Names;
  6. validating the CMP server;
  7. using shared-secret authentication;
  8. saving the issued certificate and chain;
  9. validating the certificate;
  10. converting an existing CSR into a CMP request;
  11. renewing or re-keying a certificate;
  12. revoking a certificate;
  13. using a configuration file for automation;
  14. 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 commandPurpose
irInitialization Request
crCertificate Request
kurKey Update Request
p10crPKCS#10 certificate request
rrRevocation Request
genmGeneral 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:

  • -serial for identifying certificates during revocation;
  • -srvcertout;
  • several CA-certificate update options;
  • expanded -cacertsout behavior.

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:

ValueReason
0unspecified
1keyCompromise
2cACompromise
3affiliationChanged
4superseded
5cessationOfOperation
6certificateHold
8removeFromCRL
9privilegeWithdrawn
10aACompromise

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

OptionPurpose
-cmdSelects the CMP operation
-serverSpecifies the CMP HTTP/HTTPS server
-pathSpecifies the remote CMP path
-profileRequests a named certificate profile
-newkeySpecifies the key for the requested certificate
-newkeypassSupplies the new-key password
-subjectSpecifies the requested subject DN
-sansRequests Subject Alternative Names
-daysRequests certificate validity
-csrSupplies a PKCS#10 CSR
-oldcertSpecifies a certificate to update or revoke
-certSupplies the CMP client certificate
-keySupplies the CMP client private key
-refSupplies a shared-secret reference value
-secretSupplies the CMP shared secret
-trustedSupplies trust for CMP message validation
-certoutSaves an issued certificate
-chainoutSaves its certificate chain
-issuerSpecifies issuer information
-serialIdentifies a certificate by serial
-revreasonSpecifies revocation reason
-tls_usedEnables TLS for CMP transport
-tls_trustedSupplies HTTPS trust
-verbosityControls logging detail
-reqoutSaves CMP request messages
-rspoutSaves CMP response messages
-centralkeygenRequests central key generation in OpenSSL 3.5+
-newkeyoutSaves 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:

  1. Generate private keys locally unless centralized generation is intentionally required.
  2. Protect enrollment shared secrets.
  3. Do not put secrets directly into scripts or Git.
  4. Validate the CMP server or message signer.
  5. Validate HTTPS independently when HTTPS transport is used.
  6. Review requested SANs and profiles.
  7. Verify the issued certificate before deployment.
  8. Confirm the certificate matches the private key.
  9. Store certificate chains separately when useful.
  10. Protect client authentication certificates and keys.
  11. Restrict access to verbose CMP logs.
  12. Treat captured CMP request and response files as potentially sensitive.
  13. Use short-lived bootstrap credentials when supported.
  14. Migrate from shared-secret bootstrap to certificate-based authentication where appropriate.
  15. 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.

linux,  openssl

Reader Interactions

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Primary Sidebar

Popular Posts

PKCS12

openssl s_client

Keytool

Keytool list

ECDSA vs RSA

OpenSSL

PKCS7

Certificate Decoder

PKI for DevOps Engineers – Free Training Series

PKI for DevOps Training Hub

Lesson 1 – How TLS and PKI Work

Lesson 2 – Understanding X.509 Certificates

Lesson 3 – Certificate Chains Explained

Lesson 4 – Debug TLS with OpenSSL

Lesson 5 – Verify Certificate Chains

Lesson 6 – Creating CSRs with OpenSSL

Lesson 7 – Working with PKCS12 Certificates

Lesson 8 – Java Keystores and keytool

Lesson 9 – Certificate Expiration Monitoring

Lesson 10 – Automating Certificate Renewal

Lesson 11 – Common TLS Errors

Lesson 12 – PKI Architecture for DevOps

Recent Posts

  • OpenSSL dgst: Create Checksums and Verify Digital Signatures
  • OpenSSL crl: Check Certificate Revocation Lists and Revoked Certificates
  • OpenSSL crl2pkcs7: Create PKCS#7 and P7B Certificate Bundles
  • OpenSSL cms: Sign, Verify, Encrypt, and Decrypt Files
  • OpenSSL CMP: Automate Certificate Enrollment and Renewal

Footer

  • Twitter
  • YouTube

Copyright © 2026