Почему X509_CRL_verify() не работает?

Я пишу библиотеку, используя openssl (v.1.0.1k) для проверки сертификатов на основе сертификата эмитента и списка отзыва. Мой первый шаг - убедиться, что CLR пришел от эмитента. Я проверил, что сертификат и CLR были сгенерированы правильно, и проверьте его с помощью следующей командной строки:

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

Тем не мение! Я не могу заставить работать CRL с помощью X509_CRL_verify(). Это всегда сообщает: "Ожидая: СЕРТИФИКАТ"

вывод из 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:

Мне интересно, есть ли у него проблемы, потому что мой сертификат является "доверенным" сертификатом. Я должен использовать PEM_read_bio_x509_AUX() для загрузки сертификата вместо обычного PEM_read_bio_x509(). Что-то еще, что я должен сделать перед проверкой доверенных сертификатов?

Вот проверочный код:

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();
            }
        }

Вот сертификат эмитента:

-----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-----

И CRL:

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

О, и да, я инициализировал стеки openssl:

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

Спасибо!

2 ответа

Решение

После нескольких дней, копаясь в коде openssl, я нашел ответ, который, кажется, работает. Если я добавлю сертификат CA в хранилище x509, а затем вытащу издателя из X509_get_by_subject(), я смогу получить открытый ключ и использовать его для проверки CRL. Вот результирующий "рабочий" код:

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;
    }

Я не совсем уверен, почему это было необходимо, но кажется, что он извлекает надлежащий открытый ключ, необходимый для проверки подписи CRL.

Вам следует OpenSSL_add_all_algorithms(); перед проверкой сертификата. Вот мой код для проверки сертификата различными способами. Первый способ - использование открытого ключа, получаемого из корневого сертификата, другой - проверка сертификата с помощью корневого сертификата.

int CertificateChecker::X509_Verify(const unsigned char* certRoot, unsigned long rootCertLen, const unsigned char* cert , unsigned long certLen)
{
    int ret = -1;
    X509 *usrCert = NULL;
    X509 *rootCert = NULL;

    //rootCert = d2i_X509(NULL, (const unsigned char**)&certRoot, rootCertLen); //for cert with der format
    BIO* bio = BIO_new_mem_buf((void*)certRoot, -1);
    rootCert = PEM_read_bio_X509(bio, NULL, 0, NULL);
    BIO_free(bio);
    if( NULL == rootCert){
        printf("root cert d2i_X509 failed\n");
        return -1;
    }

    //usrCert = d2i_X509(NULL, (const unsigned char**)&cert,certLen);
    bio = BIO_new_mem_buf((void*)cert, -1);
    usrCert = PEM_read_bio_X509(bio, NULL, 0, NULL);
    BIO_free(bio);
    if(usrCert == NULL){
        printf(" usr Cert d2i_X509 failed\n");
        return -1;
    }
    OpenSSL_add_all_algorithms();
    //start. verify the Certificate with public key.
    EVP_PKEY * pubkey = X509_get_pubkey(rootCert);
    //verify. result less than or 0 means not verified or some error.
    ret = X509_verify(usrCert, pubkey);
    //free the public key.
    EVP_PKEY_free(pubkey);
    //end. verify the Certification with public key.

    //start. verify the Certificate with root certificate.
    X509_STORE_CTX *ctx = NULL;
    X509_STORE *certStore = NULL;

    certStore = X509_STORE_new();
    X509_STORE_add_cert(certStore, rootCert);
    ctx = X509_STORE_CTX_new();
    if (1 == X509_STORE_CTX_init(ctx,certStore,usrCert,NULL))
    {
        ret = X509_verify_cert(ctx);
        long nCode = X509_STORE_CTX_get_error(ctx);
        const char * pChError = X509_verify_cert_error_string(nCode);
        printf("\r\n err info: %s \r\n", pChError);
    }
    X509_STORE_CTX_cleanup(ctx);
    X509_STORE_CTX_free(ctx);
    X509_STORE_free(certStore);
    //end. verify the Certificate with root certificate.

    X509_free(usrCert);
    X509_free(rootCert);

    return ret;
}
Другие вопросы по тегам