From: Dr. Stephen Henson Date: Fri, 29 Aug 2008 11:37:21 +0000 (+0000) Subject: Add support for CRLs partitioned by reason code. X-Git-Tag: OpenSSL_0_9_8k^2~268 X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=commitdiff_plain;h=4b96839f069a2c9fef3d1feffca2880361181544 Add support for CRLs partitioned by reason code. Tidy CRL scoring system. Add new CRL path validation error. --- diff --git a/CHANGES b/CHANGES index 654537ee3e..6e1bf9c0a4 100644 --- a/CHANGES +++ b/CHANGES @@ -4,6 +4,18 @@ Changes between 0.9.8i and 0.9.9 [xx XXX xxxx] + *) Support for CRLs partitioned by reason code. Reorganise CRL processing + code and add additional score elements. Validate alternate CRL paths + as part of the CRL checking and indicate a new error "CRL path validation + error" in this case. Applications wanting additional details can use + the verify callback and check the new "parent" field. If this is not + NULL CRL path validation is taking place. Existing applications wont + see this because it requires extended CRL support which is off by + default. + + This work was sponsored by Google. + [Steve Henson] + *) Support for freshest CRL extension. This work was sponsored by Google. @@ -12,7 +24,7 @@ *) Initial indirect CRL support. Currently only supported in the CRLs passed directly and not via lookup. Process certificate issuer CRL entry extension and lookup CRL entries by bother issuer name - and serial number. Check and proces CRL issuer entry in IDP extension. + and serial number. Check and process CRL issuer entry in IDP extension. This work was sponsored by Google. [Steve Henson] diff --git a/crypto/asn1/x_crl.c b/crypto/asn1/x_crl.c index e6346374dc..86adbe3e5f 100644 --- a/crypto/asn1/x_crl.c +++ b/crypto/asn1/x_crl.c @@ -203,6 +203,7 @@ static int crl_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, crl->akid = NULL; crl->flags = 0; crl->idp_flags = 0; + crl->idp_reasons = CRLDP_ALL_REASONS; crl->meth = default_crl_method; crl->meth_data = NULL; crl->issuers = NULL; @@ -308,6 +309,7 @@ static void setup_idp(X509_CRL *crl, ISSUING_DIST_POINT *idp) if (idp->onlysomereasons->length > 1) crl->idp_reasons |= (idp->onlysomereasons->data[1] << 8); + crl->idp_reasons &= CRLDP_ALL_REASONS; } DIST_POINT_set_dpname(idp->distpoint, X509_CRL_get_issuer(crl)); diff --git a/crypto/x509/x509_txt.c b/crypto/x509/x509_txt.c index 2017f86a77..c44f753c46 100644 --- a/crypto/x509/x509_txt.c +++ b/crypto/x509/x509_txt.c @@ -181,6 +181,8 @@ const char *X509_verify_cert_error_string(long n) return("unsupported or invalid name constraint syntax"); case X509_V_ERR_UNSUPPORTED_NAME_SYNTAX: return("unsupported or invalid name syntax"); + case X509_V_ERR_CRL_PATH_VALIDATION_ERROR: + return("CRL path validation error"); default: BIO_snprintf(buf,sizeof buf,"error number %ld",n); diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c index e92a9c3e3b..4d7a94520c 100644 --- a/crypto/x509/x509_vfy.c +++ b/crypto/x509/x509_vfy.c @@ -79,12 +79,19 @@ static int check_trust(X509_STORE_CTX *ctx); static int check_revocation(X509_STORE_CTX *ctx); static int check_cert(X509_STORE_CTX *ctx); static int check_policy(X509_STORE_CTX *ctx); -static int crl_akid_check(X509_STORE_CTX *ctx, X509_CRL *crl, X509 **pissuer); -static int idp_check_scope(X509 *x, X509_CRL *crl, int *pimatch); + +static int get_crl_score(X509_STORE_CTX *ctx, X509 **pissuer, + unsigned int *preasons, + X509_CRL *crl, X509 *x); +static void crl_akid_check(X509_STORE_CTX *ctx, X509_CRL *crl, + X509 **pissuer, int *pcrl_score); +static int crl_crldp_check(X509 *x, X509_CRL *crl, int crl_score, + unsigned int *preasons); static int check_crl_path(X509_STORE_CTX *ctx, X509 *x); static int check_crl_chain(X509_STORE_CTX *ctx, STACK_OF(X509) *cert_path, STACK_OF(X509) *crl_path); + static int internal_verify(X509_STORE_CTX *ctx); const char X509_version[]="X.509" OPENSSL_VERSION_PTEXT; @@ -649,24 +656,33 @@ static int check_cert(X509_STORE_CTX *ctx) x = sk_X509_value(ctx->chain, cnum); ctx->current_cert = x; ctx->current_issuer = NULL; - /* Try to retrieve relevant CRL */ - ok = ctx->get_crl(ctx, &crl, x); - /* If error looking up CRL, nothing we can do except - * notify callback - */ - if(!ok) + ctx->current_reasons = 0; + while (ctx->current_reasons != CRLDP_ALL_REASONS) { - ctx->error = X509_V_ERR_UNABLE_TO_GET_CRL; - ok = ctx->verify_cb(0, ctx); - goto err; + /* Try to retrieve relevant CRL */ + ok = ctx->get_crl(ctx, &crl, x); + /* If error looking up CRL, nothing we can do except + * notify callback + */ + if(!ok) + { + ctx->error = X509_V_ERR_UNABLE_TO_GET_CRL; + ok = ctx->verify_cb(0, ctx); + goto err; + } + ctx->current_crl = crl; + ok = ctx->check_crl(ctx, crl); + if (!ok) + goto err; + ok = ctx->cert_crl(ctx, crl, x); + if (!ok) + goto err; + X509_CRL_free(crl); + crl = NULL; } - ctx->current_crl = crl; - ok = ctx->check_crl(ctx, crl); - if (!ok) goto err; - ok = ctx->cert_crl(ctx, crl, x); err: - ctx->current_crl = NULL; X509_CRL_free(crl); + ctx->current_crl = NULL; return ok; } @@ -677,7 +693,8 @@ static int check_crl_time(X509_STORE_CTX *ctx, X509_CRL *crl, int notify) { time_t *ptime; int i; - ctx->current_crl = crl; + if (notify) + ctx->current_crl = crl; if (ctx->param->flags & X509_V_FLAG_USE_CHECK_TIME) ptime = &ctx->param->check_time; else @@ -686,15 +703,19 @@ static int check_crl_time(X509_STORE_CTX *ctx, X509_CRL *crl, int notify) i=X509_cmp_time(X509_CRL_get_lastUpdate(crl), ptime); if (i == 0) { + if (!notify) + return 0; ctx->error=X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD; - if (!notify || !ctx->verify_cb(0, ctx)) + if (!ctx->verify_cb(0, ctx)) return 0; } if (i > 0) { + if (!notify) + return 0; ctx->error=X509_V_ERR_CRL_NOT_YET_VALID; - if (!notify || !ctx->verify_cb(0, ctx)) + if (!ctx->verify_cb(0, ctx)) return 0; } @@ -704,133 +725,205 @@ static int check_crl_time(X509_STORE_CTX *ctx, X509_CRL *crl, int notify) if (i == 0) { + if (!notify) + return 0; ctx->error=X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD; - if (!notify || !ctx->verify_cb(0, ctx)) + if (!ctx->verify_cb(0, ctx)) return 0; } if (i < 0) { + if (!notify) + return 0; ctx->error=X509_V_ERR_CRL_HAS_EXPIRED; - if (!notify || !ctx->verify_cb(0, ctx)) + if (!ctx->verify_cb(0, ctx)) return 0; } } - ctx->current_crl = NULL; + if (notify) + ctx->current_crl = NULL; return 1; } -/* Based on a set of possible CRLs decide which one is best suited - * to handle the current certificate. This is determined by a number - * of criteria. If any of the "must" criteria is not satisfied then - * the candidate CRL is rejected. If all "must" and all "should" are - * satisfied the CRL is accepted. If no CRL satisfies all criteria then - * a "best CRL" is used to provide some meaningful error information. - * - * CRL issuer name must match "nm" if not NULL. - * If IDP is present: - * a. it must be consistent. - * b. onlyuser, onlyCA, onlyAA should match certificate being checked. - * c. indirectCRL must be FALSE. - * d. onlysomereason must be absent. - * e. if name present a DP in certificate CRLDP must match. - * If AKID present it should match certificate AKID. - * Check time should fall between lastUpdate and nextUpdate. - */ +/* CRL score values */ + +/* No unhandled critical extensions */ + +#define CRL_SCORE_NOCRITICAL 0x100 + +/* certificate is within CRL scope */ + +#define CRL_SCORE_SCOPE 0x080 + +/* CRL times valid */ + +#define CRL_SCORE_TIME 0x040 + +/* Issuer name matches certificate */ -/* IDP name field matches CRLDP or IDP name not present */ -#define CRL_SCORE_SCOPE 4 -/* AKID present and matches cert, or AKID not present */ -#define CRL_SCORE_AKID 2 -/* times OK */ -#define CRL_SCORE_TIME 1 +#define CRL_SCORE_ISSUER_NAME 0x020 -#define CRL_SCORE_ALL 7 +/* If this score or above CRL is probably valid */ -/* IDP flags which cause a CRL to be rejected */ +#define CRL_SCORE_VALID (CRL_SCORE_NOCRITICAL|CRL_SCORE_TIME|CRL_SCORE_SCOPE) -#define IDP_REJECT (IDP_INVALID|IDP_REASONS) +/* CRL issuer is certificate issuer */ -static int get_crl_sk(X509_STORE_CTX *ctx, X509_CRL **pcrl, - X509_NAME *nm, STACK_OF(X509_CRL) *crls) +#define CRL_SCORE_ISSUER_CERT 0x018 + +/* CRL issuer is on certificate path */ + +#define CRL_SCORE_SAME_PATH 0x008 + +/* CRL issuer matches CRL AKID */ + +#define CRL_SCORE_AKID 0x004 + +/* CRL is complete, not delta */ + +#define CRL_SCORE_COMPLETE 0x002 + +static int get_crl_sk(X509_STORE_CTX *ctx, X509_CRL **pcrl, X509 **pissuer, + int *pscore, unsigned int *preasons, + STACK_OF(X509_CRL) *crls) { - int i, crl_score, best_score = -1; + int i, crl_score, best_score = *pscore; + unsigned int reasons, best_reasons; + X509 *x = ctx->current_cert; X509_CRL *crl, *best_crl = NULL; X509 *crl_issuer, *best_crl_issuer = NULL; for (i = 0; i < sk_X509_CRL_num(crls); i++) { - int imatch = 1; - crl_score = 0; - crl_issuer = NULL; crl = sk_X509_CRL_value(crls, i); - if (nm && X509_NAME_cmp(nm, X509_CRL_get_issuer(crl))) - { - /* Issuer name does not match: could be indirect */ - if (!(ctx->param->flags & X509_V_FLAG_EXTENDED_CRL_SUPPORT)) - continue; - if (!(crl->idp_flags & IDP_INDIRECT)) - continue; - imatch = 0; - } - if (check_crl_time(ctx, crl, 0)) - crl_score |= CRL_SCORE_TIME; - - if (crl->idp_flags & IDP_PRESENT) - { - if (crl->idp_flags & IDP_REJECT) - continue; - if (idp_check_scope(ctx->current_cert, crl, &imatch)) - crl_score |= CRL_SCORE_SCOPE; - } - else - crl_score |= CRL_SCORE_SCOPE; - - /* If no issuer match at this point try next CRL */ - if (!imatch) - continue; - - if (crl_akid_check(ctx, crl, &crl_issuer)) - crl_score |= CRL_SCORE_AKID; - /* If CRL matches criteria and issuer is not different use it */ - if (crl_score == CRL_SCORE_ALL && !crl_issuer) - { - *pcrl = crl; - CRYPTO_add(&crl->references, 1, CRYPTO_LOCK_X509_CRL); - return 1; - } + reasons = *preasons; + crl_score = get_crl_score(ctx, &crl_issuer, &reasons, crl, x); if (crl_score > best_score) { best_crl = crl; best_crl_issuer = crl_issuer; best_score = crl_score; + best_reasons = reasons; } } + if (best_crl) { + if (*pcrl) + X509_CRL_free(*pcrl); *pcrl = best_crl; - ctx->current_issuer = best_crl_issuer; + *pissuer = best_crl_issuer; + *pscore = best_score; + *preasons = best_reasons; CRYPTO_add(&best_crl->references, 1, CRYPTO_LOCK_X509); } + + if (best_score >= CRL_SCORE_VALID) + return 1; + return 0; } -static int crl_akid_check(X509_STORE_CTX *ctx, X509_CRL *crl, X509 **pissuer) +/* For a given CRL return how suitable it is for the supplied certificate 'x'. + * The return value is a mask of several criteria. + * If the issuer is not the certificate issuer this is returned in *pissuer. + * The reasons mask is also used to determine if the CRL is suitable: if + * no new reasons the CRL is rejected, otherwise reasons is updated. + */ + +static int get_crl_score(X509_STORE_CTX *ctx, X509 **pissuer, + unsigned int *preasons, + X509_CRL *crl, X509 *x) + { + + int crl_score = 0; + unsigned int tmp_reasons = *preasons, crl_reasons; + + /* First see if we can reject CRL straight away */ + + /* Invalid IDP cannot be processed */ + if (crl->idp_flags & IDP_INVALID) + return 0; + /* Reason codes or indirect CRLs need extended CRL support */ + if (!(ctx->param->flags & X509_V_FLAG_EXTENDED_CRL_SUPPORT)) + { + if (crl->idp_flags & (IDP_INDIRECT | IDP_REASONS)) + return 0; + } + else if (crl->idp_flags & IDP_REASONS) + { + /* If no new reasons reject */ + if (!(crl->idp_reasons & ~tmp_reasons)) + return 0; + } + /* If issuer name doesn't match certificate need indirect CRL */ + if (X509_NAME_cmp(X509_get_issuer_name(x), X509_CRL_get_issuer(crl))) + { + if (!(crl->idp_flags & IDP_INDIRECT)) + return 0; + } + else + crl_score |= CRL_SCORE_ISSUER_NAME; + + if (!(crl->flags & EXFLAG_CRITICAL)) + crl_score |= CRL_SCORE_NOCRITICAL; + + /* Check expiry */ + if (check_crl_time(ctx, crl, 0)) + crl_score |= CRL_SCORE_TIME; + + /* Check authority key ID and locate certificate issuer */ + crl_akid_check(ctx, crl, pissuer, &crl_score); + + /* If we can't locate certificate issuer at this point forget it */ + + if (!(crl_score & CRL_SCORE_AKID)) + return 0; + + /* Check cert for matching CRL distribution points */ + + if (crl_crldp_check(x, crl, crl_score, &crl_reasons)) + { + /* If no new reasons reject */ + if (!(crl_reasons & ~tmp_reasons)) + return 0; + tmp_reasons |= crl_reasons; + crl_score |= CRL_SCORE_SCOPE; + } + + *preasons = tmp_reasons; + + return crl_score; + + } + +static void crl_akid_check(X509_STORE_CTX *ctx, X509_CRL *crl, + X509 **pissuer, int *pcrl_score) { - X509 *crl_issuer; + X509 *crl_issuer = NULL; X509_NAME *cnm = X509_CRL_get_issuer(crl); int cidx = ctx->error_depth; int i; - if (!crl->akid) - return 1; + if (cidx != sk_X509_num(ctx->chain) - 1) cidx++; + crl_issuer = sk_X509_value(ctx->chain, cidx); + if (X509_check_akid(crl_issuer, crl->akid) == X509_V_OK) - return 1; + { + if (*pcrl_score & CRL_SCORE_ISSUER_NAME) + { + *pcrl_score |= CRL_SCORE_AKID|CRL_SCORE_ISSUER_CERT; + *pissuer = crl_issuer; + return; + } + } + for (cidx++; cidx < sk_X509_num(ctx->chain); cidx++) { crl_issuer = sk_X509_value(ctx->chain, cidx); @@ -838,15 +931,16 @@ static int crl_akid_check(X509_STORE_CTX *ctx, X509_CRL *crl, X509 **pissuer) continue; if (X509_check_akid(crl_issuer, crl->akid) == X509_V_OK) { + *pcrl_score |= CRL_SCORE_AKID|CRL_SCORE_SAME_PATH; *pissuer = crl_issuer; - return 1; + return; } } /* Anything else needs extended CRL support */ if (!(ctx->param->flags & X509_V_FLAG_EXTENDED_CRL_SUPPORT)) - return 0; + return; /* Otherwise the CRL issuer is not on the path. Look for it in the * set of untrusted certificates. @@ -854,20 +948,15 @@ static int crl_akid_check(X509_STORE_CTX *ctx, X509_CRL *crl, X509 **pissuer) for (i = 0; i < sk_X509_num(ctx->untrusted); i++) { crl_issuer = sk_X509_value(ctx->untrusted, i); - if (X509_NAME_cmp(X509_get_subject_name(crl_issuer), - X509_CRL_get_issuer(crl))) + if (X509_NAME_cmp(X509_get_subject_name(crl_issuer), cnm)) continue; if (X509_check_akid(crl_issuer, crl->akid) == X509_V_OK) { - if (check_crl_path(ctx, crl_issuer)) - { - *pissuer = crl_issuer; - return 1; - } + *pissuer = crl_issuer; + *pcrl_score |= CRL_SCORE_AKID; + return; } } - - return 0; } /* Check the path of a CRL issuer certificate. This creates a new @@ -881,6 +970,7 @@ static int check_crl_path(X509_STORE_CTX *ctx, X509 *x) { X509_STORE_CTX crl_ctx; int ret; + /* Don't allow recursive CRL path validation */ if (ctx->parent) return 0; if (!X509_STORE_CTX_init(&crl_ctx, ctx->ctx, x, ctx->untrusted)) @@ -896,14 +986,12 @@ static int check_crl_path(X509_STORE_CTX *ctx, X509 *x) /* Verify CRL issuer */ ret = X509_verify_cert(&crl_ctx); - /* Maybe send path check result back to parent? */ if (!ret) goto err; /* Check chain is acceptable */ ret = check_crl_chain(ctx, ctx->chain, crl_ctx.chain); - err: X509_STORE_CTX_cleanup(&crl_ctx); return ret; @@ -1003,30 +1091,28 @@ static int idp_check_dp(DIST_POINT_NAME *a, DIST_POINT_NAME *b) } -static int idp_check_crlissuer(DIST_POINT *dp, X509_CRL *crl, int *pimatch) +static int crldp_check_crlissuer(DIST_POINT *dp, X509_CRL *crl, int crl_score) { int i; X509_NAME *nm = X509_CRL_get_issuer(crl); /* If no CRLissuer return is successful iff don't need a match */ if (!dp->CRLissuer) - return *pimatch; + return !!(crl_score & CRL_SCORE_ISSUER_NAME); for (i = 0; i < sk_GENERAL_NAME_num(dp->CRLissuer); i++) { GENERAL_NAME *gen = sk_GENERAL_NAME_value(dp->CRLissuer, i); if (gen->type != GEN_DIRNAME) continue; if (!X509_NAME_cmp(gen->d.directoryName, nm)) - { - *pimatch = 1; return 1; - } } return 0; } -/* Check IDP name matches at least one CRLDP name */ +/* Check CRLDP and IDP */ -static int idp_check_scope(X509 *x, X509_CRL *crl, int *pimatch) +static int crl_crldp_check(X509 *x, X509_CRL *crl, int crl_score, + unsigned int *preasons) { int i; if (crl->idp_flags & IDP_ONLYATTR) @@ -1041,20 +1127,22 @@ static int idp_check_scope(X509 *x, X509_CRL *crl, int *pimatch) if (crl->idp_flags & IDP_ONLYCA) return 0; } - if (!crl->idp->distpoint && *pimatch) - return 1; + *preasons = crl->idp_reasons; for (i = 0; i < sk_DIST_POINT_num(x->crldp); i++) { DIST_POINT *dp = sk_DIST_POINT_value(x->crldp, i); - /* We don't handle these at present */ - if (dp->reasons) - continue; - if (idp_check_dp(dp->distpoint, crl->idp->distpoint)) + if (crldp_check_crlissuer(dp, crl, crl_score)) { - if (idp_check_crlissuer(dp, crl, pimatch)) + if (!crl->idp || + idp_check_dp(dp->distpoint, crl->idp->distpoint)) + { + *preasons &= dp->dp_reasons; return 1; + } } } + if ((!crl->idp || !crl->idp->distpoint) && (crl_score & CRL_SCORE_ISSUER_NAME)) + return 1; return 0; } @@ -1066,39 +1154,37 @@ static int idp_check_scope(X509 *x, X509_CRL *crl, int *pimatch) static int get_crl(X509_STORE_CTX *ctx, X509_CRL **pcrl, X509 *x) { int ok; + X509 *issuer = NULL; + int crl_score = 0; + unsigned int reasons; X509_CRL *crl = NULL; STACK_OF(X509_CRL) *skcrl; - X509_NAME *nm; - nm = X509_get_issuer_name(x); - ok = get_crl_sk(ctx, &crl, nm, ctx->crls); + X509_NAME *nm = X509_get_issuer_name(x); + reasons = ctx->current_reasons; + ok = get_crl_sk(ctx, &crl, &issuer, &crl_score, &reasons, ctx->crls); if (ok) - { - *pcrl = crl; - return 1; - } + goto done; /* Lookup CRLs from store */ skcrl = ctx->lookup_crls(ctx, nm); /* If no CRLs found and a near match from get_crl_sk use that */ - if (!skcrl) - { - if (crl) - { - *pcrl = crl; - return 1; - } - return 0; - } + if (!skcrl && crl) + goto done; - get_crl_sk(ctx, &crl, NULL, skcrl); + get_crl_sk(ctx, &crl, &issuer, &crl_score, &reasons, skcrl); sk_X509_CRL_pop_free(skcrl, X509_CRL_free); + done: + /* If we got any kind of CRL use it and return success */ if (crl) { + ctx->current_issuer = issuer; + ctx->current_crl_score = crl_score; + ctx->current_reasons = reasons; *pcrl = crl; return 1; } @@ -1145,27 +1231,35 @@ static int check_crl(X509_STORE_CTX *ctx, X509_CRL *crl) if(!ok) goto err; } - if (crl->idp_flags & IDP_PRESENT) + if (!(ctx->current_crl_score & CRL_SCORE_SCOPE)) + { + ctx->error = X509_V_ERR_DIFFERENT_CRL_SCOPE; + ok = ctx->verify_cb(0, ctx); + if(!ok) goto err; + } + + if (!(ctx->current_crl_score & CRL_SCORE_TIME)) + { + ok = check_crl_time(ctx, crl, 1); + if (!ok) + goto err; + } + + if (!(ctx->current_crl_score & CRL_SCORE_SAME_PATH)) + { + if (!check_crl_path(ctx, ctx->current_issuer)) { - int dmy = 1; - if (crl->idp_flags & IDP_INVALID) - { - ctx->error = X509_V_ERR_INVALID_EXTENSION; - ok = ctx->verify_cb(0, ctx); - if(!ok) goto err; - } - if (crl->idp_flags & IDP_REASONS) - { - ctx->error = X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE; - ok = ctx->verify_cb(0, ctx); - if(!ok) goto err; - } - if (!idp_check_scope(ctx->current_cert, crl, &dmy)) - { - ctx->error = X509_V_ERR_DIFFERENT_CRL_SCOPE; - ok = ctx->verify_cb(0, ctx); - if(!ok) goto err; - } + ctx->error = X509_V_ERR_CRL_PATH_VALIDATION_ERROR; + ok = ctx->verify_cb(0, ctx); + if(!ok) goto err; + } + } + + if (crl->idp_flags & IDP_INVALID) + { + ctx->error = X509_V_ERR_INVALID_EXTENSION; + ok = ctx->verify_cb(0, ctx); + if(!ok) goto err; } /* Attempt to get issuer certificate public key */ @@ -1189,10 +1283,6 @@ static int check_crl(X509_STORE_CTX *ctx, X509_CRL *crl) } } - ok = check_crl_time(ctx, crl, 1); - if (!ok) - goto err; - ok = 1; err: diff --git a/crypto/x509/x509_vfy.h b/crypto/x509/x509_vfy.h index a5006c2d8b..d1e5af64f4 100644 --- a/crypto/x509/x509_vfy.h +++ b/crypto/x509/x509_vfy.h @@ -269,6 +269,9 @@ struct x509_store_ctx_st /* X509_STORE_CTX */ X509 *current_issuer; /* cert currently being tested as valid issuer */ X509_CRL *current_crl; /* current CRL */ + int current_crl_score; /* score of current CRL */ + unsigned int current_reasons; /* Reason mask */ + X509_STORE_CTX *parent; /* For CRL path validation: parent context */ CRYPTO_EX_DATA ex_data; @@ -349,6 +352,7 @@ void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth); #define X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE 51 #define X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX 52 #define X509_V_ERR_UNSUPPORTED_NAME_SYNTAX 53 +#define X509_V_ERR_CRL_PATH_VALIDATION_ERROR 54 /* The application is not happy */ #define X509_V_ERR_APPLICATION_VERIFICATION 50 diff --git a/crypto/x509v3/v3_crld.c b/crypto/x509v3/v3_crld.c index 001edec39a..17a1fbf62c 100644 --- a/crypto/x509v3/v3_crld.c +++ b/crypto/x509v3/v3_crld.c @@ -191,6 +191,7 @@ static int set_dist_point_name(DIST_POINT_NAME **pdp, X509V3_CTX *ctx, } static const BIT_STRING_BITNAME reason_flags[] = { +{0, "Unused", "unused"}, {1, "Key Compromise", "keyCompromise"}, {2, "CA Compromise", "CACompromise"}, {3, "Affiliation Changed", "affiliationChanged"}, diff --git a/crypto/x509v3/v3_purp.c b/crypto/x509v3/v3_purp.c index bdf72227e5..2234bf147a 100644 --- a/crypto/x509v3/v3_purp.c +++ b/crypto/x509v3/v3_purp.c @@ -318,6 +318,16 @@ static void setup_dp(X509 *x, DIST_POINT *dp) { X509_NAME *iname = NULL; int i; + if (dp->reasons) + { + if (dp->reasons->length > 0) + dp->dp_reasons = dp->reasons->data[0]; + if (dp->reasons->length > 1) + dp->dp_reasons |= (dp->reasons->data[1] << 8); + dp->dp_reasons &= CRLDP_ALL_REASONS; + } + else + dp->dp_reasons = CRLDP_ALL_REASONS; if (!dp->distpoint || (dp->distpoint->type != 1)) return; for (i = 0; i < sk_GENERAL_NAME_num(dp->CRLissuer); i++) diff --git a/crypto/x509v3/x509v3.h b/crypto/x509v3/x509v3.h index c4a8cfca84..c824cf01f3 100644 --- a/crypto/x509v3/x509v3.h +++ b/crypto/x509v3/x509v3.h @@ -223,11 +223,14 @@ union { /* If relativename then this contains the full distribution point name */ X509_NAME *dpname; } DIST_POINT_NAME; +/* All existing reasons */ +#define CRLDP_ALL_REASONS 0x807f struct DIST_POINT_st { DIST_POINT_NAME *distpoint; ASN1_BIT_STRING *reasons; GENERAL_NAMES *CRLissuer; +int dp_reasons; }; typedef STACK_OF(DIST_POINT) CRL_DIST_POINTS;