Esempio n. 1
0
void
openssl_time_callback (const SSL* ssl, int where, int ret)
{
  if (where == SSL_CB_CONNECT_LOOP &&
      (ssl->state == SSL3_ST_CR_SRVR_HELLO_A || ssl->state == SSL3_ST_CR_SRVR_HELLO_B))
  {
    // XXX TODO: If we want to trust the remote system for time,
    // can we just read that time out of the remote system and if the
    // cert verifies, decide that the time is reasonable?
    // Such a process seems to indicate that a once valid cert would be
    // forever valid - we stopgap that by ensuring it isn't less than
    // the latest compiled_time and isn't above max_reasonable_time...
    // XXX TODO: Solve eternal question about the Chicken and the Egg...
    uint32_t compiled_time = RECENT_COMPILE_DATE;
    uint32_t max_reasonable_time = MAX_REASONABLE_TIME;
    uint32_t server_time;
    verb("V: freezing time for x509 verification");
    memcpy(&server_time, ssl->s3->server_random, sizeof(uint32_t));
    if (compiled_time < ntohl(server_time)
        &&
        ntohl(server_time) < max_reasonable_time)
    {
      verb("V: remote peer provided: %d, preferred over compile time: %d",
            ntohl(server_time), compiled_time);
      verb("V: freezing time with X509_VERIFY_PARAM_set_time");
      X509_VERIFY_PARAM_set_time(ssl->ctx->cert_store->param,
                                 (time_t) ntohl(server_time) + 86400);
    } else {
      die("V: the remote server is a false ticker! server: %d compile: %d",
           ntohl(server_time), compiled_time);
    }
  }
}
Esempio n. 2
0
int
mono_btls_x509_verify_param_set_time (MonoBtlsX509VerifyParam *param, long time)
{
	if (!param->owns)
		return -1;
	X509_VERIFY_PARAM_set_time (param->param, time);
	return 1;
}
Esempio n. 3
0
bool bdoc::X509Cert::verify(X509_STORE* aStore, struct tm* tm) const
{
	if (aStore == NULL) {
		THROW_STACK_EXCEPTION("Invalid argument to verify");
	}

	X509_STORE* store = aStore;
	X509_STORE** ppStore = NULL;
	X509_STORE_scope xst(ppStore);

	X509_STORE_CTX *csc = X509_STORE_CTX_new();
	X509_STORE_CTX_scope csct(&csc);
	if (csc == NULL) {
		THROW_STACK_EXCEPTION("Failed to create X509_STORE_CTX %s",ERR_reason_error_string(ERR_get_error()));
	}

	X509* x = getX509();
	X509_scope xt(&x);
	if (!X509_STORE_CTX_init(csc, store, x, NULL)) {
		THROW_STACK_EXCEPTION("Failed to init X509_STORE_CTX %s",ERR_reason_error_string(ERR_get_error()));
	}

	if (tm != NULL) {
		time_t t = timegm(tm);
		if (t == -1) {
			THROW_STACK_EXCEPTION("Given time cannot be represented as calendar time");
		}

		X509_VERIFY_PARAM *param = X509_STORE_CTX_get0_param(csc);
		if (param == NULL) {
			THROW_STACK_EXCEPTION("Failed to retrieve X509_STORE_CTX verification parameters %s",
				ERR_reason_error_string(ERR_get_error()));
		}
		X509_VERIFY_PARAM_set_time(param, t);
	}

	int ok = X509_verify_cert(csc);

	if (ok != 1) {
		int err = X509_STORE_CTX_get_error(csc);
		X509Cert cause(X509_STORE_CTX_get_current_cert (csc));
		std::ostringstream s;
		s << "Unable to verify " << cause.getSubject();
		s << ". Cause: " << X509_verify_cert_error_string(err);
		switch (err) {
			case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
				{
					THROW_STACK_EXCEPTION("Certificate issuer missing: %s", s.str().c_str());
				}
			default: THROW_STACK_EXCEPTION(s.str().c_str()); break;
		}
	}

	return (ok == 1);
}
Esempio n. 4
0
int opt_verify(int opt, X509_VERIFY_PARAM *vpm)
{
    int i;
    ossl_intmax_t t = 0;
    ASN1_OBJECT *otmp;
    X509_PURPOSE *xptmp;
    const X509_VERIFY_PARAM *vtmp;

    assert(vpm != NULL);
    assert(opt > OPT_V__FIRST);
    assert(opt < OPT_V__LAST);

    switch ((enum range)opt) {
    case OPT_V__FIRST:
    case OPT_V__LAST:
        return 0;
    case OPT_V_POLICY:
        otmp = OBJ_txt2obj(opt_arg(), 0);
        if (otmp == NULL) {
            BIO_printf(bio_err, "%s: Invalid Policy %s\n", prog, opt_arg());
            return 0;
        }
        X509_VERIFY_PARAM_add0_policy(vpm, otmp);
        break;
    case OPT_V_PURPOSE:
        /* purpose name -> purpose index */
        i = X509_PURPOSE_get_by_sname(opt_arg());
        if (i < 0) {
            BIO_printf(bio_err, "%s: Invalid purpose %s\n", prog, opt_arg());
            return 0;
        }

        /* purpose index -> purpose object */
        xptmp = X509_PURPOSE_get0(i);

        /* purpose object -> purpose value */
        i = X509_PURPOSE_get_id(xptmp);

        if (!X509_VERIFY_PARAM_set_purpose(vpm, i)) {
            BIO_printf(bio_err,
                       "%s: Internal error setting purpose %s\n",
                       prog, opt_arg());
            return 0;
        }
        break;
    case OPT_V_VERIFY_NAME:
        vtmp = X509_VERIFY_PARAM_lookup(opt_arg());
        if (vtmp == NULL) {
            BIO_printf(bio_err, "%s: Invalid verify name %s\n",
                       prog, opt_arg());
            return 0;
        }
        X509_VERIFY_PARAM_set1(vpm, vtmp);
        break;
    case OPT_V_VERIFY_DEPTH:
        i = atoi(opt_arg());
        if (i >= 0)
            X509_VERIFY_PARAM_set_depth(vpm, i);
        break;
    case OPT_V_VERIFY_AUTH_LEVEL:
        i = atoi(opt_arg());
        if (i >= 0)
            X509_VERIFY_PARAM_set_auth_level(vpm, i);
        break;
    case OPT_V_ATTIME:
        if (!opt_imax(opt_arg(), &t))
            return 0;
        if (t != (time_t)t) {
            BIO_printf(bio_err, "%s: epoch time out of range %s\n",
                       prog, opt_arg());
            return 0;
        }
        X509_VERIFY_PARAM_set_time(vpm, (time_t)t);
        break;
    case OPT_V_VERIFY_HOSTNAME:
        if (!X509_VERIFY_PARAM_set1_host(vpm, opt_arg(), 0))
            return 0;
        break;
    case OPT_V_VERIFY_EMAIL:
        if (!X509_VERIFY_PARAM_set1_email(vpm, opt_arg(), 0))
            return 0;
        break;
    case OPT_V_VERIFY_IP:
        if (!X509_VERIFY_PARAM_set1_ip_asc(vpm, opt_arg()))
            return 0;
        break;
    case OPT_V_IGNORE_CRITICAL:
        X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_IGNORE_CRITICAL);
        break;
    case OPT_V_ISSUER_CHECKS:
        /* NOP, deprecated */
        break;
    case OPT_V_CRL_CHECK:
        X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_CRL_CHECK);
        break;
    case OPT_V_CRL_CHECK_ALL:
        X509_VERIFY_PARAM_set_flags(vpm,
                                    X509_V_FLAG_CRL_CHECK |
                                    X509_V_FLAG_CRL_CHECK_ALL);
        break;
    case OPT_V_POLICY_CHECK:
        X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_POLICY_CHECK);
        break;
    case OPT_V_EXPLICIT_POLICY:
        X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_EXPLICIT_POLICY);
        break;
    case OPT_V_INHIBIT_ANY:
        X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_INHIBIT_ANY);
        break;
    case OPT_V_INHIBIT_MAP:
        X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_INHIBIT_MAP);
        break;
    case OPT_V_X509_STRICT:
        X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_X509_STRICT);
        break;
    case OPT_V_EXTENDED_CRL:
        X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_EXTENDED_CRL_SUPPORT);
        break;
    case OPT_V_USE_DELTAS:
        X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_USE_DELTAS);
        break;
    case OPT_V_POLICY_PRINT:
        X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_NOTIFY_POLICY);
        break;
    case OPT_V_CHECK_SS_SIG:
        X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_CHECK_SS_SIGNATURE);
        break;
    case OPT_V_TRUSTED_FIRST:
        X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_TRUSTED_FIRST);
        break;
    case OPT_V_SUITEB_128_ONLY:
        X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_SUITEB_128_LOS_ONLY);
        break;
    case OPT_V_SUITEB_128:
        X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_SUITEB_128_LOS);
        break;
    case OPT_V_SUITEB_192:
        X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_SUITEB_192_LOS);
        break;
    case OPT_V_PARTIAL_CHAIN:
        X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_PARTIAL_CHAIN);
        break;
    case OPT_V_NO_ALT_CHAINS:
        X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_NO_ALT_CHAINS);
        break;
    case OPT_V_NO_CHECK_TIME:
        X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_NO_CHECK_TIME);
        break;
    }
    return 1;

}
Esempio n. 5
0
int opt_verify(int opt, X509_VERIFY_PARAM *vpm)
{
    unsigned long ul;
    int i;
    ASN1_OBJECT *otmp;
    X509_PURPOSE *xptmp;
    const X509_VERIFY_PARAM *vtmp;

    assert(vpm != NULL);
    assert(opt > OPT_V__FIRST);
    assert(opt < OPT_V__LAST);

    switch ((enum range)opt) {
    case OPT_V__FIRST:
    case OPT_V__LAST:
        return 0;
    case OPT_V_POLICY:
        otmp = OBJ_txt2obj(opt_arg(), 0);
        if (otmp == NULL) {
            BIO_printf(bio_err, "%s: Invalid Policy %s\n", prog, opt_arg());
            return 0;
        }
        X509_VERIFY_PARAM_add0_policy(vpm, otmp);
        break;
    case OPT_V_PURPOSE:
        i = X509_PURPOSE_get_by_sname(opt_arg());
        if (i < 0) {
            BIO_printf(bio_err, "%s: Invalid purpose %s\n", prog, opt_arg());
            return 0;
        }
        xptmp = X509_PURPOSE_get0(i);
        i = X509_PURPOSE_get_id(xptmp);
        X509_VERIFY_PARAM_set_purpose(vpm, i);
        break;
    case OPT_V_VERIFY_NAME:
        vtmp = X509_VERIFY_PARAM_lookup(opt_arg());
        if (vtmp == NULL) {
            BIO_printf(bio_err, "%s: Invalid verify name %s\n",
                       prog, opt_arg());
            return 0;
        }
        X509_VERIFY_PARAM_set1(vpm, vtmp);
        break;
    case OPT_V_VERIFY_DEPTH:
        i = atoi(opt_arg());
        if (i >= 0)
            X509_VERIFY_PARAM_set_depth(vpm, i);
        break;
    case OPT_V_ATTIME:
        opt_ulong(opt_arg(), &ul);
        if (ul)
            X509_VERIFY_PARAM_set_time(vpm, (time_t)ul);
        break;
    case OPT_V_VERIFY_HOSTNAME:
        if (!X509_VERIFY_PARAM_set1_host(vpm, opt_arg(), 0))
            return 0;
        break;
    case OPT_V_VERIFY_EMAIL:
        if (!X509_VERIFY_PARAM_set1_email(vpm, opt_arg(), 0))
            return 0;
        break;
    case OPT_V_VERIFY_IP:
        if (!X509_VERIFY_PARAM_set1_ip_asc(vpm, opt_arg()))
            return 0;
        break;
    case OPT_V_IGNORE_CRITICAL:
        X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_IGNORE_CRITICAL);
        break;
    case OPT_V_ISSUER_CHECKS:
        X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_CB_ISSUER_CHECK);
        break;
    case OPT_V_CRL_CHECK:
        X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_CRL_CHECK);
        break;
    case OPT_V_CRL_CHECK_ALL:
        X509_VERIFY_PARAM_set_flags(vpm,
                                    X509_V_FLAG_CRL_CHECK |
                                    X509_V_FLAG_CRL_CHECK_ALL);
        break;
    case OPT_V_POLICY_CHECK:
        X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_POLICY_CHECK);
        break;
    case OPT_V_EXPLICIT_POLICY:
        X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_EXPLICIT_POLICY);
        break;
    case OPT_V_INHIBIT_ANY:
        X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_INHIBIT_ANY);
        break;
    case OPT_V_INHIBIT_MAP:
        X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_INHIBIT_MAP);
        break;
    case OPT_V_X509_STRICT:
        X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_X509_STRICT);
        break;
    case OPT_V_EXTENDED_CRL:
        X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_EXTENDED_CRL_SUPPORT);
        break;
    case OPT_V_USE_DELTAS:
        X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_USE_DELTAS);
        break;
    case OPT_V_POLICY_PRINT:
        X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_NOTIFY_POLICY);
        break;
    case OPT_V_CHECK_SS_SIG:
        X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_CHECK_SS_SIGNATURE);
        break;
    case OPT_V_TRUSTED_FIRST:
        X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_TRUSTED_FIRST);
        break;
    case OPT_V_SUITEB_128_ONLY:
        X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_SUITEB_128_LOS_ONLY);
        break;
    case OPT_V_SUITEB_128:
        X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_SUITEB_128_LOS);
        break;
    case OPT_V_SUITEB_192:
        X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_SUITEB_192_LOS);
        break;
    case OPT_V_PARTIAL_CHAIN:
        X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_PARTIAL_CHAIN);
        break;
    case OPT_V_NO_ALT_CHAINS:
        X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_NO_ALT_CHAINS);
    }
    return 1;

}
Esempio n. 6
0
/**
 * xmlSecOpenSSLX509StoreVerify:
 * @store:              the pointer to X509 key data store klass.
 * @certs:              the untrusted certificates stack.
 * @crls:               the crls stack.
 * @keyInfoCtx:         the pointer to <dsig:KeyInfo/> element processing context.
 *
 * Verifies @certs list.
 *
 * Returns: pointer to the first verified certificate from @certs.
 */
X509*
xmlSecOpenSSLX509StoreVerify(xmlSecKeyDataStorePtr store, XMLSEC_STACK_OF_X509* certs,
                             XMLSEC_STACK_OF_X509_CRL* crls, xmlSecKeyInfoCtx* keyInfoCtx) {
    xmlSecOpenSSLX509StoreCtxPtr ctx;
    STACK_OF(X509)* certs2 = NULL;
    STACK_OF(X509_CRL)* crls2 = NULL;
    X509 * res = NULL;
    X509 * cert;
    X509 * err_cert = NULL;
    X509_STORE_CTX *xsc;
    char buf[256];
    int err = 0;
    int i;
    int ret;

    xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecOpenSSLX509StoreId), NULL);
    xmlSecAssert2(certs != NULL, NULL);
    xmlSecAssert2(keyInfoCtx != NULL, NULL);

    xsc = X509_STORE_CTX_new();
    if(xsc == NULL) {
        xmlSecOpenSSLError(xmlSecKeyDataStoreGetName(store), "X509_STORE_CTX_new");
        goto done;
    }

    ctx = xmlSecOpenSSLX509StoreGetCtx(store);
    xmlSecAssert2(ctx != NULL, NULL);
    xmlSecAssert2(ctx->xst != NULL, NULL);

    /* dup certs */
    certs2 = sk_X509_dup(certs);
    if(certs2 == NULL) {
        xmlSecOpenSSLError(xmlSecKeyDataStoreGetName(store), "sk_X509_dup");
        goto done;
    }

    /* add untrusted certs from the store */
    if(ctx->untrusted != NULL) {
        for(i = 0; i < sk_X509_num(ctx->untrusted); ++i) {
            ret = sk_X509_push(certs2, sk_X509_value(ctx->untrusted, i));
            if(ret < 1) {
                xmlSecOpenSSLError(xmlSecKeyDataStoreGetName(store), "sk_X509_push");
                goto done;
            }
        }
    }

    /* dup crls but remove all non-verified */
    if(crls != NULL) {
        crls2 = sk_X509_CRL_dup(crls);
        if(crls2 == NULL) {
            xmlSecOpenSSLError(xmlSecKeyDataStoreGetName(store), "sk_X509_CRL_dup");
            goto done;
        }

        for(i = 0; i < sk_X509_CRL_num(crls2); ) {
            ret = xmlSecOpenSSLX509VerifyCRL(ctx->xst, sk_X509_CRL_value(crls2, i));
            if(ret == 1) {
                ++i;
            } else if(ret == 0) {
                (void)sk_X509_CRL_delete(crls2, i);
            } else {
                xmlSecError(XMLSEC_ERRORS_HERE,
                            xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
                            "xmlSecOpenSSLX509VerifyCRL",
                            XMLSEC_ERRORS_R_XMLSEC_FAILED,
                            XMLSEC_ERRORS_NO_MESSAGE);
                goto done;
            }
        }
    }

    /* remove all revoked certs */
    for(i = 0; i < sk_X509_num(certs2);) {
        cert = sk_X509_value(certs2, i);

        if(crls2 != NULL) {
            ret = xmlSecOpenSSLX509VerifyCertAgainstCrls(crls2, cert);
            if(ret == 0) {
                (void)sk_X509_delete(certs2, i);
                continue;
            } else if(ret != 1) {
                xmlSecError(XMLSEC_ERRORS_HERE,
                            xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
                            "xmlSecOpenSSLX509VerifyCertAgainstCrls",
                            XMLSEC_ERRORS_R_XMLSEC_FAILED,
                            XMLSEC_ERRORS_NO_MESSAGE);
                goto done;
            }
        }

        if(ctx->crls != NULL) {
            ret = xmlSecOpenSSLX509VerifyCertAgainstCrls(ctx->crls, cert);
            if(ret == 0) {
                (void)sk_X509_delete(certs2, i);
                continue;
            } else if(ret != 1) {
                xmlSecError(XMLSEC_ERRORS_HERE,
                            xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
                            "xmlSecOpenSSLX509VerifyCertAgainstCrls",
                            XMLSEC_ERRORS_R_XMLSEC_FAILED,
                            XMLSEC_ERRORS_NO_MESSAGE);
                goto done;
            }
        }
        ++i;
    }

    /* get one cert after another and try to verify */
    for(i = 0; i < sk_X509_num(certs2); ++i) {
        cert = sk_X509_value(certs2, i);
        if(xmlSecOpenSSLX509FindNextChainCert(certs2, cert) == NULL) {

            ret = X509_STORE_CTX_init(xsc, ctx->xst, cert, certs2);
            if(ret != 1) {
                xmlSecOpenSSLError(xmlSecKeyDataStoreGetName(store),
                                   "X509_STORE_CTX_init");
                goto done;
            }

            if(keyInfoCtx->certsVerificationTime > 0) {
                X509_STORE_CTX_set_time(xsc, 0, keyInfoCtx->certsVerificationTime);
            }

            {
                X509_VERIFY_PARAM * vpm = NULL;
                unsigned long vpm_flags = 0;

                vpm = X509_VERIFY_PARAM_new();
                if(vpm == NULL) {
                    xmlSecOpenSSLError(xmlSecKeyDataStoreGetName(store),
                                       "X509_VERIFY_PARAM_new");
                    goto done;
                }
                vpm_flags = X509_VERIFY_PARAM_get_flags(vpm);
                vpm_flags &= (~X509_V_FLAG_CRL_CHECK);

                if(keyInfoCtx->certsVerificationTime > 0) {
                    vpm_flags |= X509_V_FLAG_USE_CHECK_TIME;
                    X509_VERIFY_PARAM_set_time(vpm, keyInfoCtx->certsVerificationTime);
                }

                X509_VERIFY_PARAM_set_depth(vpm, keyInfoCtx->certsVerificationDepth);
                X509_VERIFY_PARAM_set_flags(vpm, vpm_flags);
                X509_STORE_CTX_set0_param(xsc, vpm);
            }


            ret         = X509_verify_cert(xsc);
            err_cert    = X509_STORE_CTX_get_current_cert(xsc);
            err         = X509_STORE_CTX_get_error(xsc);

            X509_STORE_CTX_cleanup (xsc);

            if(ret == 1) {
                res = cert;
                goto done;
            } else if(ret < 0) {
                const char* err_msg;

                buf[0] = '\0';
                X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof buf);
                err_msg = X509_verify_cert_error_string(err);
                xmlSecError(XMLSEC_ERRORS_HERE,
                            xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
                            "X509_verify_cert",
                            XMLSEC_ERRORS_R_CRYPTO_FAILED,
                            "subj=%s;err=%d;msg=%s",
                            xmlSecErrorsSafeString(buf),
                            err,
                            xmlSecErrorsSafeString(err_msg));
                goto done;
            } else if(ret == 0) {
                const char* err_msg;

                buf[0] = '\0';
                X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof buf);
                err_msg = X509_verify_cert_error_string(err);
                xmlSecError(XMLSEC_ERRORS_HERE,
                            xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
                            "X509_verify_cert",
                            XMLSEC_ERRORS_R_CRYPTO_FAILED,
                            "subj=%s;err=%d;msg=%s",
                            xmlSecErrorsSafeString(buf),
                            err,
                            xmlSecErrorsSafeString(err_msg));
            }
        }
    }

    /* if we came here then we found nothing. do we have any error? */
    if((err != 0) && (err_cert != NULL)) {
        const char* err_msg;

        err_msg = X509_verify_cert_error_string(err);
        switch (err) {
        case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
            X509_NAME_oneline(X509_get_issuer_name(err_cert), buf, sizeof buf);
            xmlSecError(XMLSEC_ERRORS_HERE,
                        xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
                        NULL,
                        XMLSEC_ERRORS_R_CERT_ISSUER_FAILED,
                        "err=%d;msg=%s;issuer=%s",
                        err,
                        xmlSecErrorsSafeString(err_msg),
                        xmlSecErrorsSafeString(buf));
            break;
        case X509_V_ERR_CERT_NOT_YET_VALID:
        case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
            xmlSecError(XMLSEC_ERRORS_HERE,
                        xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
                        NULL,
                        XMLSEC_ERRORS_R_CERT_NOT_YET_VALID,
                        "err=%d;msg=%s", err,
                        xmlSecErrorsSafeString(err_msg));
            break;
        case X509_V_ERR_CERT_HAS_EXPIRED:
        case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
            xmlSecError(XMLSEC_ERRORS_HERE,
                        xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
                        NULL,
                        XMLSEC_ERRORS_R_CERT_HAS_EXPIRED,
                        "err=%d;msg=%s", err,
                        xmlSecErrorsSafeString(err_msg));
            break;
        default:
            xmlSecError(XMLSEC_ERRORS_HERE,
                        xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
                        NULL,
                        XMLSEC_ERRORS_R_CERT_VERIFY_FAILED,
                        "err=%d;msg=%s", err,
                        xmlSecErrorsSafeString(err_msg));
        }
    }

done:
    if(certs2 != NULL) {
        sk_X509_free(certs2);
    }
    if(crls2 != NULL) {
        sk_X509_CRL_free(crls2);
    }
    if(xsc != NULL) {
        X509_STORE_CTX_free(xsc);
    }
    return(res);
}