int net_nfc_util_openssl_verify_certificate(net_nfc_openssl_verify_context_s *context)
{
	int result = 0;
	X509_STORE_CTX *store_ctx = NULL;

	store_ctx = X509_STORE_CTX_new();
	if (store_ctx != NULL)
	{
		X509_STORE_set_flags(context->store, 0);
		if (X509_STORE_CTX_init(store_ctx, context->store, context->signer_cert, 0) == true)
		{
			result = X509_verify_cert(store_ctx);
		}
		else
		{
			DEBUG_ERR_MSG("X509_STORE_CTX_init failed");
		}

		X509_STORE_CTX_free(store_ctx);
	}
	else
	{
		DEBUG_ERR_MSG("X509_STORE_CTX_new failed");
	}

	return result;
}
Exemplo n.º 2
0
TrustedObject::TrustedObject() {

	// add keys
	pub = EVP_PKEY_new();
	priv = EVP_PKEY_new();
	untrustPub = EVP_PKEY_new();

	cryptsuite::loadRSAPublicKey(TRUSTED_PUB, &pub);
	cryptsuite::loadRSAPrivateKey(TRUSTED_PRIV, &priv);
	cryptsuite::loadRSAPublicKey(UNTRUSTED_PUB, &untrustPub);

	// load trusted certificate
	if ( ! cryptsuite::loadX509Cert(TRUSTED_CERT, &CA) ) {
		fprintf(fpErr, "Error: Could not load CA cert\n");
	}

	// create X509 context
	ctx = X509_STORE_CTX_new();
	if (ctx == NULL) {
		fprintf(fpErr, "Error: Failed to create certificate store\n");
	}

	// add trusted certificate to stack
	STACK_OF(X509) *sk = sk_X509_new_null();
	sk_X509_push(sk, CA);
	if ( X509_STORE_CTX_init(ctx, NULL, NULL, NULL) != 1) {
		fprintf(fpErr, "Error: Failed to init cert store\n");
	} 
	X509_STORE_CTX_trusted_stack(ctx, sk);
}
Exemplo n.º 3
0
static int ssl_verify_ca(X509 *target_cert)
{
    STACK_OF(X509) *ca_stack = NULL;
    X509_STORE_CTX *store_ctx = NULL;
    int ret;

    store_ctx = X509_STORE_CTX_new();

    ret = X509_STORE_CTX_init(store_ctx, ca_store, target_cert, ca_stack);

    if (ret != 1) {
        printf("X509_STORE_CTX_init fail, ret = %d", ret);
        goto end;
    }
    ret = X509_verify_cert(store_ctx);
    if (ret != 1) {
        printf("X509_verify_cert fail, ret = %d, error id = %d, %s\n",
               ret, store_ctx->error,
               X509_verify_cert_error_string(store_ctx->error));
        goto end;
    }
end:
    if (store_ctx) {
        X509_STORE_CTX_free(store_ctx);
    }

    return (ret == 1) ? 0 : -1;

}
Exemplo n.º 4
0
/**
 * Check if X509Cert is signed by trusted issuer
 * @return 0 or openssl error_code. Get human readable cause with X509_verify_cert_error_string(code)
 * @throw IOException if error
 */
int digidoc::X509Cert::verify() const throw(IOException)
{
    X509_STORE_CTX *csc = X509_STORE_CTX_new(); X509_STORE_CTX_scope csct(&csc);
    if (!csc)
        THROW_IOEXCEPTION("Failed to create X509_STORE_CTX %s",ERR_reason_error_string(ERR_get_error()));

    X509_STORE *store = digidoc::X509CertStore::getInstance()->getCertStore();
    X509* x = getX509(); X509_scope xt(&x);
    if(!X509_STORE_CTX_init(csc, store, x, NULL))
        THROW_IOEXCEPTION("Failed to init X509_STORE_CTX %s",ERR_reason_error_string(ERR_get_error()));

    int ok = X509_verify_cert(csc);

    if(!ok)
    {
        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:
        {
            IOException e(__FILE__, __LINE__, s.str());
            e.setCode( Exception::CertificateIssuerMissing );
            throw e;
            break;
        }
        default: THROW_IOEXCEPTION(s.str().c_str()); break;
        }
    }

    return ok;
}
Exemplo n.º 5
0
static int
SSL_CTX_use_certificate_file_with_check(
	SSL_CTX *ctx, 
	char *file, 
	int type)
{
	FILE *fp;
	X509 *x509;
	X509_STORE_CTX *sctx;
	int ret;
	ret = SSL_CTX_use_certificate_file(ctx, file, type);
	if(!ret) return ret;
	if(!(fp = fopen(file, "r"))) {
		return -1;
	}
	x509 = PEM_read_X509(fp, NULL, NULL, NULL);
	if(!x509){
		rewind(fp);
		x509 = d2i_X509_fp(fp, NULL);
	}
	fclose(fp);
	if(!x509) return -1;
	X509_STORE_add_cert(ctx->cert_store, x509);
	sctx = X509_STORE_CTX_new();
	X509_STORE_CTX_init(sctx, ctx->cert_store, x509, NULL);
	X509_STORE_CTX_set_verify_cb(sctx, LocalVerifyCallBack);
	X509_verify_cert(sctx);
	X509_STORE_CTX_free(sctx);
	CheckValidPeriod(x509);
	return ret;
}
int check (X509_STORE *ctx, const char *file)
{
	X509 *cert = NULL;
	int res = 0;
	X509_STORE_CTX *csc;
	cert = load_cert_from_file (file);

	if (!cert)
		return 0;

	csc = X509_STORE_CTX_new();
	if (!csc)
	{
		if (cert)
			X509_free(cert);
		return 0;
	}

	X509_STORE_set_flags(ctx, 0);
	if(!X509_STORE_CTX_init(csc, ctx, cert, 0))
	{
		if (cert)
			X509_free(cert);
		if (csc)
			X509_STORE_CTX_free(csc);
		return 0;
	}
	res = X509_verify_cert(csc);
	X509_STORE_CTX_free(csc);
	X509_free(cert);
	return (res > 0);
}
Exemplo n.º 7
0
int main(int argc, char *argv[]) {
    X509 *cert;
    X509_STORE *store;
    X509_LOOKUP *lookup;
    X509_STORE_CTX *verify_ctx;
    FILE *fp;

    OpenSSL_add_all_algorithms();
    ERR_load_crypto_strings();

    /* frist read the client certificate */
    if (!(fp = fopen(CLIENT_CERT, "r"))) {
        int_error("Error reading client certificate file");
    }
    if (!(cert = PEM_read_X509(fp, NULL, NULL, NULL))) {
        int_error("Error reading client certificate in file");
    }
    fclose(fp);

    /* create the cert store and set the verify callback */
    if (!(store = X509_STORE_new())) {
        int_error("Error creating X509_STORE_CTX object");
    }
    X509_STORE_set_verify_cb_func(store, verify_callback);

    /* load the CA certificates and CRLs */
    if (X509_STORE_load_locations(store, CA_FILE, CA_DIR) != 1) {
        int_error("Error loading the CA file or directory");
    }
    if (X509_STORE_set_default_paths(store) != 1) {
        int_error("Error loading the system-wide CA certificates");
    }
    if (!(lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file()))) {
        int_error("Error creating X509_LOOKUP object");
    }
    if (X509_load_crl_file(lookup, CRL_FILE, X509_FILETYPE_PEM) != 1) {
        int_error("Error reading the CRL file");
    }

    /* set the flags of the store so that the CRLs are consulted */
    X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);

    /* create a verification context and initialize it */
    if (!(verify_ctx = X509_STORE_CTX_new())) {
        int_error("Error creating X509_STORE_CTX object");
    }
    if (X509_STORE_CTX_init(verify_ctx, store, cert, NULL) != 1) {
        int_error("Error initializing verification context");
    }

    /* verify the certificate */
    if (X509_verify_cert(verify_ctx) != 1) {
        int_error("Error verifying the certificate");
    }
    else {
        printf("Certificate verified correctly!\n");
    }
    return 0;
}
Exemplo n.º 8
0
static GTlsCertificateFlags
g_tls_database_openssl_verify_chain (GTlsDatabase             *database,
                                     GTlsCertificate          *chain,
                                     const gchar              *purpose,
                                     GSocketConnectable       *identity,
                                     GTlsInteraction          *interaction,
                                     GTlsDatabaseVerifyFlags   flags,
                                     GCancellable             *cancellable,
                                     GError                  **error)
{
  GTlsDatabaseOpenssl *self = G_TLS_DATABASE_OPENSSL (database);
  GTlsDatabaseOpensslPrivate *priv;
  STACK_OF(X509) *certs;
  X509_STORE_CTX *csc;
  X509 *x;
  GTlsCertificateFlags result = 0;

  g_return_val_if_fail (G_IS_TLS_CERTIFICATE_OPENSSL (chain),
                        G_TLS_CERTIFICATE_GENERIC_ERROR);

  priv = g_tls_database_openssl_get_instance_private (self);

  if (g_cancellable_set_error_if_cancelled (cancellable, error))
    return G_TLS_CERTIFICATE_GENERIC_ERROR;

  certs = convert_certificate_chain_to_openssl (G_TLS_CERTIFICATE_OPENSSL (chain));

  csc = X509_STORE_CTX_new ();

  x = g_tls_certificate_openssl_get_cert (G_TLS_CERTIFICATE_OPENSSL (chain));
  if (!X509_STORE_CTX_init (csc, priv->store, x, certs))
    {
      X509_STORE_CTX_free (csc);
      sk_X509_free (certs);
      return G_TLS_CERTIFICATE_GENERIC_ERROR;
    }

  if (X509_verify_cert (csc) <= 0)
    result = g_tls_certificate_openssl_convert_error (X509_STORE_CTX_get_error (csc));

  X509_STORE_CTX_free (csc);
  sk_X509_free (certs);

  if (g_cancellable_set_error_if_cancelled (cancellable, error))
    return G_TLS_CERTIFICATE_GENERIC_ERROR;

  /* We have to check these ourselves since openssl
   * does not give us flags and UNKNOWN_CA will take priority.
   */
  result |= double_check_before_after_dates (G_TLS_CERTIFICATE_OPENSSL (chain));

  if (identity)
    result |= g_tls_certificate_openssl_verify_identity (G_TLS_CERTIFICATE_OPENSSL (chain),
                                                         identity);

  return result;
}
Exemplo n.º 9
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);
}
Exemplo n.º 10
0
static int check_certificate_by_signer (X509 *peercert)
{
  X509_STORE_CTX *xsc;
  X509_STORE *ctx;
  int pass = 0, i;

  ctx = X509_STORE_new ();
  if (ctx == NULL) return 0;

  if (option (OPTSSLSYSTEMCERTS))
  {
    if (X509_STORE_set_default_paths (ctx))
      pass++;
    else
      dprint (2, (debugfile, "X509_STORE_set_default_paths failed\n"));
  }

  if (X509_STORE_load_locations (ctx, SslCertFile, NULL))
    pass++;
  else
    dprint (2, (debugfile, "X509_STORE_load_locations failed\n"));

  for (i = 0; i < sk_X509_num (SslSessionCerts); i++)
    pass += (X509_STORE_add_cert (ctx, sk_X509_value (SslSessionCerts, i)) != 0);

  if (pass == 0)
  {
    /* nothing to do */
    X509_STORE_free (ctx);
    return 0;
  }

  xsc = X509_STORE_CTX_new();
  if (xsc == NULL) return 0;
  X509_STORE_CTX_init (xsc, ctx, peercert, SslSessionCerts);

  pass = (X509_verify_cert (xsc) > 0);
#ifdef DEBUG
  if (! pass)
  {
    char buf[SHORT_STRING];
    int err;

    err = X509_STORE_CTX_get_error (xsc);
    snprintf (buf, sizeof (buf), "%s (%d)",
	X509_verify_cert_error_string(err), err);
    dprint (2, (debugfile, "X509_verify_cert: %s\n", buf));
    dprint (2, (debugfile, " [%s]\n", peercert->name));
  }
#endif
  X509_STORE_CTX_free (xsc);
  X509_STORE_free (ctx);

  return pass;
}
Exemplo n.º 11
0
/*
 * Test for CVE-2015-1793 (Alternate Chains Certificate Forgery)
 *
 * Chain is as follows:
 *
 * rootCA (self-signed)
 *   |
 * interCA
 *   |
 * subinterCA       subinterCA (self-signed)
 *   |                   |
 * leaf ------------------
 *   |
 * bad
 *
 * rootCA, interCA, subinterCA, subinterCA (ss) all have CA=TRUE
 * leaf and bad have CA=FALSE
 *
 * subinterCA and subinterCA (ss) have the same subject name and keys
 *
 * interCA (but not rootCA) and subinterCA (ss) are in the trusted store
 * (roots.pem)
 * leaf and subinterCA are in the untrusted list (untrusted.pem)
 * bad is the certificate being verified (bad.pem)
 *
 * Versions vulnerable to CVE-2015-1793 will fail to detect that leaf has
 * CA=FALSE, and will therefore incorrectly verify bad
 *
 */
static int test_alt_chains_cert_forgery(const char *roots_f,
                                        const char *untrusted_f,
                                        const char *bad_f)
{
    int ret = 0;
    int i;
    X509 *x = NULL;
    STACK_OF(X509) *untrusted = NULL;
    BIO *bio = NULL;
    X509_STORE_CTX *sctx = NULL;
    X509_STORE *store = NULL;
    X509_LOOKUP *lookup = NULL;

    store = X509_STORE_new();
    if (store == NULL)
        goto err;

    lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
    if (lookup == NULL)
        goto err;
    if(!X509_LOOKUP_load_file(lookup, roots_f, X509_FILETYPE_PEM))
        goto err;

    untrusted = load_certs_from_file(untrusted_f);

    if ((bio = BIO_new_file(bad_f, "r")) == NULL)
        goto err;

    if((x = PEM_read_bio_X509(bio, NULL, 0, NULL)) == NULL)
        goto err;

    sctx = X509_STORE_CTX_new();
    if (sctx == NULL)
        goto err;

    if (!X509_STORE_CTX_init(sctx, store, x, untrusted))
        goto err;

    i = X509_verify_cert(sctx);

    if(i == 0 && X509_STORE_CTX_get_error(sctx) == X509_V_ERR_INVALID_CA) {
        /* This is the result we were expecting: Test passed */
        ret = 1;
    }
 err:
    X509_STORE_CTX_free(sctx);
    X509_free(x);
    BIO_free(bio);
    sk_X509_pop_free(untrusted, X509_free);
    X509_STORE_free(store);
    if (ret != 1)
        ERR_print_errors_fp(stderr);
    return ret;
}
Exemplo n.º 12
0
// VerifyChain verifies the certificate chain in chain
// according to the verification options given as opts.
bool X509VerifierPrivate::VerifyChain(std::vector<X509Certificate> chain, const X509VerifierOptions &opts) {
	bool status = false;
	X509_STORE_CTX *ctx = X509_STORE_CTX_new();
	STACK_OF(X509) *untrusted = sk_X509_new_null();

	// Ensure that we have a chain to check on.
	if (chain.empty()) {
		goto out;
	}

	// If we've been passed a DNS name in opts,
	// we should check whether the leaf certificate
	// matches that before doing the more expensive
	// checks.
	if (!opts.dns_name.empty()) {
		if (!X509HostnameVerifier::VerifyHostname(chain.at(0), opts.dns_name)) {
			std::cerr << "X509VerifierPrivate - hostname verification failed" << std::endl;
			goto out;
		}
	}

	// Extract our chain into the format that OpenSSL
	// expects for verification.
	for (X509Certificate &cert : chain) {
		X509 *cur = cert.dptr_->AsOpenSSLX509();
		sk_X509_push(untrusted, cur);
	}

	// Set up the X509_STORE_CTX to verify according to opts.
	X509_STORE_CTX_init(ctx, store_, sk_X509_value(untrusted, 0), untrusted);
	// If a time is not specified in opts, use the current system time.
	if (opts.time == 0) {
		X509_STORE_CTX_set_time(ctx, 0, std::time(nullptr));
	} else {
		X509_STORE_CTX_set_time(ctx, 0, opts.time);
	}
	// If a dns_name is specified in opts, use the SSL server policy.
	if (!opts.dns_name.empty()) {
		X509_STORE_CTX_set_purpose(ctx, X509_PURPOSE_SSL_SERVER);
		X509_STORE_CTX_set_trust(ctx, X509_TRUST_SSL_SERVER);
	}

	if (X509_verify_cert(ctx) == 1) {
		status = true;
	} else {
		std::cerr << "X509VerifierPrivate - verification error: " << X509_verify_cert_error_string(ctx->error) << std::endl;
	}

out:
	sk_X509_pop_free(untrusted, X509_free);
	X509_STORE_CTX_free(ctx);
	return status;
}
Exemplo n.º 13
0
boolean x509_verify_cert(CryptoCert cert, rdpSettings* settings)
{
	char* cert_loc;
	X509_STORE_CTX* csc;
	boolean status = false;
	X509_STORE* cert_ctx = NULL;
	X509_LOOKUP* lookup = NULL;
	X509* xcert = cert->px509;

	cert_ctx = X509_STORE_new();

	if (cert_ctx == NULL)
		goto end;

	OpenSSL_add_all_algorithms();
	lookup = X509_STORE_add_lookup(cert_ctx, X509_LOOKUP_file());

	if (lookup == NULL)
		goto end;

	lookup = X509_STORE_add_lookup(cert_ctx, X509_LOOKUP_hash_dir());

	if (lookup == NULL)
		goto end;

	X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT);
	cert_loc = get_local_certloc(settings->home_path);

	if(cert_loc != NULL)
	{
		X509_LOOKUP_add_dir(lookup, cert_loc, X509_FILETYPE_ASN1);
		xfree(cert_loc);
	}

	csc = X509_STORE_CTX_new();

	if (csc == NULL)
		goto end;

	X509_STORE_set_flags(cert_ctx, 0);

	if(!X509_STORE_CTX_init(csc, cert_ctx, xcert, 0))
		goto end;

	if (X509_verify_cert(csc) == 1)
		status = true;

	X509_STORE_CTX_free(csc);
	X509_STORE_free(cert_ctx);

end:
	return status;
}
Exemplo n.º 14
0
static VALUE 
ossl_x509stctx_alloc(VALUE klass)
{
    X509_STORE_CTX *ctx;
    VALUE obj;

    if((ctx = X509_STORE_CTX_new()) == NULL){
        ossl_raise(eX509StoreError, NULL);
    }
    WrapX509StCtx(klass, obj, ctx);

    return obj;
}
Exemplo n.º 15
0
/*****************************************************************************
 *
 * Low-level x509 functions
 *
 *****************************************************************************/
static int
xmlSecOpenSSLX509VerifyCRL(X509_STORE* xst, X509_CRL *crl ) {
    X509_STORE_CTX *xsc = NULL;
    X509_OBJECT *xobj = NULL;
    EVP_PKEY *pkey = NULL;
    int ret;

    xmlSecAssert2(xst != NULL, -1);
    xmlSecAssert2(crl != NULL, -1);

    xsc = X509_STORE_CTX_new();
    if(xsc == NULL) {
        xmlSecOpenSSLError(NULL, "X509_STORE_CTX_new");
        goto err;
    }
    xobj = X509_OBJECT_new();
    if(xobj == NULL) {
        xmlSecOpenSSLError(NULL, "X509_OBJECT_new");
        goto err;
    }

    ret = X509_STORE_CTX_init(xsc, xst, NULL, NULL);
    if(ret != 1) {
        xmlSecOpenSSLError(NULL, "X509_STORE_CTX_init");
        goto err;
    }
    ret = X509_STORE_CTX_get_by_subject(xsc, X509_LU_X509,
                                        X509_CRL_get_issuer(crl), xobj);
    if(ret <= 0) {
        xmlSecOpenSSLError(NULL, "X509_STORE_CTX_get_by_subject");
        goto err;
    }
    pkey = X509_get_pubkey(X509_OBJECT_get0_X509(xobj));
    if(pkey == NULL) {
        xmlSecOpenSSLError(NULL, "X509_get_pubkey");
        goto err;
    }
    ret = X509_CRL_verify(crl, pkey);
    EVP_PKEY_free(pkey);
    if(ret != 1) {
        xmlSecOpenSSLError(NULL, "X509_CRL_verify");
    }
    X509_STORE_CTX_free(xsc);
    X509_OBJECT_free(xobj);
    return((ret == 1) ? 1 : 0);

err:
    X509_STORE_CTX_free(xsc);
    X509_OBJECT_free(xobj);
    return(-1);
}
Exemplo n.º 16
0
int SslOcspStapling::getCertId(X509 *pCert)
{
    int     i, n;
    X509                *pXissuer;
    X509_STORE          *pXstore;
    STACK_OF(X509)      *pXchain;
    X509_STORE_CTX      *pXstore_ctx;


    pXchain = m_pCtx->extra_certs;
    n = sk_X509_num(pXchain);
    for (i = 0; i < n; i++)
    {
        pXissuer = sk_X509_value(pXchain, i);
        if (X509_check_issued(pXissuer, pCert) == X509_V_OK)
        {
            CRYPTO_add(&pXissuer->references, 1, CRYPTO_LOCK_X509);
            m_pCertId = OCSP_cert_to_id(NULL, pCert, pXissuer);
            X509_free(pXissuer);
            return 0;
        }
    }
    pXstore = SSL_CTX_get_cert_store(m_pCtx);
    if (pXstore == NULL)
    {
        setLastErrMsg("SSL_CTX_get_cert_store failed!\n");
        return LS_FAIL;
    }
    pXstore_ctx = X509_STORE_CTX_new();
    if (pXstore_ctx == NULL)
    {
        setLastErrMsg("X509_STORE_CTX_new failed!\n");
        return LS_FAIL;
    }
    if (X509_STORE_CTX_init(pXstore_ctx, pXstore, NULL, NULL) == 0)
    {
        setLastErrMsg("X509_STORE_CTX_init failed!\n");
        return LS_FAIL;
    }
    n = X509_STORE_CTX_get1_issuer(&pXissuer, pXstore_ctx, pCert);
    X509_STORE_CTX_free(pXstore_ctx);
    if ((n == -1) || (n == 0))
    {
        setLastErrMsg("X509_STORE_CTX_get1_issuer failed!\n");
        return LS_FAIL;
    }
    m_pCertId = OCSP_cert_to_id(NULL, pCert, pXissuer);
    X509_free(pXissuer);
    return 0;
}
Exemplo n.º 17
0
BOOL x509_verify_certificate(CryptoCert cert, char* certificate_store_path)
{
	X509_STORE_CTX* csc;
	BOOL status = FALSE;
	X509_STORE* cert_ctx = NULL;
	X509_LOOKUP* lookup = NULL;
	X509* xcert = cert->px509;

	cert_ctx = X509_STORE_new();

	if (cert_ctx == NULL)
		goto end;

	OpenSSL_add_all_algorithms();
	lookup = X509_STORE_add_lookup(cert_ctx, X509_LOOKUP_file());

	if (lookup == NULL)
		goto end;

	lookup = X509_STORE_add_lookup(cert_ctx, X509_LOOKUP_hash_dir());

	if (lookup == NULL)
		goto end;

	X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT);

	if (certificate_store_path != NULL)
	{
		X509_LOOKUP_add_dir(lookup, certificate_store_path, X509_FILETYPE_ASN1);
	}

	csc = X509_STORE_CTX_new();

	if (csc == NULL)
		goto end;

	X509_STORE_set_flags(cert_ctx, 0);

	if (!X509_STORE_CTX_init(csc, cert_ctx, xcert, 0))
		goto end;

	if (X509_verify_cert(csc) == 1)
		status = TRUE;

	X509_STORE_CTX_free(csc);
	X509_STORE_free(cert_ctx);

end:
	return status;
}
Exemplo n.º 18
0
		bool SSLSocket::verifyKeyprint(const string& expKP, bool allowUntrusted) noexcept
		{
			if (!ssl)
				return true;
				
			if (expKP.empty() || expKP.find("/") == string::npos)
				return allowUntrusted;
				
			verifyData.reset(new CryptoManager::SSLVerifyData(allowUntrusted, expKP));
			SSL_set_ex_data(ssl, CryptoManager::idxVerifyData, verifyData.get());
			
			SSL_CTX* ssl_ctx = SSL_get_SSL_CTX(ssl);
			X509_STORE* store = X509_STORE_new();
			bool result = false;
			int err = SSL_get_verify_result(ssl);
			if (ssl_ctx && store)
			{
				X509_STORE_CTX* vrfy_ctx = X509_STORE_CTX_new();
				X509* cert = SSL_get_peer_certificate(ssl);
				
				if (vrfy_ctx && cert && X509_STORE_CTX_init(vrfy_ctx, store, cert, SSL_get_peer_cert_chain(ssl)))
				{
					X509_STORE_CTX_set_ex_data(vrfy_ctx, SSL_get_ex_data_X509_STORE_CTX_idx(), ssl);
					X509_STORE_CTX_set_verify_cb(vrfy_ctx, SSL_CTX_get_verify_callback(ssl_ctx));
					
					int verify_result = 0;
					if ((verify_result = X509_verify_cert(vrfy_ctx)) >= 0)
					{
						err = X509_STORE_CTX_get_error(vrfy_ctx);
						
						// Watch out for weird library errors that might not set the context error code
						if (err == X509_V_OK && verify_result <= 0)
							err = X509_V_ERR_UNSPECIFIED;
							
						// This is for people who don't restart their clients and have low expiration time on their cert
						result = (err == X509_V_OK || err == X509_V_ERR_CERT_HAS_EXPIRED) || (allowUntrusted && err != X509_V_ERR_APPLICATION_VERIFICATION);
					}
				}
				
				if (cert) X509_free(cert);
				if (vrfy_ctx) X509_STORE_CTX_free(vrfy_ctx);
				if (store) X509_STORE_free(store);
			}
			
			// KeyPrint is a strong indicator of trust
			SSL_set_verify_result(ssl, err);
			
			return result;
		}
Exemplo n.º 19
0
bool Chain::verifyChain(Handle<CertificateCollection> chain, Handle<CrlCollection> crls){
	LOGGER_FN();

	try{
		LOGGER_OPENSSL(X509_STORE_CTX_new);
		X509_STORE_CTX *ctx = X509_STORE_CTX_new();
		if (!ctx) {
			THROW_OPENSSL_EXCEPTION(0, Revocation, NULL, "Error create new store ctx");
		}

		LOGGER_OPENSSL(X509_STORE_new);
		X509_STORE *st = X509_STORE_new();
		if (!st) {
			THROW_OPENSSL_EXCEPTION(0, Revocation, NULL, "Error create new store");
		}

		for (int i = 0, c = chain->length(); i < c; i++){
			LOGGER_OPENSSL(X509_STORE_add_cert);
			X509_STORE_add_cert(st, X509_dup(chain->items(i)->internal()));
		}

		X509_CRL *xtempCRL = NULL;

		LOGGER_OPENSSL(X509_STORE_CTX_init);
		X509_STORE_CTX_init(ctx, st, chain->items(0)->internal(), chain->internal());

		LOGGER_OPENSSL(X509_STORE_CTX_set0_crls);
		X509_STORE_CTX_set0_crls(ctx, crls->internal());

		LOGGER_OPENSSL(X509_STORE_CTX_set_flags);
		X509_STORE_CTX_set_flags(ctx, X509_V_FLAG_CRL_CHECK);
		LOGGER_OPENSSL(X509_STORE_CTX_set_flags);
		X509_STORE_CTX_set_flags(ctx, X509_V_FLAG_CRL_CHECK_ALL);

		LOGGER_OPENSSL(X509_verify_cert);
		if (X509_verify_cert(ctx) <= 0){
			return false;
		}

		return true;
	}
	catch (Handle<Exception> e){
		THROW_EXCEPTION(0, Chain, e, "Error verify chain (provider store)");
	}	
}
bool X509Certificate_OpenSSL::verify(ref <const X509Certificate> caCert_) const
{
	ref <const X509Certificate_OpenSSL> caCert =
		caCert_.dynamicCast <const X509Certificate_OpenSSL>();


	bool verified = false;
	bool error = true;

	X509_STORE *store = X509_STORE_new();

	if (store)
	{
		X509_STORE_CTX *verifyCtx = X509_STORE_CTX_new();

		if (verifyCtx)
		{
			if (X509_STORE_add_cert(store, caCert->m_data->cert))
			{
				X509_STORE_CTX_init(verifyCtx, store, m_data->cert, NULL);

				int ret = X509_verify_cert(verifyCtx);

				if (ret == 1)
				{
					verified = true;
					error = false;
				}
				else if (ret == 0)
				{
					verified = false;
					error = false;
				}

				//X509_verify_cert_error_string(vrfy_ctx->error)

				X509_STORE_CTX_free(verifyCtx);
			}
		}

		X509_STORE_free(store);
	}

	return verified && !error;
}
Exemplo n.º 21
0
static int
SSL_CTX_use_certificate_with_check(
	SSL_CTX *ctx, 
	X509 *x509)
{
	int ret;
	X509_STORE_CTX *sctx;
	ret = SSL_CTX_use_certificate(ctx, x509);
	if(!ret)return ret;
	X509_STORE_add_cert(ctx->cert_store, x509);
	sctx = X509_STORE_CTX_new();
	X509_STORE_CTX_init(sctx, ctx->cert_store, x509, NULL);
	X509_STORE_CTX_set_verify_cb(sctx, LocalVerifyCallBack);
	X509_verify_cert(sctx);
	X509_STORE_CTX_free(sctx);
	CheckValidPeriod(x509);
	return ret;
}
Exemplo n.º 22
0
Arquivo: ca.c Projeto: gunhu/OpenSMTPD
int
ca_X509_verify(void *certificate, void *chain, const char *CAfile,
    const char *CRLfile, const char **errstr)
{
	X509_STORE     *store = NULL;
	X509_STORE_CTX *xsc = NULL;
	int		ret = 0;

	if ((store = X509_STORE_new()) == NULL)
		goto end;

	if (!X509_STORE_load_locations(store, CAfile, NULL)) {
		log_warn("warn: unable to load CA file %s", CAfile);
		goto end;
	}
	X509_STORE_set_default_paths(store);

	if ((xsc = X509_STORE_CTX_new()) == NULL)
		goto end;

	if (X509_STORE_CTX_init(xsc, store, certificate, chain) != 1)
		goto end;

	X509_STORE_CTX_set_verify_cb(xsc, ca_verify_cb);

	ret = X509_verify_cert(xsc);

end:
	*errstr = NULL;
	if (ret != 1) {
		if (xsc)
			*errstr = X509_verify_cert_error_string(xsc->error);
		else if (ERR_peek_last_error())
			*errstr = ERR_error_string(ERR_peek_last_error(), NULL);
	}

	if (xsc)
		X509_STORE_CTX_free(xsc);
	if (store)
		X509_STORE_free(store);

	return ret > 0 ? 1 : 0;
}
Exemplo n.º 23
0
SEXP PKI_verify_cert(SEXP sCA, SEXP sCert) {
    X509 *cert;
    X509_STORE *store;
    X509_STORE_CTX *ctx;
    int rv;
    PKI_init();
    cert = retrieve_cert(sCert, "");
    store = X509_STORE_new();
    if (TYPEOF(sCA) == VECSXP) {
	int i;
	for (i = 0; i < LENGTH(sCA); i++)
	    X509_STORE_add_cert(store, retrieve_cert(VECTOR_ELT(sCA, i),"CA "));
    } else
	X509_STORE_add_cert(store, retrieve_cert(sCA, "CA "));
    ctx = X509_STORE_CTX_new();
    X509_STORE_CTX_init(ctx, store, cert, NULL);
    rv = X509_verify_cert(ctx);
    X509_STORE_CTX_free(ctx);
    X509_STORE_free(store);
    return ScalarLogical((rv == 1) ? TRUE : FALSE);
}
Exemplo n.º 24
0
bool SSLSocket::verifyKeyprint(const string& expKP, bool allowUntrusted) noexcept {
	if(!ssl)
		return true;

	if(expKP.empty() || expKP.find("/") == string::npos)
		return allowUntrusted; 

	verifyData.reset(new CryptoManager::SSLVerifyData(allowUntrusted, expKP));
	SSL_set_ex_data(ssl, CryptoManager::idxVerifyData, verifyData.get());

	SSL_CTX* ssl_ctx = SSL_get_SSL_CTX(ssl);
	X509_STORE* store = SSL_CTX_get_cert_store(ctx);

	bool result = allowUntrusted;
	int err = SSL_get_verify_result(ssl);
	if(ssl_ctx && store) {
		X509_STORE_CTX* vrfy_ctx = X509_STORE_CTX_new();
		X509* cert = SSL_get_peer_certificate(ssl);
		if(vrfy_ctx && cert && X509_STORE_CTX_init(vrfy_ctx, store, cert, SSL_get_peer_cert_chain(ssl))) {
			auto vrfy_cb = SSL_CTX_get_verify_callback(ssl_ctx);

			X509_STORE_CTX_set_ex_data(vrfy_ctx, SSL_get_ex_data_X509_STORE_CTX_idx(), ssl);
			X509_STORE_CTX_set_verify_cb(vrfy_ctx, vrfy_cb);

			if(X509_verify_cert(vrfy_ctx) >= 0) {
				err = X509_STORE_CTX_get_error(vrfy_ctx);
				// This is for people who don't restart their clients and have low expiration time on their cert
				result = (err == X509_V_OK) || (err == X509_V_ERR_CERT_HAS_EXPIRED);
			}
		}

		if(cert) X509_free(cert);
		if(vrfy_ctx) X509_STORE_CTX_free(vrfy_ctx);
	}

	// KeyPrint is a strong indicator of trust (TODO: check that this KeyPrint is mediated by a trusted hub)
	SSL_set_verify_result(ssl, err);

	return result;
}
Exemplo n.º 25
0
/** Returns status of certification:  0 for invalid, 1 for valid. */
static int valid_cert(X509 *cert, char *hostname)
{
  int i;
  char buf[4096];
  X509_STORE *store = X509_STORE_new();
  X509_STORE_CTX *ctx = X509_STORE_CTX_new();
  for (i = 0; trusted_ca[i] != NULL; i++) {
    X509 *cacert = get_cert_from_file(trusted_ca[i]);
    if (cacert)
      X509_STORE_add_cert(store, cacert);
  }
  X509_STORE_CTX_init(ctx, store, cert, sk_X509_new_null());
  if (X509_verify_cert(ctx) == 0)
    return 0;
  X509_NAME_get_text_by_NID(X509_get_subject_name(cert), NID_commonName,
    buf, sizeof(buf) - 1);
  // anal-retentive:  make sure the hostname isn't as long as the
  // buffer, since we don't want to match only because of truncation
  if (strlen(hostname) >= sizeof(buf) - 1)
    return 0;
  return (!strcmp(buf, hostname));
}
Exemplo n.º 26
0
static ngx_int_t
ngx_ssl_stapling_issuer(ngx_conf_t *cf, ngx_ssl_t *ssl)
{
    int                  i, n, rc;
    X509                *cert, *issuer;
    X509_STORE          *store;
    X509_STORE_CTX      *store_ctx;
    STACK_OF(X509)      *chain;
    ngx_ssl_stapling_t  *staple;

    staple = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_stapling_index);
    cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index);

#if OPENSSL_VERSION_NUMBER >= 0x10001000L
    SSL_CTX_get_extra_chain_certs(ssl->ctx, &chain);
#else
    chain = ssl->ctx->extra_certs;
#endif

    n = sk_X509_num(chain);

    ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ssl->log, 0,
                   "SSL get issuer: %d extra certs", n);

    for (i = 0; i < n; i++) {
        issuer = sk_X509_value(chain, i);
        if (X509_check_issued(issuer, cert) == X509_V_OK) {
#if OPENSSL_VERSION_NUMBER >= 0x10100001L
            X509_up_ref(issuer);
#else
            CRYPTO_add(&issuer->references, 1, CRYPTO_LOCK_X509);
#endif

            ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ssl->log, 0,
                           "SSL get issuer: found %p in extra certs", issuer);

            staple->cert = cert;
            staple->issuer = issuer;

            return NGX_OK;
        }
    }

    store = SSL_CTX_get_cert_store(ssl->ctx);
    if (store == NULL) {
        ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
                      "SSL_CTX_get_cert_store() failed");
        return NGX_ERROR;
    }

    store_ctx = X509_STORE_CTX_new();
    if (store_ctx == NULL) {
        ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
                      "X509_STORE_CTX_new() failed");
        return NGX_ERROR;
    }

    if (X509_STORE_CTX_init(store_ctx, store, NULL, NULL) == 0) {
        ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
                      "X509_STORE_CTX_init() failed");
        X509_STORE_CTX_free(store_ctx);
        return NGX_ERROR;
    }

    rc = X509_STORE_CTX_get1_issuer(&issuer, store_ctx, cert);

    if (rc == -1) {
        ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
                      "X509_STORE_CTX_get1_issuer() failed");
        X509_STORE_CTX_free(store_ctx);
        return NGX_ERROR;
    }

    if (rc == 0) {
        ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
                      "\"ssl_stapling\" ignored, issuer certificate not found");
        X509_STORE_CTX_free(store_ctx);
        return NGX_DECLINED;
    }

    X509_STORE_CTX_free(store_ctx);

    ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ssl->log, 0,
                   "SSL get issuer: found %p in cert store", issuer);

    staple->cert = cert;
    staple->issuer = issuer;

    return NGX_OK;
}
Exemplo n.º 27
0
    openssl_push_asn1object(L, general_name->d.registeredID);
    lua_setfield(L, -2, "registeredID");
    lua_pushstring(L, "registeredID");
    lua_setfield(L, -2, "type");
    break;
  default:
    lua_pushstring(L, "unsupport");
    lua_setfield(L, -2, "type");
  }
  return 1;
};

static int check_cert(X509_STORE *ca, X509 *x, STACK_OF(X509) *untrustedchain, int purpose)
{
  int ret = 0;
  X509_STORE_CTX *csc = X509_STORE_CTX_new();
  if (csc)
  {
    X509_STORE_set_flags(ca, X509_V_FLAG_CHECK_SS_SIGNATURE);
    if (X509_STORE_CTX_init(csc, ca, x, untrustedchain) == 1)
    {
      if (purpose > 0)
      {
        X509_STORE_CTX_set_purpose(csc, purpose);
      }
      ret = X509_verify_cert(csc);
      if (ret == 1)
        ret = X509_V_OK;
      else
        ret = X509_STORE_CTX_get_error(csc);
    }
Exemplo n.º 28
0
/* This function makes sure the certificate is still valid by not having any
 * compromised certificates in the chain.
 * If there is no Certificate Revocation List (CRL) it may be that the private
 * keys have not been compromised or the CRL has not been generated by the
 * Certificate Authority (CA)
 *
 * returns: 0 if certificate is valid, X509 store error code otherwise */
static int validate_certificate(void)
{
	X509_LOOKUP *lookup = NULL;
	X509_STORE_CTX *verify_ctx = NULL;

	/* TODO: CRL and Chains are not required for the current setup, but we may
	 * implement them in the future 
	if (!crl) {
		printf("No certificate revocation list provided\n");
	}
	if (!chain) {
		printf("No certificate chain provided\n");
	}
	*/

	/* create the cert store and set the verify callback */
	if (!(store = X509_STORE_new())) {
		fprintf(stderr, "Failed X509_STORE_new() for %s\n", CERTNAME);
		goto error;
	}

	X509_STORE_set_verify_cb_func(store, verify_callback);

	/* Add the certificates to be verified to the store */
	if (!(lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file()))) {
		fprintf(stderr, "Failed X509_STORE_add_lookup() for %s\n", CERTNAME);
		goto error;
	}

	/*  Load the our Root cert, which can be in either DER or PEM format */
	if (!X509_load_cert_file(lookup, CERTNAME, X509_FILETYPE_PEM)) {
		fprintf(stderr, "Failed X509_load_cert_file() for %s\n", CERTNAME);
		goto error;
	}

	if (crl) {
		if (!(lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file())) ||
		    (X509_load_crl_file(lookup, crl, X509_FILETYPE_PEM) != 1)) {
			fprintf(stderr, "Failed X509 crl init for %s\n", CERTNAME);
			goto error;
		}
		/* set the flags of the store so that CLRs are consulted */
		X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
	}

	/* create a verification context and initialize it */
	if (!(verify_ctx = X509_STORE_CTX_new())) {
		fprintf(stderr, "Failed X509_STORE_CTX_new() for %s\n", CERTNAME);
		goto error;
	}

	if (X509_STORE_CTX_init(verify_ctx, store, cert, NULL) != 1) {
		fprintf(stderr, "Failed X509_STORE_CTX_init() for %s\n", CERTNAME);
		goto error;
	}

	/* Specify which cert to validate in the verify context.
	 * This is required because we may add multiple certs to the X509 store,
	 * but we want to validate a specific one out of the group/chain. */
	X509_STORE_CTX_set_cert(verify_ctx, cert);

	/* verify the certificate */
	if (X509_verify_cert(verify_ctx) != 1) {
		fprintf(stderr, "Failed X509_verify_cert() for %s\n", CERTNAME);
		goto error;
	}

	X509_STORE_CTX_free(verify_ctx);

	/* Certificate verified correctly */
	return 0;

error:
	ERR_print_errors_fp(stderr);

	if (verify_ctx) {
		X509_STORE_CTX_free(verify_ctx);
	}

	return verify_ctx->error;
}
Exemplo n.º 29
0
/* This function makes sure the certificate is still valid by not having any
 * compromised certificates in the chain.
 * If there is no Certificate Revocation List (CRL) it may be that the private
 * keys have not been compromised or the CRL has not been generated by the
 * Certificate Authority (CA)
 *
 * returns: 0 if certificate is valid, X509 store error code otherwise */
static int validate_certificate(X509 *cert, const char *certificate_path, const char *crl)
{
	X509_LOOKUP *lookup = NULL;
	X509_STORE_CTX *verify_ctx = NULL;

	//TODO: Implement a chain verification when required

	/* create the cert store and set the verify callback */
	if (!(store = X509_STORE_new())) {
		error("Failed X509_STORE_new() for %s\n", certificate_path);
		goto error;
	}

	X509_STORE_set_verify_cb_func(store, verify_callback);

	if (X509_STORE_set_purpose(store, X509_PURPOSE_ANY) != 1) {
		error("Failed X509_STORE_set_purpose() for %s\n", certificate_path);
		goto error;
	}

	/* Add the certificates to be verified to the store */
	if (!(lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file()))) {
		error("Failed X509_STORE_add_lookup() for %s\n", certificate_path);
		goto error;
	}

	/*  Load the our Root cert, which can be in either DER or PEM format */
	if (!X509_load_cert_file(lookup, certificate_path, X509_FILETYPE_PEM)) {
		error("Failed X509_load_cert_file() for %s\n", certificate_path);
		goto error;
	}

	if (crl) {
		if (!(lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file())) ||
		    (X509_load_crl_file(lookup, crl, X509_FILETYPE_PEM) != 1)) {
			error("Failed X509 crl init for %s\n", certificate_path);
			goto error;
		}
		/* set the flags of the store so that CLRs are consulted */
		X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
	}

	/* create a verification context and initialize it */
	if (!(verify_ctx = X509_STORE_CTX_new())) {
		error("Failed X509_STORE_CTX_new() for %s\n", certificate_path);
		goto error;
	}

	if (X509_STORE_CTX_init(verify_ctx, store, cert, NULL) != 1) {
		error("Failed X509_STORE_CTX_init() for %s\n", certificate_path);
		goto error;
	}
	/* Specify which cert to validate in the verify context.
	 * This is required because we may add multiple certs to the X509 store,
	 * but we want to validate a specific one out of the group/chain. */
	X509_STORE_CTX_set_cert(verify_ctx, cert);

	/* verify the certificate */
	if (X509_verify_cert(verify_ctx) != 1) {
		error("Failed X509_verify_cert() for %s\n", certificate_path);
		goto error;
	}

	X509_STORE_CTX_free(verify_ctx);

	if (validate_authority(cert) < 0) {
		error("Failed to validate certificate using 'Authority Information Access'\n");
		return -1;
	}

	/* Certificate verified correctly */
	return 0;

error:
	ERR_print_errors_fp(stderr);

	if (verify_ctx) {
		X509_STORE_CTX_free(verify_ctx);
	}

	return X509_STORE_CTX_get_error(verify_ctx);
}
bool PaymentRequestPlus::getMerchant(X509_STORE* certStore, QString& merchant) const
{
    merchant.clear();

    if (!IsInitialized())
        return false;

    // One day we'll support more PKI types, but just
    // x509 for now:
    const EVP_MD* digestAlgorithm = NULL;
    if (paymentRequest.pki_type() == "x509+sha256") {
        digestAlgorithm = EVP_sha256();
    }
    else if (paymentRequest.pki_type() == "x509+sha1") {
        digestAlgorithm = EVP_sha1();
    }
    else if (paymentRequest.pki_type() == "none") {
        qDebug() << "PaymentRequestPlus::getMerchant : Payment request: pki_type == none";
        return false;
    }
    else {
        qDebug() << "PaymentRequestPlus::getMerchant : Payment request: unknown pki_type " << QString::fromStdString(paymentRequest.pki_type());
        return false;
    }

    payments::X509Certificates certChain;
    if (!certChain.ParseFromString(paymentRequest.pki_data())) {
        qDebug() << "PaymentRequestPlus::getMerchant : Payment request: error parsing pki_data";
        return false;
    }

    std::vector<X509*> certs;
    const QDateTime currentTime = QDateTime::currentDateTime();
    for (int i = 0; i < certChain.certificate_size(); i++) {
        QByteArray certData(certChain.certificate(i).data(), certChain.certificate(i).size());
        QSslCertificate qCert(certData, QSsl::Der);
        if (currentTime < qCert.effectiveDate() || currentTime > qCert.expiryDate()) {
            qDebug() << "PaymentRequestPlus::getMerchant : Payment request: certificate expired or not yet active: " << qCert;
            return false;
        }
#if QT_VERSION >= 0x050000
        if (qCert.isBlacklisted()) {
            qDebug() << "PaymentRequestPlus::getMerchant : Payment request: certificate blacklisted: " << qCert;
            return false;
        }
#endif
        const unsigned char *data = (const unsigned char *)certChain.certificate(i).data();
        X509 *cert = d2i_X509(NULL, &data, certChain.certificate(i).size());
        if (cert)
            certs.push_back(cert);
    }
    if (certs.empty()) {
        qDebug() << "PaymentRequestPlus::getMerchant : Payment request: empty certificate chain";
        return false;
    }

    // The first cert is the signing cert, the rest are untrusted certs that chain
    // to a valid root authority. OpenSSL needs them separately.
    STACK_OF(X509) *chain = sk_X509_new_null();
    for (int i = certs.size()-1; i > 0; i--) {
        sk_X509_push(chain, certs[i]);
    }
    X509 *signing_cert = certs[0];

    // Now create a "store context", which is a single use object for checking,
    // load the signing cert into it and verify.
    X509_STORE_CTX *store_ctx = X509_STORE_CTX_new();
    if (!store_ctx) {
        qDebug() << "PaymentRequestPlus::getMerchant : Payment request: error creating X509_STORE_CTX";
        return false;
    }

    char *website = NULL;
    bool fResult = true;
    try
    {
        if (!X509_STORE_CTX_init(store_ctx, certStore, signing_cert, chain))
        {
            int error = X509_STORE_CTX_get_error(store_ctx);
            throw SSLVerifyError(X509_verify_cert_error_string(error));
        }

        // Now do the verification!
        int result = X509_verify_cert(store_ctx);
        if (result != 1) {
            int error = X509_STORE_CTX_get_error(store_ctx);
            throw SSLVerifyError(X509_verify_cert_error_string(error));
        }
        X509_NAME *certname = X509_get_subject_name(signing_cert);

        // Valid cert; check signature:
        payments::PaymentRequest rcopy(paymentRequest); // Copy
        rcopy.set_signature(std::string(""));
        std::string data_to_verify;                     // Everything but the signature
        rcopy.SerializeToString(&data_to_verify);

        EVP_MD_CTX ctx;
        EVP_PKEY *pubkey = X509_get_pubkey(signing_cert);
        EVP_MD_CTX_init(&ctx);
        if (!EVP_VerifyInit_ex(&ctx, digestAlgorithm, NULL) ||
                !EVP_VerifyUpdate(&ctx, data_to_verify.data(), data_to_verify.size()) ||
                !EVP_VerifyFinal(&ctx, (const unsigned char*)paymentRequest.signature().data(), paymentRequest.signature().size(), pubkey)) {

            throw SSLVerifyError("Bad signature, invalid PaymentRequest.");
        }

        // OpenSSL API for getting human printable strings from certs is baroque.
        int textlen = X509_NAME_get_text_by_NID(certname, NID_commonName, NULL, 0);
        website = new char[textlen + 1];
        if (X509_NAME_get_text_by_NID(certname, NID_commonName, website, textlen + 1) == textlen && textlen > 0) {
            merchant = website;
        }
        else {
            throw SSLVerifyError("Bad certificate, missing common name.");
        }
        // TODO: detect EV certificates and set merchant = business name instead of unfriendly NID_commonName ?
    }
    catch (SSLVerifyError& err)
    {
        fResult = false;
        qDebug() << "PaymentRequestPlus::getMerchant : SSL error: " << err.what();
    }

    if (website)
        delete[] website;
    X509_STORE_CTX_free(store_ctx);
    for (unsigned int i = 0; i < certs.size(); i++)
        X509_free(certs[i]);

    return fResult;
}