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