X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=crypto%2Fx509%2Fx509_vfy.c;h=b6f16bb77220afcfda900d79a6d26d4380d5fef4;hp=cb7936f2b3d89658bdffa55fc43c2dffa84183c7;hb=a48fb0400c9c45d56144966b774998ebe37804ef;hpb=d43c4497ce1611373c3a3e5b433dfde4907d1a69 diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c index cb7936f2b3..b6f16bb772 100644 --- a/crypto/x509/x509_vfy.c +++ b/crypto/x509/x509_vfy.c @@ -69,6 +69,7 @@ #include #include #include +#include "x509_lcl.h" /* CRL score values */ @@ -113,6 +114,7 @@ static int check_issued(X509_STORE_CTX *ctx, X509 *x, X509 *issuer); static X509 *find_issuer(X509_STORE_CTX *ctx, STACK_OF(X509) *sk, X509 *x); static int check_chain_extensions(X509_STORE_CTX *ctx); static int check_name_constraints(X509_STORE_CTX *ctx); +static int check_id(X509_STORE_CTX *ctx); static int check_trust(X509_STORE_CTX *ctx); static int check_revocation(X509_STORE_CTX *ctx); static int check_cert(X509_STORE_CTX *ctx); @@ -149,11 +151,45 @@ static int x509_subject_cmp(X509 **a, X509 **b) return X509_subject_name_cmp(*a,*b); } #endif +/* Return 1 is a certificate is self signed */ +static int cert_self_signed(X509 *x) + { + X509_check_purpose(x, -1, 0); + if (x->ex_flags & EXFLAG_SS) + return 1; + else + return 0; + } + +/* Given a certificate try and find an exact match in the store */ + +static X509 *lookup_cert_match(X509_STORE_CTX *ctx, X509 *x) + { + STACK_OF(X509) *certs; + X509 *xtmp = NULL; + int i; + /* Lookup all certs with matching subject name */ + certs = ctx->lookup_certs(ctx, X509_get_subject_name(x)); + if (certs == NULL) + return NULL; + /* Look for exact match */ + for (i = 0; i < sk_X509_num(certs); i++) + { + xtmp = sk_X509_value(certs, i); + if (!X509_cmp(xtmp, x)) + break; + } + if (i < sk_X509_num(certs)) + CRYPTO_add(&xtmp->references,1,CRYPTO_LOCK_X509); + else + xtmp = NULL; + sk_X509_pop_free(certs, X509_free); + return xtmp; + } int X509_verify_cert(X509_STORE_CTX *ctx) { X509 *x,*xtmp,*chain_ss=NULL; - X509_NAME *xn; int bad_chain = 0; X509_VERIFY_PARAM *param = ctx->param; int depth,i,ok=0; @@ -205,8 +241,23 @@ int X509_verify_cert(X509_STORE_CTX *ctx) */ /* If we are self signed, we break */ - xn=X509_get_issuer_name(x); - if (ctx->check_issued(ctx, x,x)) break; + if (cert_self_signed(x)) + break; + /* If asked see if we can find issuer in trusted store first */ + if (ctx->param->flags & X509_V_FLAG_TRUSTED_FIRST) + { + ok = ctx->get_issuer(&xtmp, ctx, x); + if (ok < 0) + return ok; + /* If successful for now free up cert so it + * will be picked up again later. + */ + if (ok > 0) + { + X509_free(xtmp); + break; + } + } /* If we were passed a cert chain, use it first */ if (ctx->untrusted != NULL) @@ -242,8 +293,7 @@ int X509_verify_cert(X509_STORE_CTX *ctx) i=sk_X509_num(ctx->chain); x=sk_X509_value(ctx->chain,i-1); - xn = X509_get_subject_name(x); - if (ctx->check_issued(ctx, x, x)) + if (cert_self_signed(x)) { /* we have a self signed certificate */ if (sk_X509_num(ctx->chain) == 1) @@ -291,8 +341,8 @@ int X509_verify_cert(X509_STORE_CTX *ctx) if (depth < num) break; /* If we are self signed, we break */ - xn=X509_get_issuer_name(x); - if (ctx->check_issued(ctx,x,x)) break; + if (cert_self_signed(x)) + break; ok = ctx->get_issuer(&xtmp, ctx, x); @@ -310,10 +360,17 @@ int X509_verify_cert(X509_STORE_CTX *ctx) } /* we now have our chain, lets check it... */ - xn=X509_get_issuer_name(x); - /* Is last certificate looked up self signed? */ - if (!ctx->check_issued(ctx,x,x)) + i = check_trust(ctx); + + /* If explicitly rejected error */ + if (i == X509_TRUST_REJECTED) + goto end; + /* If not explicitly trusted then indicate error unless it's + * a single self signed certificate in which case we've indicated + * an error already and set bad_chain == 1 + */ + if (i != X509_TRUST_TRUSTED && !bad_chain) { if ((chain_ss == NULL) || !ctx->check_issued(ctx, x, chain_ss)) { @@ -351,9 +408,7 @@ int X509_verify_cert(X509_STORE_CTX *ctx) if (!ok) goto end; - /* The chain extensions are OK: check trust */ - - if (param->trust > 0) ok = check_trust(ctx); + ok = check_id(ctx); if (!ok) goto end; @@ -367,6 +422,17 @@ int X509_verify_cert(X509_STORE_CTX *ctx) ok = ctx->check_revocation(ctx); if(!ok) goto end; + i = X509_chain_check_suiteb(&ctx->error_depth, NULL, ctx->chain, + ctx->param->flags); + if (i != X509_V_OK) + { + ctx->error = i; + ctx->current_cert = sk_X509_value(ctx->chain, ctx->error_depth); + ok = cb(0, ctx); + if (!ok) + goto end; + } + /* At this point, we have a chain and need to verify it */ if (ctx->verify != NULL) ok=ctx->verify(ctx); @@ -403,14 +469,18 @@ end: static X509 *find_issuer(X509_STORE_CTX *ctx, STACK_OF(X509) *sk, X509 *x) { int i; - X509 *issuer; + X509 *issuer, *rv = NULL;; for (i = 0; i < sk_X509_num(sk); i++) { issuer = sk_X509_value(sk, i); if (ctx->check_issued(ctx, x, issuer)) - return issuer; + { + rv = issuer; + if (x509_check_cert_time(ctx, rv, 1)) + break; + } } - return NULL; + return rv; } /* Given a possible certificate and issuer check them */ @@ -418,7 +488,27 @@ static X509 *find_issuer(X509_STORE_CTX *ctx, STACK_OF(X509) *sk, X509 *x) static int check_issued(X509_STORE_CTX *ctx, X509 *x, X509 *issuer) { int ret; + if (x == issuer) + return cert_self_signed(x); ret = X509_check_issued(issuer, x); + if (ret == X509_V_OK) + { + int i; + X509 *ch; + /* Special case: single self signed certificate */ + if (cert_self_signed(x) && sk_X509_num(ctx->chain) == 1) + return 1; + for (i = 0; i < sk_X509_num(ctx->chain); i++) + { + ch = sk_X509_value(ctx->chain, i); + if (ch == issuer || !X509_cmp(ch, issuer)) + { + ret = X509_V_ERR_PATH_LOOP; + break; + } + } + } + if (ret == X509_V_OK) return 1; /* If we haven't asked for issuer errors don't set ctx */ @@ -645,30 +735,87 @@ static int check_name_constraints(X509_STORE_CTX *ctx) return 1; } +static int check_id_error(X509_STORE_CTX *ctx, int errcode) + { + ctx->error = errcode; + ctx->current_cert = ctx->cert; + ctx->error_depth = 0; + return ctx->verify_cb(0, ctx); + } + +static int check_id(X509_STORE_CTX *ctx) + { + X509_VERIFY_PARAM *vpm = ctx->param; + X509_VERIFY_PARAM_ID *id = vpm->id; + X509 *x = ctx->cert; + if (id->host && X509_check_host(x, id->host, 0, id->hostflags) <= 0) + { + if (!check_id_error(ctx, X509_V_ERR_HOSTNAME_MISMATCH)) + return 0; + } + if (id->email && X509_check_email(x, id->email, id->emaillen, 0) <= 0) + { + if (!check_id_error(ctx, X509_V_ERR_EMAIL_MISMATCH)) + return 0; + } + if (id->ip && X509_check_ip(x, id->ip, id->iplen, 0) <= 0) + { + if (!check_id_error(ctx, X509_V_ERR_IP_ADDRESS_MISMATCH)) + return 0; + } + return 1; + } + static int check_trust(X509_STORE_CTX *ctx) { -#ifdef OPENSSL_NO_CHAIN_VERIFY - return 1; -#else int i, ok; - X509 *x; + X509 *x = NULL; int (*cb)(int xok,X509_STORE_CTX *xctx); cb=ctx->verify_cb; -/* For now just check the last certificate in the chain */ - i = sk_X509_num(ctx->chain) - 1; - x = sk_X509_value(ctx->chain, i); - ok = X509_check_trust(x, ctx->param->trust, 0); - if (ok == X509_TRUST_TRUSTED) - return 1; - ctx->error_depth = i; - ctx->current_cert = x; - if (ok == X509_TRUST_REJECTED) - ctx->error = X509_V_ERR_CERT_REJECTED; - else - ctx->error = X509_V_ERR_CERT_UNTRUSTED; - ok = cb(0, ctx); - return ok; -#endif + /* Check all trusted certificates in chain */ + for (i = ctx->last_untrusted; i < sk_X509_num(ctx->chain); i++) + { + x = sk_X509_value(ctx->chain, i); + ok = X509_check_trust(x, ctx->param->trust, 0); + /* If explicitly trusted return trusted */ + if (ok == X509_TRUST_TRUSTED) + return X509_TRUST_TRUSTED; + /* If explicitly rejected notify callback and reject if + * not overridden. + */ + if (ok == X509_TRUST_REJECTED) + { + ctx->error_depth = i; + ctx->current_cert = x; + ctx->error = X509_V_ERR_CERT_REJECTED; + ok = cb(0, ctx); + if (!ok) + return X509_TRUST_REJECTED; + } + } + /* If we accept partial chains and have at least one trusted + * certificate return success. + */ + if (ctx->param->flags & X509_V_FLAG_PARTIAL_CHAIN) + { + X509 *mx; + if (ctx->last_untrusted < sk_X509_num(ctx->chain)) + return X509_TRUST_TRUSTED; + x = sk_X509_value(ctx->chain, 0); + mx = lookup_cert_match(ctx, x); + if (mx) + { + (void)sk_X509_set(ctx->chain, 0, mx); + X509_free(x); + ctx->last_untrusted = 0; + return X509_TRUST_TRUSTED; + } + } + + /* If no trusted certs in chain at all return untrusted and + * allow standard (no issuer cert) etc errors to be indicated. + */ + return X509_TRUST_UNTRUSTED; } static int check_revocation(X509_STORE_CTX *ctx) @@ -679,7 +826,12 @@ static int check_revocation(X509_STORE_CTX *ctx) if (ctx->param->flags & X509_V_FLAG_CRL_CHECK_ALL) last = sk_X509_num(ctx->chain) - 1; else + { + /* If checking CRL paths this isn't the EE certificate */ + if (ctx->parent) + return 1; last = 0; + } for(i = 0; i <= last; i++) { ctx->error_depth = i; @@ -694,13 +846,16 @@ static int check_cert(X509_STORE_CTX *ctx) X509_CRL *crl = NULL, *dcrl = NULL; X509 *x; int ok, cnum; + unsigned int last_reasons; cnum = ctx->error_depth; x = sk_X509_value(ctx->chain, cnum); ctx->current_cert = x; ctx->current_issuer = NULL; + ctx->current_crl_score = 0; ctx->current_reasons = 0; while (ctx->current_reasons != CRLDP_ALL_REASONS) { + last_reasons = ctx->current_reasons; /* Try to retrieve relevant CRL */ if (ctx->get_crl) ok = ctx->get_crl(ctx, &crl, x); @@ -744,6 +899,15 @@ static int check_cert(X509_STORE_CTX *ctx) X509_CRL_free(dcrl); crl = NULL; dcrl = NULL; + /* If reasons not updated we wont get anywhere by + * another iteration, so exit loop. + */ + if (last_reasons == ctx->current_reasons) + { + ctx->error = X509_V_ERR_UNABLE_TO_GET_CRL; + ok = ctx->verify_cb(0, ctx); + goto err; + } } err: X509_CRL_free(crl); @@ -820,10 +984,11 @@ static int get_crl_sk(X509_STORE_CTX *ctx, X509_CRL **pcrl, X509_CRL **pdcrl, STACK_OF(X509_CRL) *crls) { int i, crl_score, best_score = *pscore; - unsigned int reasons, best_reasons; + unsigned int reasons, best_reasons = 0; X509 *x = ctx->current_cert; X509_CRL *crl, *best_crl = NULL; - X509 *crl_issuer, *best_crl_issuer = NULL; + X509 *crl_issuer = NULL, *best_crl_issuer = NULL; + for (i = 0; i < sk_X509_CRL_num(crls); i++) { crl = sk_X509_CRL_value(crls, i); @@ -870,7 +1035,7 @@ static int crl_extension_match(X509_CRL *a, X509_CRL *b, int nid) { ASN1_OCTET_STRING *exta, *extb; int i; - i = X509_CRL_get_ext_by_NID(a, nid, 0); + i = X509_CRL_get_ext_by_NID(a, nid, -1); if (i >= 0) { /* Can't have multiple occurrences */ @@ -881,7 +1046,7 @@ static int crl_extension_match(X509_CRL *a, X509_CRL *b, int nid) else exta = NULL; - i = X509_CRL_get_ext_by_NID(b, nid, 0); + i = X509_CRL_get_ext_by_NID(b, nid, -1); if (i >= 0) { @@ -1123,7 +1288,7 @@ static int check_crl_path(X509_STORE_CTX *ctx, X509 *x) /* Verify CRL issuer */ ret = X509_verify_cert(&crl_ctx); - if (!ret) + if (ret <= 0) goto err; /* Check chain is acceptable */ @@ -1386,7 +1551,7 @@ static int check_crl(X509_STORE_CTX *ctx, X509_CRL *crl) if (!(ctx->current_crl_score & CRL_SCORE_SAME_PATH)) { - if (!check_crl_path(ctx, ctx->current_issuer)) + if (check_crl_path(ctx, ctx->current_issuer) <= 0) { ctx->error = X509_V_ERR_CRL_PATH_VALIDATION_ERROR; ok = ctx->verify_cb(0, ctx); @@ -1422,6 +1587,15 @@ static int check_crl(X509_STORE_CTX *ctx, X509_CRL *crl) } else { + int rv; + rv = X509_CRL_check_suiteb(crl, ikey, ctx->param->flags); + if (rv != X509_V_OK) + { + ctx->error=rv; + ok = ctx->verify_cb(0, ctx); + if (!ok) + goto err; + } /* Verify CRL signature */ if(X509_CRL_verify(crl, ikey) <= 0) { @@ -1449,10 +1623,9 @@ static int cert_crl(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x) * a certificate was revoked. This has since been changed since * critical extension can change the meaning of CRL entries. */ - if (crl->flags & EXFLAG_CRITICAL) + if (!(ctx->param->flags & X509_V_FLAG_IGNORE_CRITICAL) + && (crl->flags & EXFLAG_CRITICAL)) { - if (ctx->param->flags & X509_V_FLAG_IGNORE_CRITICAL) - return 1; ctx->error = X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION; ok = ctx->verify_cb(0, ctx); if(!ok) @@ -1524,7 +1697,7 @@ static int check_policy(X509_STORE_CTX *ctx) return 1; } -static int check_cert_time(X509_STORE_CTX *ctx, X509 *x) +int x509_check_cert_time(X509_STORE_CTX *ctx, X509 *x, int quiet) { time_t *ptime; int i; @@ -1537,6 +1710,8 @@ static int check_cert_time(X509_STORE_CTX *ctx, X509 *x) i=X509_cmp_time(X509_get_notBefore(x), ptime); if (i == 0) { + if (quiet) + return 0; ctx->error=X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD; ctx->current_cert=x; if (!ctx->verify_cb(0, ctx)) @@ -1545,6 +1720,8 @@ static int check_cert_time(X509_STORE_CTX *ctx, X509 *x) if (i > 0) { + if (quiet) + return 0; ctx->error=X509_V_ERR_CERT_NOT_YET_VALID; ctx->current_cert=x; if (!ctx->verify_cb(0, ctx)) @@ -1554,6 +1731,8 @@ static int check_cert_time(X509_STORE_CTX *ctx, X509 *x) i=X509_cmp_time(X509_get_notAfter(x), ptime); if (i == 0) { + if (quiet) + return 0; ctx->error=X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD; ctx->current_cert=x; if (!ctx->verify_cb(0, ctx)) @@ -1562,6 +1741,8 @@ static int check_cert_time(X509_STORE_CTX *ctx, X509 *x) if (i < 0) { + if (quiet) + return 0; ctx->error=X509_V_ERR_CERT_HAS_EXPIRED; ctx->current_cert=x; if (!ctx->verify_cb(0, ctx)) @@ -1589,6 +1770,11 @@ static int internal_verify(X509_STORE_CTX *ctx) xs=xi; else { + if (ctx->param->flags & X509_V_FLAG_PARTIAL_CHAIN) + { + xs = xi; + goto check_cert; + } if (n <= 0) { ctx->error=X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE; @@ -1608,7 +1794,12 @@ static int internal_verify(X509_STORE_CTX *ctx) while (n >= 0) { ctx->error_depth=n; - if (!xs->valid) + + /* Skip signature check for self signed certificates unless + * explicitly asked for. It doesn't add any security and + * just wastes time. + */ + if (!xs->valid && (xs != xi || (ctx->param->flags & X509_V_FLAG_CHECK_SS_SIGNATURE))) { if ((pkey=X509_get_pubkey(xi)) == NULL) { @@ -1618,13 +1809,6 @@ static int internal_verify(X509_STORE_CTX *ctx) if (!ok) goto end; } else if (X509_verify(xs,pkey) <= 0) - /* XXX For the final trusted self-signed cert, - * this is a waste of time. That check should - * optional so that e.g. 'openssl x509' can be - * used to detect invalid self-signatures, but - * we don't verify again and again in SSL - * handshakes and the like once the cert has - * been declared trusted. */ { ctx->error=X509_V_ERR_CERT_SIGNATURE_FAILURE; ctx->current_cert=xs; @@ -1641,7 +1825,8 @@ static int internal_verify(X509_STORE_CTX *ctx) xs->valid = 1; - ok = check_cert_time(ctx, xs); + check_cert: + ok = x509_check_cert_time(ctx, xs, 0); if (!ok) goto end; @@ -1723,10 +1908,11 @@ int X509_cmp_time(const ASN1_TIME *ctm, time_t *cmp_time) offset= -offset; } atm.type=ctm->type; + atm.flags = 0; atm.length=sizeof(buff2); atm.data=(unsigned char *)buff2; - if (X509_time_adj(&atm,-offset*60, cmp_time) == NULL) + if (X509_time_adj(&atm, offset*60, cmp_time) == NULL) return 0; if (ctm->type == V_ASN1_UTCTIME) @@ -1751,19 +1937,28 @@ ASN1_TIME *X509_gmtime_adj(ASN1_TIME *s, long adj) return X509_time_adj(s, adj, NULL); } -ASN1_TIME *X509_time_adj(ASN1_TIME *s, long adj, time_t *in_tm) +ASN1_TIME *X509_time_adj(ASN1_TIME *s, long offset_sec, time_t *in_tm) + { + return X509_time_adj_ex(s, 0, offset_sec, in_tm); + } + +ASN1_TIME *X509_time_adj_ex(ASN1_TIME *s, + int offset_day, long offset_sec, time_t *in_tm) { time_t t; - int type = -1; if (in_tm) t = *in_tm; else time(&t); - t+=adj; - if (s) type = s->type; - if (type == V_ASN1_UTCTIME) return ASN1_UTCTIME_set(s,t); - if (type == V_ASN1_GENERALIZEDTIME) return ASN1_GENERALIZEDTIME_set(s, t); - return ASN1_TIME_set(s, t); + if (s && !(s->flags & ASN1_STRING_FLAG_MSTRING)) + { + if (s->type == V_ASN1_UTCTIME) + return ASN1_UTCTIME_adj(s,t, offset_day, offset_sec); + if (s->type == V_ASN1_GENERALIZEDTIME) + return ASN1_GENERALIZEDTIME_adj(s, t, offset_day, + offset_sec); + } + return ASN1_TIME_adj(s, t, offset_day, offset_sec); } int X509_get_pubkey_parameters(EVP_PKEY *pkey, STACK_OF(X509) *chain) @@ -1808,6 +2003,125 @@ int X509_get_pubkey_parameters(EVP_PKEY *pkey, STACK_OF(X509) *chain) return 1; } +/* Make a delta CRL as the diff between two full CRLs */ + +X509_CRL *X509_CRL_diff(X509_CRL *base, X509_CRL *newer, + EVP_PKEY *skey, const EVP_MD *md, unsigned int flags) + { + X509_CRL *crl = NULL; + int i; + STACK_OF(X509_REVOKED) *revs = NULL; + /* CRLs can't be delta already */ + if (base->base_crl_number || newer->base_crl_number) + { + X509err(X509_F_X509_CRL_DIFF, X509_R_CRL_ALREADY_DELTA); + return NULL; + } + /* Base and new CRL must have a CRL number */ + if (!base->crl_number || !newer->crl_number) + { + X509err(X509_F_X509_CRL_DIFF, X509_R_NO_CRL_NUMBER); + return NULL; + } + /* Issuer names must match */ + if (X509_NAME_cmp(X509_CRL_get_issuer(base), + X509_CRL_get_issuer(newer))) + { + X509err(X509_F_X509_CRL_DIFF, X509_R_ISSUER_MISMATCH); + return NULL; + } + /* AKID and IDP must match */ + if (!crl_extension_match(base, newer, NID_authority_key_identifier)) + { + X509err(X509_F_X509_CRL_DIFF, X509_R_AKID_MISMATCH); + return NULL; + } + if (!crl_extension_match(base, newer, NID_issuing_distribution_point)) + { + X509err(X509_F_X509_CRL_DIFF, X509_R_IDP_MISMATCH); + return NULL; + } + /* Newer CRL number must exceed full CRL number */ + if (ASN1_INTEGER_cmp(newer->crl_number, base->crl_number) <= 0) + { + X509err(X509_F_X509_CRL_DIFF, X509_R_NEWER_CRL_NOT_NEWER); + return NULL; + } + /* CRLs must verify */ + if (skey && (X509_CRL_verify(base, skey) <= 0 || + X509_CRL_verify(newer, skey) <= 0)) + { + X509err(X509_F_X509_CRL_DIFF, X509_R_CRL_VERIFY_FAILURE); + return NULL; + } + /* Create new CRL */ + crl = X509_CRL_new(); + if (!crl || !X509_CRL_set_version(crl, 1)) + goto memerr; + /* Set issuer name */ + if (!X509_CRL_set_issuer_name(crl, X509_CRL_get_issuer(newer))) + goto memerr; + + if (!X509_CRL_set_lastUpdate(crl, X509_CRL_get_lastUpdate(newer))) + goto memerr; + if (!X509_CRL_set_nextUpdate(crl, X509_CRL_get_nextUpdate(newer))) + goto memerr; + + /* Set base CRL number: must be critical */ + + if (!X509_CRL_add1_ext_i2d(crl, NID_delta_crl, base->crl_number, 1, 0)) + goto memerr; + + /* Copy extensions across from newest CRL to delta: this will set + * CRL number to correct value too. + */ + + for (i = 0; i < X509_CRL_get_ext_count(newer); i++) + { + X509_EXTENSION *ext; + ext = X509_CRL_get_ext(newer, i); + if (!X509_CRL_add_ext(crl, ext, -1)) + goto memerr; + } + + /* Go through revoked entries, copying as needed */ + + revs = X509_CRL_get_REVOKED(newer); + + for (i = 0; i < sk_X509_REVOKED_num(revs); i++) + { + X509_REVOKED *rvn, *rvtmp; + rvn = sk_X509_REVOKED_value(revs, i); + /* Add only if not also in base. + * TODO: need something cleverer here for some more complex + * CRLs covering multiple CAs. + */ + if (!X509_CRL_get0_by_serial(base, &rvtmp, rvn->serialNumber)) + { + rvtmp = X509_REVOKED_dup(rvn); + if (!rvtmp) + goto memerr; + if (!X509_CRL_add0_revoked(crl, rvtmp)) + { + X509_REVOKED_free(rvtmp); + goto memerr; + } + } + } + /* TODO: optionally prune deleted entries */ + + if (skey && md && !X509_CRL_sign(crl, skey, md)) + goto memerr; + + return crl; + + memerr: + X509err(X509_F_X509_CRL_DIFF, ERR_R_MALLOC_FAILURE); + if (crl) + X509_CRL_free(crl); + return NULL; + } + int X509_STORE_CTX_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) { @@ -1854,16 +2168,24 @@ STACK_OF(X509) *X509_STORE_CTX_get_chain(X509_STORE_CTX *ctx) STACK_OF(X509) *X509_STORE_CTX_get1_chain(X509_STORE_CTX *ctx) { - int i; - X509 *x; - STACK_OF(X509) *chain; - if (!ctx->chain || !(chain = sk_X509_dup(ctx->chain))) return NULL; - for (i = 0; i < sk_X509_num(chain); i++) - { - x = sk_X509_value(chain, i); - CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509); - } - return chain; + if (!ctx->chain) + return NULL; + return X509_chain_up_ref(ctx->chain); + } + +X509 *X509_STORE_CTX_get0_current_issuer(X509_STORE_CTX *ctx) + { + return ctx->current_issuer; + } + +X509_CRL *X509_STORE_CTX_get0_current_crl(X509_STORE_CTX *ctx) + { + return ctx->current_crl; + } + +X509_STORE_CTX *X509_STORE_CTX_get0_parent_ctx(X509_STORE_CTX *ctx) + { + return ctx->parent; } void X509_STORE_CTX_set_cert(X509_STORE_CTX *ctx, X509 *x) @@ -1986,6 +2308,9 @@ int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509, ctx->error_depth=0; ctx->current_cert=NULL; ctx->current_issuer=NULL; + ctx->current_crl=NULL; + ctx->current_crl_score=0; + ctx->current_reasons=0; ctx->tree = NULL; ctx->parent = NULL; @@ -2005,7 +2330,7 @@ int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509, if (store) ret = X509_VERIFY_PARAM_inherit(ctx->param, store->param); else - ctx->param->flags |= X509_VP_FLAG_DEFAULT|X509_VP_FLAG_ONCE; + ctx->param->inh_flags |= X509_VP_FLAG_DEFAULT|X509_VP_FLAG_ONCE; if (store) {