[devel] I: Cryptocom openssl patch
Konstantin A. Lepikhov
=?iso-8859-1?q?lakostis_=CE=C1_altlinux=2Eorg?=
Вт Июн 14 09:55:00 MSD 2005
Hi!
Данное письмо будет интересно тем, кто занимается реализацией поддержки
национальной криптографии на базе пакета openssl. Как правило, если туда
добавляется поддержка каких-то новых алгоритмов, то приходится
модифицировать довольно много кода самой библиотеки, в результате чего
конечная сертификация продукта на базе openssl сводится к сертификации
_всего_ кода openssl с национальной криптографией. Не так давно,
российская компания "Криптоком" (www.cryptocom.ru), опубликовала в списке
рассылки разработчиков openssl-dev довольно интересный патч, позволяющий
разнести реализацию криптоалгоритмов и код криптобиблиотеки. Сделано это
через расширенный интерфейс ENGINE, который уже присутствовал в openssl,
но был завязан только на аппаратные реализации симметричных шифров. Чем
это удобно - можно теперь сертифицировать только криптомодуль, а не весь
код openssl или приложения, что значительно сокращает сроки подготовки
ПО на базе openssl. Детали реализации изложены в приложенном драфте
описания патча. Пока у самой компании довольно много планов относительно
данного патча, но наиболее приоритетным считается один - чтобы этот патч
вошел в openssl upstream или, в крайнем случае, в contrib. Для этого
предлагается (с согласия участников ALTLinux Team) организовать
специальную ветку в Сизифе для тестирования и популяризации данного патча.
Если у кого-то из Team есть предложения по дальнейшей работе в данном
направлении (например, готовое решение на базе измененного openssl), прошу
делится этими мыслями, разработчики из Криптоком данный спискок тоже
читают (через архивы).
--
WBR, Konstantin chat with ==>ICQ: 109916175
Lepikhov, speak to ==>JID: lakostis на jabber.org
aka L.A. Kostis write to ==>mailto:lakostis на pisem.net.nospam
...The information is like the bank... (c) EC8OR
----------- следующая часть -----------
Предыстория
~~~~~~~~~~~
В сообщении
http://marc.theaimsgroup.com/?l=openssl-dev&m=109947214028600&w=2
мы описывали наши предложения по генерализации архитектуры работы с
асимметричными алгоритмами. В данном сообщении мы представляем очередную
версию нашего патча, реализующую наши предложения.
Обусловленность задачи
~~~~~~~~~~~~~~~~~~~~~~
Задача интересна прежде всего с точки зрения возможности легкого
добавления в openssl национальной криптографии.
Требования по сертификации криптографического программного
обеспечения некоторых стран (в частности России) делают законным
использование решений, в которых сертифицирован только модуль,
непосредственно реализующий национальные криптоалгоритмы.
Поэтому наличие сертифицированного (коммерческого) криптографического
модуля, совместимого с OpenSSL, позволит пользователям применять
сертифицированные криптоалгоритмы в решениях на базе любых OpenSource
приложений, использующих OpenSSL.
Кроме того, наличие стандартизированного и документированного интерфейса
для добавления новых алгоритмов упростит разработку и тестирование
реализаций ранее неподдерживаемых алгоритмов и увеличит надежность этих
модификаций, так как для добавления нового алгоритма не будет
требоваться внесение многочисленных модификцаций в ядро OpenSSL.
Новые возможности, добавляемые патчем
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Цель данного патча - сделать возможным добавление в виде подгружаемых
модулей engine не только новых реализаций существующих ассиметричных
криптографических алгоритмов (DSA, RSA, ECDSA) но и добавление новых
асимметричных алгоритмов. Существующее API OpenSSL позволяет только
выбирать ту или иную реализацию стандартных алгоритмов, предоставляемую
разработчиками engine.
В частности, наша компания смогла, опираясь на данный патч, реализовать
для OpenSSL российские криптографические алгоритмы электронной подписи
GOST-1994, GOST-2001.
Мы протестировали для нашей реализации всю функциональность PKI и работу
с подписанными и зашифрованными сообщениями (SMIME).
Описание патча
~~~~~~~~~~~~~~
Предлагаемый патч делает работу с асимметричными алгоритмами на уровне
ядра OpenSSL полностью аналогичной работе с симметричными алгоритмами и
алгоритмами дайджеста.
Патч решает проблему использования одного
алгоритма дайджеста с несколькими алгоритмами подписи без клонирования
и заведения отдельных OID для, по сути своей, нескольких экземпляров
одного алгоритма. Идея аналогична присутствующей в закомментированном
виде в evp.h структуре EVP_PKEY_MD.
Патч вводит структуру EVP_ASYMMETRIC, аналогичную EVP_CIPHER и
EVP_MD и API управления данной структурой, аналогичное имеющемуся
для EVP_CIPHER/EVP_MD.
Эта структура содержит
- NID реализуемого алгоритма,
- Тип реализуемого алгоритма (RSA/DSA/EC/DH),
- NID используемого с ним алгоритма дайджеста, если алгоритм, как DSA или
российские алгоритмы, требует специфического дайджеста (DSA требует SHA1,
российские алгоритмы подписи - российских алгоритмов дайджеста),
- NID используемой комбинации "алгоритм подписи - алгоритм дайджеста", в
случае, если это не удается определить из поля pkey_type
соответствующего дайджеста.
- указатели на специфичные для алгоритмов функции, осуществляющие:
- разбор параметров генерации ключа (используются в команде
openssl req) (синтаксис опции -newkey генерализован и сделан
расширяемым),
- конвертацию из представления в X509-сертификате во внутреннее
представление OpenSSL и обратно открытого ключа,
- конвертацию из представления в X509-сертификате во внутреннее
представление OpenSSL и обратно параметров алгоритма,
- конвертацию из представления в PKCS8-формате во внутреннее
представление OpenSSL и обратно секретного ключа,
- сохранение ASN1-параметров алгоритма в SIGNER_INFO
PKCS7-структуры,
- сохранение и разбор информации о получателе зашифрованного
сообщения.
- выработку и проверку подписи.
Патч не реализует предложенную в нашем оригинальном пропозале
генерализацию работы с эллиптическими кривыми, так как нам оказалось
проще инкапсулировать преобразование параметров алгоритма ГОСТ 2001 в
структуру EC_GROUP в вышеупомянутые функции соответствующего алгоритма.
Добавлена поддержка асимметричных алгоритмов на уровень ENGINE API,
аналогичная существовавшим там функциям
ENGINE_get_ciphers/ENGINE_get_digests. Эти функции задействованы, в
частности, в команде openssl engine.
Все алгоритмы с открытым ключом, поддерживаемые OpenSSL (RSA, DSA, DH,
ECDSA, ECDH) переведены на работу через таблицу ассиметричных
алгоритмов. При этом комплект тестов, входящий в дистрибутив OpenSSL
полностью выполняется.
API EVP_ASYMMETRIC и его использование
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Все описанные в этом разделе функции, если не оговорено особо,
возвращают положительное значение в случае успеха и неположительное -
в случае ошибки.
/* Recieves EVP_PKEY to store parameters, string from openssl req */
/* options and BIO channel to report errors to */
int (*parse_keygeneration_params)(EVP_PKEY *newkey,const char *params,
BIO* bio_err);
Принимает указатель на структуру EVP_PKEY, в которую при успехе
сохраняются параметры, строковое представление параметров и BIO,
используемое для выдачи сообщений об ошибках.
Функция предназначена для разбора параметра командной строки команды
openssl req. Эта функция должна быть определена для того, чтобы была
возможность создания X509-сертификатов с алгоритмом, соответствующим
данному EVP_ASYMMETRIC. Возвращает длину ключа в случае успеха.
Эта фукнция используется для замены условной компиляции файла req.c.
/* Parses ASN1_STRUCTRE of public key (typically from X509 cert) */
int (*d2i_pub_key)(EVP_PKEY *key, const unsigned char *buf, long length);
Эта функция используется для приведения прочитанного из сертификата
открытого ключа ко внутреннему представлению. Должна быть определена
для всех алгоритмов, для которых есть возможность создания
сертификатов.
/* Parses private key ASN1 STRUCTURE. Handles some cases of broken */
/* PKCS8 returning appropriate constant in the int *broken field */
int (*d2i_PKCS8_key)(EVP_PKEY *key, const unsigned char *buf, long length, int *broken);
Эта функция используется для приведения прочитанного из сертификата
секретного ключа ко внутреннему представлению. Должна быть определена
для всех алгоритмов, для которых есть возможность создания
сертификатов. Обрабатывает legacy-форматы секретных ключей.
/* Parses ASN1 STRUCTURE of algorithm parameters */
/* If algorithm doesn't need parameters, this field could be NULL. */
/* Otherwise it should allocate algorithm-type specific parameter */
/* structure and assign it to pkey->pkey. It should also set */
/* save_parameters field of pkey to true. */
int (*d2i_algor_params) (EVP_PKEY *pkey,const ASN1_TYPE *param);
Функция предназначена для разбора хранимых в сертификате или секретном
ключе параметров алгоритма. Если алгоритм не сохраняет свои параметры
в сертификате, эту функцию можно не определять. В противном случае она
должна сохранять алгоритм-специфичные параметры в соответствующем поле
структуры EVP_PKEY и выставлять в true поле save_parameters.
/* Packs public key into buffer according to algorithm specific */
/* rules */
int (*i2d_pub_key)(EVP_PKEY *key, unsigned char **buf);
Функция выполняет упаковку открытого ключа в ASN1-структуру. Должна
быть определена для возможности создания сертификатов.
/* Packs private key into buffer according to algorithm specific */
/* rules */
int (*i2d_priv_key)(EVP_PKEY *key, unsigned char **buf);
Функция выполняет упаковку секретного ключа в PKCS8-структуру. Должна
быть определена для возможности создания сертификатов.
/* Fills given freshly allocated ASN1_TYPE structure with algorithm */
/* parameters. Returns length of the structure. If param is NULL, */
/* just returns length. Returns -1 on error. */
int (*i2d_algor_params) (EVP_PKEY *key, ASN1_TYPE *param);
Функция сохраняет параметры алгоритма в переданной ASN1-структуре. При
передаче NULL возвращает необходимую длину.
int (*i2d_signature_algor) (X509_ALGOR* param);
Функция сохраняет NID алгоритма подписи и параметры подписи в переданную
структуру X509_ALGOR.
/* S/MIME key encryption and pack */
/* Returns non-positive value on error, positive on success */
int (*pkcs7_key_transport_encrypt) (EVP_PKEY *pubk, const unsigned char *key,int key_len, ASN1_OCTET_STRING *);
Эта функция предназначена для упаковки ключа, с помощью которого
выполняется симметричное шифрование сообщения, при отправке
шифрованных S/MIME сообщений. Сейчас она рассчитана в соответствии с
ограничениями текущей реализации OpenSSL на упаковку RSA-подобной
структуры KeyTransRecipientInfo (RFC 2630, 6.2.1; драфты от
"КриптоПро"). Должна быть определена в случае, когда алгоритм
планируется использовать для создания зашифрованных S/MIME сообщений.
Российские криптоалгоритмы используют KeyTransRecipientInfo для
передачи эфемерных ключей из-за особенностей реализации Windows,
рассматривающей любой алгоритм как RSA-подобный.
/* S/MIME key unpack and decryption */
/* Returns negative absolute value of required size on too small buffer
* zero on error, decrypted key size on success*/
int (*pkcs7_key_transport_decrypt) (EVP_PKEY* priv, unsigned char *key, int max_key_len, const ASN1_OCTET_STRING * data);
Эта функция предназначена для распаковки симметричного ключа в
зашифрованных S/MIME сообщениях. В случае недостаточного размера
переданного буфера, если такая возможность есть, возвращает
отрицательное значение, равное по абсолютной величине необходимой
длине буфера. В случае успеха возвращает длину симметричного ключа.
/* Signature generation. */
/* Returns non-negative value on success. */
int (*sign) (const EVP_PKEY *priv, int dgst_type,
const unsigned char *dgst_buf, unsigned int dgst_len,
unsigned char *sigret, unsigned int *siglen);
Вырабатывает подпись.
/* Signature verification. */
/* Returns non-negative value on success. */
int (*verify) (const EVP_PKEY *pub, int dgst_type,
const unsigned char *dgst_buf, unsigned int dgst_len,
const unsigned char *sigbuf, unsigned int siglen);
Проверяет подпись.
В случае, когда для EVP_ASYMMETRIC определяются функции sign и verify,
рекомендуется определять их через соответствующие функции union'а
method, чтобы обеспечить возможность легкой смены реализации через
смену method (например, для аппаратных решений).
Добавлена функция
EVP_PKEY* EVP_PKEY_by_asymmetric(const EVP_ASYMMETRIC *as);
Она аналогична EVP_PKEY_new, за тем исключением, что выполняет более
полную инициализацию структуры EVP_PKEY, так как располагает большей
информацией.
В структуру ENGINE добавлен callback, отвечающий за работу с
EVP_ASYMMETRIC.
В API ENGINE добавлены функции
ENGINE_ASYMS_PTR ENGINE_get_asyms(const ENGINE *e), аналогичная
ENGINE_get_digests/ENGINE_get_ciphers, и возвращающая
соответствующий callback,
ENGINE_set_asyms(ENGINE *e, ENGINE_ASYMS_PTR f), устанавливающая
callback,
const EVP_ASYMMETRIC *ENGINE_get_asym(ENGINE *e, int nid), аналогичная
ENGINE_get_digest/ENGINE_get_cipher, obtains an asymmetric implementation
from an ENGINE functional reference,
ENGINE *ENGINE_get_asym_engine(int nid), аналогичная
ENGINE_get_cipher_engine/ENGINE_get_digest_engine, возвращающая ENGINE,
в котором реализован алгоритм, относящийся к искомому nid.
Описание конкретных изменений
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
В коде libcrypto и утилиты openssl (команд, связанных с PKI и SMIME)
явные ветвления по типу алгоритма с открытым ключом
заменены на поиск алгоритма в таблице по его имени или OID-у и вызов
соответствующих функций по указателям, содержащимся в структуре
EVP_ASYMMETRIC.
Благодаря этому удалось отказаться также от условной компиляции многих
файлов уровня EVP и выше в зависимости от макросов OPENSSL_NO_RSA,
OPENSSL_NO_DSA и OPENSSL_NO_EC.
Условная компиляция остается только при добавлении алгоритмов в таблицу
(файл crypto/evp/c_alla.c, добавляемый нашим патчем). Во всех остальных
ситуациях алгоритм, не поддерживаемый текущим вариантом компиляции
просто не находится в таблице, что приводит к соответствующему сообщению
об ошибке.
Явное прописывание дайджеста, жестко требуемого по спецификации того или
иного алгоритма, также заменено на поиск по значению из соответствующего
поля структуры EVP_ASYMMETRIC.
Добавлена функция EVP_PKEY_by_asymmetric, создающая
новый экземпляр структуры EVP_PKEY и инициализирующая его в зависимости
от типа алгоритма.
В функциях EVP_SignFinal и EVP_VerifyFinal перед вызовом соответствующей
функции дайджеста проверяется, есть ли функция sign/verify у структуры
EVP_ASYMMETRIC, соответствующей переданному ключу.
В функциях ASN1_sign и ASN1_item_sign алгоритм связки "дайджест-подпись"
берется из дайджеста. Если результат - NID_undef, то он берется из
EVP_ASYMMETRIC, соответствующей переданному ключу.
Предлагаемый патч по умолчанию сохраняет секретные ключи
в формате PKCS8, так как этот формат универсален и позволяет работать с
любыми алгоритмами, в то время как непатченный OpenSSL по умолчанию
использует алгоритм-специфичные форматы секретных ключей. При экспорте
секретных ключей из PKCS12-структуры они также экспортируются в
PKCS8-формате.
Для преобразования в исторически сложившиеся форматы предполагается, как
и в исходной версии нашего предложения, использовать команду openssl pkcs8.
Кроме того, с целью упрощения логики создания PKCS8-файлов, нами
изменена логика записи DSA-ключей и RSA в формат PKCS8. В текущем снапшоте
создание PKCS8 структуры для DSA, удовлетворяющей стандарту, является
частным случаем создания broken структуры. Т.е.
функция EVP_PKEY2PKCS8 вызывает функцию EVP_PKEY2PKCS8_broken.
В результате применения нашего патча функция EVP_PKEY2PKCS8 создает
корректную с точки зрения стандарта структуру, а функция
EVP_PKEY2PKCS8_broken сначала создает стандартную структуру вызовом
EVP_PKEY2PKCS8, а потом, если необходимо breaks it.
Команде openssl smime добавлена интерпретация ключей -algname, где имя
алгоритма в зависимости от осуществляемой операции может быть либо
алгоритмом дайджеста, либо алгоритмом шифрования.
При реализации работы с S/MIME мы опирались на специфицированные в
draft'ах "Соглашения о совместимости СКЗИ российских производителей".
Хотя используемая семантика соответствует KeyAgreement (RFC2630, 6.2.2),
эти документы специфицируют расширение формата KeyTransport (RFC2630,
6.2.1). Это связано, в частности, с необходимостью встраивания в
Microsoft Windows, где применяется RSA-подобная схема.
Эта же функциональность реализована в OpenSSL (до нашего патча
там поддерживались только RSA-ключи получателя).
К сожалению, в процессе разработки патча мы столкнулись с проблемами,
возникающими при создании объектов функцией OBJ_create изнутри
динамически подгружаемых библиотек.
Проблема заключается в том, что необходимо, чтобы динамически созданные
внутри engine объекты существовали
а) в момент разбора командной строки openssl, так как они определяют
допустимый набор параметров команд dgst, enc и req (после
генерализации опции -newkey)
б) в момент выполнения EVP_cleanup, так как при помещении алгоритмов в
соответствующие таблицы функциями EVP_add_cipher, EVP_add_digest,
EVP_add_asymmetric в поле name структуры OBJ_NAME прписывается ссылка
на поле sn либо ln структуры ASN1_OBJECT. Соответственно, есил
динамически размещенный объект, на который ссылается OBJ_NAME уже
освобожден в тот момент, когда мы пытаемся удалить OBJ_NAME из таблицы
с помощью функции lh_delete, происходит segmentation fault.
Для того, чтобы преодолеть эту проблему, мы перенесли очистку таблицы
объектов из отдельных процедур, реализующих команды openssl (req_main,
x509_main, ca_main etc) в код процедуры main файла openssl.c ПОСЛЕ вызова
apps_shutdown.
Reference implementation of engine
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Планы на будущее
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
В предлагаемом патче не реализована поддержка национальных криптографических
алгоритмов собственно в протоколе SSL. Обеспечение такой поддержки в текущей
архитектуре этой части OpenSSL является довольно сложной задачей, поэтому нам
показалось целесообразным выделить эти работы в отдельный этап.
Кроме того, предлагаемый патч обеспечивает возможность использования
национальных криптографических алгоритмов после подгрузки реализующего их
модуля engine. В существующих программах, использующих OpenSSL, такая
подгрузка не предусмотрена. Эта проблема может быть решена, если OpenSSL будет
собрана с необходимым модулем engine. Однако данное решение неудобно для тех,
кто использует бинарные дистрибутивы программного обеспечения (например,
дистрибутивы ОС Linux) и не хочет терять совместимости с системой обновления
соответствующих дистрибутивов.
Поэтому в будущем мы планируем усовершенствовать возможность управление
подгрузкой модулей engine через файлы конфигурации.
Мы планируем реализовать поддержку российских алгоритмов в PKCS12 (в
настоящее время используются классические алгоритмы) и поддержку
экспорта зашифрованных секретных ключей с использованием предоставляемых
engine алгоритмов.
----------- следующая часть -----------
Было удалено вложение не в текстовом формате...
Имя : =?iso-8859-1?q?=CF=D4=D3=D5=D4=D3=D4=D7=D5=C5=D4?=
Тип : application/pgp-signature
Размер : 189 байтов
Описание: =?iso-8859-1?q?=CF=D4=D3=D5=D4=D3=D4=D7=D5=C5=D4?=
Url : <http://lists.altlinux.org/pipermail/devel/attachments/20050614/973310c8/attachment-0001.bin>
Подробная информация о списке рассылки Devel