OCSP

This page describes general concepts of EJBCA's OCSP responder. For exact instructions of how to set it up, see OCSP Management.

Introduction

OCSP (Online Certificate Status Protocol) is used by PKI-clients to verify the validity of certificates in real-time. This is done by sending a request for the status of a specific certificate to an OCSP responder. The responder may or may not be the same as the CA. The OCSP responder sends a signed reply, containing the requested status information back to the client. The client uses this status information to determine whether the certificate is valid for use or revoked.

The OCSP servlet receives OCSP request over http(s) and sends back a status response signed by the CA.

The OCSP service receives requests on http://localhost:8080/ejbca/publicweb/status/ocsp. The servlet can process requests for certificates signed by a CA running in EJBCA, as long as the CAs OCSP service has not been deactivated.

For a CA to be valid as an OCSP-responder it must have the KeyUsage 'Digital Signature' in the certificate profile used to create the CA. This KeyUsage must be included if the CA is to sign OCSP-responses. The default certificate profiles for CAs includes the key usage 'Digital Signature'.

To generate an OCSP request using OpenSSL (works with both internal and external OCSP responders):

openssl ocsp -issuer Test-CA.pem -CAfile Test-CA-chain.pem -cert CertificateToCheck.pem -req_text -url http://localhost:8080/ejbca/publicweb/status/ocsp

To issue GET requests for testing, the following methodology can be used (replace with your own data):

openssl ocsp -noverify -no_nonce -respout ocsp.resp -reqout ocsp.req -issuer ManagementCA.cacert.pem -cert ejbca-test2.primekey.se -url "http://ejbca-test2.primekey.se:8080/ejbca/publicweb/status/ocsp" -header "HOST" "ejbca-test2.primekey.se" -text
openssl enc -in ocsp.req -out ocsp.req.b64 -a
curl --verbose --url http://ejbca-test2.primekey.se:8080/ejbca/publicweb/status/ocsp/MEkwRzBFMEMwQTAJBgUrDgMCGgUABBT1x9iHOmegR7sYp5Fzdo/u3FMBRgQUH1DTnzl9lscAe3WBTUPCWR+xwpQCCDlpiyU2q5Rb

If Firefox is to request and accept OCSP-responses from a CA not in the default trust store, it must be configured to trust this CA:

  1. In Advanced > Certificates > View Certificates > Authorities, import and select the CA certificate, and checking the appropriate Trust options.

  2. If Query OCSP responder servers to confirm the current validity of certificates in Advanced > Certificates is selected, and certificates include an OCSP Service URL (AIA extension), Firefox will query the OCSP server when for example double-clicking on a certificate in the certificate manager.

An appropriate URL for validation is: http://hostname:8080/ejbca/publicweb/status/ocsp and doc/samples contains a sample on how to check revocation with OCSP using the new APIs as of JDK 1.5.

Revoked CA Certificates

When the first entry in the CA certificate chain matching an OCSP request is revoked with one of the reason codes "keyCompromise", "cACompromise", "aACompromise" or "unspecified", the status of the requested certificate will be returned as revoked with reason "cACompromise". This is in accordance with RFC6960, section 2.7.

This means that you can instantly block the use of leaf certificates by revoking the issuer of these certificates using for example the "cACompromise" reason code, even if the CA certificate is still considered valid according to a CRL at the client.

This also applies if you revoke a cross-signed CA certificate for one of these reasons or import such a CA revocation status update to you VAs. It is still recommended that you revoke the individual certificates, to ensure that they appear in fallback CRLs.

Expired Certificates

EJBCA keeps the status of expired certificates in the database, so the responder will answer queries also for expired certificates unless you remove them from the database. In the internal EJBCA database, the status of expired certificates is set to ARCHIVED in the database (CertificateData table) by the CRL creation job. The ARCHIVED status does not affect the response sent by the OCSP responder.

The algorithm is:

  • If status is CERT_REVOKED, the certificate is revoked, and reason and date is picked up.

  • If status is CERT_ARCHIVED and reason is NOT REMOVEFROMCRL or NOT_REVOKED, the certificate is revoked, and reason and date is picked up.

  • If status is CERT_ARCHIVED and reason is REMOVEFROMCRL or NOT_REVOKED, the certificate is NOT revoked.

  • If status is neither CERT_REVOKED or CERT_ARCHIVED, the certificate is NOT revoked.

The archive cutoff extension is used as defined in RFC 6960.

Setting up an OCSP Responder on a Remote VA

You can set up separated OCSP responders in EJBCA in order to isolate the CA from the Internet and still be able to answer OCSP requests. Additionally, you can set up firewalls so that only outgoing traffic is allowed from the CA, and nothing to the CA.

Separated OCSP responders is also good when you do not require high-performance clustering for the CA, but you do need high-performance for the OCSP responders. This is a common setup, if the CA only issues certificates once every year for one million users, this does not put much pressure on the CA, but the OCSP responders can be put under high load continuously.

For information on how to set up stand-alone, separated OCSP responders, see OCSP Management.

Multiple Responders and CA Certificates

The OCSP responder can have many responder certificates, each issued by one CA and mapped by an OcspKeyBinding. This means that the responder can answer requests targeted at multiple CAs. There is no built-in limitation on the number of CAs that can be handled.

Selection of OCSP Signing Certificate from a Request

In the OCSP request as defined in RFC 6960, the hash of both issuing CA's Subject DN and public key is available:

CertID ::= SEQUENCE {
hashAlgorithm AlgorithmIdentifier,
issuerNameHash OCTET STRING, – Hash of issuer's DN
issuerKeyHash OCTET STRING, – Hash of issuer's public key
serialNumber CertificateSerialNumber }

EJBCA selects OcspKeyBinding based on the subject DN and public key of the CA certificate that issued an OCSP signing certificate. The issuing CA certificate is determined from the OCSP certificate chain and the construction of the chain is described below.

CA Key Renewal Considerations

EJBCA considers two X.509 CA certificates as the same CA if they share the same Subject DN and as different versions of the same CA if the public key is different. Since both subject and key pair is used in the request, you will need two OcspKeyBindings (one issued before key renewal and one after) to be able to serve OCSP requests where clients use CA certificate for both the old and new key pair in their requests.

EJBCA currently only allows you to issue an OCSP signing certificate from the latest version of the CA. Thus, before such a CA key renewal, you will need to issue OCSP signing certificates that will last for the life-time of the CA certificate.

Certificate Chain Construction

EJBCA builds the chain for each OCSP signing certificate by looking for the latest CA certificate with a Subject DN equal to the Issuer DN of the OCSP signing certificate. Unless the found CA certificate is self-signed, the procedure is repeated until the full chain is built.

If the built chain is unable to verify the OCSP signing certificate (due to CA certificate key renewal), a different algorithm is used where EJBCA uses the internal CertificateData.cAFingerprint value to determine the exact certificate that has issued an OCSP signing certificate. Similar to the case where we build the chain using the Issuer DN of the OCSP signing certificate, the process is repeated until a full chain leading up to a self-signed CA is built.

OCSP Response Certificate Chain

For efficiency reasons, it is possible to configure EJBCA to either omit including the signing certificate or its certificate chain in the OCSP response. Setting the relevant configuration in the $EJBCA_HOME/conf/ocsp.properties file or in the Internal Key Binding in the GUI, has the following effect:

  • If ocsp.includesignercert=true and ocsp.includecertchain=true, the signing certificate and its chain, except for the signing certificate root CA certificate, will be included in the OCSP response. If the signing certificate IS the root CA certificate, then the root CA certificate will be included in the response any way.

  • If ocsp.includesignercert=true and ocsp.includecertchain=false, only the signing certificate will be included in the OCSP response even if it was a root CA certificate.

  • If ocsp.includesignercert=false, neither the signing certificate nor the certificate chain will be included in the OCSP response regardless of the value of ocsp.includecertchain

Audit and Account Logging

There are three types of logs that can be generated by the OCSP responder:

  • OCSP service logs

  • OCSP transaction log

  • OCSP audit log

OCSP Service Logs

The OCSP service logs using Log4j to the JBoss server.log. The JBoss server log is located in JBOSS_HOME/server/default/log/server.log and the logging is configured in JBOSS_HOME/server/default/conf/jboss-log4j.xml.

The OCSP Transaction Log

The OCSP transaction log can be used to log various information about ocsp-requests. Transaction logging logs summary lines for all OCSP request/responses, which can be used for charging clients if you are running a commercial OCSP service.

To turn on transaction logs logs, copy ocsp.properties.sample to ocsp.properties and change:

#ocsp.trx-log = false

to

ocsp.trx-log = true

then uncomment the other lines below that starts with ocsp.trx-log. Change the ocsp.trx-log-log-date line if you want to change how the time recorded in logging should be output. The value should be on the same format as for javas DateFormat, information on valid configurations can be found here.

ocsp.trx-log-log-date = yyyy-MM-dd:HH:mm:ss

ocsp.trx-log-pattern is a pattern for use with ocsp.audit-order to replace constants with values during logging. For most purposes you will not need to change this string.

Use ocsp.trx-log-order to specify what information should be logged and in what order. You can also configure what characters you want in between. If you want your log to display all of the values available you only have to un-comment it.

Available values for the transaction log are:

Transaction Log Value

Description

LOG_ID

An integer identifying that starts from 1 and is increased for every received request.

SESSION_ID

A random 32 Byte long String generated when the OCSP-responder is started.

STATUS

The status of the OCSP-Request.

SUCCESSFUL = 0;
MALFORMED_REQUEST = 1;
INTERNAL_ERROR = 2;
TRY_LATER = 3;
SIG_REQUIRED = 5;
UNAUTHORIZED = 6;

CLIENT_IP

IP of the client making the request.

REQ_NAME

The BC normalized Distinguished Name of the client making the request.

REQ_NAME_RAW

The unnormalized Distinguished Name of the client making the request.

SIGN_ISSUER_NAME_DN

The BC normalized issuer Distinguished Name of the certificate used to sign the request.

SIGN_SUBJECT_NAME

The BC normalized Subject Distinguished Name of the certificate used to sign the request.

SIGN_SERIAL_NO

Certificate serial number of the certificate used to sign the request.

NUM_CERT_ID

The number of certificates to check revocation status for.

ISSUER_NAME_DN

The BC normalized issuer Distinguished Name of the requested certificate.

ISSUER_NAME_DN_RAW

The unnormalized issuer Distinguished Name of the requested certificate.

ISSUER_NAME_HASH

SHA1 hash of the issuer DN.

ISSUER_KEY

The public key of the issuer of a requested certificate.

DIGEST_ALGOR

Algorithm used by requested certificate to hash issuer key and issuer name.

SERIAL_NO

Serial number of the a requested certificate.

CERT_STATUS

The requested certificate revocation status. 0=good, 1=revoked, 2=unknown.

REV_REASON

The requested certificate revocation reason, or -1, if not revoked. Set to 6 (certificateHold) when certificate is unknown, even if status returned is good.

REPLY_TIME

The time measured between when the request is received by the responder and when the response is sent. This time includes the time it takes to read the request bytes.

PROCESS_TIME

The time measured between when the request has been read by the responder and when the response is sent. This time starts after the request bytes have been read.

CERT_PROFILE_ID

The integer identifier of the certificate profile that was used to issue the requested certificate.

FORWARDED_FOR

The HTTP X-Forwarded-For header value.

The OCSP Audit Log

Do not confuse the OCSP Audit Log with the standard EJBCA Audit Log. OCSP operations are not logged in a standard PKI installation, but a specific audit log can be written to disk for OCSP in particular.

The OCSP audit log logs entire requests and responses. This can be useful when requests and responses are signed because the information can be used to verify requests and responses afterwards. Audit logging is configured in the same way as transaction logging. Valid values for audit logging are:

Audit Log Value

Description

LOG_ID

An integer identifying that starts from 1 and is increased for every received request.

SESSION_ID

A random 32 Byte long String generated when the OCSP-responder is started.

OCSPREQUEST

The (hex encoded) byte[] ocsp-request that came with the http-request.

OCSPRESPONSE

The (hex encoded) byte[] ocsp-response that was included in the http-response.

Note that LOG_ID are of the same value in both trx log and audit log for any request. This means they can be cross referenced. You can retrieve information from the transaction log and verify that the information is valid by using the audit Log.

Configuring Output Files for OCSP Logging

For JBoss you can configure logging in JBOSS_HOME/standalone/configuration/standalone.xml to put the transaction and audit logs in separate files:

If using JBoss EAP 6 and an application specific log4j configuration, set the property org.jboss.as.logging.per-deployment=true in standalone.xml or using the JBoss CLI.

<periodic-rotating-file-handler name="OCSPTRANSACTION" autoflush="true">
<formatter>
<pattern-formatter pattern="%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%E%n"/>
</formatter>
<file relative-to="jboss.server.log.dir" path="transactions.log"/>
<suffix value=".yyyy-MM-dd"/>
<append value="true"/>
</periodic-rotating-file-handler>
<periodic-rotating-file-handler name="OCSPAUDIT" autoflush="true">
<formatter>
<pattern-formatter pattern="%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%E%n"/>
</formatter>
<file relative-to="jboss.server.log.dir" path="audit.log"/>
<suffix value=".yyyy-MM-dd"/>
<append value="true"/>
</periodic-rotating-file-handler>
<logger category="org.cesecore.certificates.ocsp.logging.TransactionLogger" use-parent-handlers="false">
<level name="DEBUG"/>
<handlers>
<handler name="OCSPTRANSACTION"/>
</handlers>
</logger>
<logger category="org.cesecore.certificates.ocsp.logging.AuditLogger" use-parent-handlers="false">
<level name="DEBUG"/>
<handlers>
<handler name="OCSPAUDIT"/>
</handlers>
</logger

Safer Log4j Logging

The default behavior when logging fails, such as when the destination disk is full or disconnected, is to continue responding as normal. If you prefer the responder not to send OCSP-responses when logging fails you can use the following configuration:

  1. From your EJBCA folder, run:
    ant jbosslog4jsafer

  2. On JBoss 7 / EAP 6 build and deploy a new ejbca.ear that includes jbosslog4jsafer.jar with:

    ant ejbca.ear
    ant deployear
  3. Set 'ocsp.log-safer = true' in ocsp.properties (and enable ocsp.trx-log and ocsp.audit-log of course).

  4. Modify your JBoss logging to use the SaferDailyRollingFileAppender and ProbableErrorHandler. For example:

    <appender name="OCSPTRANSACTION" class="org.cesecore.util.log.SaferDailyRollingFileAppender">
    <errorHandler class="org.cesecore.util.log.ProbableErrorHandler" />
    <param name="File" value="${jboss.server.log.dir}/transactions.log" />
    <param name="Append" value="true" />
    <!-- Rollover at midnight each day -->
    <param name="DatePattern" value="'.'yyyy-MM-dd" />
    <layout class="org.apache.log4j.PatternLayout">
    <!-- The default pattern: Date Priority [Category] Message\n -->
    <param name="ConversionPattern" value="%d %-5p [%c] %m%n" />
    </layout>
    </appender>
    <appender name="OCSPAUDIT" class="org.cesecore.util.log.SaferDailyRollingFileAppender">
    <errorHandler class="org.cesecore.util.log.ProbableErrorHandler" />
    <param name="File" value="${jboss.server.log.dir}/audit.log" />
    <param name="Append" value="true" />
     
    <!-- Rollover at midnight each day -->
    <param name="DatePattern" value="'.'yyyy-MM-dd" />
    <layout class="org.apache.log4j.PatternLayout">
    <!-- The default pattern: Date Priority [Category] Message\n -->
    <param name="ConversionPattern" value="%d %-5p [%c] %m%n" />
    </layout>
    </appender>
    <logger name="org.cesecore.certificates.ocsp.logging.TransactionLogger">
    <level value="DEBUG" />
    <appender-ref ref="OCSPTRANSACTION" />
    </logger>
    <logger name="org.cesecore.certificates.ocsp.logging.AuditLogger">
    <level value="DEBUG" />
    <appender-ref ref="OCSPAUDIT" />
    </logger>

    If you use category instead of logger Log4j will output warnings on startup.

  5. Start JBoss and you are ready.

Using the OCSP API

The learn the API, you can study the included source code. The client API is used in the class org.ejbca.core.protocol.ocsp.OCSPUnidClient. The EJBCA Client Toolbox can serve as a good sample for using the API, in the class org.ejbca.ui.cli.Ocsp.

Database Indexes

As your OCSP database grows with revoked, and active, certificates you will need database indexes to maintain good performance. See the file doc/sql-scripts/create-index-ejbca.sql (section for certificate data) for indexes needed for CA and OCSP operations.

OCSP GET

The GET OCSP request is defined in RFC 6960 (and RFC2560) A.1 as:

'GET {url}/{url-encoding of base-64 encoding of the DER encoding of the OCSPRequest}'.

A base64-encoded request can contain the reserved characters '+', '/' and '=', but will be handled correctly both in their %-escaped and original form by the responder, since it's unclear if they do conflict as defined in RFC 2396 2.2.

Not all web-product handles the encoded '/' (%2F) nicely. JBoss/Tomcat has to be started with -Dorg.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH=true added to JAVA_OPT in JBOSS_HOME/bin/run.conf. On Glassfish this JVM option is configured under Application Server Settings.

Responses with longer validity and caching

RFC 6960 (and RFC2560) defines thisUpdate, nextUpdate and producedAt. producedAt is always included in the response and is the time the response was created. thisUpdate and nextUpdate is enabled by configuring 'ocsp.untilNextUpdate' in ocsp.properties or in the OcspKeyBinding. thisUpdate will be the time a singleResponse is embedded in the main response and nextUpdate will be 'untilNextUpdate' seconds later than thisUpdate. This enables clients that supports this feature to re-use a valid response and decrease to load on the OCSP-responder.

RFC 5019 defines how to use HTTP cache headers as defined in RFC 2616 for OCSP HTTP GET requests. By using the headers Last-Modified, Expires, max-age and Date, less intelligent nextwork component like HTTP caches can cache respones. This enables re-use of responses to decrease the load on the OCSP-responder and can shorten reponse times by deploying caches closer to the actual OCSP consumers. HTTP cache headers is enabled by configuring configuring 'ocsp.maxAge' in ocsp.properties or in the OcspKeyBinding.

When using RFC 5019 style HTTP headers, JBoss users should be aware that the Date header is overwritten with a cached value. Since generating the Date-string is computationally heavy for regular small GET requests, it is generated about once per second. So a response will have a Last-Modified that is one second in the future from Date from time to time.

A regular Apache HTTP server can be used for caching requests, load-balancing and dropping some unwanted requests:

<VirtualHost *:80>
# Use as much memory as possible for the cache (in 1 kB blocks)
# 1GB of memory at ~2kB/ocsp request would hold about 500000 different requests
CacheEnable mem /
MCacheSize 1048576
MCacheMaxObjectCount 1000000
MCacheMinObjectSize 1
MCacheMaxObjectSize 4096
 
# Using disk-cache will allow a much larger pool of cached entires and the operation system
# will cache those files, but you are responsible for cleaning up old cache-entries using
# the "htcacheclean" tool. A disk cache will also live through a server restart.
# The user running apache has to have read/write access to "/var/cache/ocsp".
#CacheEnable disk /
#CacheRoot /var/cache/ocsp
 
# Ignore requests for uncached responses.. this will protect the OCSP from
# DOS attacks using "Cache-Control: no-cache" or "Pragma: no-cache"
CacheIgnoreCacheControl On
 
ProxyRequests Off
 
<Location>
# Everybody is welcome here..
Allow from all
Order allow,deny
 
# ..or just those from networks that is supposed to use the service
#Deny from all
#Order deny,allow
#allow from 127.
#allow from 172.16.212.1
 
ProxyPassReverse balancer://mycluster-kerb/
</Location>
 
# Proxy requests to OCSP instances (only one machine currently configured)
<Proxy balancer://mycluster-kerb>
# proxy_ajp has to be enabled for ajp-proxying
BalancerMember ajp://127.0.0.1:8009/ejbca/publicweb/status/ocsp
# proxy_http has to be enabled for http-proxying
#BalancerMember http://ocsp2.domain.org:8080/ejbca/publicweb/status/ocsp
#BalancerMember http://ocsp3.domain.org:8080/ejbca/publicweb/status/ocsp
</Proxy>
 
# We only want RFC 5019 compliant URLs to be forwarded to the OCSP, the rest
# should get a "404 Not found" or "414 Request-URI Too Large."
LimitRequestLine 257
RewriteEngine On
RewriteCond %{REQUEST_METHOD} get [NC]
RewriteRule ^/([a-zA-Z0-9+=/]+)$ balancer://mycluster-kerb/$1 [P,L]
 
# Possible values include: debug, info, notice, warn, error, crit,
# alert, emerg.
LogLevel debug
CustomLog /var/log/apache2/access.log combined
ErrorLog /var/log/apache2/error.log
</VirtualHost>

Usage Examples

Adobe Reader

A good example of using OCSP is to check digitally signed PDF documents using Adobe Reader.

To verify certificates in Adobe Reader, you must first add the CA certificate as trusted in Adobe Reader. You can do that in the menu Document > Trusted Identities. Choose Certificates in the list menu and click Add contacts to browse to the CA-certificate that you have downloaded in DER format (for example by choosing download to IE on the public EJBCA pages). The CA certificate must have been saved with a name ending with .cer. After adding the new contact, click Edit trust and check at least Signatures and as trusted root and Certified documents. Applies for both internal and external OCSP responders.

Certificates that have an OCSP service locator will be verified against the OCSP responder. You can configure this in the certificate profile used to issue certificates.

If you sign PDF documents with embedded OCSP responses, these responses must include a nextUpdate field, and the timestamp must be within the thisUpdate and nextUpdate period of the OCSP response.