[devel] X509v3: CRL Distribution Points: help is needed
Paul Wolneykien
manowar на altlinux.org
Пт Авг 10 15:52:26 MSK 2018
08.08.2018 19:52, Paul Wolneykien пишет:
> 08.08.2018 19:33, Alexey V. Vissarionov пишет:
>> On 2018-08-08 18:43:25 +0300, manowar на altlinux.org wrote:
>> > Вот как выглядит в разобранном виде та часть файла подписи,
>> > которая отвечает за CRL: [...]
>> > Теперь, собственно, сам вопрос: структура выше соответствует
>> > двум разным CRL?
>>
>> Нет - это один CRL, для которого предусмотрена возможность взять
>> его как с локального зеркала (pki-lan), так и снаружи у ГРЧЦ.
Итак, я, прежде всего, точно выяснил, что же записано в оговоренной
секции сертификата. Разберу подробно тут, вдруг кому будет полезно (что
называется --- отвечаю сам себе).
Начинается всё с
SEQUENCE(2 elem) --- Так кодируется экземпляр расширения
(extension) X.509. Элементами списка (именно --- 2 элемента) являются:
OBJECT IDENTIFIER 2.5.29.31 --- кодовый номер расширения и
OCTET STRING (длинная строка, длиной 153 байта) --- его
содержимое, которое мы разбираем ниже:
SEQUENCE(2 elem) --- Снова список. На этот раз --- это список,
состоящий из нескольких DistributionPoint, каждый из которых является
тоже списком с количеством элементов от 0 до 3 (поскольку все они
опциональные):
SEQUENCE(1 elem) --- Это DistributionPoint с единственным
указанным элементом, осталось понять, каким:
[0](1 elem) --- Теперь ясно, что это элемент с тегом [0], а
именно --- DistributionPointName. Он, в свою очередь может быть
представлен двумя различными способами, поэтому следом снова указывается:
[0](1 elem) --- Тем самым выбирается вариант fullName,
помеченный в схеме тегом [0] и имеющим тип GeneralNames. Тип
GeneralNames представляет собой список из 1 или более альтернативных
значений, в котором каждая альтернатива обозначается тегом с номером от
[0] до [8]. Поэтому следом идёт наконец:
[6]http://pki-lan/ocsp... --- Это
uniformResourceIdentifier (тег [6]) типа IA5String.
Второй DistributionPoint оформлен точно так же, как первый. Поэтому
формально --- это именно два разных DistributionPoint, т.е. два разных
CRL. И в каждом DistributionPoint только один URI.
То, что возможно сделать иначе: задать несколько URI для каждой
DistributionPoint --- можно узнать, например, и следующей инструкции:
https://www.pixelstech.net/article/1445498968-Generate-certificate-with-cRLDistributionPoints-extension-using-OpenSSL
08.08.2018 19:33, Alexey V. Vissarionov пишет:
> On 2018-08-08 18:43:25 +0300, manowar на altlinux.org wrote:
> > не Интернет. А это значит, что издатель подписи (сертификата)
> > рассчитывал на то, что оба указанных им адреса будут расценены
> > как альтернативные и, при недоступности первого, проверяющий
> > перейдёт по второму.
>
> Именно так. Локальное зеркало - best practice, ибо недоступность
> CRL может привести к тому, что отозванный сертификат будет принят
> как рабочий.
>
> > Но dirmngr (из пакета gnupg2) считает иначе: он расценивает
> > указанную информацию как список из двух различных CRL, которые,
> > следовательно, оба требуются для проверки подписи.
>
> Идея здравая, но реализована, мягко говоря, per rectum.
> ...
> Проверять, действительно, нужно все источники (на случай, если
> какое-то свежее изменение в апстриме не доехало до зеркала), но
> отваливаться по UTV (unable to verify|validate) следует только
> когда недоступны _все_ источники.
А вот теперь вопрос, чья это идея (последний абзац выше): это твоё
личное представление о том, как должно быть или всё таки нечто
общепринятое? Допустим, ты сомневаешься насчёт верности реализации в
GnuPG. Но как тебе такое:
static X509_CRL *load_crl_crldp(STACK_OF(DIST_POINT) *crldp)
{
int i;
const char *urlptr = NULL;
for (i = 0; i < sk_DIST_POINT_num(crldp); i++) {
DIST_POINT *dp = sk_DIST_POINT_value(crldp, i);
urlptr = get_dp_url(dp);
if (urlptr)
return load_crl(urlptr, FORMAT_HTTP);
}
return NULL;
}
Это я обнаружил в OpenSSL. И там, как видно, внутри цикла выход по
return на _первой_ же непустой DistributionPoint. Следовательно,
реализация OpenSSL рассчитана на то, что _все_ указанные источники будут
доступны. И если какой-то недоступен, то будет ошибка (там bio_err
внутри load_crl).
Проверяем на нашем примере:
$ openssl verify -engine gost -CAfile parsed2.txt -crl_download
-crl_check parsed.txt
engine "gost" set.
Error loading CRL from
http://pki-lan/ocsp/6b00868389d200cf56b86be4e336101e1f72aec3.crl
140430750978520:error:2006A066:BIO routines:BIO_get_host_ip:bad hostname
lookup:b_sock.c:146:host=pki-lan
parsed.txt: 1.2.643.100.3 = ...
error 3 at 0 depth lookup:unable to get certificate CRL
Получаем тот же результат, что и через GnuPG. С той лишь разницей, что
в GnuPG заложен перебор нескольких альтернативных URI для одной
DistributionPoint, а вот OpenSSL даже не предполагает альтернатив ---
все должны быть доступны.
Получается, что предположение о том, что в разбираемом сертификате оба
URI нужно расценивать как альтернативные, не подтверждается ни теорией
(структурой в ASN.1), ни практикой (openssl verify).
Или скажешь, что OpenSSL тоже не аргумент? А кто же тогда у них главный?
Подробная информация о списке рассылки Devel