Пакет Network Security Services и утилита oidcalc

    При реализации проекта, связанного с использованием российской криптографических алгоритмов в почтовом клиенте KMail, в приложении Kleopatra и GnuPG, для перевода российских oid-ов из точечно-десятичной формы в DER-кодировку, я решил воспользоваться утилитой oidcalc из пакета NSS (Network Security Services), который предустановлен во всех дистрибутивах Linux, включая отечественные клоны. Полученный код использовался в работе.

    И все шло хорошо, пока не попался oid, в котором был десятичная цифра 0 (нуль), а именно «1.2.643.2.2.36.0» (szOID_GostR3410_2001_CryptoPro_XchA_ParamSet). И здесь меня ожидал неприятный сюрприз – мой код перестал работать. В какой-то момент я решил посмотреть, а во что же переводится этот oid:

    # oidcalc 1.2.643.2.2.36.0
    0x2a, 0x85, 0x3, 0x2, 0x2, 0x24,
    #

    Но должно было быть 0x2a, 0x85, 0x3, 0x2, 0x2, 0x24, 0x0, — завершающий шестнадцатеричный нуль отсутствовал.

    Попробовал перевести другой oid «1.2.643.3.6.0.1» (КриптоПро УЦ, Срок действия сертификата 1 месяц):

    # oidcalc 1.2.643.3.6.0.1
    0x2a, 0x85, 0x3, 0x3 0x3, 0x6, 0x1,
    #

    Тот же печальный ркзультат – отсутствует предпоследний байт с нулем. Стало ясно, что утилита oidcalc выбрасывает нули из oid-а. Следующий пример только подтвердил это предположение:

    # oidcalc 1.2.643.3.6.1
    0x2a, 0x85, 0x3, 0x3 0x3, 0x6, 0x1,
    #

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

    # ./oid 1.2.643.2.2.36.0
    06 07 2A 85 03 02 02 24 00
    # ./oid 1.2.643.3.6.0.1
    06 07 2A 85 03 03 06 00 01
    #

    Утилита oid выводит результат уже в ASN1-кодировки, где первый байт определяет тип последовательности, второй байт – длину последовательности в байтах, а далее идет сам oid в шестнадцатеричном представлении.

    После этого оставалось проанализировать исходный код утилиты oidcalc.c и вмести минимальные изменения:

           . . .
            memset(buf, 0, sizeof(buf));
            val = atoi(curstr);
            count = 0;
    /*Добавить проверку*/
        if(curstr[0] != '0')
    	
            while (val) {
                buf[count] = (val & 0x7f);
                val = val >> 7;
                count++;
            }
    /*если все же нуль*/
        else
    	buf[count++] = 0x00;
            . . . 

    Теперь, если пересобрать утилиту, то все работает прекрасно:

    #oidcalc 1.2.643.2.2.36.0
    0x2a, 0x85, 0x3, 0x2, 0x2, 0x24, 0x0,
    #oidcalc 1.2.643.3.6.0.1
    0x2a, 0x85, 0x3, 0x3, 0x6, 0x0, 0x1,
    #

    В чем же ошибся разработчик утилиты? В мелочи. Для перевода числа из строки в целое автор использует функции atoi, которая возвращает 0 (нуль) и в случае перевода символа '0' и случае невозможности перевода (задано не число). Оказалось достаточным добавить дополнительную проверку и все заработало.

    Писал ли я разработчикам NSS? Да, писал. Тем более, что пакет NSS с подключаемыми с криптографическими токенами/смаркартами, поддерживающими интерфейс PKCS#11, является фактически криптографическим ядром приложений от Mozilla, а также используется в браузерах Chrome от Google. Ответа не последовало, код не исправлен. Поэтому и появилась эта заметка, чтобы кто-то другой не наступил на эти грабли как ваш покорный слуга. Ну и, конечно, будем надеяться, что поставщики отечественных форков/клонов Linux исправят в своих пакетах эту ошибку.
    Поделиться публикацией
    Реклама помогает поддерживать и развивать наши сервисы

    Подробнее
    Реклама
    Комментарии 0

    Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.