Встраивание через Единую библиотеку PKCS #11

Единая библиотека PKCS #11 предоставляет высокоуровневый интерфейс (см. API Единой библиотеки PKCS #11) для взаимодействия с JaCarta-2 ГОСТ по стандарту PKCS #11 v2.30.

Установка Единой библиотеки PKCS #11

Microsoft Windows

Для Microsoft Windows Единая библиотека PKCS #11 не требует установки в систему и входит в состав JaCarta-2 SDK в виде динамической библиотеки:

  • SDK/lib/Win32/jcPKCS11-2.dll – библиотека под 32–битную архитектуру;
  • SDK/lib/Win64/jcPKCS11-2.dll – библиотека под 64–битную архитектуру.

macOS

Шаги по установке библиотеки:

  1. Отключить System Integrity Protection.
    • Перезагрузите компьютер. При включении зажмите на клавиатуре клавиши ⌘ R (Command+R).

    • После загрузки ОС на экране появится меню восстановления. Откройте раздел “Утилиты” и запустите “Терминал”.

    • В открывшемся окне Терминала выполните команду:

      $ csrutil disable
      
    • Перезагрузите компьютер через меню, чтобы настройки вступили в силу.

  2. Установить пакет pcsc-lite, если он не установлен.

    Например, пакет можно установить при помощи пакетного менеджера Homebrew:

    $ brew install pcsc-lite
    
  3. Установить библиотеку.

    Запустите инсталлятор SDK/lib/macOS/jcPKCS11-2_x.x.x.x.pkg и следуйте инструкциям установщика.

    Библиотека будет установлена в качестве Framework в /Library/Frameworks/jcPKCS11-2.framework.

  4. Включить System Integrity Protection.
    • Перезагрузите компьютер. При включении зажмите на клавиатуре клавиши ⌘ R (Command+R).

    • После загрузки ОС на экране появится меню восстановления. Откройте раздел “Утилиты” и запустите “Терминал”.

    • В открывшемся окне Терминала выполните команду:

      $ csrutil enable
      
    • Перезагрузите компьютер через меню, чтобы настройки вступили в силу.

GNU/Linux

Шаги по установке библиотеки:

  1. Проверить наличие пакетов и установить, если их нет:
    • для ОС семейства Debian – pcscd, libpcsclite1, libccid.
    • для ОС семейства CentOS – pcsc-lite.
  2. Установить библиотеку.

    В зависимости от вашего GNU/Linux дистрибутива запустите соответствующий инсталлятор:
    • GNU/Linux 32–бита:
      • SDK/lib/linux-i386/jcPKCS11-2_x.x.x.x_i386.deb. Библиотека будет установлена в /usr/lib/libjcPKCS11-2.so.
      • SDK/lib/linux-i386/jcPKCS11-2_x.x.x.x_i386.rpm. Библиотека будет установлена в /usr/lib/libjcPKCS11-2.so.
    • GNU/Linux 64–бита:
      • SDK/lib/linux-x86_64/jcPKCS11-2_x.x.x.x_amd64.deb. Библиотека будет установлена в /usr/lib/libjcPKCS11-2.so.
      • SDK/lib/linux-x86_64/jcPKCS11-2_x.x.x.x_x86_64.rpm. Библиотека будет установлена в /usr/lib64/libjcPKCS11-2.so.

Интеграция в приложение

Совет

В документации по Единой библиотеке PKCS #11 в разделах:

Библиотека jcPKCS11-2 поставляется в виде динамической библиотеки:
  • dll – для Microsoft Windows;
  • dylib – для macOS;
  • so – для GNU/Linux.

Для использования jcPKCS11-2 в проекте выполните следующие шаги:

  1. Прилинкуйте библиотеку к проекту. Пути до библиотеки в зависимости от ОС:

    Microsoft Windows:
    • библиотека под 32–битную архитектуру – SDK/lib/Win32/jcPKCS11-2.dll;
    • библиотека под 64–битную архитектуру – SDK/lib/Win64/jcPKCS11-2.dll.
    macOS:
    • библиотека в качестве Framework установленная при помощи .pkg пакета – /Library/Frameworks/jcPKCS11-2.framework.
    GNU/Linux 32–бита:
    • библиотека, установленная при помощи .deb пакета – /usr/lib/libjcPKCS11-2.so;
    • библиотека, установленная при помощи .rpm пакета – /usr/lib/libjcPKCS11-2.so.
    GNU/Linux 64–бита:
    • библиотека, установленная при помощи .deb пакета – /usr/lib/libjcPKCS11-2.so;
    • библиотека, установленная при помощи .rpm пакета – /usr/lib64/libjcPKCS11-2.so.

    Примечание

    В примерах, входящих в состав JaCarta-2 SDK, путь до библиотеки (PKCS_LIB_PATH) устанавливается в SDK/sources/CMakeLists.sdk, а затем используется в SDK/sources/common/tools.make и SDK/sources/common/P11Loader.cpp.

  2. В коде подключите заголовочный файл jcPKCS11.h.

    Пример:

    #include "jcPKCS11.h"
    
  3. Если вы подключаете динамическую библиотеку в Runtime, то подгрузите из нее необходимые функции.

    • Вызовите функцию C_GetFunctionList() для получения функций стандарта PKCS #11, реализованных в библиотеке. Все они описаны в разделе Функции, входящие в стандарт PKCS #11.

      Пример:

      /// ...
      
      // Список функций, входящих в стандарт PKCS #11
      CK_FUNCTION_LIST_PTR funcs = NULL_PTR;
      
      // Загрузить функцию для получения списка функций, входящих в стандарт PKCS #11
      CK_C_GetFunctionList C_GetFunctionList = (CK_C_GetFunctionList) GetFunction(libHandle, "C_GetFunctionList");
      if (C_GetFunctionList == NULL_PTR)
      {
        printf("ERROR: C_GetFunctionList hasn't been found in module\n");
        return;
      }
      
      // Загрузить функции, входящие в стандарт PKCS #11
      rv = C_GetFunctionList(&funcs);
      if (rv != CKR_OK)
      {
        printf("ERROR: C_GetFunctionList is failed: 0x%08x\n", rv);
        return;
      }
      printf("C_GetFunctionList - OK\n");
      
      /// ...
      
      // Использование на примере инициализации библиотеки
      rv = funcs->C_Initialize(NULL_PTR);
      if (rv != CKR_OK)
      {
        printf("ERROR: C_Initialize is failed: 0x%08x\n", rv);
        return;
      }
      printf("C_Initialize - OK\n");
      
      /// ...
      
    • Вызовите функцию JC_GetFunctionList() для получения дополнительных функций, реализованных в библиотеке, но не входящих в стандарт PKCS #11. Все они описаны в разделе Функции, не входящие в стандарт PKCS #11.

      Этот шаг следует выполнять, если Вам требуются функции расширения.

      Пример:

      /// ...
      
      // Список дополнительных функций, не входящих в стандарт PKCS #11
      JC_FUNCTION_LIST_PTR funcsExtra = NULL_PTR;
      
      // Загрузить функцию для получения списка дополнительных функций, не входящих в стандарт PKCS #11
      FP_JC_GetFunctionList JC_GetFunctionList = (FP_JC_GetFunctionList) GetFunction(libHandle, "JC_GetFunctionList");
      if (JC_GetFunctionList == NULL_PTR)
      {
        printf("ERROR: C_GetFunctionList hasn't been found in module\n");
        return;
      }
      
      // Загрузить дополнительные функции, не входящие в стандарт PKCS #11
      rv = JC_GetFunctionList(&funcsExtra);
      if (rv != CKR_OK)
      {
        printf("ERROR: JC_GetFunctionList is failed: 0x%08x\n", rv);
        return;
      }
      printf("JC_GetFunctionList - OK\n");
      
      /// ...
      
      // Использование на примере получения версии библиотеки jcPKCS11-2
      JC_VERSION_INFO versionInfo;
      CK_RV rv = funcsExtra->JC_GetVersionInfo(&versionInfo);
      if (rv != CKR_OK)
      {
        printf("ERROR: JC_GetVersionInfo is failed: 0x%08x\n", rv);
        return;
      }
      printf("JC_GetVersionInfo - OK\n");
      
      /// ...
      

    Примечание

    В примерах, входящих в состав JaCarta-2 SDK, класс P11Loader демонстрирует использование библиотеки jcPKCS11-2 под Microsoft Windows, macOS и GNU/Linux.

    Класс объявлен и реализован в SDK/sources/common/P11Loader.h и SDK/sources/common/P11Loader.cpp соответственно.

  4. Проект готов для использования Единой библиотеки PKCS #11.

Работа с примерами

Сборка примеров

Примеры JaCarta-2 SDK предназначены для сборки на платформах Microsoft Windows, GNU/Linux и macOS. Для сборки примеров необходима утилита CMake минимальной версии 2.8 (рекомендуется 3.6), генерирующая проектные файлы для сборки примеров (.sln, Makefile).

В зависимости от вида ОС необходима установка штатными средствами ОС следующих пакетов:
  • для Debian – gcc, g++, make;
  • для CentOS – gcc, gcc-c++, make;
  • для macOS – make, gcc.
Для сборки примеров:
  • под Microsoft Windows – запустите командный файл ./sources/make.bat (проекты будут располагаться в каталоге ./out, исполняемые файлы в ./bin);
  • под GNU/Linux и macOS запустите скрипт ./sources/make.sh (артефакты сборки будут располагаться в каталоге ./out, исполняемые файлы в ./bin).

Дополнительные рекомендации указаны в комментариях к каждому примеру.

Список примеров

  • CertificateRenewal – применение функций расширения JC_CreateCertificateRenewal() и JC_CreateCertificateRenewal2() для создания запроса на перевыпуск сертификата.
  • certificateRequest – составление запроса на сертификат и записи полученного сертификата на JaCarta-2 ГОСТ.
  • CMS – создание и расшифрование CMS сообщений, использующих алгоритмы ГОСТ Р 34.10–2001, ГОСТ Р 34.10–2012 и ГОСТ 28147–89.
  • cmsSignAndVerify – создание и проверку сообщений в формате CMS типа signed data.
  • data – поиск, создание и удаление бинарных объектов.
  • deriveKey2012 – пример демонстрирует следующие действия:
    1. Генерация новой ключевой пары Отправителя по ГОСТ Р 34.10–2012 (длина ключа 256 бит).
    2. Выведение ключа согласования по RFC 4357 пункт 5.2 с указанием значения открытого ключа Получателя.
  • digest2012 – генерация хэш-последовательности по ГОСТ Р 34.10–2012 (длина ключа 256 бит) и ГОСТ Р 34.10–2012 (длина ключа 512 бит).
  • encryptDecrypt – зашифрование и расшифрование данных согласно ГОСТ 28147–89.
  • getCertificateInfo – получение информации о сертификатах на JaCarta-2 ГОСТ.
  • HMAC – вычисление и проверку HMAC по RFC 2104 c использованием алгоритмов вычисления хэш-суммы:
    • ГОСТ Р 34.11–94;
    • ГОСТ Р 34.11–2012 (длина хэш–кода 256 бит);
    • ГОСТ Р 34.11–2012 (длина хэш–кода 512 бит).
  • info – получение информации о библиотеке, слоте и токене.
  • initUser – очистка всех пользовательских данных с JaCarta-2 ГОСТ и автоматическое создание файловой системы PKCS #11.
  • MAC – создание и проверка имитовставки согласно ГОСТ 28147–89.
  • pinUser – смена PIN-кода пользователя.
  • pinUserUnblock – снятие блокировки PIN-кода пользователя с помощью предъявления PUK-кода.
  • signAndVerify – пример демонстрирует следующие действия:
    1. Генерация новой ключевой пары ГОСТ Р 34.10–2001.
    2. Подпись и проверка подписи по алгоритму ГОСТ Р 34.10–2001.
  • signAndVerify2012 – пример демонстрирует следующие действия:
    1. Генерация новой ключевой пары ГОСТ Р 34.10–2012 (длина ключа 256 бит).
    2. Подпись и проверка подписи с хэшированием по алгоритму ГОСТ Р 34.10–2012 (длина ключа 256 бит).
  • signAndVerifyCryptoPro – пример демонстрирует следующие действия:
    1. Генерация новой ключевой пары ГОСТ Р 34.10–2001 на токене и экспорт открытого ключа.
    2. Импорт открытого ключа в КриптоПро CSP.
    3. Подпись данных на токене и проверка подписи при помощи КриптоПро CSP.
  • signAndVerifyCryptoPro2012 – пример демонстрирует следующие действия:
    1. Генерация новой ключевой пары ГОСТ Р 34.10–2012 (длина ключа 256 бит) на токене и экспорт открытого ключа.
    2. Импорт открытого ключа в КриптоПро CSP.
    3. Подпись данных на токене и проверка подписи при помощи КриптоПро CSP.
  • signAndVerifyExternalHash2012 – пример демонстрирует следующие действия:
    1. Генерация новой ключевой пары ГОСТ Р 34.10–2012 (длина ключа 256 бит).
    2. Хеширование данных по алгоритму ГОСТ Р 34.11–2012 (длина хэш–кода 256 бит).
    3. Подпись и проверка подписи по алгоритму ГОСТ Р 34.10–2012.
  • signAndVerifySignaturePIN – использование дополнительного PIN-кода подписи для подтверждения операции.
  • verifyWithChainOfTrust – пример демонстрирует проверку цепочки сертификатов:
    1. Проверку подписи сертификата доверенным открытым ключом.
    2. Поиск виртуального открытого ключа для проверки следующего сертификата в цепочке.
    3. Проверяется подпись данных.

Особенности встраивания

PIN-код подписи

PIN-код подписи используется как дополнительный фактор для подтверждения операции подписи. Его использование не отменяет необходимость предъявления PIN-кода пользователя для работы в режиме пользователя.

Установка, смена и предъявление

PIN-код подписи устанавливается с помощью функции JC_KT2_SetSignaturePIN(). После установки PIN-код подписи пользователь уже не сможет его удалить, только изменить на новый.

Для изменения PIN-кода подписи необходимо вызвать функцию JC_KT2_ChangeSignaturePIN().

PIN-код подписи может быть удалён только после инициализации устройства администратором с помощью ПО «АРМ администратора безопасности JaCarta-2 ГОСТ» или «АРМ разработчика JaCarta-2 ГОСТ».

PIN-код подписи предъявляется с помощью функции C_Login() с параметром userType равном CKU_SIGNATURE. Вызов C_Logout() переключит текущую сессию в гостевую. Т.е. нельзя отменить PIN-код подписи отдельно от сессии пользователя.

Использование PIN-кода подписи

Предъявление PIN-кода подписи является опциональным для каждой ключевой пары на устройстве. Необходимость предъявления задаётся атрибутом CKA_ALWAYS_AUTHENTICATE:

  • CK_TRUE – необходимо предъявление PIN-кода подписи;
  • CK_FALSE – предъявление PIN-кода подписи не требуется.

Атрибут неизменяемый, т.е. необходимость использования PIN-кода подписи для каждой ключевой пары задаётся на этапе её создания.

Подготовка PIN-кода подписи к использованию:

  • установить PIN-код подписи на токен с помощью функции JC_KT2_SetSignaturePIN().
  • сгенерировать ключевую пару при помощи функции C_GenerateKeyPair(), где в шаблоне закрытого ключа установить атрибут CKA_ALWAYS_AUTHENTICATE в CK_TRUE.

Примечание

Если не установить PIN-код подписи, но при этом создать ключевую пару с необходимостью его предъявления, то такой ключевой парой нельзя будет подписать до установки PIN-кода подписи.

Использование PIN-кода подписи:

  1. Предъявить PIN-код пользователя, вызвав функцию C_Login() с параметром userType равном CKU_USER. Произойдет переход в пользовательскую сессию.
  2. Предъявить PIN-код подписи, вызвав функцию C_Login() с параметром userType равном CKU_SIGNATURE. Сессия не изменится, т.е. останется пользовательской.
  3. Подписать данные или создать запрос на сертификат.
  4. Сбросить состояние аутентификации, вызвав функцию C_Login(). Произойдет переход в гостевую сессию.

Строгий сеанс работы

Единая библиотека PKCS #11 позволяет включить строгий сеанс работы с токеном, в котором:
  • все данные, передаваемые между библиотекой и токеном, шифруются;
  • устройство входит в эксклюзивный режим работы и отвергает попытки любых сторонних приложений получить доступ к его функциям.
Это защищает от попыток вредоносных приложений:
  • подменить подписываемый документ в канале связи между библиотекой и токеном;
  • использовать состояние “залогиненности” JaCarta-2 ГОСТ для подписи посторонних поддельных документов.

Для его включения необходимо вызвать функцию C_Login() с параметром userType равном CKU_USER_SM.

Примечание

Строгий сеанс не поддерживается для смарт-карт JaCarta-2 ГОСТ, подключенных к Антифрод-терминалу.