Поддержка Рутокен ЭЦП в OpenSSL

Внимание! Приведенная на форуме инструкция устарела. Актуальная инструкция находится по адресу http://dev.rutoken.ru/pages/viewpage.ac … d=18055184

Открываем проект по поддержке Рутокен ЭЦП в OpenSSL.

Цель – позволить через стандартный интерфейс OpenSSL выполнять по российским криптографическим стандартам на “борту” Рутокен ЭЦП базовые криптографические операции:

  • симметричное шифрование и имитовставка по ГОСТ 28147-89

  • хэширование по ГОСТ Р 34-11.94

  • электронная подпись по ГОСТ Р 34-10.2001

  • распределение ключей VKO 34.10-2001

и высокоуровневые криптографические операции и протоколы

  • электронная подпись и шифрование PKCS#7, CMS, S/MIME

  • заявки на сертификаты PKCS#10

  • сертификаты X.509 и списки отзыва

  • функциональность PKI

  • протокол TLS

  • онлайн-проверка статуса сертификата (OCSP)

  • временные метки (TSP)

Поддержка российских стандартов в OpenSSL сделана в соответствии с RFC, что обеспечивает совместимость c продуктами различных производителей:

  • используются параметры российских алгоритмов в соответствии с RFC 4357 в

    • электронной подписи ГОСТ Р 34.10-2001

    • распределении ключей VKO 34.10-2001

    • хэшировании ГОСТ Р 34-11.94

  • поддержка защищенных сообщений CMS, PKCS#7, S/MIME с использованием российских алгоритмов  в соответствии с RFC 4490

  • функциональность PKI c укладкой открытого ключа ГОСТ Р 34-10.2001 по RFC 4491

  • реализован протокол TLS с поддержкой шифрсьютов с российскими алгоритмами в соответствии с draft-chudov-cryptopro-cptls.

На текущий момент времени существует альфа-версия “плагина” к OpenSSL – engine PKCS11_GOST, которая поддерживает работу с OpenSSL версии 1.0.0 и выше.

На форуме будут описываться различные варианты использования OpenSSL c Рутокен ЭЦП через утилиту openssl и приводиться  программные примеры использования OpenSSL c Рутокен ЭЦП.

Re: Поддержка Рутокен ЭЦП в OpenSSL

Установка, конфигурирование и использование OpenSSL для работы с  Рутокен ЭЦП на платформе win32

ВАЖНО:  поддерживается OpenSSL, начиная с версии 1.0.0

Скачиваем дистрибутив OpenSSL для 32-разрядной Windows на странице http://www.slproweb.com/products/Win32OpenSSL.html и устанавливаем его. При установке в диалоге “Select Additional Tasks” следует выбрать “The OpenSSL” binaries (/bin) directory”

Обратите внимание, что скачанная сборка требует для работы установленного Visual C++ 2008 Redistributables, который так же следует скачать с этой страницы и установить.

Затем скачиваем архив с engine pkcs11_gost https://www.rutoken.ru/download/softwar … -4.2.0.zip. Этот архив содержит:

  • библиотеку pkcs11_gost.dll – “плагин” к OpenSSL

  • библиотеку libp11.dll – “надстройку” над библиотекой PKCS#11, через которую осуществляется работа с Рутокен ЭЦП

  • библиотеку libltdl3.dll

  • конфигурационный файл openssl.cfg

Копируем эти файлы в папку установки OpenSSL/bin.
При этом в папке установки уже имеется конфигурационный файл openssl.cfg, его следует заменить.

Для того, чтобы утилита openssl.exe работала с нашим конфигурационным файлом его следует явно указать. Самый надежный способ это сделать – прописать в переменные окружения OPENSSL_CONF=[полный путь к openssl.cfg].  Либо непосредственно в командной строке, в которой будет использоваться openssl.exe сказать SET OPENSSL_CONF=[полный путь к openssl.cfg].
Затем следует установить драйвера Рутокен для win32, которые можно скачать на  странице https://www.rutoken.ru/hotline/download/drivers/.

Не забудьте подключить Рутокен ЭЦП и отформатировать его через Панель управления->Панель управления Рутокен.
Теперь подготовительная работа закончена, приступим к выполнению криптоопераций. Перейдем в папку установки OpenSSL/bin

  • для начала аппаратно сгенерируем ключ подписи/обмена ГОСТ Р 34.10-2001 “внутри”  Рутокен ЭЦП:

    openssl genpkey -engine pkcs11_gost -algorithm GOST2001 -pkeyopt slot_key_id:50 -pkeyopt paramset:A -pkeyopt pin:12345678

    • slot_key_id – номер слота: id ключа (например, 0:50). Если слот не указан, то автоматически используется первый найденный подключенный Рутокен ЭЦП

    • paramset – параметры ключа ГОСТ Р 34.10-2001 согласно RFC 4357. Поддерживаются следующие наборы параметров:

      • A - набор параметров с OID 1.2.643.2.2.35.1

      • B - набор параметров с OID 1.2.643.2.2.35.2

      • C  - набор параметров с OID 1.2.643.2.2.35.3

      • XA - набор параметров с OID 1.2.643.2.2.36.0

      • XB - набор параметров с OID 1.2.643.2.2.36.1

    • pin – PIN-код Рутокен ЭЦП

    Команда генерации ключа в результате работы выдаст сообщение “Error writing key”. Это происходит потому, что ключ генерируется аппаратно “внутри”  токена и никогда не экспортируется наружу и openssl.exe не может сохранить его в файл.

  • создадим заявку на сертификат в формате PKCS#10 для  созданного ключа:


    openssl req -engine pkcs11_gost -new -key 50 -keyform engine -out req.csr


    В процессе работы команда попросит ввести PIN-код. После этого потребуется указать
    State or Province []: Moscow
    Locality []:  RU
    Organization Name []: Aktiv Company
    Organizational Unit Name []: development
    Common Name []: tester
    Email []: tester@rutoken.ru

    Набор вводимой информации при формировании заявки определяется в конфигурационным файлом openssl.cfg. Заявка будет сохранена в файл req.csr.

  • создадим самоподписанный корневой сертификат, для того чтобы выдать пользовательский сертификат на заявку, полученную на 2 шаге. Для начала сгенерируем внутри токена ключ УЦ:


    openssl genpkey -engine pkcs11_gost -algorithm GOST2001 -pkeyopt slot_key_id:100 -pkeyopt paramset:A -pkeyopt pin:12345678


    затем сами себе выдадим корневой  сертификат для этого ключа


    openssl req -engine pkcs11_gost -x509 -new -key 100 -keyform engine -out ca.crt


    В процессе работы команды потребуется ввести PIN-код, а затем указать информацию, которая будет занесена в сертификат:


    State or Province []: Moscow
    Locality []:  RU
    Organization Name []: Aktiv Company
    Organizational Unit Name []: administration
    Common Name []: ca
    Email []: ca@rutoken.ru


    Корневой сертификат будет сохранен в файл ca.crt.

  • выпустим сертификат по заявке, полученной на шаге 2. Для этого в папке  установки OpenSSL/bin создадим папку demoCA, в которой создадим папку newcerts. В папке demoCA создадим пустой файл index.txt и файл serial, в котором напишем 01. Это позволит нам вести учет выданных сертификатов. Команда выдачи сертификата:


    openssl ca -engine pkcs11_gost -keyfile 100 -keyform engine -cert ca.crt -in req.csr -out tester.crt


    На вопросы следует отвечать “yes”.

  • подпись произвольного файла “присоединенной” подписью в формате S/MIME:


    openssl smime -engine pkcs11_gost -sign -in [имя файла] -out [подписанный файл] -nodetach -binary -signer tester.crt -inkey 50 -keyform engine


    в формате PKCS#7:


    openssl smime -engine pkcs11_gost -sign -in [имя файла] -out [подписанный файл] -nodetach -binary -signer tester.crt -inkey 50 -keyform engine -outform PEM


    в формате CMS:


    openssl cms -engine pkcs11_gost -sign -in [имя файла] -out [подписанный файл] -nodetach -binary -signer tester.crt -inkey 50 -keyform engine -outform PEM

    Для того, чтобы подписать файл “отсоединенной” подписью уберите ключ -nodetach.

  • проверка “присоединенной” подписи S/MIME


    openssl smime -engine pkcs11_gost -verify -in [подписанный файл] -inform SMIME -CAfile ca.crt -out [файл, в который будет сохранено содержимое]


    проверка “присоединенной ” подписи PKCS#7


    openssl smime -engine pkcs11_gost -verify -in [подписанный файл] -inform PEM -CAfile ca.crt -out [файл, в который будет сохранено содержимое]


    проверка “присоединенной ” подписи CMS


    openssl cms -engine pkcs11_gost -verify -in [подписанный файл] -inform PEM -CAfile ca.crt -out [файл, в который будет сохранено содержимое]


Re: Поддержка Рутокен ЭЦП в OpenSSL

Установка, конфигурирование и использование OpenSSL для работы с  Рутокен ЭЦП на платформе Linux x86

ВАЖНО:  поддерживается OpenSSL, начиная с версии 1.0.0

Приводятся инструкции для Ubuntu 11.10, для других видов Linux делается по аналогии.

Установим OpenSSL:

sudo aptitude install openssl

Проверим версию OpenSSL:

openssl version.

У меня команда выдала OpenSSL 1.0.0e 6 Sep 2011.

Затем установим системное программное обеспечение, необходимое для работы Рутокен ЭЦП:

  • CCID-драйвер

    sudo aptitude install libccid

  • PCSC
    sudo aptitude install libpcsclite1 pcscd

Запускаем pcscd

sudo pcscd

Установим libtool:

sudo aptitude install libtool


Затем следует скачать архив с плагином к OpenSSL.

Для x86 по ссылке https://www.rutoken.ru/download/softwar … -2-x86.zip.
Для x64 по ссылке http://ubuntuone.com/2vPRtZZA1jSHRilHa292xd.

Архив содержит файлы:

  • libpkcs11_gost.so - engine OpenSSL, которая обеспечивает работу с Рутокен ЭЦП по российским криптоалгоритмам

  • librtpkcs11ecp.so - библиотека PKCS#11 для Рутокен ЭЦП

  • libp11.so.2 - "надстройка" над библиотекой PKCS#11

  • openssl.cnf - конфигурационный файл OpenSSL

Конфигурационный файл следует положить в  /etc/ssl, имеющийся там файл следует переписать.

В конфигурационном файле имеется секция

[pkcs11_section]
engine_id = pkcs11_gost
dynamic_path = /usr/lib/pkcs11-gost/libpkcs11_gost.so
MODULE_PATH = /usr/lib/pkcs11-gost/librtpkcs11ecp.so
init = 0

Библиотеку libpkcs11_gost.so следует положить согласно конфигурационному файлу в папку  /usr/lib/pkcs11-gost/.
Librtpkcs11ecp.so следует положить согласно конфигурационному файлу, в папку  /usr/lib/pkcs11-gost/, а библиотеку libp11.so.2 положить в папку /usr/lib.

После этого можно использовать openssl так же, как в посте для win32.

Re: Поддержка Рутокен ЭЦП в OpenSSL

Программный пример создания заявки на сертификат в формате PKCS#10 , реализованный на OpenSSL. Генерация ключа ГОСТ Р 34.10-2001 и подпись заявки происходят "на борту" Рутокен ЭЦП

Для сборки примера под платформу Win32 с помощью cl.exe требуются заголовочные файлы OpenSSL и статическая библиотека libeay32.lib. Полный комплект OpenSSL для win32 с нужными либами и заголовочными файлами можно скачать по ссылке http://www.slproweb.com/download/Win32O … 1_0_0e.exe.

Приложение следует собирать с опцией /MT.

Для работы собранного приложения в environment следует добавить переменную окружения OPENSSL_ENGINES, в которой указать путь к папке, в которой располагаются библиотеки pkcs11_gost.dll и gost.dll. Кроме того, библиотеки libeay32.dll, libp11.dll  и libltdl3.dll должны находиться либо в текущей директории приложения, либо в директории, прописанной в переменной окружения PATH.

Приложение имеет параметры командной строки SLOT токена:ID ключа и PIN-код.

Пример запуска приложения:

request_pkcs10 100 12345678

Получить тестовый сертификат по созданной заявке можно, например, здесь http://www.cryptopro.ru/certsrv/certrqxt.asp. Для этого заявку следует сохранить в файл командой

request_pkcs10 101 12345678 > req.csr

а затем содержимое файла вставить в форму на сайте. ВНИМАНИЕ, ниже на форуме представлен пример записи сертификата на токен. Для его работы требуется сертификат в формате PEM. Поэтому рекомендуется при получении сертификата выбрать формат хранения Base64.


#include <windows.h>
#include <openssl/lhash.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/crypto.h> /* for CRYPTO_* and SSLeay_version */
#include <openssl/rand.h>
#include <openssl/md4.h>
#include <openssl/des.h>
#include <openssl/engine.h>
#include <openssl/pkcs12.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>


#define CMD_MODULE_PATH                 (ENGINE_CMD_BASE+1)
#define CMD_PIN                                   (ENGINE_CMD_BASE+2)
#define CMD_LOAD_CERT_CTRL            (ENGINE_CMD_BASE+5)
#define CMD_SAVE_CERT_CTRL             (ENGINE_CMD_BASE+6)

#define GOST2001_KEY_TYPE                 811

ENGINE* LoadEngine(const char* engine_name, const char* pkcs11_provider, const char* pin) 
{
    ENGINE* engine_pkcs11=NULL;

    engine_pkcs11=ENGINE_by_id(
        engine_name);
    if(!engine_pkcs11) 
        return NULL;    
    
    if(!ENGINE_ctrl(engine_pkcs11, CMD_MODULE_PATH, 0, 
            (void*)pkcs11_provider, NULL)) {
        ENGINE_free(engine_pkcs11);                
        return NULL;
    }

    if(pin) {
        if(!ENGINE_ctrl(engine_pkcs11, CMD_PIN, 0, 
                (void*)pin, NULL)) {
            ENGINE_free(engine_pkcs11);                    
            return NULL;
        }
    }

    if(!ENGINE_init(engine_pkcs11)) {
        ENGINE_free(engine_pkcs11);        
        return NULL;
    }    

    if(!ENGINE_set_default(engine_pkcs11, ENGINE_METHOD_ALL)) {
        ENGINE_free(engine_pkcs11);        
        return NULL;
    }

    return engine_pkcs11;
}

void UnloadEngine(ENGINE* engine_pkcs11) 
{
    ENGINE_finish(engine_pkcs11);
    ENGINE_free(engine_pkcs11);
}

/* создает объект расширения сертификата */ 
X509_EXTENSION* 
create_X509_extension
(
        char* name, 
        char *value
)
{
    X509_EXTENSION *ex;
    ex = X509V3_EXT_conf(NULL, NULL, name, value);
    if (!ex)
        return NULL;
    return ex;    
 }


X509_REQ* create_request(
    EVP_PKEY*    pKey,
    const char* common_name,        /* понятное имя субъекта */
    const char* org,                /* организация */
    const char* org_unit,            /* подразделение организации */
    const char* city,                /* город */
    const char* region,                /* регион */
    const char* country,            /* страна */
    const char* email,                /* почтовый адрес */
    const char* keyUsages,            /* способы использования ключа, через , */
    const char* extendedKeyUsages    /* расширенные способы использования ключа, через ; */    
)
{
    X509_REQ*    req            =    NULL;
    X509_NAME*    subject        =    NULL;    
    BOOL        bGoodEmail    =    TRUE;

    subject    = X509_NAME_new();    
    
    /* добавляем CN */
    if(common_name && strlen(common_name)>0) {    
        if(!X509_NAME_add_entry_by_NID(
                subject, NID_commonName, 
                MBSTRING_UTF8, (unsigned char*)common_name, 
                -1, -1, 0)) {
            X509_NAME_free(subject);
            return NULL;    
        }
    }

    /* добавляем название организации */
    if(org && strlen(org)>0) 
        if(!X509_NAME_add_entry_by_NID(
                subject, NID_organizationName, 
                MBSTRING_UTF8, (unsigned char*)org, 
                -1, -1, 0)) {
            X509_NAME_free(subject);
            return NULL;    
        }

    /* добавляем название подразделения */
    if(org_unit && strlen(org_unit)>0) 
        if(!X509_NAME_add_entry_by_NID(
                subject, NID_organizationalUnitName, 
                MBSTRING_UTF8, (unsigned char*)org_unit, 
                -1, -1, 0)) {
            X509_NAME_free(subject);
            return NULL;
        }

    /* добавляем locality */
    if(city && strlen(city)>0) 
        if(!X509_NAME_add_entry_by_NID(
                subject, NID_localityName, 
                MBSTRING_UTF8, (unsigned char*)city, 
                -1, -1, 0)) {
            X509_NAME_free(subject);
            return NULL;
        }
    

    if(region && strlen(region)>0) 
        if(!X509_NAME_add_entry_by_NID(
                subject, NID_stateOrProvinceName, 
                MBSTRING_UTF8, (unsigned char*)region, 
                -1, -1, 0)) {
            X509_NAME_free(subject);
            return NULL;
        }

    if(country && strlen(country)>0) 
        if(!X509_NAME_add_entry_by_NID(
                subject, NID_countryName, 
                MBSTRING_UTF8, (unsigned char*)country, 
                -1, -1, 0)) {
            X509_NAME_free(subject);
            return NULL;
        }

    if(email && strlen(email)>0) {
        for (int i=0; i<strlen(email); i++) 
            if (email[i]&0x80) {            
                bGoodEmail=FALSE;
                break;        
            }    
    
        if(bGoodEmail) {
            if(!X509_NAME_add_entry_by_NID(
                    subject, NID_pkcs9_emailAddress, 
                    MBSTRING_UTF8, (unsigned char*)email, 
                    -1, -1, 0)) {
                X509_NAME_free(subject);
                return NULL;
            }
        }
    }
            
    req=X509_REQ_new();
    if(!req) {
        X509_NAME_free(subject);
        return NULL;
    }
    
    /* установка версии */
    if(!X509_REQ_set_version(req, 0)) {
        X509_REQ_free(req);
        X509_NAME_free(subject);
        return NULL;
    }

    /* установка subject */    
    if(!X509_REQ_set_subject_name(req, subject)) {        
        X509_REQ_free(req);        
        X509_NAME_free(subject);                
        return NULL;
    }

    /* установка открытого ключа */
    if(!X509_REQ_set_pubkey(req, pKey)) {
        X509_REQ_free(req);
        X509_NAME_free(subject);
        return NULL;    
    }


    /* установка keyUsage */
    X509_EXTENSION* keyUsageExt = 
        create_X509_extension("keyUsage", (char*)keyUsages); 
    if(!keyUsageExt) {
        X509_REQ_free(req);
        X509_NAME_free(subject);
        return NULL;    
    }
        
    /* установка extendedkeyUsage */                                                   
    X509_EXTENSION* extendedKeyUsageExt = 
        create_X509_extension("extendedKeyUsage", (char*)extendedKeyUsages); 
    if(!extendedKeyUsageExt) {
        X509_EXTENSION_free(keyUsageExt);
        X509_REQ_free(req);
        X509_NAME_free(subject);
        return NULL;
    }

    STACK_OF(X509_EXTENSION)* extension_stack = 
        sk_X509_EXTENSION_new_null();
    if(!extension_stack) {
        X509_EXTENSION_free(extendedKeyUsageExt);
        X509_EXTENSION_free(keyUsageExt);
        X509_REQ_free(req);
        X509_NAME_free(subject);
        return NULL;
    }

    sk_X509_EXTENSION_push(extension_stack, keyUsageExt);
    sk_X509_EXTENSION_push(extension_stack, extendedKeyUsageExt);

    if(!X509_REQ_add_extensions(req, extension_stack)) {
        X509_EXTENSION_free(extendedKeyUsageExt);
        X509_EXTENSION_free(keyUsageExt);
        X509_REQ_free(req);
        X509_NAME_free(subject);
        return NULL;
    }

    /* подпись заявки закрытым ключом */
    if(!X509_REQ_sign(req, pKey, EVP_get_digestbyname("md_gost94"))) {
        X509_EXTENSION_free(extendedKeyUsageExt);
        X509_EXTENSION_free(keyUsageExt);
        X509_REQ_free(req);
        X509_NAME_free(subject);
        return NULL;
    }

    sk_X509_EXTENSION_pop_free
        (extension_stack,X509_EXTENSION_free);    
    X509_NAME_free(subject);
    
    return req;    
    
}


int main(int argc, char* argv[])
{
    BIO*            bio_req=NULL;
    BIO*            bio_key=NULL;
    X509_REQ*        pRequest=NULL;    
    BUF_MEM*        pbmReq;
    char*            cRequest=NULL;    
    UI_METHOD*        uim=NULL;
    int                reason=0;    
    EVP_PKEY*        key1=NULL;    
    EVP_PKEY*        newkey=NULL;
    EVP_PKEY_CTX*    ctx=NULL;    
    ENGINE*            engine_pkcs11=NULL;
        
    if(!argv[1] || !argv[2]) {
    fprintf(stderr, "Bad parameters!");
    return 1;
    }

    /* инициализируем OpenSSL */    
    ENGINE_load_builtin_engines();                    
    OPENSSL_add_all_algorithms_noconf();    

    /* загружаем engine, реализующую работу с 
        Рутокен ЭЦП через библиотеку PKCS#11 */
    engine_pkcs11=LoadEngine(
        "pkcs11_gost", 
        "rtPKCS11ECP.dll", 
        NULL);
    if(!engine_pkcs11)         
        return 1;    

    key1=EVP_PKEY_new();
    if(!key1) {
        UnloadEngine(engine_pkcs11);        
        return 1;
    }
        
    /* тип ключа ГОСТ Р 34.10-2001 */
    if(!EVP_PKEY_set_type(key1, GOST2001_KEY_TYPE)) {
        EVP_PKEY_free(key1);
        UnloadEngine(engine_pkcs11);        
        return 1;
    }

    ctx=EVP_PKEY_CTX_new(key1, NULL);    
    if(!ctx) {
        EVP_PKEY_free(key1);
        UnloadEngine(engine_pkcs11);            
        return 1;
    }

    if(!EVP_PKEY_keygen_init(ctx)) {        
        EVP_PKEY_CTX_free(ctx);
        UnloadEngine(engine_pkcs11);        
        return 1;
    }

    /* параметры ключа */
    if(!EVP_PKEY_CTX_ctrl_str(ctx, "paramset", "A")) {
        EVP_PKEY_CTX_free(ctx);
        UnloadEngine(engine_pkcs11);                
        return 1;
    }

    /* ID ключа */
    if(!EVP_PKEY_CTX_ctrl_str(ctx, "slot_key_id", argv[1])) {        
        EVP_PKEY_CTX_free(ctx);
        UnloadEngine(engine_pkcs11);        
        return 1;
    }

    /* PIN-код токена */
    if(!EVP_PKEY_CTX_ctrl_str(ctx, "pin", argv[2])) {        
        EVP_PKEY_CTX_free(ctx);
        UnloadEngine(engine_pkcs11);        
        return 1;
    }        

    /* генерация ключа */
    if(!EVP_PKEY_keygen(ctx,&newkey)) {
        EVP_PKEY_CTX_free(ctx);
        UnloadEngine(engine_pkcs11);        
        return 1;
    }    

    /* создание запроса на сертификат */
    pRequest=create_request(
        newkey, 
        "tester", 
        "rutoken",
        "development", 
        "Moscow", 
        "Moscow", 
        "ru", 
        "tester@rutoken.ru",     
        "digitalSignature,keyEncipherment", 
        "clientAuth,emailProtection");
    
    if(!pRequest) {        
        EVP_PKEY_free(newkey);
        EVP_PKEY_CTX_free(ctx);            
        UnloadEngine(engine_pkcs11);        
        return 1;
    }

    bio_req=BIO_new(BIO_s_mem());
    if(!bio_req) {        
        X509_REQ_free(pRequest);
        EVP_PKEY_free(newkey);
        EVP_PKEY_CTX_free(ctx);            
        UnloadEngine(engine_pkcs11);        
        return 1;
    }

    if(!PEM_write_bio_X509_REQ(bio_req, pRequest)) {        
        BIO_free(bio_req);
        X509_REQ_free(pRequest);        
        EVP_PKEY_free(newkey);
        EVP_PKEY_CTX_free(ctx);            
        UnloadEngine(engine_pkcs11);        
        return 1;
    }
    
    BIO_get_mem_ptr(bio_req, &pbmReq);    
    if(!pbmReq) {        
        BIO_free(bio_req);
        X509_REQ_free(pRequest);        
        EVP_PKEY_free(newkey);
        EVP_PKEY_CTX_free(ctx);            
        UnloadEngine(engine_pkcs11);        
        return 1;
    }
    pbmReq->data[pbmReq->length]='\0';

    fprintf(stdout, "%s", pbmReq->data);    
    
    BIO_free(bio_req);
    bio_req=NULL;
    
        
    X509_REQ_free(pRequest);    
    EVP_PKEY_free(newkey);
    EVP_PKEY_CTX_free(ctx);            

    UnloadEngine(engine_pkcs11);
        
    return 0;
}

Re: Поддержка Рутокен ЭЦП в OpenSSL

Программный пример записи сертификата на Рутокен ЭЦП.

Приложение имеет два параметра командной строки: полный путь к файлу сертификата, слот токена:id сертификата. Сертификат считывается из файла, в котором он хранится в формате PEM, и записывается на токен в формате DER.

#include <windows.h>
#include <openssl/lhash.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/crypto.h> /* for CRYPTO_* and SSLeay_version */
#include <openssl/rand.h>
#include <openssl/md4.h>
#include <openssl/des.h>
#include <openssl/engine.h>
#include <openssl/pkcs12.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>


#define CMD_MODULE_PATH                 (ENGINE_CMD_BASE+1)
#define CMD_PIN                         (ENGINE_CMD_BASE+2)
#define CMD_LOAD_CERT_CTRL                (ENGINE_CMD_BASE+5)
#define    CMD_SAVE_CERT_CTRL                (ENGINE_CMD_BASE+6)

/* структура для взаимодействия с engine_pkcs11 */
typedef struct _CERT_PKCS11_INFO {
    const char*    s_slot_cert_id;
    X509*        cert;
    const char*    label;
} CERT_PKCS11_INFO;

ENGINE* LoadEngine(const char* engine_name, const char* pkcs11_provider, const char* pin) 
{
    ENGINE* engine_pkcs11=NULL;

    engine_pkcs11=ENGINE_by_id(
        engine_name);
    if(!engine_pkcs11) 
        return NULL;    
    
    if(!ENGINE_ctrl(engine_pkcs11, CMD_MODULE_PATH, 0, 
            (void*)pkcs11_provider, NULL)) {
        ENGINE_free(engine_pkcs11);                
        return NULL;
    }

    if(pin) {
        if(!ENGINE_ctrl(engine_pkcs11, CMD_PIN, 0, 
                (void*)pin, NULL)) {
            ENGINE_free(engine_pkcs11);                    
            return NULL;
        }
    }

    if(!ENGINE_init(engine_pkcs11)) {
        ENGINE_free(engine_pkcs11);        
        return NULL;
    }    

    if(!ENGINE_set_default(engine_pkcs11, ENGINE_METHOD_ALL)) {
        ENGINE_free(engine_pkcs11);        
        return NULL;
    }

    return engine_pkcs11;
}

void UnloadEngine(ENGINE* engine_pkcs11) 
{
    ENGINE_finish(engine_pkcs11);
    ENGINE_free(engine_pkcs11);
}

/*
параметры:
    argv[1] - путь к файлу с сертификатом в формате PEM 
    argv[2] - SLOT:ID сертификата  
*/
int main(int argc, char* argv[])
{
    int                    len              =    0;
    X509*                x509          =    NULL;
    BIO*                bio_cert      =    NULL;    
    BIO*                bio_der          =    NULL;
    ENGINE*                engine_pkcs11 = NULL;
    CERT_PKCS11_INFO    cert_info;    
    
    if(!argv[1] || !argv[2]) {
        fprintf(stderr, "Bad parameters!");
        return 1;
    }
    
    /* инициализируем OpenSSL */    
    ENGINE_load_builtin_engines();                    
    OPENSSL_add_all_algorithms_noconf();    

    /* загружаем engine, реализующую работу с 
        Рутокен ЭЦП через библиотеку PKCS#11 */
    engine_pkcs11=LoadEngine(
        "pkcs11_gost", 
        "rtPKCS11ECP.dll", 
        NULL);
    if(!engine_pkcs11)         
        return 1;    

    bio_cert=BIO_new_file(argv[1], "rb");
    if(!bio_cert)             
        return 1;    
    
    x509=PEM_read_bio_X509(bio_cert, NULL, NULL, NULL);
    if(!x509) {
        BIO_free(bio_cert);            
        return 1;                
    }     

    cert_info.s_slot_cert_id=argv[2];
    cert_info.cert=x509;
    cert_info.label="My certificate";

    if(!ENGINE_ctrl(engine_pkcs11, CMD_SAVE_CERT_CTRL, 0, 
            (void*)&cert_info, NULL)) {
        fprintf(stderr, "error ENGINE_ctrl");
        ENGINE_free(engine_pkcs11);                
        return 1;
    }

    fprintf(stderr, "success");

    return 0;    
}

Re: Поддержка Рутокен ЭЦП в OpenSSL

Программный пример подписи данных "на борту" Рутокен ЭЦП в формате PKCS#7 по ГОСТ Р 34-10.2001 c помощью ключа и сертификата, хранящихся на токене

#include <windows.h>
#include <openssl/lhash.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/crypto.h> /* for CRYPTO_* and SSLeay_version */
#include <openssl/rand.h>
#include <openssl/md4.h>
#include <openssl/des.h>
#include <openssl/engine.h>
#include <openssl/pkcs12.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>


#define ENGINE_PKCS11_PIN_MESSAGE        "PKCS#11 token PIN"

#define CMD_MODULE_PATH                 (ENGINE_CMD_BASE+1)
#define CMD_PIN                         (ENGINE_CMD_BASE+2)
#define CMD_LOAD_CERT_CTRL                (ENGINE_CMD_BASE+5)
#define    CMD_SAVE_CERT_CTRL                (ENGINE_CMD_BASE+6)

/* структура для взаимодействия с engine_pkcs11 */
typedef struct _CERT_PKCS11_INFO {
    const char*    s_slot_cert_id;
    X509*        cert;
    const char*    label;
} CERT_PKCS11_INFO;

ENGINE* LoadEngine(const char* engine_name, const char* pkcs11_provider, const char* pin) 
{
    ENGINE* engine_pkcs11=NULL;

    engine_pkcs11=ENGINE_by_id(
        engine_name);
    if(!engine_pkcs11) 
        return NULL;    
    
    if(!ENGINE_ctrl(engine_pkcs11, CMD_MODULE_PATH, 0, 
            (void*)pkcs11_provider, NULL)) {
        ENGINE_free(engine_pkcs11);                
        return NULL;
    }

    if(pin) {
        if(!ENGINE_ctrl(engine_pkcs11, CMD_PIN, 0, 
                (void*)pin, NULL)) {
            ENGINE_free(engine_pkcs11);                    
            return NULL;
        }
    }

    if(!ENGINE_init(engine_pkcs11)) {
        ENGINE_free(engine_pkcs11);        
        return NULL;
    }    

    if(!ENGINE_set_default(engine_pkcs11, ENGINE_METHOD_ALL)) {
        ENGINE_free(engine_pkcs11);        
        return NULL;
    }

    return engine_pkcs11;
}

void UnloadEngine(ENGINE* engine_pkcs11) 
{
    ENGINE_finish(engine_pkcs11);
    ENGINE_free(engine_pkcs11);
}

int pin_cb(UI *ui, UI_STRING *uis) 
{
    char* pPin=NULL;
    char* pString=NULL;

    pString=(char*)UI_get0_output_string(uis);
    if(!pString) 
        return 0;

    if(!strncmp(pString, ENGINE_PKCS11_PIN_MESSAGE, 
        strlen(ENGINE_PKCS11_PIN_MESSAGE))) {    
        pPin=(char*)UI_get_app_data(ui);
        if(!pPin)         
            return 0;    

        UI_set_result(ui, uis, pPin);
        return 1;
    } else 
        return 0;
}

/*
параметры:
    argv[1] - SLOT:ID ключа 
    argv[2] - PIN-код токена  
    argv[3] - SLOT:ID сертификата
    argv[4]    - тип подписи (attached или detached)
*/
int main(int argc, char* argv[])
{
    BIO*                bio_cert        =    NULL;
    BIO*                in                =    NULL;
    BIO*                out                =    NULL;    
    BUF_MEM*            pbmOut            =    NULL;
    EVP_PKEY*            pKey            =    NULL;
    UI_METHOD*            uim                =    NULL;    
    PKCS7*                p7                =    NULL;
    char*                pSignature        =    NULL;
    int                    flags            =    0;
    int                    reason            =    0;
    ENGINE*                engine_pkcs11    =    NULL;
    unsigned char*        data            =    NULL;
    CERT_PKCS11_INFO    cert_info;    
    
    if(!argv[1] || !argv[2] ||
        !argv[3] || !argv[4]) {
        fprintf(stderr, "Bad parameters!");
        return 1;
    }
    
    /* инициализируем OpenSSL */    
    ENGINE_load_builtin_engines();                    
    OPENSSL_add_all_algorithms_noconf();    

    /* случайный буфер */
    data=(unsigned char*)OPENSSL_malloc(1000);

    /* загружаем engine, реализующую работу с 
        Рутокен ЭЦП через библиотеку PKCS#11 */
    engine_pkcs11=LoadEngine(
        "pkcs11_gost", 
        "rtPKCS11ECP.dll", 
        NULL);
    if(!engine_pkcs11)         
        return 1;    
                
    memset(&cert_info, 0, sizeof(cert_info));
            
    uim=UI_create_method("CryptoPacket");
    if(!uim) {
        UnloadEngine(engine_pkcs11);        
        return NULL;
    }
    
    UI_method_set_reader(uim, pin_cb);        

    /* считываем закрытый ключ */
    pKey=ENGINE_load_private_key(engine_pkcs11, argv[1], uim, (void*)argv[2]);
    if(!pKey) {        
        UnloadEngine(engine_pkcs11);        
        return NULL;    
    }

    cert_info.s_slot_cert_id=argv[3];
    
    /* считывем сертификат */
    if(!ENGINE_ctrl(engine_pkcs11, CMD_LOAD_CERT_CTRL, 0, &cert_info, NULL)) {
        EVP_PKEY_free(pKey);
        UnloadEngine(engine_pkcs11);        
        return NULL;    
    }

    BIO_free(bio_cert);
        
    in=BIO_new_mem_buf((void*)data, 1000);    
    if(!in) {
        EVP_PKEY_free(pKey);
        UnloadEngine(engine_pkcs11);        
        return NULL;    
    }
                    
    out=BIO_new(BIO_s_mem()); 
    if(!out) {    
        BIO_free(in);
        EVP_PKEY_free(pKey);        
        UnloadEngine(engine_pkcs11);        
        return NULL;    
    }

    if(!strcmp(argv[4],"detached"))
        flags=PKCS7_DETACHED|PKCS7_BINARY;
    else
        flags=PKCS7_BINARY;

    /* подпись pkcs#7 */
    p7=PKCS7_sign(cert_info.cert, pKey, NULL, in, flags);    
    if(!p7) {                
        BIO_free(out);    
        BIO_free(in);
        EVP_PKEY_free(pKey);            
        UnloadEngine(engine_pkcs11);        
        return NULL;
    }

    if(!PEM_write_bio_PKCS7(out, p7)) {    
        PKCS7_free(p7);        
        BIO_free(out);        
        BIO_free(in);
        EVP_PKEY_free(pKey);        
        UnloadEngine(engine_pkcs11);        
        return NULL;        
    }
    
    BIO_get_mem_ptr(out, &pbmOut);    
    if(!pbmOut) {        
        PKCS7_free(p7);
        BIO_free(out);        
        BIO_free(in);
        EVP_PKEY_free(pKey);        
        UnloadEngine(engine_pkcs11);        
        return NULL;        
    }

    pbmOut->data[pbmOut->length]='\0';

    fprintf(stdout, "%s", pbmOut->data);
        
    CRYPTO_cleanup_all_ex_data();

    PKCS7_free(p7);    
    BIO_free(in);
    EVP_PKEY_free(pKey);                

    UnloadEngine(engine_pkcs11);

    return 0;
}

Re: Поддержка Рутокен ЭЦП в OpenSSL

Электронная подпись в браузере с помощью OpenSSL и Рутокен ЭЦП

http://habrahabr.ru/blogs/infosecurity/134890/

Re: Поддержка Рутокен ЭЦП в OpenSSL

Здравствуйте.

У меня возникли ошибки при работе с РуТокен+openssl+gost на Linux.  Этих
ошибок не возникло с тем же токеном на win32.

Привожу последовательность действий:



Токен отформатирован в WinXP с настройками по умолчанию,
кроме поля "Политика смены PIN-кода Пользователа", где
выбрана опция "Администратором".

Переходим к Ubuntu Linux 11.10

$ uname -a
Linux virt-ub1110 3.0.0-12-generic #20-Ubuntu SMP Fri Oct 7 14:50:42 UTC 2011 i686 i686 i386 GNU/Linux

Согласно инструкции установлены пакеты libccid, libpcsclite1, pcscd и libtool

$ dpkg --print-avail libccid libpcsclite1 pcscd libtool >/dev/null && echo OK
OK

и файлы из архива для pkcs11


$ ls -l /usr/lib/pkcs11-gost
total 2280
-rw-r--r-- 1 root root  190263 2012-02-02 11:54 libpkcs11_gost.so
-rw-r--r-- 1 root root 2138760 2012-02-02 11:54 librtpkcs11ecp.so

$ grep -A 5 '\[pkcs11_section' /etc/ssl/openssl.cnf
[pkcs11_section]
engine_id                 = pkcs11_gost
dynamic_path         = /usr/lib/pkcs11-gost/libpkcs11_gost.so
MODULE_PATH         = /usr/lib/pkcs11-gost/librtpkcs11ecp.so
init                     = 0

$ ls -l /usr/lib/libp11.so.2
-rw-r--r-- 1 root root 202646 2012-02-02 11:54 /usr/lib/libp11.so.2

В инструкции пропущено, запускаю pcscd.

$ sudo pcscd -df

... (приложен протокол)


Далее пытаюсь сгенерировать ключ

$ openssl genpkey -engine pkcs11_gost -algorithm GOST2001 -pkeyopt slot_key_id:50 -pkeyopt paramset:A -pkeyopt pin:12345678
engine "pkcs11_gost" set.
failed to enumerate slots
Error generating key
3078858904:error:80003030:Vendor defined:PKCS11_check_token:Device error:p11_slot.c:411:
3078858904:error:81091086:lib(129):PKCS11_FIND_LOGIN_TOKEN:fail enumenate slots:engine_pkcs11.c:451:


Протокол работы pcscd соответствует следующим событиям:

1. запуск pcscd
2. вставили токен
3. openssl genpkey...
4. вытащили токен
5. остановили pcscd

pcscdaemon.c:230:main() pcscd set to foreground with debug send to stderr
configfile.l:245:DBGetReaderListDir() Parsing conf directory: /etc/reader.conf.d
configfile.l:287:DBGetReaderList() Parsing conf file: /etc/reader.conf.d/libccidtwin
pcscdaemon.c:550:main() pcsc-lite 1.7.2 daemon ready.
hotplug_libudev.c:258:get_driver() Looking for a driver for VID: 0x1D6B, PID: 0x0001, path: /dev/bus/usb/002/001
hotplug_libudev.c:258:get_driver() Looking for a driver for VID: 0x1D6B, PID: 0x0001, path: /dev/bus/usb/002/001
hotplug_libudev.c:258:get_driver() Looking for a driver for VID: 0x80EE, PID: 0x0021, path: /dev/bus/usb/002/002
hotplug_libudev.c:258:get_driver() Looking for a driver for VID: 0x1D6B, PID: 0x0002, path: /dev/bus/usb/001/001
hotplug_libudev.c:258:get_driver() Looking for a driver for VID: 0x0A89, PID: 0x0030, path: /dev/bus/usb/002/010
hotplug_libudev.c:309:HPAddDevice() Adding USB device: Aktiv Rutoken ECP
readerfactory.c:934:RFInitializeReader() Attempting startup of Aktiv Rutoken ECP 00 00 using /usr/lib/pcsc/drivers/ifd-ccid.bundle/Contents/Linux/libccid.so
readerfactory.c:824:RFBindFunctions() Loading IFD Handler 3.0
ifdhandler.c:1750:init_driver() Driver version: 1.4.4
ifdhandler.c:1767:init_driver() LogLevel: 0x0003
ifdhandler.c:1778:init_driver() DriverOptions: 0x0000
ifdhandler.c:79:IFDHCreateChannelByName() lun: 0, device: usb:0a89/0030:libudev:0:/dev/bus/usb/002/010
ccid_usb.c:245:OpenUSBByName() ifdManufacturerString: Ludovic Rousseau (ludovic.rousseau@free.fr)
ccid_usb.c:246:OpenUSBByName() ifdProductString: Generic CCID driver
ccid_usb.c:247:OpenUSBByName() Copyright: This driver is protected by terms of the GNU Lesser General Public License version 2.1, or (at your option) any later version.
ccid_usb.c:504:OpenUSBByName() Found Vendor/Product: 0A89/0030 (Aktiv Rutoken ECP)
ccid_usb.c:506:OpenUSBByName() Using USB bus/device: 2/10
ccid_usb.c:936:get_data_rates() IFD does not support GET_DATA_RATES request: -9
ifdhandler.c:401:IFDHGetCapabilities() tag: 0xFB3, usb:0a89/0030:libudev:0:/dev/bus/usb/002/010 (lun: 0)
readerfactory.c:290:RFAddReader() Using the pcscd polling thread
ifdhandler.c:401:IFDHGetCapabilities() tag: 0xFAE, usb:0a89/0030:libudev:0:/dev/bus/usb/002/010 (lun: 0)
ifdhandler.c:489:IFDHGetCapabilities() Reader supports 1 slot(s)
ifdhandler.c:1151:IFDHPowerICC() action: PowerUp, usb:0a89/0030:libudev:0:/dev/bus/usb/002/010 (lun: 0)
eventhandler.c:256:EHStatusHandlerThread() powerState: POWER_STATE_POWERED
Card ATR: 3B 8B 01 52 75 74 6F 6B 65 6E 20 44 53 20 C1 
ifdhandler.c:1151:IFDHPowerICC() action: PowerDown, usb:0a89/0030:libudev:0:/dev/bus/usb/002/010 (lun: 0)
eventhandler.c:446:EHStatusHandlerThread() powerState: POWER_STATE_UNPOWERED
winscard_msg_srv.c:202:ProcessEventsServer() Common channel packet arrival
winscard_msg_srv.c:214:ProcessEventsServer() ProcessCommonChannelRequest detects: 10
pcscdaemon.c:91:SVCServiceRunLoop() A new context thread creation is requested: 10
winscard_svc.c:297:ContextThread() Thread is started: dwClientID=10, threadContext @9605EB8
winscard_svc.c:315:ContextThread() Received command: CMD_VERSION from client 10
winscard_svc.c:327:ContextThread() Client is protocol version 4:2
winscard_svc.c:347:ContextThread() CMD_VERSION rv=0x0 for client 10
winscard_svc.c:315:ContextThread() Received command: ESTABLISH_CONTEXT from client 10
winscard.c:193:SCardEstablishContext() Establishing Context: 0x1033BF2
winscard_svc.c:406:ContextThread() ESTABLISH_CONTEXT rv=0x0 for client 10
winscard_svc.c:315:ContextThread() Received command: CMD_GET_READERS_STATE from client 10
winscard_svc.c:315:ContextThread() Received command: CMD_GET_READERS_STATE from client 10
winscard_svc.c:315:ContextThread() Received command: CMD_GET_READERS_STATE from client 10
winscard_svc.c:315:ContextThread() Received command: CMD_GET_READERS_STATE from client 10
winscard_svc.c:315:ContextThread() Received command: CONNECT from client 10
winscard.c:235:SCardConnect() Attempting Connect to Aktiv Rutoken ECP 00 00 using protocol: 3
ifdhandler.c:1151:IFDHPowerICC() action: PowerUp, usb:0a89/0030:libudev:0:/dev/bus/usb/002/010 (lun: 0)
winscard.c:309:SCardConnect() power up complete.
Card ATR: 3B 8B 01 52 75 74 6F 6B 65 6E 20 44 53 20 C1 
winscard.c:328:SCardConnect() powerState: POWER_STATE_INUSE
prothandler.c:127:PHSetProtocol() Attempting PTS to T=1
ifdhandler.c:700:IFDHSetProtocolParameters() protocol T=1, usb:0a89/0030:libudev:0:/dev/bus/usb/002/010 (lun: 0)
winscard.c:406:SCardConnect() Active Protocol: T=1
winscard.c:426:SCardConnect() hCard Identity: 15ec1
winscard_svc.c:447:ContextThread() CONNECT rv=0x0 for client 10
winscard_svc.c:315:ContextThread() Received command: BEGIN_TRANSACTION from client 10
winscard.c:1057:SCardBeginTransaction() Status: 0x00000000
winscard_svc.c:499:ContextThread() BEGIN_TRANSACTION rv=0x0 for client 10
winscard_svc.c:315:ContextThread() Received command: CMD_GET_READERS_STATE from client 10
winscard_svc.c:315:ContextThread() Received command: STATUS from client 10
winscard_svc.c:555:ContextThread() STATUS rv=0x0 for client 10
winscard_svc.c:315:ContextThread() Received command: GET_ATTRIB from client 10
ifdhandler.c:401:IFDHGetCapabilities() tag: 0x90303, usb:0a89/0030:libudev:0:/dev/bus/usb/002/010 (lun: 0)
winscard_svc.c:675:ContextThread() GET_ATTRIB rv=0x0 for client 10
winscard_svc.c:315:ContextThread() Received command: END_TRANSACTION from client 10
winscard.c:1194:SCardEndTransaction() Status: 0x00000000
winscard_svc.c:515:ContextThread() END_TRANSACTION rv=0x0 for client 10
winscard_svc.c:315:ContextThread() Received command: DISCONNECT from client 10
winscard.c:826:SCardDisconnect() Active Contexts: 1
winscard.c:827:SCardDisconnect() dwDisposition: 0
winscard.c:992:SCardDisconnect() powerState: POWER_STATE_GRACE_PERIOD
ifdhandler.c:401:IFDHGetCapabilities() tag: 0xFB2, usb:0a89/0030:libudev:0:/dev/bus/usb/002/010 (lun: 0)
winscard_svc.c:484:ContextThread() DISCONNECT rv=0x0 for client 10
winscard_svc.c:315:ContextThread() Received command: CMD_GET_READERS_STATE from client 10
winscard_svc.c:315:ContextThread() Received command: CMD_GET_READERS_STATE from client 10
winscard_svc.c:315:ContextThread() Received command: CONNECT from client 10
winscard.c:235:SCardConnect() Attempting Connect to Aktiv Rutoken ECP 00 00 using protocol: 3
winscard.c:328:SCardConnect() powerState: POWER_STATE_INUSE
winscard.c:406:SCardConnect() Active Protocol: T=1
winscard.c:426:SCardConnect() hCard Identity: 1da05
winscard_svc.c:447:ContextThread() CONNECT rv=0x0 for client 10
winscard_svc.c:315:ContextThread() Received command: BEGIN_TRANSACTION from client 10
winscard.c:1057:SCardBeginTransaction() Status: 0x00000000
winscard_svc.c:499:ContextThread() BEGIN_TRANSACTION rv=0x0 for client 10
winscard_svc.c:315:ContextThread() Received command: CMD_GET_READERS_STATE from client 10
winscard_svc.c:315:ContextThread() Received command: STATUS from client 10
winscard_svc.c:555:ContextThread() STATUS rv=0x0 for client 10
winscard_svc.c:315:ContextThread() Received command: END_TRANSACTION from client 10
winscard.c:1194:SCardEndTransaction() Status: 0x00000000
winscard_svc.c:515:ContextThread() END_TRANSACTION rv=0x0 for client 10
winscard_svc.c:315:ContextThread() Received command: DISCONNECT from client 10
winscard.c:826:SCardDisconnect() Active Contexts: 1
winscard.c:827:SCardDisconnect() dwDisposition: 0
winscard.c:992:SCardDisconnect() powerState: POWER_STATE_GRACE_PERIOD
ifdhandler.c:401:IFDHGetCapabilities() tag: 0xFB2, usb:0a89/0030:libudev:0:/dev/bus/usb/002/010 (lun: 0)
winscard_svc.c:484:ContextThread() DISCONNECT rv=0x0 for client 10
winscard_svc.c:315:ContextThread() Received command: CMD_GET_READERS_STATE from client 10
winscard_svc.c:315:ContextThread() Received command: CMD_GET_READERS_STATE from client 10
winscard_svc.c:315:ContextThread() Received command: CONNECT from client 10
winscard.c:235:SCardConnect() Attempting Connect to Aktiv Rutoken ECP 00 00 using protocol: 3
winscard.c:328:SCardConnect() powerState: POWER_STATE_INUSE
winscard.c:406:SCardConnect() Active Protocol: T=1
winscard.c:426:SCardConnect() hCard Identity: 1e8a2
winscard_svc.c:447:ContextThread() CONNECT rv=0x0 for client 10
winscard_svc.c:315:ContextThread() Received command: CMD_GET_READERS_STATE from client 10
winscard_svc.c:315:ContextThread() Received command: CMD_GET_READERS_STATE from client 10
winscard_svc.c:315:ContextThread() Received command: CMD_GET_READERS_STATE from client 10
winscard_svc.c:315:ContextThread() Received command: CMD_GET_READERS_STATE from client 10
winscard_svc.c:315:ContextThread() Received command: CONNECT from client 10
winscard.c:235:SCardConnect() Attempting Connect to  using protocol: 3
winscard.c:241:SCardConnect() Reader  Not Found
winscard_svc.c:447:ContextThread() CONNECT rv=0x80100009 for client 10
winscard_svc.c:315:ContextThread() Received command: CMD_GET_READERS_STATE from client 10
winscard_svc.c:315:ContextThread() Received command: CMD_GET_READERS_STATE from client 10
winscard_svc.c:315:ContextThread() Received command: CMD_GET_READERS_STATE from client 10
winscard_svc.c:315:ContextThread() Received command: CMD_GET_READERS_STATE from client 10
winscard_svc.c:315:ContextThread() Received command: CONNECT from client 10
winscard.c:235:SCardConnect() Attempting Connect to  using protocol: 3
winscard.c:241:SCardConnect() Reader  Not Found
winscard_svc.c:447:ContextThread() CONNECT rv=0x80100009 for client 10
winscard_svc.c:315:ContextThread() Received command: CMD_GET_READERS_STATE from client 10
winscard_svc.c:315:ContextThread() Received command: CMD_GET_READERS_STATE from client 10
winscard_svc.c:315:ContextThread() Received command: CMD_GET_READERS_STATE from client 10
winscard_svc.c:315:ContextThread() Received command: CMD_GET_READERS_STATE from client 10
winscard_svc.c:315:ContextThread() Received command: CONNECT from client 10
winscard.c:235:SCardConnect() Attempting Connect to  using protocol: 3
winscard.c:241:SCardConnect() Reader  Not Found
winscard_svc.c:447:ContextThread() CONNECT rv=0x80100009 for client 10
winscard_svc.c:315:ContextThread() Received command: CMD_GET_READERS_STATE from client 10
winscard_svc.c:315:ContextThread() Received command: CMD_GET_READERS_STATE from client 10
winscard_svc.c:315:ContextThread() Received command: CMD_GET_READERS_STATE from client 10
winscard_svc.c:315:ContextThread() Received command: CMD_GET_READERS_STATE from client 10
winscard_svc.c:315:ContextThread() Received command: CONNECT from client 10
winscard.c:235:SCardConnect() Attempting Connect to  using protocol: 3
winscard.c:241:SCardConnect() Reader  Not Found
winscard_svc.c:447:ContextThread() CONNECT rv=0x80100009 for client 10
winscard_svc.c:315:ContextThread() Received command: CMD_GET_READERS_STATE from client 10
winscard_svc.c:315:ContextThread() Received command: CMD_GET_READERS_STATE from client 10
winscard_svc.c:315:ContextThread() Received command: CMD_GET_READERS_STATE from client 10
winscard_svc.c:315:ContextThread() Received command: CMD_GET_READERS_STATE from client 10
winscard_svc.c:315:ContextThread() Received command: CONNECT from client 10
winscard.c:235:SCardConnect() Attempting Connect to Aktiv Rutoken ECP 00 00 using protocol: 3
winscard.c:328:SCardConnect() powerState: POWER_STATE_INUSE
winscard.c:406:SCardConnect() Active Protocol: T=1
winscard.c:426:SCardConnect() hCard Identity: 17bde
winscard_svc.c:447:ContextThread() CONNECT rv=0x0 for client 10
winscard_svc.c:315:ContextThread() Received command: BEGIN_TRANSACTION from client 10
winscard.c:1057:SCardBeginTransaction() Status: 0x00000000
winscard_svc.c:499:ContextThread() BEGIN_TRANSACTION rv=0x0 for client 10
winscard_svc.c:315:ContextThread() Received command: CMD_GET_READERS_STATE from client 10
winscard_svc.c:315:ContextThread() Received command: STATUS from client 10
winscard_svc.c:555:ContextThread() STATUS rv=0x0 for client 10
winscard_svc.c:315:ContextThread() Received command: GET_ATTRIB from client 10
ifdhandler.c:401:IFDHGetCapabilities() tag: 0x90303, usb:0a89/0030:libudev:0:/dev/bus/usb/002/010 (lun: 0)
winscard_svc.c:675:ContextThread() GET_ATTRIB rv=0x0 for client 10
winscard_svc.c:315:ContextThread() Received command: END_TRANSACTION from client 10
winscard.c:1194:SCardEndTransaction() Status: 0x00000000
winscard_svc.c:515:ContextThread() END_TRANSACTION rv=0x0 for client 10
winscard_svc.c:315:ContextThread() Received command: DISCONNECT from client 10
winscard.c:826:SCardDisconnect() Active Contexts: 2
winscard.c:827:SCardDisconnect() dwDisposition: 0
winscard_svc.c:484:ContextThread() DISCONNECT rv=0x0 for client 10
winscard_svc.c:315:ContextThread() Received command: CMD_GET_READERS_STATE from client 10
winscard_svc.c:315:ContextThread() Received command: CMD_GET_READERS_STATE from client 10
winscard_svc.c:315:ContextThread() Received command: CONNECT from client 10
winscard.c:235:SCardConnect() Attempting Connect to Aktiv Rutoken ECP 00 00 using protocol: 3
winscard.c:328:SCardConnect() powerState: POWER_STATE_INUSE
winscard.c:406:SCardConnect() Active Protocol: T=1
winscard.c:426:SCardConnect() hCard Identity: 1721b
winscard_svc.c:447:ContextThread() CONNECT rv=0x0 for client 10
winscard_svc.c:315:ContextThread() Received command: BEGIN_TRANSACTION from client 10
winscard.c:1057:SCardBeginTransaction() Status: 0x00000000
winscard_svc.c:499:ContextThread() BEGIN_TRANSACTION rv=0x0 for client 10
winscard_svc.c:315:ContextThread() Received command: CMD_GET_READERS_STATE from client 10
winscard_svc.c:315:ContextThread() Received command: STATUS from client 10
winscard_svc.c:555:ContextThread() STATUS rv=0x0 for client 10
winscard_svc.c:315:ContextThread() Received command: GET_ATTRIB from client 10
ifdhandler.c:401:IFDHGetCapabilities() tag: 0x90303, usb:0a89/0030:libudev:0:/dev/bus/usb/002/010 (lun: 0)
winscard_svc.c:675:ContextThread() GET_ATTRIB rv=0x0 for client 10
winscard_svc.c:315:ContextThread() Received command: END_TRANSACTION from client 10
winscard.c:1194:SCardEndTransaction() Status: 0x00000000
winscard_svc.c:515:ContextThread() END_TRANSACTION rv=0x0 for client 10
winscard_svc.c:315:ContextThread() Received command: DISCONNECT from client 10
winscard.c:826:SCardDisconnect() Active Contexts: 2
winscard.c:827:SCardDisconnect() dwDisposition: 0
winscard_svc.c:484:ContextThread() DISCONNECT rv=0x0 for client 10
winscard_svc.c:315:ContextThread() Received command: CMD_GET_READERS_STATE from client 10
winscard_svc.c:315:ContextThread() Received command: CMD_GET_READERS_STATE from client 10
winscard_svc.c:315:ContextThread() Received command: CONNECT from client 10
winscard.c:235:SCardConnect() Attempting Connect to Aktiv Rutoken ECP 00 00 using protocol: 3
winscard.c:328:SCardConnect() powerState: POWER_STATE_INUSE
winscard.c:406:SCardConnect() Active Protocol: T=1
winscard.c:426:SCardConnect() hCard Identity: 1d64d
winscard_svc.c:447:ContextThread() CONNECT rv=0x0 for client 10
winscard_svc.c:315:ContextThread() Received command: BEGIN_TRANSACTION from client 10
winscard.c:1057:SCardBeginTransaction() Status: 0x00000000
winscard_svc.c:499:ContextThread() BEGIN_TRANSACTION rv=0x0 for client 10
winscard_svc.c:315:ContextThread() Received command: CMD_GET_READERS_STATE from client 10
winscard_svc.c:315:ContextThread() Received command: STATUS from client 10
winscard_svc.c:555:ContextThread() STATUS rv=0x0 for client 10
winscard_svc.c:315:ContextThread() Received command: TRANSMIT from client 10
winscard.c:1551:SCardTransmit() Send Protocol: T=1
ifdhandler.c:1280:IFDHTransmitToICC() usb:0a89/0030:libudev:0:/dev/bus/usb/002/010 (lun: 0)
ccid_usb.c:659:ReadUSB() read failed (2/10): -7 Success
ifdwrapper.c:525:IFDTransmit() Card not transacted: 612
winscard.c:1576:SCardTransmit() Card not transacted: 0x80100016
winscard_svc.c:602:ContextThread() TRANSMIT rv=0x80100016 for client 10
winscard_svc.c:315:ContextThread() Received command: TRANSMIT from client 10
winscard.c:1551:SCardTransmit() Send Protocol: T=1
ifdhandler.c:1280:IFDHTransmitToICC() usb:0a89/0030:libudev:0:/dev/bus/usb/002/010 (lun: 0)
ccid_usb.c:659:ReadUSB() read failed (2/10): -7 Success
ifdwrapper.c:525:IFDTransmit() Card not transacted: 612
winscard.c:1576:SCardTransmit() Card not transacted: 0x80100016
winscard_svc.c:602:ContextThread() TRANSMIT rv=0x80100016 for client 10
winscard_svc.c:315:ContextThread() Received command: END_TRANSACTION from client 10
winscard.c:1194:SCardEndTransaction() Status: 0x00000000
winscard_svc.c:515:ContextThread() END_TRANSACTION rv=0x0 for client 10
winscard_svc.c:315:ContextThread() Received command: DISCONNECT from client 10
winscard.c:826:SCardDisconnect() Active Contexts: 2
winscard.c:827:SCardDisconnect() dwDisposition: 0
winscard_svc.c:484:ContextThread() DISCONNECT rv=0x0 for client 10
winscard_svc.c:315:ContextThread() Received command: RELEASE_CONTEXT from client 10
winscard.c:204:SCardReleaseContext() Releasing Context: 0x1033BF2
winscard.c:826:SCardDisconnect() Active Contexts: 1
winscard.c:827:SCardDisconnect() dwDisposition: 0
winscard.c:992:SCardDisconnect() powerState: POWER_STATE_GRACE_PERIOD
ifdhandler.c:401:IFDHGetCapabilities() tag: 0xFB2, usb:0a89/0030:libudev:0:/dev/bus/usb/002/010 (lun: 0)
winscard_svc.c:421:ContextThread() RELEASE_CONTEXT rv=0x0 for client 10
winscard_svc.c:307:ContextThread() Client die: 10
winscard_svc.c:916:MSGCleanupClient() Thread is stopping: dwClientID=10, threadContext @9605EB8
winscard_svc.c:922:MSGCleanupClient() Freeing SCONTEXT @9605EB8
eventhandler.c:458:EHStatusHandlerThread() powerState: POWER_STATE_POWERED
ifdhandler.c:1151:IFDHPowerICC() action: PowerDown, usb:0a89/0030:libudev:0:/dev/bus/usb/002/010 (lun: 0)
eventhandler.c:446:EHStatusHandlerThread() powerState: POWER_STATE_UNPOWERED
hotplug_libudev.c:565:HPEstablishUSBNotifications() Device removed
hotplug_libudev.c:258:get_driver() Looking for a driver for VID: 0x1D6B, PID: 0x0001, path: /dev/bus/usb/002/001
hotplug_libudev.c:258:get_driver() Looking for a driver for VID: 0x1D6B, PID: 0x0001, path: /dev/bus/usb/002/001
hotplug_libudev.c:258:get_driver() Looking for a driver for VID: 0x80EE, PID: 0x0021, path: /dev/bus/usb/002/002
hotplug_libudev.c:258:get_driver() Looking for a driver for VID: 0x1D6B, PID: 0x0002, path: /dev/bus/usb/001/001
hotplug_libudev.c:507:HPRescanUsbBus() Removing USB device[0]: /dev/bus/usb/002/010
eventhandler.c:148:EHDestroyEventHandler() Stomping thread.
ifdhandler.c:401:IFDHGetCapabilities() tag: 0xFB1, usb:0a89/0030:libudev:0:/dev/bus/usb/002/010 (lun: 0)
ifdhandler.c:401:IFDHGetCapabilities() tag: 0xFB2, usb:0a89/0030:libudev:0:/dev/bus/usb/002/010 (lun: 0)
eventhandler.c:177:EHDestroyEventHandler() Waiting polling thread
eventhandler.c:469:EHStatusHandlerThread() Die
eventhandler.c:188:EHDestroyEventHandler() Thread stomped.
readerfactory.c:985:RFUnInitializeReader() Attempting shutdown of Aktiv Rutoken ECP 00 00.
ifdhandler.c:293:IFDHCloseChannel() usb:0a89/0030:libudev:0:/dev/bus/usb/002/010 (lun: 0)
ccid_usb.c:620:WriteUSB() write failed (2/10): -4 No such device
readerfactory.c:861:RFUnloadReader() Unloading reader driver.

Re: Поддержка Рутокен ЭЦП в OpenSSL

Похоже на ошибку в libusb.
http://ludovicrousseau.blogspot.com/201 … ement.html

Re: Поддержка Рутокен ЭЦП в OpenSSL

Я наверное неправильно выразился насчет возникновения ошибок.  У меня ни разу корректно не отработала ни
одна openssl команда, из приведенных в инструкции для Linux.  Хотелось бы узнать как проверить
работоспособность токена и библиотеки на Linux: какие действия повторить (дистрибутив, пакеты... поставить) чтобы отработали команды, работающие на win32.

Re: Поддержка Рутокен ЭЦП в OpenSSL

Судя по логу, libusb то видит токен, то нет.

Объясняться это может багом в libusb (на который вам дали ссылку). Пакеты вы все нужные
поставили, но дело в том, что лаги USB-транспорта приводят к неправильной работе всей конструкции.

Попробуйте взять libusb с исправленной ошибкой (в более свежих branches).

Re: Поддержка Рутокен ЭЦП в OpenSSL

Добрый день.
А где я могу взять библиотеки для Linux x64?

Re: Поддержка Рутокен ЭЦП в OpenSSL

Да, спасибо, заработало после установки libusb-1.0-0_1.0.9~rc3-2_i386.deb.

Re: Поддержка Рутокен ЭЦП в OpenSSL

Иванов Алексей, в ближайшее время соберем и под x64.


roman, очень хорошо, что все завелось.

Re: Поддержка Рутокен ЭЦП в OpenSSL

Виктор Ткаченко пишет:

Иванов Алексей, в ближайшее время соберем и под x64.

Спасибо. Буду ждать.