Exemple #1
0
/**
 * destroy function
 */
static void mod_destroy(void)
{
	if(privKey_evp)
	{
		EVP_PKEY_free(privKey_evp);
	}

	if(store)
	{
		X509_STORE_free(store);
	}

	if(verify_ctx)
	{
		X509_STORE_CTX_free(verify_ctx);
	}

	EVP_cleanup();

	if((verCert != verCertWithSlash) && verCertWithSlash)
	{
		pkg_free(verCertWithSlash);
	}
}
Exemple #2
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;
}
Exemple #3
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;
}
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;
}
/*============================================================================
 * OpcUa_P_OpenSSL_PKI_ValidateCertificate
 *===========================================================================*/
OpcUa_StatusCode OpcUa_P_OpenSSL_PKI_ValidateCertificate(
    OpcUa_PKIProvider*          a_pProvider,
    OpcUa_ByteString*           a_pCertificate,
    OpcUa_Void*                 a_pCertificateStore,
    OpcUa_Int*                  a_pValidationCode /* Validation return codes from OpenSSL */
    )
{
    OpcUa_P_OpenSSL_CertificateStore_Config*    pCertificateStoreCfg;

    const unsigned char* p;

    X509*               pX509Certificate        = OpcUa_Null;
    STACK_OF(X509)*     pX509Chain              = OpcUa_Null;
    X509_STORE_CTX*     verify_ctx              = OpcUa_Null;    /* holds data used during verification process */
    char                CertFile[MAX_PATH];
    struct dirent **dirlist = NULL;
    int numCertificates = 0, i;

OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "PKI_ValidateCertificate");

    OpcUa_ReturnErrorIfArgumentNull(a_pProvider);
    OpcUa_ReturnErrorIfArgumentNull(a_pProvider->Handle);
    OpcUa_ReturnErrorIfArgumentNull(a_pCertificate);
    OpcUa_ReturnErrorIfArgumentNull(a_pCertificateStore);
    OpcUa_ReturnErrorIfArgumentNull(a_pValidationCode);

    pCertificateStoreCfg = (OpcUa_P_OpenSSL_CertificateStore_Config*)a_pProvider->Handle;

    /* convert DER encoded bytestring certificate to openssl X509 certificate */
    p = a_pCertificate->Data;
    if(!(pX509Certificate = d2i_X509((X509**)OpcUa_Null, &p, a_pCertificate->Length)))
    {
        OpcUa_GotoErrorWithStatus(OpcUa_Bad);
    }

    while(p < a_pCertificate->Data + a_pCertificate->Length)
    {
        X509* pX509AddCertificate;
        if(!(pX509AddCertificate = d2i_X509((X509**)OpcUa_Null, &p, a_pCertificate->Data + a_pCertificate->Length - p)))
        {
            OpcUa_GotoErrorWithStatus(OpcUa_Bad);
        }
        if(pX509Chain == NULL)
        {
            pX509Chain = sk_X509_new_null();
            OpcUa_GotoErrorIfAllocFailed(pX509Chain);
        }
        if(!sk_X509_push(pX509Chain, pX509AddCertificate))
        {
            X509_free(pX509AddCertificate);
            OpcUa_GotoErrorWithStatus(OpcUa_Bad);
        }
    }

    /* create verification context and initialize it */
    if(!(verify_ctx = X509_STORE_CTX_new()))
    {
        OpcUa_GotoErrorWithStatus(OpcUa_Bad);
    }

#if (OPENSSL_VERSION_NUMBER > 0x00907000L)
    if(X509_STORE_CTX_init(verify_ctx, (X509_STORE*)a_pCertificateStore, pX509Certificate, pX509Chain) != 1)
    {
        OpcUa_GotoErrorWithStatus(OpcUa_Bad);
    }
#else
    X509_STORE_CTX_init(verify_ctx, (X509_STORE*)a_pCertificateStore, pX509Certificate, pX509Chain);
#endif

    if(X509_STORE_CTX_set_app_data(verify_ctx, pCertificateStoreCfg) != 1)
    {
        OpcUa_GotoErrorWithStatus(OpcUa_Bad);
    }

    if((pCertificateStoreCfg->Flags & OPCUA_P_PKI_OPENSSL_CHECK_REVOCATION_ALL) == OPCUA_P_PKI_OPENSSL_CHECK_REVOCATION_ALL_EXCEPT_SELF_SIGNED
        && !verify_ctx->check_issued(verify_ctx, pX509Certificate, pX509Certificate))
    {
        /* set the flags of the store so that CRLs are consulted */
        X509_STORE_CTX_set_flags(verify_ctx, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
    }

    /* verify the certificate */
    *a_pValidationCode = X509_V_OK;
    if(X509_verify_cert(verify_ctx) <= 0)
    {
        *a_pValidationCode = verify_ctx->error;
        switch(verify_ctx->error)
        {
        case X509_V_ERR_CERT_HAS_EXPIRED:
        case X509_V_ERR_CERT_NOT_YET_VALID:
        case X509_V_ERR_CRL_NOT_YET_VALID:
        case X509_V_ERR_CRL_HAS_EXPIRED:
        case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
        case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
        case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD:
        case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD:
            {
                uStatus = OpcUa_BadCertificateTimeInvalid;
                break;
            }
        case X509_V_ERR_CERT_REVOKED:
            {
                uStatus = OpcUa_BadCertificateRevoked;
                break;
            }
        case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
        case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
        case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
            {
                uStatus = OpcUa_BadCertificateUntrusted;
                break;
            }
        case X509_V_ERR_CERT_SIGNATURE_FAILURE:
            {
                uStatus = OpcUa_BadSecurityChecksFailed;
                break;
            }
        default:
            {
                uStatus = OpcUa_BadCertificateInvalid;
            }
        }
        OpcUa_GotoErrorIfBad(uStatus);
    }

    if(pCertificateStoreCfg->Flags & OPCUA_P_PKI_OPENSSL_REQUIRE_CHAIN_CERTIFICATE_IN_TRUST_LIST)
    {
        FILE*            pCertificateFile;
        X509*            pTrustCert;
        STACK_OF(X509)*  chain;
        int              trusted, n;

        chain = X509_STORE_CTX_get_chain(verify_ctx);
        trusted = 0;
        if(pCertificateStoreCfg->CertificateTrustListLocation == NULL || pCertificateStoreCfg->CertificateTrustListLocation[0] == '\0')
        {
            uStatus = OpcUa_Bad;
            OpcUa_GotoErrorIfBad(uStatus);
        }

        numCertificates = scandir(pCertificateStoreCfg->CertificateTrustListLocation, &dirlist, certificate_filter_der, alphasort);
        for (i=0; i<numCertificates; i++)
        {
            uStatus = OpcUa_P_OpenSSL_BuildFullPath(pCertificateStoreCfg->CertificateTrustListLocation, dirlist[i]->d_name, MAX_PATH, CertFile);
            OpcUa_GotoErrorIfBad(uStatus);

            /* read DER certificates */
            pCertificateFile = fopen(CertFile, "r");
            if(pCertificateFile == OpcUa_Null)
            {
                continue; /* ignore access errors */
            }

            pTrustCert = d2i_X509_fp(pCertificateFile, (X509**)OpcUa_Null);
            fclose(pCertificateFile);
            if(pTrustCert == OpcUa_Null)
            {
                continue; /* ignore parse errors */
            }

            for(n = 0; n < sk_X509_num(chain); n++)
            {
                if (X509_cmp(sk_X509_value(chain, n), pTrustCert) == 0)
                    break;
            }

            X509_free(pTrustCert);
            if(n < sk_X509_num(chain))
            {
                trusted = 1;
                break;
            }
        }
        for (i=0; i<numCertificates; i++)
        {
            free(dirlist[i]);
        }
        free(dirlist);
        dirlist = NULL;

        if(!trusted)
        {
            uStatus = OpcUa_BadCertificateUntrusted;
            OpcUa_GotoErrorIfBad(uStatus);
        }
    }

    X509_STORE_CTX_free(verify_ctx);
    X509_free(pX509Certificate);
    if(pX509Chain != OpcUa_Null)
    {
        sk_X509_pop_free(pX509Chain, X509_free);
    }

OpcUa_ReturnStatusCode;
OpcUa_BeginErrorHandling;

    if(dirlist != NULL)
    {
        for (i=0; i<numCertificates; i++)
        {
            free(dirlist[i]);
        }
        free(dirlist);
    }

    if(verify_ctx != OpcUa_Null)
    {
        X509_STORE_CTX_free(verify_ctx);
    }

    if(pX509Certificate != OpcUa_Null)
    {
        X509_free(pX509Certificate);
    }

    if(pX509Chain != OpcUa_Null)
    {
        sk_X509_pop_free(pX509Chain, X509_free);
    }

OpcUa_FinishErrorHandling;
}
Exemple #7
0
int crl_main(int argc, char **argv)
{
    X509_CRL *x = NULL;
    BIO *out = NULL;
    X509_STORE *store = NULL;
    X509_STORE_CTX *ctx = NULL;
    X509_LOOKUP *lookup = NULL;
    X509_OBJECT *xobj = NULL;
    EVP_PKEY *pkey;
    const EVP_MD *digest = EVP_sha1();
    unsigned long nmflag = 0;
    char nmflag_set = 0;
    char *infile = NULL, *outfile = NULL, *crldiff = NULL, *keyfile = NULL;
    const char *CAfile = NULL, *CApath = NULL, *prog;
    OPTION_CHOICE o;
    int hash = 0, issuer = 0, lastupdate = 0, nextupdate = 0, noout = 0;
    int informat = FORMAT_PEM, outformat = FORMAT_PEM, keyformat = FORMAT_PEM;
    int ret = 1, num = 0, badsig = 0, fingerprint = 0, crlnumber = 0;
    int text = 0, do_ver = 0, noCAfile = 0, noCApath = 0;
    int i;
#ifndef OPENSSL_NO_MD5
    int hash_old = 0;
#endif

    prog = opt_init(argc, argv, crl_options);
    while ((o = opt_next()) != OPT_EOF) {
        switch (o) {
        case OPT_EOF:
        case OPT_ERR:
 opthelp:
            BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
            goto end;
        case OPT_HELP:
            opt_help(crl_options);
            ret = 0;
            goto end;
        case OPT_INFORM:
            if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat))
                goto opthelp;
            break;
        case OPT_IN:
            infile = opt_arg();
            break;
        case OPT_OUTFORM:
            if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat))
                goto opthelp;
            break;
        case OPT_OUT:
            outfile = opt_arg();
            break;
        case OPT_KEYFORM:
            if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &keyformat))
                goto opthelp;
            break;
        case OPT_KEY:
            keyfile = opt_arg();
            break;
        case OPT_GENDELTA:
            crldiff = opt_arg();
            break;
        case OPT_CAPATH:
            CApath = opt_arg();
            do_ver = 1;
            break;
        case OPT_CAFILE:
            CAfile = opt_arg();
            do_ver = 1;
            break;
        case OPT_NOCAPATH:
            noCApath =  1;
            break;
        case OPT_NOCAFILE:
            noCAfile =  1;
            break;
        case OPT_HASH_OLD:
#ifndef OPENSSL_NO_MD5
            hash_old = ++num;
#endif
            break;
        case OPT_VERIFY:
            do_ver = 1;
            break;
        case OPT_TEXT:
            text = 1;
            break;
        case OPT_HASH:
            hash = ++num;
            break;
        case OPT_ISSUER:
            issuer = ++num;
            break;
        case OPT_LASTUPDATE:
            lastupdate = ++num;
            break;
        case OPT_NEXTUPDATE:
            nextupdate = ++num;
            break;
        case OPT_NOOUT:
            noout = ++num;
            break;
        case OPT_FINGERPRINT:
            fingerprint = ++num;
            break;
        case OPT_CRLNUMBER:
            crlnumber = ++num;
            break;
        case OPT_BADSIG:
            badsig = 1;
            break;
        case OPT_NAMEOPT:
            nmflag_set = 1;
            if (!set_name_ex(&nmflag, opt_arg()))
                goto opthelp;
            break;
        case OPT_MD:
            if (!opt_md(opt_unknown(), &digest))
                goto opthelp;
        }
    }
    argc = opt_num_rest();
    if (argc != 0)
        goto opthelp;

    if (!nmflag_set)
        nmflag = XN_FLAG_ONELINE;

    x = load_crl(infile, informat);
    if (x == NULL)
        goto end;

    if (do_ver) {
        if ((store = setup_verify(CAfile, CApath, noCAfile, noCApath)) == NULL)
            goto end;
        lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
        if (lookup == NULL)
            goto end;
        ctx = X509_STORE_CTX_new();
        if (ctx == NULL || !X509_STORE_CTX_init(ctx, store, NULL, NULL)) {
            BIO_printf(bio_err, "Error initialising X509 store\n");
            goto end;
        }

        xobj = X509_STORE_CTX_get_obj_by_subject(ctx, X509_LU_X509,
                                                 X509_CRL_get_issuer(x));
        if (xobj == NULL) {
            BIO_printf(bio_err, "Error getting CRL issuer certificate\n");
            goto end;
        }
        pkey = X509_get_pubkey(X509_OBJECT_get0_X509(xobj));
        X509_OBJECT_free(xobj);
        if (!pkey) {
            BIO_printf(bio_err, "Error getting CRL issuer public key\n");
            goto end;
        }
        i = X509_CRL_verify(x, pkey);
        EVP_PKEY_free(pkey);
        if (i < 0)
            goto end;
        if (i == 0)
            BIO_printf(bio_err, "verify failure\n");
        else
            BIO_printf(bio_err, "verify OK\n");
    }

    if (crldiff) {
        X509_CRL *newcrl, *delta;
        if (!keyfile) {
            BIO_puts(bio_err, "Missing CRL signing key\n");
            goto end;
        }
        newcrl = load_crl(crldiff, informat);
        if (!newcrl)
            goto end;
        pkey = load_key(keyfile, keyformat, 0, NULL, NULL, "CRL signing key");
        if (!pkey) {
            X509_CRL_free(newcrl);
            goto end;
        }
        delta = X509_CRL_diff(x, newcrl, pkey, digest, 0);
        X509_CRL_free(newcrl);
        EVP_PKEY_free(pkey);
        if (delta) {
            X509_CRL_free(x);
            x = delta;
        } else {
            BIO_puts(bio_err, "Error creating delta CRL\n");
            goto end;
        }
    }

    if (badsig) {
        const ASN1_BIT_STRING *sig;

        X509_CRL_get0_signature(x, &sig, NULL);
        corrupt_signature(sig);
    }

    if (num) {
        for (i = 1; i <= num; i++) {
            if (issuer == i) {
                print_name(bio_out, "issuer=", X509_CRL_get_issuer(x),
                           nmflag);
            }
            if (crlnumber == i) {
                ASN1_INTEGER *crlnum;
                crlnum = X509_CRL_get_ext_d2i(x, NID_crl_number, NULL, NULL);
                BIO_printf(bio_out, "crlNumber=");
                if (crlnum) {
                    i2a_ASN1_INTEGER(bio_out, crlnum);
                    ASN1_INTEGER_free(crlnum);
                } else
                    BIO_puts(bio_out, "<NONE>");
                BIO_printf(bio_out, "\n");
            }
            if (hash == i) {
                BIO_printf(bio_out, "%08lx\n",
                           X509_NAME_hash(X509_CRL_get_issuer(x)));
            }
#ifndef OPENSSL_NO_MD5
            if (hash_old == i) {
                BIO_printf(bio_out, "%08lx\n",
                           X509_NAME_hash_old(X509_CRL_get_issuer(x)));
            }
#endif
            if (lastupdate == i) {
                BIO_printf(bio_out, "lastUpdate=");
                ASN1_TIME_print(bio_out, X509_CRL_get0_lastUpdate(x));
                BIO_printf(bio_out, "\n");
            }
            if (nextupdate == i) {
                BIO_printf(bio_out, "nextUpdate=");
                if (X509_CRL_get0_nextUpdate(x))
                    ASN1_TIME_print(bio_out, X509_CRL_get0_nextUpdate(x));
                else
                    BIO_printf(bio_out, "NONE");
                BIO_printf(bio_out, "\n");
            }
            if (fingerprint == i) {
                int j;
                unsigned int n;
                unsigned char md[EVP_MAX_MD_SIZE];

                if (!X509_CRL_digest(x, digest, md, &n)) {
                    BIO_printf(bio_err, "out of memory\n");
                    goto end;
                }
                BIO_printf(bio_out, "%s Fingerprint=",
                           OBJ_nid2sn(EVP_MD_type(digest)));
                for (j = 0; j < (int)n; j++) {
                    BIO_printf(bio_out, "%02X%c", md[j], (j + 1 == (int)n)
                               ? '\n' : ':');
                }
            }
        }
    }
    out = bio_open_default(outfile, 'w', outformat);
    if (out == NULL)
        goto end;

    if (text)
        X509_CRL_print(out, x);

    if (noout) {
        ret = 0;
        goto end;
    }

    if (outformat == FORMAT_ASN1)
        i = (int)i2d_X509_CRL_bio(out, x);
    else
        i = PEM_write_bio_X509_CRL(out, x);
    if (!i) {
        BIO_printf(bio_err, "unable to write CRL\n");
        goto end;
    }
    ret = 0;

 end:
    if (ret != 0)
        ERR_print_errors(bio_err);
    BIO_free_all(out);
    X509_CRL_free(x);
    X509_STORE_CTX_free(ctx);
    X509_STORE_free(store);
    return (ret);
}
int32_t mz_crypt_sign_verify(uint8_t *message, int32_t message_size, uint8_t *signature, int32_t signature_size)
{
    CMS_ContentInfo *cms = NULL;
    STACK_OF(X509) *signers = NULL;
    STACK_OF(X509) *intercerts = NULL;
    X509_STORE *cert_store = NULL;
    X509_LOOKUP *lookup = NULL;
    X509_STORE_CTX *store_ctx = NULL;
    BIO *message_bio = NULL;
    BIO *signature_bio = NULL;
    BUF_MEM *buf_mem = NULL;
    int32_t signer_count = 0;
    int32_t result = 0;
    int32_t i = 0;
    int32_t err = MZ_SIGN_ERROR;


    if (message == NULL || message_size == 0 || signature == NULL || signature_size == 0)
        return MZ_PARAM_ERROR;

    mz_crypt_init();

    cert_store = X509_STORE_new();

    X509_STORE_load_locations(cert_store, "cacert.pem", NULL);
    X509_STORE_set_default_paths(cert_store);

#if 0
    BIO *yy = BIO_new_file("xyz", "wb");
    BIO_write(yy, signature, signature_size);
    BIO_flush(yy);
    BIO_free(yy);
#endif

    lookup = X509_STORE_add_lookup(cert_store, X509_LOOKUP_file());   
    if (lookup != NULL)
        X509_LOOKUP_load_file(lookup, "cacert.pem", X509_FILETYPE_PEM);
    lookup = X509_STORE_add_lookup(cert_store, X509_LOOKUP_hash_dir());
    if (lookup != NULL)
        X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT);

    signature_bio = BIO_new_mem_buf(signature, signature_size);
    message_bio = BIO_new(BIO_s_mem());

    cms = d2i_CMS_bio(signature_bio, NULL);
    if (cms)
    {
        result = CMS_verify(cms, NULL, cert_store, NULL, message_bio, CMS_NO_SIGNER_CERT_VERIFY | CMS_BINARY);
        if (result)
            signers = CMS_get0_signers(cms);
        if (signers)
            intercerts = CMS_get1_certs(cms);
        if (intercerts)
        {
            /* Verify signer certificates */
            signer_count = sk_X509_num(signers);
            if (signer_count > 0)
                err = MZ_OK;

            for (i = 0; i < signer_count; i++)
            {
                store_ctx = X509_STORE_CTX_new();
                X509_STORE_CTX_init(store_ctx, cert_store, sk_X509_value(signers, i), intercerts);
                result = X509_verify_cert(store_ctx);
                if (store_ctx)
                    X509_STORE_CTX_free(store_ctx);

                if (!result)
                {
                    err = MZ_SIGN_ERROR;
                    break;
                }
            }
        }

        BIO_get_mem_ptr(message_bio, &buf_mem);

        if (err == MZ_OK)
        {
            /* Verify the message */
            if (((int32_t)buf_mem->length != message_size) || 
                (memcmp(buf_mem->data, message, message_size) != 0))
                err = MZ_SIGN_ERROR;
        }
    }

#if 0
    if (!result)
        printf(ERR_error_string(ERR_get_error(), NULL));
#endif

    if (cms)
        CMS_ContentInfo_free(cms);
    if (message_bio)
        BIO_free(message_bio);
    if (signature_bio)
        BIO_free(signature_bio);
    if (cert_store)
        X509_STORE_free(cert_store);

    return err;
}
Exemple #9
0
int check_validity_of_cert(
    const char *cFile, const unsigned char *md5_md, unsigned char *sfileMsg,
    const int sfsize, const char* caPath
) {
    int retval = 0;
    X509 *cert;
    X509_STORE *store;
    X509_LOOKUP *lookup;
    X509_STORE_CTX *ctx = 0;
    EVP_PKEY *pubKey;
    BIO *bio;

    bio = BIO_new(BIO_s_file());
    BIO_read_filename(bio, cFile);
    if (NULL == (cert = PEM_read_bio_X509(bio, NULL, 0, NULL))) {
	    BIO_vfree(bio);
	    return 0;
    }
    // verify certificate
    store = X509_STORE_new();
    lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir());
    X509_LOOKUP_add_dir(lookup, (char *)caPath, X509_FILETYPE_PEM);
    if ((ctx = X509_STORE_CTX_new()) != 0) {
        if (X509_STORE_CTX_init(ctx, store, cert, 0) == 1)
            retval = X509_verify_cert(ctx);
        X509_STORE_CTX_free(ctx);
    }
    X509_STORE_free(store);
    
    if (retval != 1) {
        fprintf(stderr,"ERROR: Cannot verify certificate ('%s')\n", cFile);
        return 0;
    }        
    pubKey = X509_get_pubkey(cert);
    if (!pubKey) {
        X509_free(cert);
        BIO_vfree(bio);
        return 0;
    }
    if (pubKey->type == EVP_PKEY_RSA) {
        BN_CTX *c = BN_CTX_new();
        if (!c) {
	        X509_free(cert);
	        EVP_PKEY_free(pubKey);
	        BIO_vfree(bio);
	        return 0;
	    }
	    if (!RSA_blinding_on(pubKey->pkey.rsa, c)) {
	        X509_free(cert);
	        EVP_PKEY_free(pubKey);
	        BIO_vfree(bio);
	        BN_CTX_free(c);
	        return 0;
	    }
	    retval = RSA_verify(NID_md5, md5_md, MD5_DIGEST_LENGTH, sfileMsg, sfsize, pubKey->pkey.rsa);
	    RSA_blinding_off(pubKey->pkey.rsa);
	    BN_CTX_free(c);
    }
    if (pubKey->type == EVP_PKEY_DSA) {
        fprintf(stderr, "ERROR: DSA keys are not supported.\n");
        return 0;
    }
    EVP_PKEY_free(pubKey);
    X509_free(cert);
    BIO_vfree(bio);
    return retval;
}
Exemple #10
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);
}
Exemple #11
0
void openssl_x509_verify()
{
	FILE *fp;
	int uCert1Len;
	X509_CRL *Crl = NULL;
	X509_STORE_CTX *ctx = NULL;
	X509_STORE *rootCertStore = NULL;
	STACK_OF(X509) * caCertStack = NULL;
	X509 *usrCert1 = NULL, *usrCert2 = NULL, *rootCert = NULL;
	unsigned char tmp[MAX4_LEN];
	unsigned long uCert2Len, derCrlLen, derRootCertLen;
	const unsigned char *derCrl, *derRootCert, *uCert1, *uCert2;

	OpenSSL_add_all_algorithms();
	printf("\nX509_Verify info:\n");

	fp = fopen(RCERTF, "rb");
	derRootCertLen = fread(tmp, 1, 4096, fp);
	derRootCert = tmp;
	fclose(fp);
	rootCert = d2i_X509(NULL, &derRootCert, derRootCertLen);

	fp = fopen(CRLCRL, "rb");
	derCrlLen = fread(tmp, 1, 4096, fp);
	derCrl = tmp;
	fclose(fp);
	Crl = d2i_X509_CRL(NULL, &derCrl, derCrlLen);

	rootCertStore = X509_STORE_new();
	X509_STORE_add_cert(rootCertStore, rootCert);
	X509_STORE_set_flags(rootCertStore, X509_V_FLAG_CRL_CHECK);
	X509_STORE_add_crl(rootCertStore, Crl);
	ctx = X509_STORE_CTX_new();

	fp = fopen(U1CERTF, "rb");
	uCert1Len = fread(tmp, 1, 4096, fp);
	uCert1 = tmp;
	fclose(fp);
	usrCert1 = d2i_X509(NULL, &uCert1, uCert1Len);
	if (X509_STORE_CTX_init(ctx, rootCertStore, usrCert1, caCertStack) != 1) {
		perror("X509_STORE_CTX_init");
		return;
	}
	if (X509_verify_cert(ctx) != 1) {
		printf("user1.cer %s\n", X509_verify_cert_error_string(ctx->error));
		return;
	}

	fp = fopen(U2CERTF, "rb");
	uCert2Len = fread(tmp, 1, 4096, fp);
	uCert2 = tmp;
	fclose(fp);
	usrCert2 = d2i_X509(NULL, &uCert2, uCert2Len);
	if (X509_STORE_CTX_init(ctx, rootCertStore, usrCert2, caCertStack) != 1) {
		perror("X509_STORE_CTX_init");
		return;
	}
	if (X509_verify_cert(ctx) != 1) {
		printf("user2.cer %s\n", X509_verify_cert_error_string(ctx->error));
		return;
	}

	X509_free(usrCert1);
	X509_free(usrCert2);
	X509_free(rootCert);
	X509_STORE_CTX_cleanup(ctx);
	X509_STORE_CTX_free(ctx);
	X509_STORE_free(rootCertStore);

	return;
}
Exemple #12
0
/*
 * This function verifies the validity of the certificate and the matching of the
 * other part's name with the certificate.
 * It also checks the sign validity of a message.
 * It returns -1 on generic error, -3 on mismatching on certificate, 1 on success.
 * It closes the passed file pointer fp (which should have already been opened).
 * The last argument is used to distinguish if we are initializing or accepting
 * a connection and so which is the correct name to verify.
 * After verifying, It leaves the public parameter of DH and the nonce of the
 * other part respectively in **pub_buf (which is allocated) and *nonce.
 */
int verify_name(FILE* fp,unsigned char *hello_buf,unsigned int hello_len,unsigned char *sign_buf,unsigned int sign_len,unsigned char** pub_buf,unsigned int *pubbuf_len,X509_STORE* str,int* nonce,int init){	
	int sheet_len,ret;
	uint32_t tmp;
	char read_mail[DIM_MAIL],temp_mail[DIM_MAIL],*cert_mail = NULL;
	X509_STORE_CTX* cert_ctx = NULL;
	EVP_PKEY* evp = EVP_PKEY_new();
	EVP_MD_CTX* ctx = NULL;
	*pub_buf = NULL;
	if (!fp) {
		ret = -1;
		goto fail;
	}
	//We must come back to the start of fp
	rewind(fp);
	X509* cert = PEM_read_X509(fp,NULL,NULL,NULL);
	*pub_buf = NULL;
	//the following function is needed to correctly verify the certificate
	OpenSSL_add_all_algorithms();
	if((cert_ctx=X509_STORE_CTX_new())==NULL){
		ret = -1;
		goto fail;
	}
	if(X509_STORE_CTX_init(cert_ctx,str,cert,NULL)<=0){
		ret = -1;
		goto fail;
	}
	if(X509_verify_cert(cert_ctx)==0){
		//fprintf(stderr, "Error verifying certificate: %s\n", X509_verify_cert_error_string(X509_STORE_CTX_get_error(cert_ctx)));
		ret = -3;
		goto fail;	
	}
	X509_STORE_CTX_cleanup(cert_ctx);
	X509_STORE_CTX_free(cert_ctx);
	cert_ctx = NULL;
	ctx  = (EVP_MD_CTX*)calloc(1,sizeof(EVP_MD_CTX));
	EVP_MD_CTX_init(ctx);
	evp = X509_get_pubkey(cert);
	if(EVP_VerifyInit(ctx,EVP_sha512())==0){
		ret = -1;
		goto fail;
	}
	if(EVP_VerifyUpdate(ctx,hello_buf,hello_len)==0){
		ret = -1;
		goto fail;
	}
	ret=EVP_VerifyFinal(ctx,sign_buf,sign_len,evp);
	if(ret == 0){
		ret = -3;
		goto fail;
	}
	if (ret == -1) {
		goto fail;
	}
	rewind(fp);
	cert_mail = read_common_name(fp);//set it free later
	if(init == 1){
		sscanf((char *)hello_buf,"%s%s",temp_mail,read_mail);
	} else{
		sscanf((char *)hello_buf,"%s%s",read_mail,temp_mail);
	}
	sheet_len = strlen(temp_mail)+strlen(read_mail)+2;
	*pubbuf_len = hello_len - sheet_len;
	tmp = *((uint32_t *)(hello_buf+sheet_len));
	*nonce = ntohl(tmp);
	sheet_len+=sizeof(tmp);
	*pub_buf = (unsigned char*)calloc(1,*pubbuf_len);
	memcpy(*pub_buf,hello_buf+sheet_len,*pubbuf_len);
	if(strlen(cert_mail)!=strlen(read_mail)){
		ret = -3;
		goto fail;
	}
	if(strncmp(cert_mail,read_mail,strlen(cert_mail))!=0){
		ret = -3;
		goto fail;
	}
	free(ctx);
	fclose(fp);
	EVP_PKEY_free(evp);
	free(cert_mail);
	return 1;
	fail:
		fclose(fp);
		if(cert_mail!=NULL){
			free(cert_mail);
		}
		if(cert_ctx!=NULL){
			X509_STORE_CTX_cleanup(cert_ctx);
			X509_STORE_CTX_free(cert_ctx);
		}
		if(ctx!=NULL){
			free(ctx);
		}	
		if(*pub_buf!=NULL){
			free(*pub_buf);
		}
		EVP_PKEY_free(evp);
		return ret;
}
/* Helper function to trace the signing cert to a trusted CA root
 * in the OpenSSL Trust Store. */
static int checkCertOpenSSL(const GTPublicationsFile *publications_file)
{
	int res = GT_UNKNOWN_ERROR;
	unsigned char *cert_der = NULL;
	size_t cert_der_len;
	unsigned char *cert_tmp;
	X509 *cert = NULL;
	X509_STORE_CTX *store_ctx = NULL;
	X509_NAME *subj = NULL;
	ASN1_OBJECT *oid = NULL;
	char tmp_name[256];
	int rc;

	res = GTPublicationsFile_getSigningCert(publications_file, &cert_der, &cert_der_len);
	if (res != GT_OK) {
		goto cleanup;
	}

	/* Note that d2i_X509() spoils the pointer to the buffer, use a temporary copy. */
	cert_tmp = cert_der;
	cert = d2i_X509(NULL, (const unsigned char **) &cert_tmp, cert_der_len);
	if (cert == NULL) {
		res = GT_NOT_VALID_PUBLICATION;
		goto cleanup;
	}

#ifdef MAGIC_EMAIL
	subj = X509_get_subject_name(cert);
	if (subj == NULL) {
		res = GT_CRYPTO_FAILURE;
		goto cleanup;
	}
	oid = OBJ_txt2obj("1.2.840.113549.1.9.1", 1);
	if (oid == NULL) {
		res = GT_OUT_OF_MEMORY;
		goto cleanup;
	}
	rc = X509_NAME_get_text_by_OBJ(subj, oid, tmp_name, sizeof(tmp_name));
	if (rc < 0) {
		res = GT_INVALID_SIGNATURE;
		goto cleanup;
	}
	if (strcmp(tmp_name, MAGIC_EMAIL) != 0) {
		res = GT_INVALID_SIGNATURE;
		goto cleanup;
	}
#endif

	store_ctx = X509_STORE_CTX_new();
	if (store_ctx == NULL) {
		res = GT_OUT_OF_MEMORY;
		goto cleanup;
	}

	/* The truststore is not initialized by default. */
	if (GT_truststore == NULL) {
		res = GTTruststore_init(1);
		if (res != GT_OK) goto cleanup;
	}

	if (!X509_STORE_CTX_init(store_ctx, GT_truststore, cert,
			publications_file->signature->d.sign->cert)) {
		res = GT_OUT_OF_MEMORY;
		goto cleanup;
	}

	rc = X509_verify_cert(store_ctx);
	if (rc < 0) {
		res = GT_CRYPTO_FAILURE;
		goto cleanup;
	}
	if (rc != 1) {
		res = GT_CERT_NOT_TRUSTED;
		goto cleanup;
	}

	res = GT_OK;

cleanup:
	GT_free(cert_der);
	/* Do not free subj, it points into cert. */
	ASN1_OBJECT_free(oid);
	if (cert != NULL) {
		X509_free(cert);
	}
	if (store_ctx != NULL) {
		X509_STORE_CTX_free(store_ctx);
	}

	return res;
}
Exemple #14
0
// take certificate hashes, check their validity and output json that
// will indicate which certificate were used for verification, whatever
// the chain was trusted and if all certificates needed for verification
// (with the exception of root CA) were present in hashes
int process_chain(const char **cert_hashes)
{
    int ret;
    int rc; // return code from function
    char *f_name;

    X509 *cert;
    X509 *x509;

    X509_STORE *store;

    X509_STORE_CTX *csc;

    STACK_OF(X509) *ustack;
    STACK_OF(X509) *vstack;

    // load certificates to temp structures

    // first the end entity cert
    // (EE cert needs to be passed separately to OpenSSL verification context)
    f_name = hash_to_filename(cert_hashes[0]);
    if (f_name == NULL)
        return 1;

    cert = load_cert(f_name);
    free(f_name);
    if (cert == NULL) {
        printf("can't load certificate!\n");
        return 1;
    }

    // then the intermediate certificates
    ustack = sk_X509_new_null();

    for (int i=1; cert_hashes[i]!=NULL; i++) {
        //printf(".\n");
        f_name = hash_to_filename(cert_hashes[i]);
        if (f_name == NULL) {
            // file not found
            continue;
        }
        x509 = load_cert(f_name);
        if (x509 == NULL) {
            // loading cert failed
            continue;
        }
        sk_X509_push(ustack, x509);
        free(f_name);
    }

    // first try with just trusted certificates

    store = SSL_CTX_get_cert_store(trusted_only);
    if (store == NULL) {
        fprintf(stderr, "store init failed\n");
        return 1;
    }
    X509_STORE_set_flags(store, X509_V_FLAG_TRUSTED_FIRST);

    csc = X509_STORE_CTX_new();

    ret = X509_STORE_CTX_init(csc, store, cert, ustack);
    if (ret != 1) {
        return 1;
    }

    ret = X509_verify_cert(csc);

    if (ret != 1) {
       // printf("%s\n", X509_verify_cert_error_string(csc->error));
    } else {
        // chain is complete, output certificate hashes
        printf("{\"chain\":\"complete\",\"certificates\":[");
        vstack = X509_STORE_CTX_get_chain(csc);
        for(int i=0; i<sk_X509_num(vstack); i++) {
            X509 *c = sk_X509_value(vstack, i);

            const EVP_MD *digest;
            unsigned char md[EVP_MAX_MD_SIZE];
            int n;
            digest = EVP_get_digestbyname("sha256");
            X509_digest(c, digest, md, &n);
            printf("\"");
            for(int i=0; i<n; i++) {
                printf("%02x", md[i]);
            }
            printf("\"");
            if (i+1 < sk_X509_num(vstack)) {
                printf(",");
            }
        }
        printf("]}");
        X509_STORE_CTX_free(csc);
        sk_X509_pop_free(ustack, X509_free);
        X509_free(cert);
        return 0;
    }
    X509_STORE_CTX_free(csc);

    // validation failed with just the trust anchors, retry with all
    // known intermediate certificates

    store = SSL_CTX_get_cert_store(all_CAs);
    if (store == NULL) {
        fprintf(stderr, "store init failed\n");
        return 1;
    }
    X509_STORE_set_flags(store, X509_V_FLAG_TRUSTED_FIRST);

    csc = X509_STORE_CTX_new();

    ret = X509_STORE_CTX_init(csc, store, cert, ustack);
    if (ret != 1) {
        return 1;
    }

    ret = X509_verify_cert(csc);
    if (ret != 1) {
        // certificate untrusted
        printf("{\"chain\":\"untrusted\"}");
    } else {
        // chain successfully verified using all certificates,
        // print all the certs used to verify it
        printf("{\"chain\":\"incomplete\",\"certificates\":[");
        vstack = X509_STORE_CTX_get_chain(csc);
        for(int i=0; i<sk_X509_num(vstack); i++) {
            X509 *c = sk_X509_value(vstack, i);

            const EVP_MD *digest;
            unsigned char md[EVP_MAX_MD_SIZE];
            int n;
            digest = EVP_get_digestbyname("sha256");
            X509_digest(c, digest, md, &n);
            printf("\"");
            for(int i=0; i<n; i++) {
                printf("%02x", md[i]);
            }
            printf("\"");
            if (i+1 < sk_X509_num(vstack)) {
                printf(",");
            }
        }
        printf("]}");
    }

    X509_STORE_CTX_free(csc);
    sk_X509_pop_free(ustack, X509_free);
    X509_free(cert);

    return 0;
}