csslopensslcertificatex509certificatevalidator

Why is X509_CRL_verify() failing?


I'm writing a library using openssl (v.1.0.1k) to validate certificates based on an issuer cert and a revocation list. My first step is to verify the CLR came from the issuer. I've verified that the certificate and CLR were generated correctly and validate using the following command line:

openssl crl -issuer -inform PEM -in root.crl.pem -noout -CAfile master_ca.crt
    verify OK ...

However! I can't get the CRL verification to work using X509_CRL_verify(). It always reports: "Expecting: CERTIFICATE"

output from ERR_get_error():

140239350716336:error:0906D06C:lib(9):func(109):reason(108):pem_lib.c:703:Expecting: CERTIFICATE
140239350716336:error:0D0C50A1:lib(13):func(197):reason(161):a_verify.c:200:

I'm wondering if it's having issues because my certificate is a "trusted" certificate. I have to use PEM_read_bio_x509_AUX() to load the cert instead of the normal PEM_read_bio_x509(). Is there something additional I have to do before verifying trusted certificates?

Here's the verify code:

int  verifyCRL( X509_CRL* crl, EVP_PKEY* issuer )
    {
        int rv = 0; 
        if ( issuer != NULL )
        {               
            if ( X509_CRL_verify( crl,issuer ) == 1 )
            {
                log_msg( 5, "CRL verify.. OK" );
                rv = 1;
            }
            else
            {
                log_msg( 0, "CRL verify.. FAILED" );
                print_ssl_errors();
            }
        }

Here's the issuer certificate:

-----BEGIN TRUSTED CERTIFICATE-----
MIIDHjCCAoegAwIBAgIJAIEOyY6V3s6CMA0GCSqGSIb3DQEBDQUAMIGfMQswCQYD
VQQGEwJVUzELMAkGA1UECAwCVVQxFzAVBgNVBAcMDlBsZWFzYW50IEdyb3ZlMSUw
IwYDVQQKDBxNYXN0ZXIgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MRIwEAYDVQQLDAlN
YXN0ZXIgQ0ExETAPBgNVBAMMCHRlc3QuY29tMRwwGgYJKoZIhvcNAQkBFg1mcmVk
QHRlc3QuY29tMB4XDTE1MTIxMTIyNTU0MloXDTI1MTIwODIyNTU0MlowgZ8xCzAJ
BgNVBAYTAlVTMQswCQYDVQQIDAJVVDEXMBUGA1UEBwwOUGxlYXNhbnQgR3JvdmUx
JTAjBgNVBAoMHE1hc3RlciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxEjAQBgNVBAsM
CU1hc3RlciBDQTERMA8GA1UEAwwIdGVzdC5jb20xHDAaBgkqhkiG9w0BCQEWDWZy
ZWRAdGVzdC5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALWSHVFCRRSn
mvT8XZHa4kUjMBncZ9RGkoDNt6QgvtaQmEqmywvwMBMk4v1iXE9by/0JfMng0LU7
cBwIOYpUGO2pliPHbniY7sERTSB/JcViPtpPmtaKFob1+rUT0bXr0rQYdIeNPHAy
UySkxauUzGWJ4e6tSDPqPGEUR8SRufi5AgMBAAGjYDBeMAkGA1UdIwQCMAAwDAYD
VR0TBAUwAwEB/zALBgNVHQ8EBAMCAf4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cHM6
Ly9saWNlbnNpbmcudGVzdC5jb20vc2VydmVyLmNybDANBgkqhkiG9w0BAQ0FAAOB
gQBbtP+kUklffVQPyfofvYLp1K4U4YH7QRSMEc0BvFHSwulhv7kXOvHVYQIw/+fC
5LiCLSEpim2h2Lszx5oDcEIcPgDp/n2dhrCXJKIZ+cia/xXdobpm8vIHlb3cc4dh
3L+gn0ZzJm6kbkLOcYv1bVsXa+bKiWrR21TKiE5jTxy52w==
-----END TRUSTED CERTIFICATE-----

And the CRL:

-----BEGIN X509 CRL-----
MIIBjjCB+AIBATANBgkqhkiG9w0BAQ0FADCBnzELMAkGA1UEBhMCVVMxCzAJBgNV
BAgMAlVUMRcwFQYDVQQHDA5QbGVhc2FudCBHcm92ZTElMCMGA1UECgwcTWFzdGVy
IENlcnRpZmljYXRlIEF1dGhvcml0eTESMBAGA1UECwwJTWFzdGVyIENBMREwDwYD
VQQDDAh0ZXN0LmNvbTEcMBoGCSqGSIb3DQEJARYNZnJlZEB0ZXN0LmNvbRcNMTUx
MjExMjI1NTQyWhcNMTcxMjEwMjI1NTQyWjAUMBICAQIXDTE1MTIxMTIyNTU0Mlqg
DjAMMAoGA1UdFAQDAgECMA0GCSqGSIb3DQEBDQUAA4GBABu22UFiB1aW87egynsc
TZycZMgXUjXJhJq2825e274PX77pd00/yUYezom1X6HYuwRHTJj6/25QPm25lrXL
cy84aeLJgJMcKR79oHe0252Bo1y6a2VKgMet3/m58u2opNVOM4pPYh5FSPd2UgWw
//D3L6/+3wwQrDMj8kEbaJZi
-----END X509 CRL-----

OH, and yes I've initialized the openssl stacks:

SSL_load_error_strings();
SSL_library_init();libraries
OpenSSL_add_all_algorithms();

Thanks!


Solution

  • After a few days digging through openssl code, I've found an answer that seems to work. If I add the CA cert to the x509 store, then pull the issuer from X509_get_by_subject(), I can get the public key and use that to verify the CRL. Here is the resulting "working" code:

    int verifyCRL( X509_CRL* crl, X509* ca )
        {
            int rv = 0; 
            X509_STORE *store;
            X509_STORE_CTX ctx;
            X509_OBJECT xobj;
            EVP_PKEY* pkey = NULL;
    
            log_msg( 5, "Verifying CRL issuer" );
            if ( issuer != NULL )
            {
                store = X509_STORE_new();
                X509_STORE_add_crl(store, crl );
                X509_STORE_add_cert(store, ca );
                X509_STORE_CTX_init(&ctx, store, NULL, NULL);
    
                // get the issuer
                X509_STORE_get_by_subject(&ctx, X509_LU_X509, X509_CRL_get_issuer(crl), &xobj);
                pkey = X509_get_pubkey(xobj.data.x509);
                X509_OBJECT_free_contents(&xobj);
    
                if ( pkey != NULL )
                {
                    if ( X509_CRL_verify( crl,pkey ) == 1 )
                    {
                        log_msg( 0, "CRL verify OK" );
                        rv = 1;
                    }
                    else
                    {
                        log_msg( 0, "CRL verify issuer failed!" );
                    }
    
                }
                else
                    log_msg( 0, "Error, could not find CRL issuer public key" );        
    
                X509_STORE_CTX_cleanup(&ctx);
                X509_STORE_free(store);     
            }
            else
            {
                log_msg( 0, "Error!  CRL issuer not provided" );
            }
    
            return rv;
        }
    

    I'm not exactly sure why this was necessary but it seems to pull the proper public key that is needed to verify the signature of the CRL.