Hi Martin:

Just a couple of quick questions:

- How are you supporting LDAP URLs for CRLDP?
- Do you implement all of the possible trust models and profile types for OCSP?
- How complete is your HTTP implementation?
- How do you hook into the application "main loop" to prevent an OCSP or CRL 
call from blocking the application?

Best Regards,

Patrick.

On 2010-12-30, at 3:29 PM, Martin Boßlet via RT wrote:

> 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);

---
Patrick Patterson
Chief PKI Architect
Carillon Information Security Inc.
http://www.carillon.ca





______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
Development Mailing List                       openssl-dev@openssl.org
Automated List Manager                           majord...@openssl.org

Reply via email to