Introduction


The example 'C' program crldisplay.c demonstrates how to extract data from a certificate revocation list (CRL), using the OpenSSL library functions.

Certificate revocation lists are described in RFC 5280 (link), see section 5. "CRL and CRL Extensions Profile". a CRL is a file containing a list of revoked certificate serial numbers, plus the revocation date. Note that the serial number is the only available identifier.

CRL type version 2 allows to add extensions that help dealing with multiple CA signing keys, and to better deal with CRL updates (deltas). Sounds complicated (I am still looking for a sample v2 CRL).

Example Code Listing


/* ------------------------------------------------------------ *
 * file:        crldisplay.c                                    *
 * purpose:     Example code how to display the content of a    *
 *              Certificate Revocation List (CRL) from a local  *
 *              file. Here I used the CRL file saved from URL   *
 *              http://EVIntl-crl.verisign.com/EVIntl2006.crl   *
 * author:      02/01/2015 Frank4DD                             *
 *                                                              *
 * compile:     gcc -o crldisplay crldisplay.c -lssl -lcrypto   *
 * ------------------------------------------------------------ */

#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/x509.h>

int main() {
  const char    crl_filestr[] = "./EVIntl2006.crl";
  BIO                 *crlbio = NULL;
  BIO                 *outbio = NULL;
  X509_CRL            *mycrl  = NULL;
  X509_NAME           *issuer = NULL;
  STACK_OF(X509_REVOKED) *rev = NULL;
  X509_REVOKED     *rev_entry = NULL;
  ASN1_TIME *last_update, *next_update;
  int i, sig, extnum, revnum;
  long version;

  /* ---------------------------------------------------------- *
   * These function calls initialize openssl for correct work.  *
   * ---------------------------------------------------------- */
  OpenSSL_add_all_algorithms();
  ERR_load_BIO_strings();
  ERR_load_crypto_strings();

  /* ---------------------------------------------------------- *
   * Create the Input/Output BIO's.                             *
   * ---------------------------------------------------------- */
  crlbio = BIO_new(BIO_s_file());
  outbio = BIO_new(BIO_s_file());
  outbio = BIO_new_fp(stdout, BIO_NOCLOSE);

  /* ---------------------------------------------------------- *
   * Load the certificate revocation list from file (DER).      *
   * ---------------------------------------------------------- */
  if (BIO_read_filename(crlbio, crl_filestr) <= 0)
    BIO_printf(outbio, "Error loading cert into memory\n");

  mycrl = d2i_X509_CRL_bio(crlbio, NULL);

  /* ---------------------------------------------------------- *
   * Print the CRL Version Number (optional)                    *
   * ---------------------------------------------------------- */
  version = X509_CRL_get_version(mycrl);
  BIO_printf(outbio, "CRL Version: %lu (0x%lx)\n", version+1, version);

  /* ---------------------------------------------------------- *
   * Print the CRL Issuer Information                           *
   * ---------------------------------------------------------- */
  issuer = X509_NAME_new();
  issuer = X509_CRL_get_issuer(mycrl);
  BIO_printf(outbio, "CRL Issuer Details: ");
  X509_NAME_print_ex(outbio, issuer, 0, XN_FLAG_ONELINE);
  BIO_printf(outbio, "\n");

  /* ---------------------------------------------------------- *
   * Print the CRL Issue Date and Time (must exist)             *
   * ---------------------------------------------------------- */
  if (last_update = X509_CRL_get_lastUpdate(mycrl)) {
    BIO_printf(outbio, "This CRL Release Date: ");
    ASN1_TIME_print(outbio, last_update);
    BIO_printf(outbio, "\n");
  }

  /* ---------------------------------------------------------- *
   * Print the CRL Next Release Date and Time (may not exist)   *
   * ---------------------------------------------------------- */
  if (next_update = X509_CRL_get_nextUpdate(mycrl)) {
    BIO_printf(outbio, "Next CRL Release Date: ");
    ASN1_TIME_print(outbio, next_update);
    BIO_printf(outbio, "\n");
  }

  /* ---------------------------------------------------------- *
   * Print the CRL Signature Algorithm                          *
   * ---------------------------------------------------------- */
  sig = OBJ_obj2nid(mycrl->sig_alg->algorithm);
  BIO_printf(outbio, " CRL Signature Format: %s\n",
             (sig == NID_undef) ? "NONE" : OBJ_nid2ln(sig));

  /* ---------------------------------------------------------- *
   * Print the Number of CRL Extensions (CRL may not have any)  *
   * ---------------------------------------------------------- */
  extnum = X509_CRL_get_ext_count(mycrl);
  BIO_printf(outbio, " Number of Extensions: %d\n", extnum);

  /* ---------------------------------------------------------- *
   * Print the Number of revoked Certs (CRL may not have any)   *
   * ---------------------------------------------------------- */
  rev = X509_CRL_get_REVOKED(mycrl);

  revnum = sk_X509_REVOKED_num(rev);
  BIO_printf(outbio, "Found # revoked certs: %d\n", revnum);

  /* ---------------------------------------------------------- *
   * Print the revoked Cert Info if avail, but no more then 10  *
   * ---------------------------------------------------------- */
  if (revnum > 0 && revnum > 10) revnum = 10;

  for(i = 0; i < revnum; i++) {
    rev_entry = sk_X509_REVOKED_value(rev, i);
    BIO_printf(outbio, "Revocation #: %d S/N: ", i);
    i2a_ASN1_INTEGER(outbio, rev_entry->serialNumber);
    BIO_printf(outbio, " Date: ");
    ASN1_TIME_print(outbio, rev_entry->revocationDate);

    // entries *can* have extensions, e.g. the revocation reason
    X509V3_extensions_print(outbio, "extensions: ",
                            rev_entry->extensions, 0, 8);
    BIO_printf(outbio, "\n");
  }

  X509_CRL_free(mycrl);
  BIO_free_all(crlbio);
  BIO_free_all(outbio);
  exit(0);
}

Compiling the Code


Compile the test program with:

> gcc -o crldisplay crldisplay.c -lssl -lcrypto

Example Output


The program expects a certificate revocation list (CRL) file "EVIntl2006.crl" in the current directory. I kept the name from the file I downloaded, which was available at URL http://EVIntl-crl.verisign.com/EVIntl2006.crl. At the time of writing, Verisign's CRL was 144KB, and had over 4000 revocation entries. The program will display the CRL file content, similar to the output shown below:

fm@susie:~> ./crldisplay
CRL Version: 1 (0x0)
CRL Issuer Details: C = US, O = "VeriSign, Inc.", OU = VeriSign Trust Network, OU = Terms of use at https://www.verisign.com/rpa (c)06, CN = VeriSign Class 3 Extended Validation SSL SGC CA
This CRL Release Date: Feb  1 09:00:11 2015 GMT
Next CRL Release Date: Feb  8 09:00:11 2015 GMT
 CRL Signature Format: sha1WithRSAEncryption
 Number of Extensions: 0
Found # revoked certs: 4046
Revocation #: 0 S/N: 01127506893B13FF8847CBA538EDDD5B Date: May  1 17:18:52 2013 GMT
Revocation #: 1 S/N: 0113C239AB7F4B7F48425EA5F7377BAF Date: Dec 27 01:03:24 2013 GMT
Revocation #: 2 S/N: 012E5C908F002B46F78F7CB737A59E99 Date: Aug  8 16:05:10 2013 GMT
Revocation #: 3 S/N: 0142AC2BAA20DEC6C7B293298FAB27CF Date: Oct 15 01:10:39 2014 GMT
Revocation #: 4 S/N: 014C23A63FE0A9CB7C27F4D3B1D57305 Date: Mar 25 16:23:13 2014 GMT
Revocation #: 5 S/N: 0153D4CD45EEC6F2D3BE57DD64728874 Date: Feb 11 16:20:52 2013 GMT
Revocation #: 6 S/N: 015531DE79F0595635681C8BB357C4E7 Date: Jan 23 15:21:31 2014 GMT
Revocation #: 7 S/N: 01631E19675C3AB1151995335F10894B Date: Mar 26 15:33:40 2014 GMT
Revocation #: 8 S/N: 0167C12EB0B259BE83D56B33BB6AEEF1 Date: Jul 30 09:32:15 2014 GMT
Revocation #: 9 S/N: 017F650CBF4EAC1F8872A56AAB167511 Date: Jun 21 01:42:00 2013 GMT

Remarks


Note: The OpenSSL commandline can display CRL file information, e.g. using openssl crl -inform DER -in EVIntl2006.crl -noout -text.


OpenSSL Logo

Topics:

Source:

Documentation: