I'd like to propose an enhancement I've worked on recently:
integrating OCSP and CRL revocation checks when verifying a
certificate using X509_STORE. It does not break compatibility with the
existing mechanism, it just adds additonal parameters to allow OCSP
revocation checking as an opt-in feature.

I added the features based on the sources in HEAD, so I'm not sure if
and how far this could be backported.

I already apologize for the long mail, but I wanted to explain my
motivations to make reviewing the code easier, and also to make it
easier to spot mistakes I made.

The main motivation was to add OCSP support to the verification
process and to minimize the implementation effort for clients by
providing them an implementation that a) covers most cases
(particularly web SSL/TLS connections) and b) minimizes the PKI
expertise needed.  Client implementation effort is now reduced to
simply providing two callbacks that are solely responsible of
downloading either a CRL or the OCSP response from a given URL (and
sending the request data in the OCSP case). Once HTTP is supported,
default implementations for those two callbacks could also be added.

Overview of new features:

CRL integration:

- in addition to the already existing get_crl callback (that was set
to NULL by default), a dl_crl callback is added and there is a default
implementation for get_crl. This default implementation tries to look
up a download URL in the CRL distribution points of the current
certificate. If it finds one, it passes the URL to the dl_crl callback
(NULL by default, has to be provided by the client); i.e. dl_crl is
responsible of downloading the CRL and passing it back.

OCSP integration:

- can be turned on with the flag X509_V_FLAG_OCSP_CHECK. Semantics are
that whenever a CRL check would be made for a certificate, the default
implementation tries to check via OCSP first. This can have three
possible outcomes:
    1. The certificate is valid
    2. The certificate is revoked
    3. The certificate has status UNKNOWN, an error occurs while
trying to validate via OCSP, or the OCSP response is invalid
In case 3, the implementation falls back to CRL, i.e. it tries to
check revocation via the existing CRL mechanism.
In case 1, CRL validation is skipped, since we can already be sure of
the certificate's validity.
Case 2 is the same except that we can be sure of the certificate's revocation.

- OCSP is controlled using the new structure X509_OCSP_CTX which can
be set for X509_STORE and X509_STORE_CTX. X509_OCSP_CTX contains OCSP
flags (those already existing for the present OCSP code) and various
callback methods:
    1. dl_ocsp: similar to dl_crl - takes a URL and is simply
responsible of retrieving the OCSP_RESPONSE by sending the
        OCSP_REQUEST to a specific URL. NULL by default, must be set
and implemented by the client.
    2. get_ocsp: Again similar to get_crl. Tries to look up a valid
OCSP URL in the certificate's AuthorityAccessInformation extension. If
        found, the default implementation delegates to dl_ocsp.
    3. check_ocsp: Responsible of verifying a OCSP_RESPONSE with
respect to a given certificate, issuer certificate and
        OCSP_REQUEST. Default implementation exists.

Additionally, there are fields to support signed OCSP requests and a
stack of X509 to represent "authorized responders", i.e. to allow
support of the authorized responder approach mentioned in RFC 2560.

There are a few things I noticed in the existing implementation that
seemed strange and that I changed. Please correct me if my thoughts
were wrong:

In File x509_vfy.c

1. If a "get_crl" callback is set in the X509_STORE(_CTX), then there
seem to be some complications with the existing workflow.
a) current_crl_score and current_reasons are never explicitly set to a
default value in X509_STORE_CTX_init. I explicitly set them to 0 on
initialization.

b. In "static int check_cert(X509_STORE_CTX *ctx)". There's the lines:

                if (ctx->get_crl)
                        ok = ctx->get_crl(ctx, &crl, x);
                else
                        ok = get_crl_delta(ctx, &crl, &dcrl, x);

I made this:

                if (ctx->get_crl)
                       {
                       ok = ctx->get_crl(ctx, &crl, x);
                       if (ok)
                                {
                                /* add crl to ctx->crls, so that it will get 
considered in
get_crl_delta */
                                }
                        }

                ok = get_crl_delta(ctx, &crl, &dcrl, x);

Otherwise you will inevitably run into an error in check_crl for the
current_crl_score checks; current_reasons is never set to
CRLDP_ALL_REASONS. This might cause an infinite loop if you set the
current_crl_score appropriately in your own get_crl callback but
forget to set current_reasons. If the above code snippet is applied,
current_crl_score and current_reasons are updated correctly and the
CRL download will fit nicely in the existing workflow.

2. static int check_revocation(X509_STORE_CTX *ctx): There's

if (ctx->param->flags & X509_V_FLAG_CRL_CHECK_ALL)
        last = sk_X509_num(ctx->chain) - 1;

shouldn't it be

if (ctx->param->flags & X509_V_FLAG_CRL_CHECK_ALL)
        last = sk_X509_num(ctx->chain) - 2;

We already have a chain with a trusted anchor certificate at the point
when we enter revocation checking. Additionally, if the anchor happens
to be a self-signed certificate, it's very unlikely to find a CRL for
this certificate and you will run into an error.

In file ocsp_vfy.c:

int OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
                                X509_STORE *st, unsigned long flags):

Upon verification of an OCSP_BASICRESP, there's the lines:

if(flags & OCSP_NOCHAIN)
                        init_res = X509_STORE_CTX_init(&ctx, st, signer, NULL);
                else
                        init_res = X509_STORE_CTX_init(&ctx, st, signer, 
bs->certs);

The else case seems insufficient. Imagine the case where the CA just
adds the OCSP signing certificate and no intermediate certificates.
Then the existing call is doomed to fail. I changed this to add not
only bs->certs, but also the certificates already available in certs,
as they possibly contain the necessary intermediate certificates.


Thanks in advance for any comments and corrections!

Best regards,
Martin Boßlet

Index: crypto/ossl_typ.h
===================================================================
RCS file: /v/openssl/cvs/openssl/crypto/ossl_typ.h,v
retrieving revision 1.24
diff -u -r1.24 ossl_typ.h
--- crypto/ossl_typ.h	13 Dec 2010 18:15:27 -0000	1.24
+++ crypto/ossl_typ.h	30 Dec 2010 01:13:12 -0000
@@ -197,7 +197,11 @@
 					int idx, long argl, void *argp);
 
 typedef struct ocsp_req_ctx_st OCSP_REQ_CTX;
+typedef struct ocsp_request_st OCSP_REQUEST;
 typedef struct ocsp_response_st OCSP_RESPONSE;
+typedef struct ocsp_basic_response_st OCSP_BASICRESP;
 typedef struct ocsp_responder_id_st OCSP_RESPID;
 
+typedef struct x509_ocsp_ctx_st X509_OCSP_CTX;
+
 #endif /* def HEADER_OPENSSL_TYPES_H */
Index: crypto/ocsp/ocsp.h
===================================================================
RCS file: /v/openssl/cvs/openssl/crypto/ocsp/ocsp.h,v
retrieving revision 1.42
diff -u -r1.42 ocsp.h
--- crypto/ocsp/ocsp.h	30 Sep 2009 21:40:55 -0000	1.42
+++ crypto/ocsp/ocsp.h	30 Dec 2010 01:13:13 -0000
@@ -88,7 +88,8 @@
 #define OCSP_NOCHECKS			0x100
 #define OCSP_TRUSTOTHER			0x200
 #define OCSP_RESPID_KEY			0x400
-#define OCSP_NOTIME			0x800
+#define OCSP_NOTIME                     0x800
+#define OCSP_NONONCE                    0x1000
 
 /*   CertID ::= SEQUENCE {
  *       hashAlgorithm            AlgorithmIdentifier,
@@ -150,11 +151,11 @@
  *       tbsRequest                  TBSRequest,
  *       optionalSignature   [0]     EXPLICIT Signature OPTIONAL }
  */
-typedef struct ocsp_request_st
+struct ocsp_request_st
 	{
 	OCSP_REQINFO *tbsRequest;
 	OCSP_SIGNATURE *optionalSignature; /* OPTIONAL */
-	} OCSP_REQUEST;
+	} /* OCSP_REQUEST */;
 
 /*   OCSPResponseStatus ::= ENUMERATED {
  *       successful            (0),      --Response has valid confirmations
@@ -300,13 +301,13 @@
      that it doesn't do the double hashing that the RFC seems to say one
      should.  Therefore, all relevant functions take a flag saying which
      variant should be used.	-- Richard Levitte, OpenSSL team and CeloCom */
-typedef struct ocsp_basic_response_st
+struct ocsp_basic_response_st
 	{
 	OCSP_RESPDATA *tbsResponseData;
 	X509_ALGOR *signatureAlgorithm;
 	ASN1_BIT_STRING *signature;
 	STACK_OF(X509) *certs;
-	} OCSP_BASICRESP;
+	} /* OCSP_BASICRESP */;
 
 /*
  *   CRLReason ::= ENUMERATED {
@@ -555,6 +556,8 @@
 
 int OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
 				X509_STORE *st, unsigned long flags);
+int OCSP_basic_find_signer(X509 **psigner, OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
+				unsigned long flags);
 
 /* BEGIN ERROR CODES */
 /* The following lines are auto generated by the script mkerr.pl. Any changes
Index: crypto/ocsp/ocsp_vfy.c
===================================================================
RCS file: /v/openssl/cvs/openssl/crypto/ocsp/ocsp_vfy.c,v
retrieving revision 1.16
diff -u -r1.16 ocsp_vfy.c
--- crypto/ocsp/ocsp_vfy.c	29 Dec 2008 16:11:55 -0000	1.16
+++ crypto/ocsp/ocsp_vfy.c	30 Dec 2010 01:13:13 -0000
@@ -60,8 +60,6 @@
 #include <openssl/err.h>
 #include <string.h>
 
-static int ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
-				X509_STORE *st, unsigned long flags);
 static X509 *ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_RESPID *id);
 static int ocsp_check_issuer(OCSP_BASICRESP *bs, STACK_OF(X509) *chain, unsigned long flags);
 static int ocsp_check_ids(STACK_OF(OCSP_SINGLERESP) *sresp, OCSP_CERTID **ret);
@@ -77,9 +75,10 @@
 	{
 	X509 *signer, *x;
 	STACK_OF(X509) *chain = NULL;
+	STACK_OF(X509) *intermediates = NULL;
 	X509_STORE_CTX ctx;
 	int i, ret = 0;
-	ret = ocsp_find_signer(&signer, bs, certs, st, flags);
+	ret = OCSP_basic_find_signer(&signer, bs, certs, flags);
 	if (!ret)
 		{
 		OCSPerr(OCSP_F_OCSP_BASIC_VERIFY, OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND);
@@ -105,7 +104,25 @@
 		if(flags & OCSP_NOCHAIN)
 			init_res = X509_STORE_CTX_init(&ctx, st, signer, NULL);
 		else
-			init_res = X509_STORE_CTX_init(&ctx, st, signer, bs->certs);
+			{
+			if (!(intermediates = sk_X509_dup(bs->certs)))
+				{
+				OCSPerr(OCSP_F_OCSP_BASIC_VERIFY,ERR_R_X509_LIB);
+				goto end;
+				}
+			if (certs)
+				{
+				for (i=0; i < sk_X509_num(certs); i++)
+					{
+					if (!(sk_X509_push(intermediates, sk_X509_value(certs, i))))
+						{
+						OCSPerr(OCSP_F_OCSP_BASIC_VERIFY,ERR_R_X509_LIB);
+						goto end;
+						}
+					}
+				}
+			init_res = X509_STORE_CTX_init(&ctx, st, signer, intermediates);
+			}
 		if(!init_res)
 			{
 			OCSPerr(OCSP_F_OCSP_BASIC_VERIFY,ERR_R_X509_LIB);
@@ -155,16 +172,17 @@
 
 	end:
 	if(chain) sk_X509_pop_free(chain, X509_free);
+	if (intermediates) sk_X509_free(intermediates); /* free stack only, leave certs */
 	return ret;
 	}
 
 
-static int ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
-				X509_STORE *st, unsigned long flags)
+int OCSP_basic_find_signer(X509 **psigner, OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
+				unsigned long flags)
 	{
 	X509 *signer;
 	OCSP_RESPID *rid = bs->tbsResponseData->responderId;
-	if ((signer = ocsp_find_signer_sk(certs, rid)))
+	if (certs && (signer = ocsp_find_signer_sk(certs, rid)))
 		{
 		*psigner = signer;
 		return 2;
Index: crypto/x509/x509.h
===================================================================
RCS file: /v/openssl/cvs/openssl/crypto/x509/x509.h,v
retrieving revision 1.172
diff -u -r1.172 x509.h
--- crypto/x509/x509.h	3 Oct 2010 18:58:09 -0000	1.172
+++ crypto/x509/x509.h	30 Dec 2010 01:13:14 -0000
@@ -1257,6 +1257,7 @@
 #define X509_F_X509_STORE_CTX_GET1_ISSUER		 146
 #define X509_F_X509_STORE_CTX_INIT			 143
 #define X509_F_X509_STORE_CTX_NEW			 142
+#define X509_F_X509_OCSP_CTX_NEW                         199
 #define X509_F_X509_STORE_CTX_PURPOSE_INHERIT		 134
 #define X509_F_X509_TO_X509_REQ				 126
 #define X509_F_X509_TRUST_ADD				 133
@@ -1291,6 +1292,8 @@
 #define X509_R_WRONG_LOOKUP_TYPE			 112
 #define X509_R_WRONG_TYPE				 122
 
+
+
 #ifdef  __cplusplus
 }
 #endif
Index: crypto/x509/x509_lu.c
===================================================================
RCS file: /v/openssl/cvs/openssl/crypto/x509/x509_lu.c,v
retrieving revision 1.34
diff -u -r1.34 x509_lu.c
--- crypto/x509/x509_lu.c	19 Feb 2010 18:27:07 -0000	1.34
+++ crypto/x509/x509_lu.c	30 Dec 2010 01:13:15 -0000
@@ -200,6 +200,8 @@
 	ret->lookup_crls = 0;
 	ret->cleanup = 0;
 
+	ret->ocsp_ctx = NULL;
+
 	if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509_STORE, ret, &ret->ex_data))
 		{
 		sk_X509_OBJECT_free(ret->objs);
@@ -248,6 +250,8 @@
 	sk_X509_LOOKUP_free(sk);
 	sk_X509_OBJECT_pop_free(vfy->objs, cleanup);
 
+	if (vfy->ocsp_ctx) X509_OCSP_CTX_free(vfy->ocsp_ctx);
+
 	CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509_STORE, vfy, &vfy->ex_data);
 	if (vfy->param)
 		X509_VERIFY_PARAM_free(vfy->param);
Index: crypto/x509/x509_txt.c
===================================================================
RCS file: /v/openssl/cvs/openssl/crypto/x509/x509_txt.c,v
retrieving revision 1.25
diff -u -r1.25 x509_txt.c
--- crypto/x509/x509_txt.c	25 Dec 2010 20:45:58 -0000	1.25
+++ crypto/x509/x509_txt.c	30 Dec 2010 01:13:15 -0000
@@ -186,6 +186,43 @@
 	case X509_V_ERR_PATH_LOOP:
 		return("Path Loop");
 
+	case X509_V_ERR_ERROR_IN_OCSP_PRODUCED_AT_FIELD:
+		return("format error in OCSP producedAt field");
+	case X509_V_ERR_ERROR_IN_OCSP_THIS_UPDATE_FIELD:
+		return("format error in OCSP thisUpdate field");
+	case X509_V_ERR_ERROR_IN_OCSP_NEXT_UPDATE_FIELD:
+		return("format error in OCSP nextUpdate field");
+	case X509_V_ERR_OCSP_NOT_YET_VALID:
+		return("OCSP response is not valid yet");
+	case X509_V_ERR_OCSP_HAS_EXPIRED:
+		return("OCSP response has expired");
+	case X509_V_ERR_UNABLE_TO_FIND_AIA:
+		return("unable to find AuthorityInformationAccess extension in certificate");
+	case X509_V_ERR_UNABLE_TO_FIND_AIA_URL:
+		return("unable to find OCSP URL in AuthorityInformationAccess extension");
+	case X509_V_ERR_ERROR_RETRIEVING_OCSP_RESPONSE:
+		return("error retrieving the OCSP response remotely");
+	case X509_V_ERR_OCSP_RESPONSE_NOT_SUCCESSFUL:
+		return("OCSP response had a status other than SUCCESSFUL");
+	case X509_V_ERR_OCSP_SIGNATURE_FAILURE:
+		return("error when validating the OCSP signature");
+	case X509_V_ERR_OCSP_UNSUPPORTED_MULTIPLE_RESP:
+		return("multiple OCSP certIDs are not supported");
+	case X509_V_ERR_OCSP_CERT_ID_MISMATCH:
+		return("certID in OCSP request differs from that in response");
+	case X509_V_ERR_OCSP_NONCE_MISMATCH:
+		return("nonces differ in OCSP request and response");
+	case X509_V_ERR_UNABLE_TO_FIND_CRL_DPS:
+		return("unable to find cRLDistributionPoint extension in certificate");
+	case X509_V_ERR_UNABLE_TO_FIND_CRL_DP_URL:
+		return("unable to find CRL URL in cRLDistributionPoint extension");
+	case X509_V_ERR_ERROR_RETRIEVING_CRL:
+		return("error retrieving the CRL remotely");
+	case  X509_V_ERR_OCSP_SIGNING_CERT_NOT_FOUND:
+		return("could not find OCSP signing certificate");
+	case X509_V_ERR_OCSP_CERT_ISSUER_NOT_TRUSTED:
+		return("OCSP certificate issuer is not trusted");
+
 	default:
 		BIO_snprintf(buf,sizeof buf,"error number %ld",n);
 		return(buf);
Index: crypto/x509/x509_vfy.c
===================================================================
RCS file: /v/openssl/cvs/openssl/crypto/x509/x509_vfy.c,v
retrieving revision 1.119
diff -u -r1.119 x509_vfy.c
--- crypto/x509/x509_vfy.c	25 Dec 2010 20:45:58 -0000	1.119
+++ crypto/x509/x509_vfy.c	30 Dec 2010 01:13:16 -0000
@@ -69,6 +69,9 @@
 #include <openssl/x509.h>
 #include <openssl/x509v3.h>
 #include <openssl/objects.h>
+#include <openssl/ocsp.h>
+#include <openssl/ssl.h>
+#include <openssl/x509_vfy.h>
 
 /* CRL score values */
 
@@ -118,6 +121,7 @@
 static int check_cert(X509_STORE_CTX *ctx);
 static int check_policy(X509_STORE_CTX *ctx);
 
+static int get_crl(X509_STORE_CTX *ctx, X509_CRL **pcrl, X509 *x);
 static int get_crl_score(X509_STORE_CTX *ctx, X509 **pissuer,
 			unsigned int *preasons,
 			X509_CRL *crl, X509 *x);
@@ -134,6 +138,19 @@
 			STACK_OF(X509) *cert_path,
 			STACK_OF(X509) *crl_path);
 
+static int check_cert_ocsp(X509_STORE_CTX *ctx, X509* x, X509 *xi);
+static int check_ocsp(X509_STORE_CTX *ctx,
+		    OCSP_REQUEST *request,
+		    OCSP_RESPONSE *ocsp,
+		    X509 *x,
+		    X509 *issuer);
+static int check_ocsp_times(X509_STORE_CTX *ctx, OCSP_BASICRESP *ocsp);
+static int get_ocsp(X509_STORE_CTX *ctx,
+		    OCSP_REQUEST **request,
+		    OCSP_RESPONSE **ocsp,
+		    X509 *x,
+		    X509 *issuer);
+
 static int internal_verify(X509_STORE_CTX *ctx);
 const char X509_version[]="X.509" OPENSSL_VERSION_PTEXT;
 
@@ -719,7 +736,8 @@
 	if (!(ctx->param->flags & X509_V_FLAG_CRL_CHECK))
 		return 1;
 	if (ctx->param->flags & X509_V_FLAG_CRL_CHECK_ALL)
-		last = sk_X509_num(ctx->chain) - 1;
+		/* do not check the root of the chain, it's trusted already */
+		last = sk_X509_num(ctx->chain) - 2;
 	else
 		{
 		/* If checking CRL paths this isn't the EE certificate */
@@ -736,23 +754,98 @@
 	return 1;
 	}
 
+/* Returns
+ *  0  if an error occurs or if the certificate has a status of UNKNOWN (i.e.
+ *  we want to use CRL information as a fallback)
+ *  1  if the response was valid and the certificate is also (i.e. we can skip
+ *  CRL lookup)
+ *  -1 if the certificate is revoked (i.e. we can also skip CRL lookup)
+ */
+static int check_cert_ocsp(X509_STORE_CTX *ctx, X509* x, X509 *xi)
+	{
+	OCSP_REQUEST *req = NULL;
+	OCSP_RESPONSE *resp = NULL;
+	int ok = 0;
+
+	/* skip if OCSP checking was not requested or the retrieval method
+	   is missing
+	 */
+	if(!(ctx->ocsp_ctx->get_ocsp))
+		return 0;
+	if (!(ok = ctx->ocsp_ctx->get_ocsp(ctx, &req, &resp, x, xi)))
+	    goto end;
+
+	ctx->current_ocsp = OCSP_response_get1_basic(resp);
+	ok = ctx->ocsp_ctx->check_ocsp(ctx, req, resp, x, xi);
+
+end:
+	ctx->current_ocsp = NULL;
+	if (req) OCSP_REQUEST_free(req);
+	if (resp) OCSP_RESPONSE_free(resp);
+	if (!ok)
+		{
+		ok = ctx->verify_cb(0, ctx);
+		}
+	return ok;
+	}
+
 static int check_cert(X509_STORE_CTX *ctx)
 	{
-	X509_CRL *crl = NULL, *dcrl = NULL;
-	X509 *x;
+    	X509_CRL *crl = NULL, *dcrl = NULL;
+	X509 *x, *xi;
 	int ok, cnum;
 	cnum = ctx->error_depth;
 	x = sk_X509_value(ctx->chain, cnum);
+	xi = sk_X509_value(ctx->chain, cnum + 1);
 	ctx->current_cert = x;
 	ctx->current_issuer = NULL;
 	ctx->current_reasons = 0;
+
+	if (ctx->param->flags & X509_V_FLAG_OCSP_CHECK)
+		{
+		ok = check_cert_ocsp(ctx, x, xi);
+		if (ok == 1) /* certificate is valid, skip CRLs */
+			goto err;
+		if (ok == -1) /* certificate is revoked, skip CRLs */
+			{
+			    ctx->error = X509_V_ERR_CERT_REVOKED;
+			    ok = 0;
+			    goto err;
+			}
+		}
+
+	/* (ok == 0 if OCSP was enabled)
+	 * means revocation status was not detectable via OCSP
+	 * -> perform CRL fallback
+	 */
 	while (ctx->current_reasons != CRLDP_ALL_REASONS)
 		{
 		/* Try to retrieve relevant CRL */
 		if (ctx->get_crl)
+			{
 			ok = ctx->get_crl(ctx, &crl, x);
-		else
-			ok = get_crl_delta(ctx, &crl, &dcrl, x);
+			if (ok)
+				{
+				/* Add downloaded CRL to the ones already constained in
+				 * store and then proceed with the usual workflow
+				 */
+				if (!ctx->crls && !(ctx->crls = sk_X509_CRL_new_null()))
+					{
+					ctx->error = X509_V_ERR_OUT_OF_MEM;
+					ok = ctx->verify_cb(0, ctx);
+					goto err;
+					}
+				if (!sk_X509_CRL_push(ctx->crls, crl))
+					{
+					ctx->error = X509_V_ERR_OUT_OF_MEM;
+					ok = ctx->verify_cb(0, ctx);
+					goto err;
+					}
+				CRYPTO_add(&crl->references, 1, CRYPTO_LOCK_X509_CRL);
+				}
+			}
+
+		ok = get_crl_delta(ctx, &crl, &dcrl, x);
 		/* If error looking up CRL, nothing we can do except
 		 * notify callback
 		 */
@@ -801,6 +894,89 @@
 
 	}
 
+static int get_crl(X509_STORE_CTX *ctx, X509_CRL **pcrl, X509 *x)
+	{
+	X509_CRL *crl = NULL;
+	X509_EXTENSION *crldp_ext;
+	CRL_DIST_POINTS *crldps = NULL;
+	DIST_POINT *dp;
+	DIST_POINT_NAME *dpn;
+	GENERAL_NAMES *names;
+	GENERAL_NAME *tmp;
+	ASN1_OCTET_STRING *data;
+	int crldppos, i, j, ret = 0;
+	unsigned char *uri = NULL;
+
+	if (!ctx->dl_crl)
+		goto err;
+
+	/* Parse CRL URL from CRL DP */
+	if ((crldppos = X509_get_ext_by_NID(x, NID_crl_distribution_points, 0)) < 0)
+		{
+		ctx->error = X509_V_ERR_UNABLE_TO_FIND_CRL_DPS;
+		goto err;
+		}
+	if (!(crldp_ext = X509_get_ext(x, crldppos)))
+		{
+		ctx->error = X509_V_ERR_APPLICATION_VERIFICATION;
+		goto err;
+		}
+	if (!(data = X509_EXTENSION_get_data(crldp_ext)))
+		{
+		ctx->error = X509_V_ERR_APPLICATION_VERIFICATION;
+		goto err;
+		}
+	if (!(crldps = d2i_CRL_DIST_POINTS(NULL,
+		                           (const unsigned char **)&(data->data),
+					   data->length)))
+		{
+		ctx->error = X509_V_ERR_APPLICATION_VERIFICATION;
+		goto err;
+		}
+
+	for (i=0; i < sk_DIST_POINT_num(crldps); i++)
+		{
+		dp = sk_DIST_POINT_value(crldps, i);
+		if (!dp->distpoint)
+			continue;
+		dpn = dp->distpoint;
+		if (!dpn->name.fullname)
+			continue;
+		names = dpn->name.fullname;
+		for (j=0; j<sk_GENERAL_NAME_num(names); j++)
+			{
+			tmp = sk_GENERAL_NAME_value(names, j);
+			if(tmp->type == GEN_URI)
+				{
+				uri = tmp->d.ia5->data;
+				break;
+				}
+			}
+		}
+
+	if (!uri)
+		{
+		ctx->error = X509_V_ERR_UNABLE_TO_FIND_CRL_DP_URL;
+		goto err;
+		}
+
+	if (!(crl = ctx->dl_crl(ctx, (char*)uri)))
+		{
+		ctx->error = X509_V_ERR_ERROR_RETRIEVING_CRL;
+		goto err;
+		}
+
+	*pcrl = crl;
+	ret = 1;
+err:
+	if (crldps) CRL_DIST_POINTS_free(crldps);
+	if (!ret)
+		{
+		ret = ctx->verify_cb(0, ctx);
+		}
+	return ret;
+	}
+
 /* Check CRL times against values in X509_STORE_CTX */
 
 static int check_crl_time(X509_STORE_CTX *ctx, X509_CRL *crl, int notify)
@@ -1434,7 +1610,7 @@
 
 			if (!(ctx->current_crl_score & CRL_SCORE_SAME_PATH))
 				{
-				if (check_crl_path(ctx, ctx->current_issuer) <= 0)
+				if (check_crl_path(ctx, issuer) <= 0)
 					{
 					ctx->error = X509_V_ERR_CRL_PATH_VALIDATION_ERROR;
 					ok = ctx->verify_cb(0, ctx);
@@ -1522,6 +1698,322 @@
 	return 1;
 	}
 
+/* Check OCSP response times against values in X509_STORE_CTX */
+static int check_ocsp_times(X509_STORE_CTX *ctx, OCSP_BASICRESP *ocsp)
+	{
+	time_t *ptime;
+	int cmp, i;
+	OCSP_SINGLERESP *resp;
+
+	if (ctx->param->flags & X509_V_FLAG_USE_CHECK_TIME)
+		ptime = &ctx->param->check_time;
+	else
+		ptime = NULL;
+
+	/* first check the producedAt value */
+	cmp=X509_cmp_time(ocsp->tbsResponseData->producedAt, ptime);
+	if (cmp == 0)
+		{
+		ctx->error=X509_V_ERR_ERROR_IN_OCSP_PRODUCED_AT_FIELD;
+		goto err;
+		}
+
+	if (cmp > 0)
+		{
+		ctx->error=X509_V_ERR_OCSP_NOT_YET_VALID;
+		goto err;
+		}
+
+	for (i=0; i < sk_OCSP_SINGLERESP_num(ocsp->tbsResponseData->responses); i++)
+		{
+		resp = sk_OCSP_SINGLERESP_value(ocsp->tbsResponseData->responses, i);
+		cmp=X509_cmp_time(resp->thisUpdate, ptime);
+		if (cmp == 0)
+			{
+			ctx->error=X509_V_ERR_ERROR_IN_OCSP_THIS_UPDATE_FIELD;
+			goto err;
+			}
+
+		if (cmp > 0)
+			{
+			ctx->error=X509_V_ERR_OCSP_NOT_YET_VALID;
+			goto err;
+			}
+		if (resp->nextUpdate)
+			{
+			cmp = X509_cmp_time(resp->nextUpdate, ptime);
+			if (cmp == 0)
+				{
+				ctx->error=X509_V_ERR_ERROR_IN_OCSP_NEXT_UPDATE_FIELD;
+				goto err;
+				}
+			if (cmp < 0)
+				{
+				ctx->error=X509_V_ERR_OCSP_HAS_EXPIRED;
+				goto err;
+				}
+			}
+		}
+
+	return 1;
+
+err:
+	return ctx->verify_cb(0, ctx);
+	}
+
+
+/* Retrieves an OCSP response for x. Sets the OCSP_RESPONSE, but also
+ * the OCSP_REQUEST that was created.
+ * Returns 0 in case of an error, 1 otherwise.
+ */
+static int get_ocsp(X509_STORE_CTX *ctx,
+		    OCSP_REQUEST **request,
+		    OCSP_RESPONSE **ocsp,
+		    X509 *x,
+		    X509 *issuer)
+	{
+	OCSP_REQUEST *req;
+	OCSP_RESPONSE *resp;
+	OCSP_CERTID *id;
+	X509_EXTENSION *aia_ext;
+	AUTHORITY_INFO_ACCESS *aia = NULL;
+	ACCESS_DESCRIPTION *ocsp_desc = NULL, *tmp;
+	ASN1_OCTET_STRING *data;
+	int aiapos, i, ok = 0;
+	unsigned char *uri;
+
+	if (!ctx->ocsp_ctx->dl_ocsp)
+		goto err;
+	
+	if (!(req = OCSP_REQUEST_new()))
+		{
+		ctx->error = X509_V_ERR_OUT_OF_MEM;
+		goto err;
+		}
+	id = OCSP_cert_to_id(EVP_sha1(), x, issuer);
+	if(!id || !OCSP_request_add0_id(req, id))
+		{
+		ctx->error = X509_V_ERR_APPLICATION_VERIFICATION;
+		goto err;
+		}
+
+	/* add a nonce if requested */
+	if (!(ctx->ocsp_ctx->flags & OCSP_NONONCE))
+		OCSP_request_add1_nonce(req, NULL, -1);
+
+	/* if signer certificate, key and digest are set, then sign the request */
+	if (ctx->ocsp_ctx->signer)
+		{
+		if (!(ctx->ocsp_ctx->key && ctx->ocsp_ctx->dgst))
+			{
+			ctx->error = X509_V_ERR_OCSP_SIGNING_FAILED;
+			goto err;
+			}
+		if (!(OCSP_request_sign(req,
+					ctx->ocsp_ctx->signer,
+					ctx->ocsp_ctx->key,
+					ctx->ocsp_ctx->dgst,
+					ctx->ocsp_ctx->signer_certs,
+					ctx->ocsp_ctx->flags)))
+			{
+			ctx->error = X509_V_ERR_OCSP_SIGNING_FAILED;
+			goto err;
+			}
+		}
+
+	/* Parse responder URL from AIA */
+	if ((aiapos = X509_get_ext_by_NID(x, NID_info_access, 0)) < 0)
+		{
+		ctx->error = X509_V_ERR_UNABLE_TO_FIND_AIA;
+		goto err;
+		}
+	if (!(aia_ext = X509_get_ext(x, aiapos)))
+		{
+		ctx->error = X509_V_ERR_APPLICATION_VERIFICATION;
+		goto err;
+		}
+	if (!(data = X509_EXTENSION_get_data(aia_ext)))
+		{
+		ctx->error = X509_V_ERR_APPLICATION_VERIFICATION;
+		goto err;
+		}
+	if (!(aia = d2i_AUTHORITY_INFO_ACCESS(NULL, 
+		                              (const unsigned char **)&(data->data),
+					      data->length)))
+		{
+		ctx->error = X509_V_ERR_APPLICATION_VERIFICATION;
+		goto err;
+		}
+
+	for (i=0; i < sk_ACCESS_DESCRIPTION_num(aia); i++)
+		{
+		tmp = sk_ACCESS_DESCRIPTION_value(aia, i);
+		if (OBJ_cmp(tmp->method, OBJ_nid2obj(NID_ad_OCSP)) == 0)
+			{
+			ocsp_desc = tmp;
+			break;
+			}
+		}
+	/* We are only interested in an ACCESS_DESCRIPTION for OCSP of type URI*/
+	if (!ocsp_desc || !ocsp_desc->location->type == GEN_URI)
+		{
+		ctx->error = X509_V_ERR_UNABLE_TO_FIND_AIA_URL;
+		goto err;
+		}
+
+	uri = ocsp_desc->location->d.ia5->data;
+	if (!(resp = ctx->ocsp_ctx->dl_ocsp(ctx, req, (char*)uri)))
+		{
+		ctx->error = X509_V_ERR_ERROR_RETRIEVING_OCSP_RESPONSE;
+		goto err;
+		}
+	
+	*request = req;
+	*ocsp = resp;
+	ok = 1;
+err:
+	if (aia) AUTHORITY_INFO_ACCESS_free(aia);
+	if (!ok)
+		{
+		ok = ctx->verify_cb(0, ctx);
+		}
+	return ok;
+	}
+
+/* First validates the OCSP response and then checks the revocation status.
+ * Returns
+ *  0  if an error occurs or if the certificate has a status of UNKNOWN
+ *  1  if the response was valid and the certificate is also
+ *  -1 if the certificate is revoked
+ */
+
+static int check_ocsp(X509_STORE_CTX *ctx, 
+		    OCSP_REQUEST *request,
+		    OCSP_RESPONSE *ocsp,
+		    X509 *x,
+		    X509 *issuer)
+	{
+	int ret = 0, status;
+	unsigned long flags;
+	OCSP_ONEREQ *single_req;
+	OCSP_SINGLERESP *single_resp;
+	X509 *ocsp_cert;
+
+	OCSP_BASICRESP *basic = NULL;
+
+	/* Check the status, reject anything else than SUCCESSFUL */
+	if (OCSP_response_status(ocsp) != OCSP_RESPONSE_STATUS_SUCCESSFUL)
+		{
+		ctx->error = X509_V_ERR_OCSP_RESPONSE_NOT_SUCCESSFUL;
+		goto end;
+		}
+
+	if (!(basic = OCSP_response_get1_basic(ocsp)))
+		{
+		ctx->error = X509_V_ERR_APPLICATION_VERIFICATION;
+		goto end;
+		}
+
+	ctx->current_ocsp = basic;
+
+	/* Check if the issuer of the OCSP certificate is the same as of the
+	 * certificate currently checked.
+	 */
+	if (!(OCSP_basic_find_signer(&ocsp_cert, basic, ctx->untrusted, 0)))
+		{
+		ctx->error = X509_V_ERR_OCSP_SIGNING_CERT_NOT_FOUND;
+		goto end;
+		}
+	if (!(ctx->check_issued(ctx, ocsp_cert, issuer)))
+		{
+		/* OCSP certificate could still be one of the authorized responders */
+		if (!ctx->ocsp_ctx->auth_responders)
+			{
+			ctx->error = X509_V_ERR_OCSP_CERT_ISSUER_NOT_TRUSTED;
+			goto end;
+			}
+		int found = 0, i;
+		for (i=0; i < sk_X509_num(ctx->ocsp_ctx->auth_responders); i++)
+			{
+			if(X509_cmp(ocsp_cert, sk_X509_value(ctx->ocsp_ctx->auth_responders, i)) == 0)
+				{   
+				found = 1;
+				break;
+				}
+			}
+		if (!found)
+			{
+			ctx->error = X509_V_ERR_OCSP_CERT_ISSUER_NOT_TRUSTED;
+			goto end;
+			}
+		}
+	/* We don't need certificate path validation, issuers are equal*/
+	flags = ctx->ocsp_ctx->flags | OCSP_NOVERIFY;
+	/* Verify the signature and validate the OCSP certificate */
+	if (!(OCSP_basic_verify(basic,
+				ctx->untrusted,
+				ctx->ctx,
+				flags)))
+		{
+		ctx->error = X509_V_ERR_OCSP_SIGNATURE_FAILURE;
+		goto end;
+		}
+
+	/* We only accept one OCSP_ONEREQ and OCSP_SINGLERESP */
+	if (OCSP_request_onereq_count(request) != 1
+		    || OCSP_resp_count(basic) != 1)
+		{
+		ctx->error = X509_V_ERR_OCSP_UNSUPPORTED_MULTIPLE_RESP;
+		goto end;
+		}
+
+	single_req = sk_OCSP_ONEREQ_value(request->tbsRequest->requestList, 0);
+	/* Check whether request CertID matches response CertID */
+	if (OCSP_resp_find(basic, single_req->reqCert, -1) != 0)
+		{
+		ctx->error = X509_V_ERR_OCSP_CERT_ID_MISMATCH;
+		goto end;
+		}
+	single_resp = sk_OCSP_SINGLERESP_value(basic->tbsResponseData->responses, 0);
+
+	
+	/* Check nonces, error case if return value is <= 0 */
+	if (OCSP_check_nonce(request, basic) <= 0)
+		{
+		ctx->error = X509_V_ERR_OCSP_NONCE_MISMATCH;
+		goto end;
+		}
+
+	if (!check_ocsp_times(ctx, basic))
+		{
+		/* error set appropriately in method */
+		goto end;
+		}
+
+	status = single_resp->certStatus->type;
+	switch (status)
+		{
+		case V_OCSP_CERTSTATUS_GOOD:
+			ret = 1;
+			break;
+		case V_OCSP_CERTSTATUS_REVOKED:
+			ret = -1;
+			break;
+		case V_OCSP_CERTSTATUS_UNKNOWN:
+			ret = 0;
+			break;
+		}
+	
+end:
+	if (basic)
+		OCSP_BASICRESP_free(basic);
+	if (!ret)
+		{
+		ret = ctx->verify_cb(0, ctx);
+		}
+	return ret;
+	}
+
 static int check_policy(X509_STORE_CTX *ctx)
 	{
 	int ret;
@@ -2033,9 +2525,50 @@
 	return ctx;
 }
 
+X509_OCSP_CTX *X509_OCSP_CTX_new(void)
+{
+	X509_OCSP_CTX *ctx;
+	ctx = (X509_OCSP_CTX *)OPENSSL_malloc(sizeof(X509_OCSP_CTX));
+	if (!ctx)
+		{
+		X509err(X509_F_X509_OCSP_CTX_NEW, ERR_R_MALLOC_FAILURE);
+		return NULL;
+		}
+	memset(ctx, 0, sizeof(X509_OCSP_CTX));
+
+	ctx->auth_responders = NULL;
+	ctx->dgst = NULL;
+	ctx->key = NULL;
+	ctx->signer = NULL;
+	ctx->signer_certs = NULL;
+	ctx->flags = 0;
+	
+	return ctx;
+}
+
+void X509_OCSP_CTX_free(X509_OCSP_CTX *ctx)
+{
+	if (!ctx)
+		return;
+	if (ctx->auth_responders) sk_X509_pop_free(ctx->auth_responders, X509_free);
+	if (ctx->key)		  EVP_PKEY_free(ctx->key);
+	if (ctx->signer)	  X509_free(ctx->signer);
+	if (ctx->signer_certs)	  sk_X509_pop_free(ctx->signer_certs, X509_free);
+	OPENSSL_free(ctx);
+}
+
 void X509_STORE_CTX_free(X509_STORE_CTX *ctx)
 {
 	X509_STORE_CTX_cleanup(ctx);
+	if (ctx->ocsp_ctx != NULL)
+		{
+		/* resources are only freed when X509_STORE holding them is freed*/
+		ctx->ocsp_ctx->auth_responders = NULL;
+		ctx->ocsp_ctx->signer = NULL;
+		ctx->ocsp_ctx->signer_certs = NULL;
+		ctx->ocsp_ctx->key = NULL;
+		OPENSSL_free(ctx->ocsp_ctx);
+		}
 	OPENSSL_free(ctx);
 }
 
@@ -2057,6 +2590,10 @@
 	ctx->error_depth=0;
 	ctx->current_cert=NULL;
 	ctx->current_issuer=NULL;
+	ctx->current_crl = NULL;
+	ctx->current_ocsp = NULL;
+	ctx->current_crl_score = 0;
+	ctx->current_reasons = 0;
 	ctx->tree = NULL;
 	ctx->parent = NULL;
 
@@ -2121,10 +2658,15 @@
 	else
 		ctx->check_revocation = check_revocation;
 
+	if (store && store->dl_crl)
+		ctx->dl_crl = store->dl_crl;
+	else
+		ctx->dl_crl = NULL;
+	
 	if (store && store->get_crl)
 		ctx->get_crl = store->get_crl;
 	else
-		ctx->get_crl = NULL;
+		ctx->get_crl = get_crl;
 
 	if (store && store->check_crl)
 		ctx->check_crl = store->check_crl;
@@ -2136,6 +2678,60 @@
 	else
 		ctx->cert_crl = cert_crl;
 
+	if (ctx->param->flags & X509_V_FLAG_OCSP_CHECK)
+		{
+		if (!(ctx->ocsp_ctx = X509_OCSP_CTX_new()))
+			{
+			OPENSSL_free(ctx);
+			X509err(X509_F_X509_STORE_CTX_INIT,ERR_R_MALLOC_FAILURE);
+			return 0;
+			}
+
+		/* copy flags */
+		if (store && store->ocsp_ctx)
+			ctx->ocsp_ctx->flags |= store->ocsp_ctx->flags;
+
+		if (store && store->ocsp_ctx)
+			ctx->ocsp_ctx->auth_responders = store->ocsp_ctx->auth_responders;
+		else
+			ctx->ocsp_ctx->auth_responders = NULL;
+
+		if (store && store->ocsp_ctx)
+			ctx->ocsp_ctx->signer = store->ocsp_ctx->signer;
+		else
+			ctx->ocsp_ctx->signer = NULL;
+
+		if (store && store->ocsp_ctx)
+			ctx->ocsp_ctx->signer_certs = store->ocsp_ctx->signer_certs;
+		else
+			ctx->ocsp_ctx->signer_certs = NULL;
+
+		if (store && store->ocsp_ctx)
+			ctx->ocsp_ctx->key = store->ocsp_ctx->key;
+		else
+			ctx->ocsp_ctx->key = NULL;
+
+		if (store && store->ocsp_ctx)
+			ctx->ocsp_ctx->dgst = store->ocsp_ctx->dgst;
+		else
+			ctx->ocsp_ctx->dgst = NULL;
+
+		if (store && store->ocsp_ctx && store->ocsp_ctx->get_ocsp)
+			ctx->ocsp_ctx->get_ocsp = store->ocsp_ctx->get_ocsp;
+		else
+			ctx->ocsp_ctx->get_ocsp = get_ocsp;
+
+		if (store && store->ocsp_ctx && store->ocsp_ctx->dl_ocsp)
+			ctx->ocsp_ctx->dl_ocsp = store->ocsp_ctx->dl_ocsp;
+		else
+			ctx->ocsp_ctx->dl_ocsp = NULL;
+
+		if (store && store->ocsp_ctx && store->ocsp_ctx->check_ocsp)
+			ctx->ocsp_ctx->check_ocsp = store->ocsp_ctx->check_ocsp;
+		else
+			ctx->ocsp_ctx->check_ocsp = check_ocsp;
+		}
+	    
 	if (store && store->lookup_certs)
 		ctx->lookup_certs = store->lookup_certs;
 	else
Index: crypto/x509/x509_vfy.h
===================================================================
RCS file: /v/openssl/cvs/openssl/crypto/x509/x509_vfy.h,v
retrieving revision 1.73
diff -u -r1.73 x509_vfy.h
--- crypto/x509/x509_vfy.h	25 Dec 2010 20:45:59 -0000	1.73
+++ crypto/x509/x509_vfy.h	30 Dec 2010 01:13:16 -0000
@@ -166,17 +166,47 @@
 typedef struct X509_VERIFY_PARAM_st
 	{
 	char *name;
-	time_t check_time;	/* Time to use */
-	unsigned long inh_flags; /* Inheritance flags */
-	unsigned long flags;	/* Various verify flags */
-	int purpose;		/* purpose to check untrusted certificates */
-	int trust;		/* trust setting to check */
-	int depth;		/* Verify depth */
+	time_t check_time;	      /* Time to use */
+	unsigned long inh_flags;      /* Inheritance flags */
+	unsigned long flags;	      /* Various verify flags */
+        int purpose;                  /* purpose to check untrusted certificates */
+	int trust;                    /* trust setting to check */
+	int depth;                    /* Verify depth */
 	STACK_OF(ASN1_OBJECT) *policies;	/* Permissible policies */
 	} X509_VERIFY_PARAM;
 
 DECLARE_STACK_OF(X509_VERIFY_PARAM)
 
+struct x509_ocsp_ctx_st
+        {
+        unsigned long flags;     /* Flags for OCSP verification/requests */
+
+        /* If the request is to be signed, the next three must be set */
+        X509 *signer;
+	EVP_PKEY *key;
+	const EVP_MD *dgst;
+
+        /* Additional certificates to be added to the request signature */
+        STACK_OF(X509) *signer_certs;
+
+        /* If an OCSP response is signed by one of these, the certificate
+           is explicitly trusted (cf. "authorized responder approachin RFC 2560 */
+        STACK_OF(X509) *auth_responders;
+
+        /* Callbacks for various operations */
+
+        /* Download an OCSP response from a given URL by sending the request */
+        OCSP_RESPONSE* (*dl_ocsp)(X509_STORE_CTX *ctx, OCSP_REQUEST *request,
+                                  char *url);
+        /* Retrieve OCSP response */
+        int (*get_ocsp)(X509_STORE_CTX *ctx, OCSP_REQUEST **request,
+                        OCSP_RESPONSE **ocsp, X509 *x, X509 *issuer);
+        /* Check OCSP validity and revocation status */
+	int (*check_ocsp)(X509_STORE_CTX *ctx, OCSP_REQUEST *request,
+                        OCSP_RESPONSE *ocsp, X509 *x, X509 *issuer);
+
+        } /* X509_OCSP_CTX */;
+
 /* This is used to hold everything.  It is used for all certificate
  * validation.  Once we have a certificate chain, the 'verify'
  * function is then called to actually check the cert chain. */
@@ -192,14 +222,29 @@
 	X509_VERIFY_PARAM *param;
 
 	/* Callbacks for various operations */
-	int (*verify)(X509_STORE_CTX *ctx);	/* called to verify a certificate */
-	int (*verify_cb)(int ok,X509_STORE_CTX *ctx);	/* error callback */
-	int (*get_issuer)(X509 **issuer, X509_STORE_CTX *ctx, X509 *x);	/* get issuers cert from ctx */
-	int (*check_issued)(X509_STORE_CTX *ctx, X509 *x, X509 *issuer); /* check issued */
-	int (*check_revocation)(X509_STORE_CTX *ctx); /* Check revocation status of chain */
-	int (*get_crl)(X509_STORE_CTX *ctx, X509_CRL **crl, X509 *x); /* retrieve CRL */
-	int (*check_crl)(X509_STORE_CTX *ctx, X509_CRL *crl); /* Check CRL validity */
-	int (*cert_crl)(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x); /* Check certificate against CRL */
+	
+        /* called to verify a certificate */
+        int (*verify)(X509_STORE_CTX *ctx);
+        /* error callback */
+	int (*verify_cb)(int ok,X509_STORE_CTX *ctx);
+        /* get issuers cert from ctx */
+	int (*get_issuer)(X509 **issuer, X509_STORE_CTX *ctx, X509 *x);
+        /* check issued */
+	int (*check_issued)(X509_STORE_CTX *ctx, X509 *x, X509 *issuer);
+        /* Check revocation status of chain */
+	int (*check_revocation)(X509_STORE_CTX *ctx);
+        /* download a CRL from a given URL */
+        X509_CRL* (*dl_crl)(X509_STORE_CTX *ctx, char *url);
+        /* retrieve CRL */
+	int (*get_crl)(X509_STORE_CTX *ctx, X509_CRL **crl, X509 *x);
+        /* Check CRL validity */
+	int (*check_crl)(X509_STORE_CTX *ctx, X509_CRL *crl);
+        /* Check certificate against CRL */
+	int (*cert_crl)(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x);
+
+        /* Contains flags and callbacks for OCSP */
+        X509_OCSP_CTX *ocsp_ctx;
+
 	STACK_OF(X509) * (*lookup_certs)(X509_STORE_CTX *ctx, X509_NAME *nm);
 	STACK_OF(X509_CRL) * (*lookup_crls)(X509_STORE_CTX *ctx, X509_NAME *nm);
 	int (*cleanup)(X509_STORE_CTX *ctx);
@@ -241,14 +286,29 @@
 	void *other_ctx;	/* Other info for use with get_issuer() */
 
 	/* Callbacks for various operations */
-	int (*verify)(X509_STORE_CTX *ctx);	/* called to verify a certificate */
-	int (*verify_cb)(int ok,X509_STORE_CTX *ctx);		/* error callback */
-	int (*get_issuer)(X509 **issuer, X509_STORE_CTX *ctx, X509 *x);	/* get issuers cert from ctx */
-	int (*check_issued)(X509_STORE_CTX *ctx, X509 *x, X509 *issuer); /* check issued */
-	int (*check_revocation)(X509_STORE_CTX *ctx); /* Check revocation status of chain */
-	int (*get_crl)(X509_STORE_CTX *ctx, X509_CRL **crl, X509 *x); /* retrieve CRL */
-	int (*check_crl)(X509_STORE_CTX *ctx, X509_CRL *crl); /* Check CRL validity */
-	int (*cert_crl)(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x); /* Check certificate against CRL */
+
+        /* called to verify a certificate */
+        int (*verify)(X509_STORE_CTX *ctx);
+	/* error callback */
+        int (*verify_cb)(int ok,X509_STORE_CTX *ctx);
+	/* get issuers cert from ctx */
+        int (*get_issuer)(X509 **issuer, X509_STORE_CTX *ctx, X509 *x);
+	/* check issued */
+        int (*check_issued)(X509_STORE_CTX *ctx, X509 *x, X509 *issuer);
+	/* Check revocation status of chain */
+        int (*check_revocation)(X509_STORE_CTX *ctx);
+        /* download a CRL from a given URL */
+        X509_CRL* (*dl_crl)(X509_STORE_CTX *ctx, char *url);
+        /* retrieve CRL */
+	int (*get_crl)(X509_STORE_CTX *ctx, X509_CRL **crl, X509 *x);
+        /* Check CRL validity */
+	int (*check_crl)(X509_STORE_CTX *ctx, X509_CRL *crl);
+        /* Check certificate against CRL */
+	int (*cert_crl)(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x);
+
+        /* Contains flags and callbacks for OCSP */
+        X509_OCSP_CTX *ocsp_ctx;
+
 	int (*check_policy)(X509_STORE_CTX *ctx);
 	STACK_OF(X509) * (*lookup_certs)(X509_STORE_CTX *ctx, X509_NAME *nm);
 	STACK_OF(X509_CRL) * (*lookup_crls)(X509_STORE_CTX *ctx, X509_NAME *nm);
@@ -268,7 +328,8 @@
 	X509 *current_cert;
 	X509 *current_issuer;	/* cert currently being tested as valid issuer */
 	X509_CRL *current_crl;	/* current CRL */
-
+        OCSP_BASICRESP *current_ocsp; /* current OCSP */
+        
 	int current_crl_score;  /* score of current CRL */
 	unsigned int current_reasons;  /* Reason mask */
 
@@ -356,6 +417,26 @@
 /* Another issuer check debug option */
 #define		X509_V_ERR_PATH_LOOP				55
 
+#define         X509_V_ERR_ERROR_IN_OCSP_PRODUCED_AT_FIELD      55
+#define         X509_V_ERR_ERROR_IN_OCSP_THIS_UPDATE_FIELD      56
+#define         X509_V_ERR_ERROR_IN_OCSP_NEXT_UPDATE_FIELD      57
+#define         X509_V_ERR_OCSP_NOT_YET_VALID                   58
+#define         X509_V_ERR_OCSP_HAS_EXPIRED                     59
+#define         X509_V_ERR_UNABLE_TO_FIND_AIA                   60
+#define         X509_V_ERR_UNABLE_TO_FIND_AIA_URL               61
+#define         X509_V_ERR_ERROR_RETRIEVING_OCSP_RESPONSE       62
+#define         X509_V_ERR_OCSP_RESPONSE_NOT_SUCCESSFUL         63
+#define         X509_V_ERR_OCSP_SIGNATURE_FAILURE               64
+#define         X509_V_ERR_OCSP_UNSUPPORTED_MULTIPLE_RESP       65
+#define         X509_V_ERR_OCSP_CERT_ID_MISMATCH                66
+#define         X509_V_ERR_OCSP_NONCE_MISMATCH                  67
+#define         X509_V_ERR_UNABLE_TO_FIND_CRL_DPS               68
+#define         X509_V_ERR_UNABLE_TO_FIND_CRL_DP_URL            69
+#define         X509_V_ERR_ERROR_RETRIEVING_CRL                 70
+#define         X509_V_ERR_OCSP_SIGNING_CERT_NOT_FOUND          71
+#define         X509_V_ERR_OCSP_CERT_ISSUER_NOT_TRUSTED         72
+#define         X509_V_ERR_OCSP_SIGNING_FAILED                  73
+
 /* The application is not happy */
 #define		X509_V_ERR_APPLICATION_VERIFICATION		50
 
@@ -393,6 +474,8 @@
 #define X509_V_FLAG_CHECK_SS_SIGNATURE		0x4000
 /* Use trusted store first */
 #define X509_V_FLAG_TRUSTED_FIRST		0x8000
+/* Use OCSP whenever possible */
+#define	X509_V_FLAG_OCSP_CHECK			0x10000
 
 
 #define X509_VP_FLAG_DEFAULT			0x1
@@ -436,6 +519,10 @@
 void X509_STORE_CTX_trusted_stack(X509_STORE_CTX *ctx, STACK_OF(X509) *sk);
 void X509_STORE_CTX_cleanup(X509_STORE_CTX *ctx);
 
+X509_OCSP_CTX *X509_OCSP_CTX_new(void);
+void X509_OCSP_CTX_free(X509_OCSP_CTX *ctx);
+void X509_OCSP_CTX_cleanup(X509_OCSP_CTX *ctx);
+
 X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m);
 
 X509_LOOKUP_METHOD *X509_LOOKUP_hash_dir(void);

Reply via email to