Commit 010fa0b3 authored by Dr. Stephen Henson's avatar Dr. Stephen Henson
Browse files

Tidy up CRL handling by checking for critical extensions when it is

loaded. Add new function X509_CRL_get0_by_serial() to lookup a revoked
entry to avoid the need to access the structure directly.

Add new X509_CRL_METHOD to allow common CRL operations (verify, lookup) to be
redirected.
parent 4ca7d975
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -4,6 +4,12 @@

 Changes between 0.9.8d and 0.9.9  [xx XXX xxxx]

  *) Add an X509_CRL_METHOD structure to allow CRL processing to be redirected
     to external functions. This can be used to increase CRL handling 
     efficiency especially when CRLs are very large by (for example) storing
     the CRL revoked certificates in a database.
     [Steve Henson]

  *) Overhaul of by_dir code. Add support for dynamic loading of CRLs so
     new CRLs added to a directory can be used. New command line option
     -verify_return_error to s_client and s_server. This causes real errors
+15 −0
Original line number Diff line number Diff line
@@ -113,3 +113,18 @@ struct evp_pkey_asn1_method_st
	int (*old_priv_encode)(const EVP_PKEY *pkey, unsigned char **pder);

	} /* EVP_PKEY_ASN1_METHOD */;

/* Method to handle CRL access.
 * In general a CRL could be very large (several Mb) and can consume large
 * amounts of resources if stored in memory by multiple processes.
 * This method allows general CRL operations to be redirected to more
 * efficient callbacks: for example a CRL entry database.
 */

struct x509_crl_method_st
	{
	int (*crl_init)(X509_CRL *crl);
	int (*crl_free)(X509_CRL *crl);
	int (*crl_lookup)(X509_CRL *crl, X509_REVOKED **ret, ASN1_INTEGER *ser);
	int (*crl_verify)(X509_CRL *crl, EVP_PKEY *pk);
	};
+71 −0
Original line number Diff line number Diff line
@@ -58,6 +58,7 @@

#include <stdio.h>
#include "cryptlib.h"
#include "asn1_locl.h"
#include <openssl/asn1t.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
@@ -111,6 +112,9 @@ static int crl_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
								void *exarg)
	{
	X509_CRL *crl = (X509_CRL *)*pval;
	STACK_OF(X509_EXTENSION) *exts;
	X509_EXTENSION *ext;
	int idx;

	switch(operation)
		{
@@ -119,6 +123,7 @@ static int crl_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
		crl->akid = NULL;
		crl->flags = 0;
		crl->idp_flags = 0;
		crl->meth = 0;
		break;

		case ASN1_OP_D2I_POST:
@@ -132,9 +137,37 @@ static int crl_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,

		crl->akid = X509_CRL_get_ext_d2i(crl,
				NID_authority_key_identifier, NULL, NULL);	
		if (crl->meth && crl->meth->crl_init)
			return crl->meth->crl_init(crl);

		/* See if we have any unhandled critical CRL extensions and 
		 * indicate this in a flag. We only currently handle IDP so
		 * anything else critical sets the flag.
		 *
		 * This code accesses the X509_CRL structure directly:
		 * applications shouldn't do this.
		 */

		exts = crl->crl->extensions;

		for (idx = 0; idx < sk_X509_EXTENSION_num(exts); idx++)
			{
			ext = sk_X509_EXTENSION_value(exts, idx);
			if (ext->critical > 0)
				{
				/* We handle IDP now so permit it */
				if (OBJ_obj2nid(ext->object) ==
					NID_issuing_distribution_point)
					continue;
				crl->flags |= EXFLAG_CRITICAL;
				break;
				}
			}
		break;

		case ASN1_OP_FREE_POST:
		if (crl->meth && crl->meth->crl_free)
			return crl->meth->crl_free(crl);
		if (crl->akid)
			AUTHORITY_KEYID_free(crl->akid);
		if (crl->idp)
@@ -217,6 +250,44 @@ int X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev)
	return 1;
}

int X509_CRL_verify(X509_CRL *crl, EVP_PKEY *r)
	{
	if (crl->meth && crl->meth->crl_verify)
		return crl->meth->crl_verify(crl, r);
	return(ASN1_item_verify(ASN1_ITEM_rptr(X509_CRL_INFO),
		crl->sig_alg, crl->signature,crl->crl,r));
	}

int X509_CRL_get0_by_serial(X509_CRL *crl,
		X509_REVOKED **ret, ASN1_INTEGER *serial)
	{
	X509_REVOKED rtmp;
	int idx;
	if (crl->meth && crl->meth->crl_lookup)
		return crl->meth->crl_lookup(crl, ret, serial);
	rtmp.serialNumber = serial;
	/* Sort revoked into serial number order if not already sorted.
	 * Do this under a lock to avoid race condition.
 	 */
	if (!sk_X509_REVOKED_is_sorted(crl->crl->revoked))
		{
		CRYPTO_w_lock(CRYPTO_LOCK_X509_CRL);
		sk_X509_REVOKED_sort(crl->crl->revoked);
		CRYPTO_w_unlock(CRYPTO_LOCK_X509_CRL);
		}
	idx = sk_X509_REVOKED_find(crl->crl->revoked, &rtmp);
	/* If found assume revoked: want something cleverer than
	 * this to handle entry extensions in V2 CRLs.
	 */
	if(idx >= 0)
		{
		if (ret)
			*ret = sk_X509_REVOKED_value(crl->crl->revoked, idx);
		return 1;
		}
	return 0;
	}

IMPLEMENT_STACK_OF(X509_REVOKED)
IMPLEMENT_ASN1_SET_OF(X509_REVOKED)
IMPLEMENT_STACK_OF(X509_CRL)
+2 −0
Original line number Diff line number Diff line
@@ -143,6 +143,8 @@ typedef struct ecdsa_method ECDSA_METHOD;
typedef struct x509_st X509;
typedef struct X509_algor_st X509_ALGOR;
typedef struct X509_crl_st X509_CRL;
typedef struct x509_crl_method_st X509_CRL_METHOD;
typedef struct x509_revoked_st X509_REVOKED;
typedef struct X509_name_st X509_NAME;
typedef struct X509_pubkey_st X509_PUBKEY;
typedef struct x509_store_st X509_STORE;
+5 −2
Original line number Diff line number Diff line
@@ -420,13 +420,13 @@ typedef struct x509_cert_pair_st {
			XN_FLAG_FN_LN | \
			XN_FLAG_FN_ALIGN)

typedef struct X509_revoked_st
struct x509_revoked_st
	{
	ASN1_INTEGER *serialNumber;
	ASN1_TIME *revocationDate;
	STACK_OF(X509_EXTENSION) /* optional */ *extensions;
	int sequence; /* load sequence */
	} X509_REVOKED;
	};

DECLARE_STACK_OF(X509_REVOKED)
DECLARE_ASN1_SET_OF(X509_REVOKED)
@@ -460,6 +460,7 @@ struct X509_crl_st
#ifndef OPENSSL_NO_SHA
	unsigned char sha1_hash[SHA_DIGEST_LENGTH];
#endif
	X509_CRL_METHOD *meth;
	} /* X509_CRL */;

DECLARE_STACK_OF(X509_CRL)
@@ -969,6 +970,8 @@ DECLARE_ASN1_FUNCTIONS(X509_CRL_INFO)
DECLARE_ASN1_FUNCTIONS(X509_CRL)

int X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev);
int X509_CRL_get0_by_serial(X509_CRL *crl,
		X509_REVOKED **ret, ASN1_INTEGER *serial);

X509_PKEY *	X509_PKEY_new(void );
void		X509_PKEY_free(X509_PKEY *a);
Loading