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.