Am 09.05.14 00:53, schrieb Stephen Henson via RT:
> On Thu May 08 15:49:11 2014, [email protected] wrote:
>>
>> I can confirm that with this patch applied my use case with
>> X509_verify_cert() works as expected (misidentification of signing
>> certificate as CRL issuer no longer occurs).
>>
>
> Could you give me more details of this case? If possible if you could send the
> certificates and CRLs involved (privately if you wish).
>
> It may be possible to address this case in X509_verify_cert() itself.

I have prepared a second test certificate "testcert2.pem", a 
corresponding CRL "testcrl.pem", and a new test program "x509_verify.c" 
that reproduces the issue in the full context of X509_verify_cert().

The callback function verify_cb() for X509_verify_cert() ignores all 
errors related to the validation of the certificate chain, in order to 
allow verification of other formal certificate requirements.

Actual result of running the test program:

verify_cb: certificate subject: CN=ATS PLOP User AKID,O=PDFlib 
GmbH,L=Munich,C=DE
X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY ignored
verify_cb: certificate subject: CN=ATS PLOP User AKID,O=PDFlib 
GmbH,L=Munich,C=DE
X509_V_ERR_KEYUSAGE_NO_CRL_SIGN not ignored
         error 35 at 0 depth lookup: key usage does not include CRL signing
X509_verify_cert returns false

Expected result:

The verify_cb() function should not be invoked with the 
X509_V_ERR_KEYUSAGE_NO_CRL_SIGN error, and X509_verify_cert() should 
return true.

-- 
Stephan

Attachment: testcert2.pem
Description: application/x509-ca-cert

Attachment: testcrl.pem
Description: application/x509-ca-cert

/*
 * Test program for OpenSSL RT bug #3349
 *
 * The verify_cb() function intentionally ignores all errors regarding
 * the verification of the certificate chain, to allow for validation of
 * other formal requirements. The problem is that the certificate to be
 * verified is misidentifed as the CRL issuer certificate, which
 * causes the incorrect X509_V_ERR_KEYUSAGE_NO_CRL_SIGN error.
 */

#include <stdio.h>
#include <openssl/err.h>
#include <openssl/bio.h>
#include <openssl/evp.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <openssl/pem.h>
#include <openssl/engine.h>

static BIO *bio_stdout = 0;

static
int
verify_cb(int ok, X509_STORE_CTX *ctx)
{
    if (!ok)
    {
        int cert_error = X509_STORE_CTX_get_error(ctx);
        X509 *current_cert = X509_STORE_CTX_get_current_cert(ctx);
        X509_NAME *x509_subject = X509_get_subject_name(current_cert);

        printf("verify_cb: certificate subject: ");
        X509_NAME_print_ex(bio_stdout, x509_subject, 0, XN_FLAG_RFC2253);
        printf("\n");

        switch (cert_error)
        {
        case X509_V_ERR_UNABLE_TO_GET_CRL:
            printf("X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT ignored\n");
            ok = 1;
            break;

        case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
            printf("X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT ignored\n");
            ok = 1;
            break;

        case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
            printf("X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN ignored\n");
            ok = 1;
            break;

        case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
            printf("X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY ignored\n");
            ok = 1;
            break;

        case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
            printf("X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE ignored\n");
            ok = 1;
            break;

        case X509_V_ERR_CERT_UNTRUSTED:
            printf("X509_V_ERR_CERT_UNTRUSTED ignored\n");
            ok = 1;
            break;

        case X509_V_ERR_KEYUSAGE_NO_CRL_SIGN:
            printf("X509_V_ERR_KEYUSAGE_NO_CRL_SIGN not ignored\n");
            break;

        default:
            break;
        }

        if (!ok)
        {
            printf("\t%serror %d at %d depth lookup: %s\n",
                X509_STORE_CTX_get0_parent_ctx(ctx) ? "[CRL path]" : "",
                cert_error,
                X509_STORE_CTX_get_error_depth(ctx),
                X509_verify_cert_error_string(cert_error));
        }
    }

    return ok;
}

int
main()
{
    BIO *pem;
    const char *certfile = "testcert2.pem";
    const char *crlfile = "testcrl.pem";

    X509 *cert;
    X509_STORE *store;
    X509_STORE_CTX *ctx;
    X509_VERIFY_PARAM *vpm;

    BIO *bio_crl;
    X509_CRL *crl;
    STACK_OF(X509_CRL) *crls;

    bio_stdout = BIO_new_fp(stdout, BIO_NOCLOSE);

    pem = BIO_new(BIO_s_file());

    BIO_read_filename(pem, certfile);

    cert = PEM_read_bio_X509_AUX(pem, NULL, NULL, NULL);

    store = X509_STORE_new();
    X509_STORE_set_verify_cb(store, verify_cb);

    vpm = X509_VERIFY_PARAM_new();
    X509_VERIFY_PARAM_set_flags(vpm,
                        X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
    X509_STORE_set1_param(store, vpm);

    bio_crl = BIO_new(BIO_s_file());
    BIO_read_filename(bio_crl, crlfile);
    crl = PEM_read_bio_X509_CRL(bio_crl, NULL, NULL, NULL);
    BIO_free(bio_crl);

    crls = sk_X509_CRL_new_null();
    sk_X509_CRL_push(crls, crl);

    ctx = X509_STORE_CTX_new();
    X509_STORE_CTX_init(ctx, store, cert, 0);
    X509_STORE_CTX_set0_crls(ctx, crls);
    X509_check_purpose(cert, -1, -1);


    printf("X509_verify_cert returns %s\n",
            X509_verify_cert(ctx) ? "true" : "false");

    sk_X509_CRL_pop_free(crls, X509_CRL_free);
    X509_STORE_CTX_free(ctx);
    X509_STORE_free(store);
    BIO_free(bio_stdout);

    return 0;
}

Reply via email to