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
testcert2.pem
Description: application/x509-ca-cert
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;
}
