Программная проверка x509v3 extendedKeyUsage - PullRequest
0 голосов
/ 09 января 2019

Фон

Мне нужно программно проверить extendedKeyUsage в сертификате x509. Моя цель здесь - убедиться, что в extendedKeyUsage присутствует только TLS Web Server Authentication, TLS Web Client Authentication. Я использую OpenSSL 1.0.2p lib на MacOS.

Ниже приведен мой код для извлечения полей extendedKeyUsage:

#include <openssl/x509v3.h>
#include <openssl/bn.h>
#include <openssl/asn1.h>
#include <openssl/x509.h>
#include <openssl/x509_vfy.h>
#include <openssl/pem.h>
#include <openssl/bio.h>

int verifyDeviceCertExtendedKeyUsage(){

    OpenSSL_add_all_algorithms();

    auto readBytes = MyApp::FileUtil::readAllBytes("path/to/pem");

    BIO *bio_mem = BIO_new(BIO_s_mem());
    BIO_puts(bio_mem, readBytes.data());
    X509 *x509 = PEM_read_bio_X509(bio_mem, NULL, NULL, NULL);

    ASN1_BIT_STRING *usage = static_cast<ASN1_BIT_STRING*>(X509_get_ext_d2i(x509, NID_ext_key_usage, NULL, NULL));
    if (usage && (usage->length > 0)){
        _CERTUTIL_LOG->debug("in verifyDeviceCertExtendedKeyUsage, usage->data[0]: {0:x}", (int)usage->data[0]);
    }
}

Кроме того, выдержка из вывода openssl x509 -text -noout -in path/to/pem:

X509v3 Extended Key Usage: 
    TLS Web Server Authentication, TLS Web Client Authentication

Выпуск

Каждый раз, когда я запускаю свой код, значение usage->data[0] отличается, что является признаком того, что мой код вызывает неопределенное поведение.

Примечание. Я использовал аналогичный код для успешного извлечения полей keyUsage, заменив NID_ext_key_usage на NID_key_usage в X509_get_ext_d2i().

Если мой код вернул правильное значение, я бы проверил его, сравнив со следующим, что в openssl/x509v3.h:

# define XKU_SSL_SERVER          0x1
# define XKU_SSL_CLIENT          0x2

Вопрос

Что-то не так с моим кодом?

Как я могу надежно получить extendedKeyUsage поля и проверить их?

Обновление

Я нашел способ, но мне неудобно сравнивать строки:

BIO *bio_mem = BIO_new(BIO_s_mem());
BIO_puts(bio_mem, readBytes.data());
X509 *x509 = PEM_read_bio_X509(bio_mem, NULL, NULL, NULL);

auto extIndex = X509_get_ext_by_NID(x509, NID_ext_key_usage, -1);
if(extIndex < 0){
    BIO_free(bio_mem);
    X509_free(x509);
    return ERR;
}

X509_EXTENSION *ext = X509_get_ext(x509, extIndex);

EXTENDED_KEY_USAGE *eku = static_cast<EXTENDED_KEY_USAGE*>(X509V3_EXT_d2i(ext));

for(int i = 0 ; i < sk_ASN1_OBJECT_num(eku) ; i++){
    char buffer[100] = {0}; // <--- init all elements with 0, compiler specific behavior?
    OBJ_obj2txt(buffer, sizeof(buffer), sk_ASN1_OBJECT_value(eku, i), 1);

    if(strcmp(buffer, "1.3.6.1.5.5.7.3.1") == 0 && strcmp(buffer, "1.3.6.1.5.5.7.3.1") == 0){
        BIO_free(bio_mem);
        X509_free(x509);
        return SUCCESS;
    }
}

1 Ответ

0 голосов
/ 11 января 2019

В openssl 1.1 это просто, если у вас есть указатель X509. Вам просто нужно использовать следующие методы: X509_get_extension_flags и X509_get_extended_key_usage

if ((X509_get_extension_flags(x509) & EXFLAG_XKUSAGE) == EXFLAG_XKUSAGE)
{
    auto const certificate_key_usage = X509_get_extended_key_usage(x509);
    if ((certificate_key_usage & (XKU_SSL_SERVER | XKU_SSL_CLIENT)) == (XKU_SSL_SERVER | XKU_SSL_CLIENT))
    {
        // has both TLS Web Server Authentication and TLS Web Client Authentication
    }
    else
    {
        // doesn't have both TLS Web Server Authentication and TLS Web Client Authentication
    }
}

Для более старых версий openssl вы должны иметь возможность определить следующее, чтобы приведенный выше код работал:

#if OPENSSL_VERSION_NUMBER < 0x10100000L
#define X509_get_extension_flags(x) (x->ex_flags)
#define X509_get_extended_key_usage(x)  (x->ex_xkusage)
#endif
...