/*
* Copyright(C) 2000 Проект ИОК
*
* Этот файл содержит информацию, являющуюся
* собственностью компании Крипто Про.
*
* Любая часть этого файла не может быть скопирована,
* исправлена, переведена на другие языки,
* локализована или модифицирована любым способом,
* откомпилирована, передана по сети с или на
* любую компьютерную систему без предварительного
* заключения соглашения с компанией Крипто Про.
*/

/*!
* \file $RCSfile$
* \version $Revision: 101663 $
* \date $Date: 2014-02-04 12:58:15 +0400 (Р’С‚, 04 С„РµРІ 2014) $
* \author $Author: sagafyin $
* \brief Интерфейс считывателей, не требующий рекурсивного восстановления контекста. По отношению к rdr.h - базовый.
*/

#if !defined( _READER_INDEPENDENT_RDR_H )
#define _READER_INDEPENDENT_RDR_H

#include "reader/sup_syse.h"
#include "reader.kit/sup_sys.h"

#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif /* HAVE_LIMITS_H */

#include "reader/support.h"
#include "BaseArithmDef_64.h"

#if defined( _MSC_VER )
#pragma warning( push )
#pragma warning( disable: 4100 4115 4201 4214 )

#include <windows.h>

#pragma warning( pop )
#endif /* defined( _MFC_VER ) */

/* **** **** defines **** **** */

/*! 
* \addtogroup rdr_ext_fkc_type
* \{
*/

/*! 
* \defgroup rdr_auth_type_const Базовые константы, используемые в функциях аутентификации
* \brief Константы для различения видов аутентификации
* \{
*/

/*! 
* \defgroup rdr_auth_type_const_types Виды аутентификации
* \brief Виды аутентификации 
* \{
*/

//! Аутентификация по PUK. Предназначена для предоставления доступа к системе аутентификации. Не требует открытия папки.
#define AUTH_TYPE_TYPE_PUK 0x10
//! Аутентификация в корне. Предназначена для разрешения создания и удаления папок. Требует входа в NULL-папку. 
#define AUTH_TYPE_TYPE_ROOT 0x20
//! Аутентификация в контейнере. Предназначена для предоставления доступа закрытому ключу контейнера.
#define AUTH_TYPE_TYPE_CONT 0x30
//! Аутентификация в УЭК по ПИН1
#define AUTH_TYPE_TYPE_USER_PIN1 0x40
//! Аутентификация в УЭК по ПИН2
#define AUTH_TYPE_TYPE_USER_PIN2 0x50
//! Маска видов аутентификации. Используется для получения вида аутентификации из auth_type.
#define AUTH_TYPE_TYPE_MASK 0xF0

/*!* \} */

/*! 
* \defgroup rdr_auth_flags Флаги признаков и свойств аутентификаций.
* \brief Флаги признаков и свойств аутентификаций. Возвращаются на #READER_FUN_GET_PARAM TCEP_auth_types
* \{
*/

//! Аутентификация по PUK позволяет устанавливать в максимальные значения любые счетчики аутентификаций и устанавливать новые параметры действующих аутентификаций (переинициализировать их).
#define AUTH_FLAG_TYPE_PUK 1
//! Аутентификация по ROOT (административная) позволяет создавать и удалять контейнеры.
#define AUTH_FLAG_TYPE_ROOT (AUTH_FLAG_TYPE_PUK<<1)
//! Аутентификация по CONT (в контейнере) разрешает использовать данные из контейнера (ключи), и менять контейнер. CONT - аутентификация в папке(контейнере), в отличие от всех остальных, которые выполняются всегда для всего носителя.
#define AUTH_FLAG_TYPE_CONT (AUTH_FLAG_TYPE_ROOT<<1)
//! Резервный вид аутентификации.
#define AUTH_FLAG_TYPE_USER_PIN1 (AUTH_FLAG_TYPE_CONT<<1)
//! Резервный вид аутентификации.
#define AUTH_FLAG_TYPE_USER_PIN2 (AUTH_FLAG_TYPE_USER_PIN1<<1)
//! На носителе нет аутентификации в каждом контейнере отдельно. Аутентификация, разрешающая создавать и удалять контейнеры, разрешает также использовать и все их данные. То есть на носителе присутствует один единственный pin.
#define AUTH_FLAG_TYPE_ROOT_CONT (AUTH_FLAG_TYPE_USER_PIN2<<1)
//! Аутентификация по ROOT также разблокировку других аутентификаций. Если зажжен флаг PUK_ROOT, то должен быть зажжен AUTH_FLAG_TYPE_ROOT.
#define AUTH_FLAG_TYPE_PUK_ROOT (AUTH_FLAG_TYPE_ROOT_CONT<<1)
//! Аутентифкация для смены аутентификаций автоматически сбрасывает счетчики ошибок аутентификации.
#define AUTH_FLAG_TYPE_RESETS_COUNTERS (AUTH_FLAG_TYPE_PUK_ROOT<<1)
//! Depricated, not used
#define AUTH_FLAG_TYPE_SET_COUNTERS_ONLY (AUTH_FLAG_TYPE_PUK_ROOT<<1)
//! После выполнения аутентифкация для смены аутентификаций можно сбросить счетчики ошибок аутентификации командой READER_FUN_CLEAR_TRIES.
#define AUTH_FLAG_TYPE_CAN_RESET_COUNTERS (AUTH_FLAG_TYPE_RESETS_COUNTERS<<1)
//! После выполнения аутентифкация для смены аутентификаций можно сменить аутентификационную информацию любой аутентификации. 
#define AUTH_FLAG_TYPE_CAN_CHANGE_AUTH (AUTH_FLAG_TYPE_CAN_RESET_COUNTERS<<1)
//! Аутентификация администратора установлена в значение по умолчанию. Если носитель поддерживает функциональность дефолтного пароля, то данный флаг должен устанавливаться на основе анализа текущего пароля.
//! Группа флагов, которые могут изменяться во время работы апплета
#define AUTH_FLAG_TYPE_IS_DEF_ROOT (AUTH_FLAG_TYPE_CAN_CHANGE_AUTH<<1)
//! Аутентификации администратора можно установить значение по умолчанию
#define AUTH_FLAG_TYPE_CAN_RESET_ROOT_DEF (AUTH_FLAG_TYPE_IS_DEF_ROOT<<1)
//! Необходимо восстановление аутентификации в контейнере после повторного открытия папки
#define AUTH_FLAG_TYPE_RESTORE_CONT_AFTER_FOLDER_OPEN (AUTH_FLAG_TYPE_CAN_RESET_ROOT_DEF<<1)
//! Во время операции сброса токена к базовому состоянию нужно выполнить какое-либо аппаратное действие. Например, вытащить токен за 5 секунд.
#define AUTH_FLAG_TYPE_HARDWARE_RESET_ROOT_DEF (AUTH_FLAG_TYPE_RESTORE_CONT_AFTER_FOLDER_OPEN<<1)
//! В команде смены пароля нужен пароль, разрешающий эту операцию.
#define AUTH_FLAG_TYPE_USE_PASSWORD_TO_CHANGE (AUTH_FLAG_TYPE_HARDWARE_RESET_ROOT_DEF<<1)
//! Аутентификации является единой для всего носителя. Флаг должен быть возвращаться из каждого апплета. Последний блок unique (XXX_123456) должен содержать одинаковое значение у разных апплетов. 
#define AUTH_FLAG_TYPE_COMMON_AUTH (AUTH_FLAG_TYPE_USE_PASSWORD_TO_CHANGE<<1)
//! Нельзя менять основную аутентификацию под ней самой, а только под PUK
#define AUTH_FLAG_TYPE_MAIN_CANT_CHANGE_ITSELF (AUTH_FLAG_TYPE_COMMON_AUTH<<1)
//! PUK установлен в значение по умолчанию. Если носитель поддерживает функциональность дефолтного пароля PUK, то данный флаг должен устанавливаться на основе анализа текущего пароля PUK.
//! Группа флагов, которые могут изменяться во время работы апплета
#define AUTH_FLAG_TYPE_IS_DEF_PUK (AUTH_FLAG_TYPE_MAIN_CANT_CHANGE_ITSELF<<1)
//! Карта автоматически форматируется, когда переходит в "кирпичное" состояни (заблокированы все пароли)
#define AUTH_FLAG_TYPE_AUTO_FORMAT (AUTH_FLAG_TYPE_IS_DEF_PUK<<1)

/*!* \} */

/*! 
* \defgroup rdr_auth_algs Способы аутентификации.
* \brief Константы, используемые для задания способа (алгоритма) аутентификации. 
* \{
*/
//! Аутентификацияна носителе не требуется, выполняется средствами провайдера. Все функции работы с носителем должны быть доступны без аутентификации. 
#define AUTH_TYPE_AUTH_NO 0x00
//! Аутентификация проводится в устройстве (например, путем предъявления отпечатка пальца).
#define AUTH_TYPE_AUTH_SELF 0x01
//! Аутентификация по явному предъявлению циферно-символьного пароля (обычная функция VERIFY, стандарт для смарт-карт).
#define AUTH_TYPE_AUTH_SIMPLE 0x02
//! Аутентификация по протоколу SESPAKE. 
#define AUTH_TYPE_AUTH_SESPAKE 0x03
//! Аутентификация по протоколу DH для носителей (при особых вариантах защищенного канала). Не используется.
#define AUTH_TYPE_AUTH_DH 0x04
//! Маска видов алгоритмов
#define AUTH_TYPE_AUTH_MASK 0x0F

/*!* \} */

/*! 
* \defgroup rdr_auth_errs Аутентификационные коды возврата
* \brief Управляющие коды возврата, уведомляющие провайдер о необходимости аутентификации. 
* \{
*/
//! Коды возврата для описания требуемых действий (обобщенный код).
#define CPR_ERR_RDR_RETCODE (CPR_ERR_RETCODE + 0x1000)
//! Требуется предварительная неопределенная аутентификация (обобщенный код).
#define CPR_ERR_RDR_NEED_AUTH (CPR_ERR_RDR_RETCODE + 0x0200)
//! Требуется ввод PUK
#define CPR_ERR_RDR_NEED_PUK_AUTH (CPR_ERR_RDR_NEED_AUTH + AUTH_TYPE_TYPE_PUK) 
//! Требуется аутентификация в корне
#define CPR_ERR_RDR_NEED_ROOT_AUTH (CPR_ERR_RDR_NEED_AUTH + AUTH_TYPE_TYPE_ROOT)
//! Требуется аутентификация в контейнере.
#define CPR_ERR_RDR_NEED_CONT_AUTH (CPR_ERR_RDR_NEED_AUTH + AUTH_TYPE_TYPE_CONT)
//! Требуется аутентификации через ввод пользовательского ПИН (например ПИН1 УЭК).
#define CPR_ERR_RDR_NEED_USER_PIN1_AUTH (CPR_ERR_RDR_NEED_AUTH + AUTH_TYPE_TYPE_USER_PIN1) 
//! Требуется аутентификации через ввод пользовательского ПИН (например ПИН2 УЭК).
#define CPR_ERR_RDR_NEED_USER_PIN2_AUTH (CPR_ERR_RDR_NEED_AUTH + AUTH_TYPE_TYPE_USER_PIN2) 
/*!* \} */
/*!* \} */

/*! 
* \defgroup rdr_return_errs Базовые управляющие коды возврата
* \brief Управляющие коды возврата, уведомляющие провайдер о необходимости выполнения какого-либо действия. 
* \{
*/
//! Требуется установить соединение с носителем.
#define CPR_ERR_RDR_NEED_CONNECT (CPR_ERR_RDR_RETCODE + 0x0301)
//! Требуется выбрать приложения.
#define CPR_ERR_RDR_NEED_APPLET (CPR_ERR_RDR_RETCODE + 0x0302)
//! Требуется открытие папки.
#define CPR_ERR_RDR_NEED_OPEN_FOLDER (CPR_ERR_RDR_RETCODE + 0x0303)
//! Требуется открытие файла.
#define CPR_ERR_RDR_NEED_OPEN_FILE (CPR_ERR_RDR_RETCODE + 0x0304)
//! Требуется установка шифрованного канала.
#define CPR_ERR_RDR_SM (CPR_ERR_RDR_RETCODE + 0x0305)
//! Требуется форматирование носителя.
#define CPR_ERR_RDR_FORMAT (CPR_ERR_RDR_RETCODE + 0x0306)

//! Для дальнейшей работы требуется смена всех паролей.
#define CPR_ERR_RDR_CHANGE_PASSWORDS (CPR_ERR_RDR_RETCODE + 0x0400)
//! Для дальнейшей работы требуется смена PUK.
#define CPR_ERR_RDR_CHANGE_PUK (CPR_ERR_RDR_CHANGE_PASSWORDS + AUTH_TYPE_TYPE_PUK)
//! Для дальнейшей работы требуется смена корневого пароля.
#define CPR_ERR_RDR_CHANGE_ROOT (CPR_ERR_RDR_CHANGE_PASSWORDS + AUTH_TYPE_TYPE_ROOT)
//! Для дальнейшей работы требуется смена пароля контейнера.
#define CPR_ERR_RDR_CHANGE_CONT (CPR_ERR_RDR_CHANGE_PASSWORDS + AUTH_TYPE_TYPE_CONT)
//! Для дальнейшей работы требуется смена пользовательского ПИН1.
#define CPR_ERR_RDR_CHANGE_USER_PIN1 (CPR_ERR_RDR_CHANGE_PASSWORDS + AUTH_TYPE_TYPE_USER_PIN1)
//! Для дальнейшей работы требуется смена пользовательского ПИН2.
#define CPR_ERR_RDR_CHANGE_USER_PIN2 (CPR_ERR_RDR_CHANGE_PASSWORDS + AUTH_TYPE_TYPE_USER_PIN2)

/*!* \} */

/*! 
* \defgroup rdr_reader_flags Флаги, возвращаемые модулем считывателя по запросу
* \brief Флаги считывателя, возвращаемые на #SUPSYS_FUN_FLAGS
* \{
*/
//! Идентификатор блока флагов носителя 
#define RDR_FLAG_BLOCK_RDR 0x3000
//! Признак отчуждаемости носителя в считывателе. 
#define RDR_FLAG_RDR_REMOVABLE 0
//! Признак наличия у носителей, подключаемых к данному считывателю, уникальных идентификаторов
#define RDR_FLAG_RDR_UNIQUE 1
//! Признак защиты ключей, хранимых в данном считывателе, сторонним контейнером. Используется только в HSM.
#define RDR_FLAG_RDR_PROTECTED 2
//! Признак виртуального считывателя. Такой считыватель предназначен только для ключей, вырабатываемых в памяти.
#define RDR_FLAG_RDR_VIRTUAL 3
//! Количество флагов. Служебное значение.
#define RDR_FLAG_RDR_VERSION_6 (RDR_FLAG_RDR_VIRTUAL+1)
//! Признак медленного считывателя. Такой считыватель всегда будет в конце списка считывателей.
#define RDR_FLAG_RDR_SLOW 4
//! Количество флагов. Служебное значение.
#define RDR_FLAG_RDR_VERSION_7 (RDR_FLAG_RDR_SLOW+1)
//! Признак того, что данные о носителе для окна при наличии выбора берутся из другого контекста считывателя.
#define RDR_FLAG_RDR_MINOR_INFO 5
//! Количество флагов. Служебное значение.
#define RDR_FLAG_RDR_VERSION_8 (RDR_FLAG_RDR_MINOR_INFO+1)

//! Макроса для получение фактического значения флагов RDR_FLAG_RDR_* модулями поддержки
#define TO_CP_FLAG(flag, value) ((value)<<(7-(flag))) 
/*!* \} */

/*! 
* \defgroup rdr_enum_flags Флаги, используемые в функциях перечисления папок
* \brief Флаги, с которыми вызывается функция #READER_FUN_FOLDER_ENUM_OPEN
* \{
*/
//! Признак перечисления только существующих папок.
#define RDR_FOLDER_ENUM_FLAG_OPEN 0x0
//! Признак перечисления имен папок, которые можно создать. Возвращаемые имена могут быть производными от настоящего имени контейнера.
#define RDR_FOLDER_ENUM_FLAG_NEW 0x1
//! Признак окончания перечисления. Может выставляться модулем поддержки в конце перечисления. 
#define RDR_FOLDER_ENUM_FLAG_END 0x2
/*!* \} */

/*! 
* \defgroup rdr_size_const Константы, используемые для указания размера объектов
* \brief Базовые константы с размерами
* \{
*/
//! Максимальная длина имени папки. 
#define RDR_FOLDER_NAME_MAX_SIZE		(256)
//! Длина массива, вмещающего координату точки кривой с модулем 256 бит
#define RDR_FKC_COORD_SIZE_256			(256/8)		// 32
//! Длина массива, вмещающего точку кривой с модулем 256 бит
#define RDR_FKC_POINT_SIZE_256			(RDR_FKC_COORD_SIZE_256 * 2) // 64
//! Длина массива, вмещающего порядок группы точки кривой с модулем 256 бит
#define RDR_FKC_ORDER_SIZE_256			(256/8)		// 32
//! Длина массива, вмещающего UKM стандартной длины
#define RDR_FKC_UKM_SIZE_256			(64/8)		// 8
//! Длина массива, вмещающего хэш-значение функции Стрибог-256
#define RDR_FKC_HASH_VALUE_SIZE_256		RDR_FKC_ORDER_SIZE_256

//! Длина массива, вмещающего координату точки кривой с модулем 512 бит
#define RDR_FKC_COORD_SIZE_512			(512/8)		// 64
//! Длина массива, вмещающего точку кривой с модулем 512 бит
#define RDR_FKC_POINT_SIZE_512			(RDR_FKC_COORD_SIZE_512 * 2) // 128
//! Длина массива, вмещающего порядок группы точки кривой с модулем 512 бит
#define RDR_FKC_ORDER_SIZE_512			(512/8)		// 64
//! Длина массива, вмещающего расширенный UKM
#define RDR_FKC_UKM_SIZE_512			(128/8)		// 16
//! Длина массива, вмещающего хэш-значение функции Стрибог-512
#define RDR_FKC_HASH_VALUE_SIZE_512		RDR_FKC_ORDER_SIZE_512
//! Длина рандомизатор SALT из протокола SESPAKE
#define RDR_FKC_RNDM_SIZE_512			16
//! Длина массива, вмещающего хэш-значение функции SHA-1
#define RDR_FKC_HASH_VALUE_SIZE_SHA1		20
//! Длина массива, вмещающего значение ключа шифрования (ключа обмена) по ГОСТ Р 34.12-2015 и ГОСТ 28147-89
#define RDR_EXCHANGE_KEY_LENGTH                 32
//! Длина массива, вмещающего значение ключа шифрования (ключа обмена) длиной 512 бит
#define RDR_EXCHANGE_KEY_512_LENGTH             64

//! Длина массива, вмещающего координату точки кривой с модулем 192 бит
#define RDR_FKC_COORD_SIZE_192			(192/8)		// 24
//! Длина массива, вмещающего координату точки кривой с модулем 224 бит
#define RDR_FKC_COORD_SIZE_224			(224/8)		// 28
//! Длина массива, вмещающего координату точки кривой с модулем 384 бит
#define RDR_FKC_COORD_SIZE_384			(384/8)		// 48

//! Длина массива, вмещающего ключ RSA
#define RDR_FKC_RSA_MAX_MODULUS_BYTES		(1024)
/*!* \} */

/*!* \} */

/*!
* \defgroup reader_types Основные типы данных подключаемых библиотек
*/

/*!
* \ingroup reader_types
* \defgroup rdr_ext_fkc_type Основные типы данных библиотеки считывателей
* \{
*/

/*!
* \brief Номер файла на носителе
*/
typedef enum {
    CF_INVALID_FILE_NUMBER = 0,
    CF_MIN_FILE_NUMBER = 1, /*!< Номер первого файла */
    CF_MASKS = CF_MIN_FILE_NUMBER, /*!< Номер файла маски закрытого ключа. */
    CF_PRIMARY, /*!< Номер файла закрытого ключа. */
    CF_HEADER, /*!< Номер файла открытой информации о ключе. */
    CF_MASKS2, /*!< Номер файла маски резервного ключа. */
    CF_PRIMARY2, /*!< Номер файла резервного ключа. */
    CF_NAME, /*!< Номер файла имени контейнера. */
    CF_DEF, /*!< Номер файла с именем контейнера по умолчанию. */
    CF_MAX_FILE_NUMBER = CF_DEF, /*!< Наибольший номер файла для обычного носителя */
    CF_CERT_KX, /*!< Номер файла с сертификатом для ключа AT_KEYEXCHANGE. (\ref csp_interface) */
    CF_CERT_SIG, /*!< Номер файла с сертификатом для ключа AT_SIGNATURE. (\ref csp_interface) */
    CF_EXT, /*!< Номер файла с расширениями. (\ref csp_interface) */
    CF_MAX_FILE_NUMBER_CSP_INT = CF_EXT /*!< Наибольший номер файла для носителя с поддержкой csp_interface */
} TRdrFileNumber;

//! Имя файла маски закрытого ключа.
#define MASKS_KEY_NAME _TEXT("masks.key")
//! Имя файла закрытого ключа.
#define PRIMARY_KEY_NAME _TEXT("primary.key")
//! Имя файла открытой информации о ключе.
#define HEADER_KEY_NAME _TEXT("header.key")
//! Имя файла маски резервного ключа.
#define MASKS2_KEY_NAME _TEXT("masks2.key")
//! Имя файла резервного ключа.
#define PRIMARY2_KEY_NAME _TEXT("primary2.key")
//! Имя файла имени контейнера. 
#define NAME_KEY_NAME _TEXT("name.key")
//! Имя файла с именем контейнера по умолчанию.
#define DEF_KEY_NAME _TEXT("def.key")
//! Имя файла с сертификатом для ключа AT_KEYEXCHANGE. (\ref csp_interface)
#define CERTIFICATE_KX_KEY_NAME _TEXT("certificate_kx.key")
//! Имя файла с сертификатом для ключа AT_SIGNATURE. (\ref csp_interface)
#define CERTIFICATE_SIG_KEY_NAME _TEXT("certificate_sig.key")
//! Имя файла с расширениями. (\ref csp_interface)
#define EXTENSIONS_KEY_NAME _TEXT("extensions.key")

/*! 
* \brief Идентификатор протокола и объекта аутентификации. Является результатом операции побитового ИЛИ способа (\ref rdr_auth_algs) и типа (\ref rdr_auth_type_const_types).
*/
typedef unsigned int TRdrLoginInfoType;

struct TRdrFolderEnumContext_;

/*! 
* \brief Контекст перечисления папок, абстрактная структура.
*/
typedef struct TRdrFolderEnumContext_ TRdrFolderEnumContext;

/*!
* \brief Контекст хэша, абстрактная структура.
*/
typedef struct TRdrHashContext_ TRdrHashContext;

//! Точка эллиптической кривой
typedef struct
{
    BYTE x[RDR_FKC_COORD_SIZE_512]; /*!< Координата (mod p) x в big-endian. В случае значений 2001 года, они пишутся с начала массива.*/
    BYTE y[RDR_FKC_COORD_SIZE_512]; /*!< Координата (mod p) y в big-endian. В случае значений 2001 года, они пишутся с начала массива.*/
} TRdrFkcPoint;

typedef struct {
    DWORD exponent;
    DWORD modulus_size;
    BYTE modulus[RDR_FKC_RSA_MAX_MODULUS_BYTES]; /*big-endian*/
} TRdrFkcRsaKey;

typedef union {
    TRdrFkcPoint point;	    //!< Точка - открытый ключ, возвращаемый при генерации
    TRdrFkcRsaKey rsa_key;  //!< RSA blob - открытый ключ, возвращаемый при генерации
} TRdrPublicKey;

//! Массив длины порядка группы точек эллиптической кривой
typedef BYTE TRdrFkcOrder[RDR_FKC_ORDER_SIZE_512];	/*!< Значение порядка группы точек (mod q) в big-endian. В случае значений 2001 года, они пишутся с начала массива.*/

//! UKM для ключа обмена
typedef BYTE TRdrFkcUKM[RDR_FKC_UKM_SIZE_512];	/*!< В случае значений 2001 года, они пишутся с начала массива.*/

//! Случайная величина - рандомизатор SESPAKE.
typedef BYTE TRdrFkcRndm12[RDR_FKC_RNDM_SIZE_512];

//! Максимально допустимое количество разных OID, поддерживаемых носителем
#define RDR_MAX_OIDS_COUNT 50

//! Идентификатор параметров элииптических кривых ГОСТ Р 34.10-2001(2012) и EC DSA
typedef enum 
{
    RDR_FKC_IDG_CP_PARAM_START = 0,                                 /*!< Служебный параметр, означающий начало перечисления .*/
    RDR_FKC_IDG_CP_OPTIONAL_PARAMSET = RDR_FKC_IDG_CP_PARAM_START,  /*!< Опциональный параметр, для 256-битных параметров, задаваемых носителем.*/
    RDR_FKC_IDG_CP_B_PARAMSET = 1,                                  /*!< Кривая id-GostR3410-2001-CryptoPro-B-ParamSet (1.2.643.2.2.35.2)*/
    RDR_FKC_IDG_CP_A_PARAMSET = 2,                                  /*!< Кривая id-GostR3410-2001-CryptoPro-A-ParamSet (1.2.643.2.2.35.1)*/
    RDR_FKC_IDG_CP_C_PARAMSET = 3,                                  /*!< Кривая id-GostR3410-2001-CryptoPro-C-ParamSet (1.2.643.2.2.35.3)*/
    RDR_FKC_IDG_CP_A_256_PARAMSET = 4,                              /*!< Кривая Эдвардса ­id-tc26-gost-3410-2012-256-paramSetA (1.2.643.7.1.2.1.1.1) */
    RDR_FKC_IDG_CP_OPTIONAL_512_PARAMSET = 8,                       /*!< Опциональный параметр, для 512-битных параметров, задаваемых носителем.*/
    RDR_FKC_IDG_CP_A_512_PARAMSET = 9,                              /*!< Кривая ­id-tc26-gost-3410-12-512-paramSetA (1.2.643.7.1.2.1.2.1).*/
    RDR_FKC_IDG_CP_B_512_PARAMSET = 10,                             /*!< Кривая ­id-tc26-gost-3410-12-512-paramSetB (1.2.643.7.1.2.1.2.2).*/
    RDR_FKC_IDG_CP_C_512_PARAMSET = 11,                             /*!< Кривая ­Эдвардса id-tc26-gost-3410-12-512-paramSetС (1.2.643.7.1.2.1.2.3).*/
    
    RDR_FKC_IDG_NIST_PRIME_192_V1 = 12,                             /*!< Кривая prime192v1 (1.2.840.10045.3.1.1).*/
    RDR_FKC_IDG_NIST_SECP_224_R1 = 13,                              /*!< Кривая secp224r1 (1.3.132.0.33).*/
    RDR_FKC_IDG_NIST_PRIME_256_V1 = 14,                             /*!< Кривая prime256v1 (1.2.840.10045.3.1.7).*/
    RDR_FKC_IDG_NIST_SECP_384_R1 = 15,                              /*!< Кривая secp384r1 (1.3.132.0.34).*/

    RDR_FKC_IDG_CP_PARAM_END = RDR_FKC_IDG_NIST_SECP_384_R1         /*!< Служебный параметр, означающий конец перечисления .*/
} TRdrFkcEllipticPointParam;

//! Идентификатор алгоритма подписи
typedef enum {
    TKeyAlgType_Unknown = 0x00,/*!< Служебный параметр, не используется.*/
    TKeyAlgType_2001 = 0x01,  /*!< ГОСТ Р 34.10-2001*/
    TKeyAlgType_2012_256 = 0x02, /*!< ГОСТ Р 34.10-2012 (256)*/
    TKeyAlgType_2012_512 = 0x03, /*!< ГОСТ Р 34.10-2012 (512)*/
    TKeyAlgType_ECDSA = 0x04, /*!< NIST */
    TKeyAlgType_RSA = 0x05 /*!< RSA */
} TKeyAlgType;

/*! 
* \brief Перечисление номеров счетчиков аутентификации SESPAKE
* \sa #rdr_folder_get_param, #rdr_folder_set_param, #rdr_get_auth_type
* 
*/
typedef enum {
    TSespakeCounterType_SESPAKE,		/*!< Счётчик операций SESPAKE*/
    TSespakeCounterType_fail, 			/*!< Счётчик неуспешных операций*/
    TSespakeCounterType_cfail, 			/*!< Счётчик последовательных неуспешных попыток*/
    TSespakeCounterType_MAX_V1			/*!< Общее число различных счетчиков*/
} TRdrFkcInfoSespakeCounter;

typedef enum {
    TRdrFkcSecureMessagingType_FKC,
    TRdrFkcSecureMessagingType_ISO,
    TRdrFkcSecureMessagingType_FKC_2015,
    TRdrFkcSecureMessagingType_FKC_AES
} TRdrFkcSecureMessagingType;

/*! \ingroup rdr_ext_folder_fkc_struct
* \brief Значения для типа запрашиваемой (записываемой) информации о папке или носителе ФКН.
*/
typedef enum {
    TCEP_sespake_counters,		/*!< Запрос счетчиков аутентификации SESPAKE для указанной аутентификации. Счетчики возвращаются в BE-формате последовательно: cSESPAKE, cFail, cCFail.*/
    TCEP_default_password,		/*!< deprecated. Правильно - TCEP_default_password_auth_type_ascii. Запрос значения по умолчанию для ROOT-аутентификации. */
    TCEP_disable_default_password,	/*!< deprecated (not used)*/
    TCEP_fkc_flags, 			/*!< Набор управляющих флагов, описывающий поведение криптографического носителя (#TRdrUniversalCarrierFlags functional_container == 1)*/
    TCEP_fkc_crypt_flags,		/*!< deprecated (not used)*/
    TCEP_auth_types,			/*!< Набор флагов, описывающий виды аутентификаций на данном приложении*/
    TCEP_uni_flags,			/*!< Набор управляющих флагов, описывающих свойства носителя*/
    TCEP_auth_state,		    	/*!< Возвращает состояние запрошенной аутентификации. ERROR_SUCCESS - выполнена; SCARD_W_CHV_BLOCKED - заблокирована; CPR_ERR_RDR_NEED_***_AUTH - не выполнена/может быть разблокирована.*/
    TCEP_header,		        /*!< Значение файла header.key (Cloud).*/
    TCEP_cloud_auth_server,		/*!< Адрес сервиса аутентификации (Cloud).*/
    TCEP_cloud_sign_server,		/*!< Адрес сервиса подписи (Cloud).*/
    TCEP_cloud_username,		/*!< Имя пользователя (Cloud).*/
    TCEP_cloud_password,		/*!< Пароль пользователя (Cloud).*/
    TCEP_cloud_OAuth2_auth_token,	/*!< access_token, полученный по протоколу OAuth2 (Cloud).*/
    TCEP_cloud_OAuth2_id_token,		/*!< id_token, полученный по протоколу OAuth2 (Cloud).*/
    TCEP_cloud_certificate,		/*!< Cертификат, инициализирующий контейнер. Параметр используется только для "псевдоконтейнеров" (Cloud).*/
    TCEP_cloud_certificate_id,		/*!< Идентификатор сертификата, уникальный для пользователя (Cloud).*/
    TCEP_fkc_csp_interface_container,	/*!< Параметры контейнера в провайдерном интерфейсе. Особый режим работы. Как правило, не используется. */
    TCEP_default_password_auth_type,	/*!< deprecated. Следует применять TCEP_default_password_auth_type_ascii. Запрос значения по умолчанию для аутентификации, 
					     задаваемой auth_type, в символах TCHAR. deprecated. */
    TCEP_default_password_auth_type_ascii, /*!< Запрос значения по умолчанию для аутентификации, задаваемой auth_type, в ASCIIZ-строке (char*).*/
    TCEP_sm_params,			/*!< Запрос параметров защищенного соединения.*/
    TCEP_cloud_extensions,		/*!< Расширения ключевого контейнера (Cloud).*/
    TCEP_cloud_permissions		/*!< Разрешения ключа(Cloud).*/
} TRdrFkcFolderEnumParam;

/*! \ingroup rdr_ext_folder_fkc_struct
* \brief Структура, содержащая счетчики аутентификации SESPAKE в BE-формате последовательно: cSESPAKE, cFail, cCFail.
* \sa \ref rdr_ext_folder_fkc_struct, #rdr_folder_get_param, #rdr_folder_set_param, #rdr_auth_info, #TRdrFkcInfoCounter
* 
*/
typedef DWORD TRdrFkcSespakeCounters[TSespakeCounterType_MAX_V1];

/*! \ingroup rdr_ext_trans_struct
* \brief Идентификатор сессии для сессионных протоколов.
* \sa #rdr_sespake_first_step
* 
*/
typedef DWORD TRdrFkcTrID;

/*!
* \brief Параметры, общие для всех типов носителей
*/
typedef struct {
    unsigned folders : 1; /*!< Наличие на носителе папок для хранения контейнеров. При 0 контейнер можно записать только один, в корневую папку.*/
    unsigned long_names : 1; /*!< Носитель поддерживает длинные имена контейнеров. Если 1, то контейнеры открываются по полному имени, иначе по имени, полученному на перечислении (#READER_FUN_FOLDER_ENUM_OPEN). Может быть установлен только, если (folders == 1). */
    unsigned can_create_folder : 1; /*!< Возможность создания папок (альтернатива - наличие предразмеченной файловой системы). Может быть установлен только, если (folders == 1). */
    unsigned functional_container : 1;  /*!< Наличие встроенных криптографических механизмов (неизвлекаемые закрытые ключи, ФКН).*/
    unsigned premapped_files : 1; /*!< Носитель имеет размеченную файловую систему и файлы неизменяемого размера: может быть установлен только если can_create_folder == 0*/
} TRdrUniversalCarrierFlags;

/*!
* \brief Параметры защищенного соединения
*/
typedef struct {
    unsigned SM : 1;		     /*!< Наличие защищенного канала между провайдером и носителем. Для SESPAKE всегда должно быть зажжено в 1.*/
    unsigned genKey : 1;	     /*!< Возможность создавать ключи/контейнеры на носителе.*/
    unsigned setKey : 1;	     /*!< Возможность устанавливать значения создаваемых на носителе ключей.*/
    unsigned presentFN : 1;	     /*!< deprecated, not used*/
    unsigned presentHash : 1;	     /*!< Наличие функций хэширования, используемых для визуализации подписи.*/
    unsigned ableDH : 2;             /*!< Режим поддержки VKO: 0 - не поддерживается; 1 - поддержка VKO без маски; 2 - поддержка маскированного VKO.*/
    unsigned real_edwards_auth : 1;  /*!< Полноценная поддержка кривых Эдвардса: в интерфейсе SESPAKE передаются точки в форме Эдвардса.*/
    unsigned csp_interface : 1;      /*!< Альтернативный интерфейс: хэдер заменяется на сертификаты и расширения. В большинстве случаев должен быть установлен в 0. (\ref csp_interface) */
    unsigned dh_supported_algid : 2; /*!< Набор поддерживаемых VKO-алгоритмов: 0 - не поддерживаются; 1 - только VKO GOST R 34.10-2001; 2 - только VKO GOST R 34.10-2012; 3 - оба.*/
    unsigned bad_rng : 1;            /*!< На токене нет надержного ДСЧ, только ПДСЧ. Для генерации ключа требуется дополнительная случайность от провайдера. */
    unsigned weak_airithmetic : 1;   /*!< На токене используется слабодоверенная арифметика, подпись нуждается в проверке. */
    unsigned gen_key_with_cert : 1;  /*!< На токене при генерации ключа сразу создаётся и сертификат на этот ключ. Подфлаг csp_interface. */
} TRdrFkcCarrierFlags;


/*! 
* \defgroup rdr_cipher_modes Поддерживаемые режимы шифрования.
* \brief Константы, используемые для задания используемого режима шифрования.
* \{
*/
//! Шифрование в режиме CBC
#define RDR_FKC_CIPHER_MODE_CBC 0 
//! Шифрование в режиме CFB
#define RDR_FKC_CIPHER_MODE_CFB 1 //!< Шифрование в режиме CFB
//! Шифрование в режиме CNT
#define RDR_FKC_CIPHER_MODE_CNT 2 //!< Шифрование в режиме CNT (рекомендуется)
/*! \}*/

/*! 
* \brief Контекст вызова провайдера
 */
typedef struct {
    void * _pCallCtx; //!< Контекст провайдера, инвалидируется при выходе из транзакции. Указатель нужно перезаписывать на каждом вызове READER_FUN_LOCK.
    void * _current_params; //!< Контекст считывателя.
    const void * _pCont; //!< Контекст контейнера.
    void * _hwnd; //!< Хэндл родительского окна приложения, использующего криптопровайдер.
    DWORD flags; //!< Флаги провайдера. Наиболее полезным является CRYPT_SILENT.
    unsigned license; //!< Разрешения лицензий.
    BOOL isService; //!< Признак работы в режиме службы
} TProvCallCtx;

/*!
* \defgroup rdr_buttons Поддерживаемые кнопки в окне сообщения.
* \brief Константы, используемые для задания кнопок, используемых в окне вывода сообщения.
* \{
*/
//! Отобразить кнопку ОК
#define RDR_MESSAGE_BUTTON_OK 1
//! Отобразить кнопку Cancel
#define RDR_MESSAGE_BUTTON_CANCEL 2
/*! \}*/

/*!
* \brief Набор кнопок, отображаемых в вызываемом окне сообщения
*/
typedef WORD TRdrButtonsMask;

/*!
* \brief Функция вычисления имитовставки
*/
typedef DWORD(*TFunComputeMac)(TProvCallCtx, const BYTE *, size_t, BYTE *, size_t *);

/*!
* \brief Функция зашифрования
*/
typedef DWORD(*TFunEncrypt)(TProvCallCtx, const BYTE *, size_t, BYTE *, size_t *, BOOL *);

/*!
* \brief Функция расшифрования
*/
typedef DWORD(*TFunDecrypt)(TProvCallCtx, const BYTE *, size_t, BYTE *, size_t *);

/*!
* \brief Функция получения пароля из кэша провайдера
*/
typedef DWORD(*TFunGetCachePassword)(TProvCallCtx, DWORD, TSupSysInfoAsciiText *);

/*!
* \brief Типа колбэка для функции вывода окна с сообщением
*/
typedef BOOL(*TWindowCheckCloseCallback)(void *);

/*!
* \brief Функция для вывода окна с сообщением
*/
typedef DWORD(*TFunShowMessage)(TProvCallCtx, const TCHAR *, TWindowCheckCloseCallback, void *, TRdrButtonsMask);

/*!
* \brief Функция для расчет хэша
*/
typedef DWORD(*TFunComputeHash)(TProvCallCtx, unsigned int /*algid*/, BYTE * /*data*/, size_t /*data_length*/, BYTE * /*hash*/, size_t * /*hash_length*/ );

/*!
* \brief Функция для расчет HMAC
*/
typedef DWORD(*TFunComputeHMAC)(TProvCallCtx, unsigned int /*algid*/, const BYTE * /*key*/, size_t /*key_length*/, const BYTE * /*data*/, size_t /*data_length*/, BYTE * /*out_hmac*/, size_t * /*out_hmac_length*/);

/*!
* \brief Функция для генерации ПСП
*/
typedef DWORD(*TFunGenRandom)(TProvCallCtx, BYTE * /*out_random*/, size_t /*in random_length*/);

/*!
* \brief Функция создания временного защищенного хранилища произвольной информации
*/
typedef void*(*TFunProtectedStoreCreate)(TProvCallCtx);

/*!
* \brief Функция уничтожения защищенного хранилища
*/
typedef void(*TFunProtectedStoreDestroy)(void * /*store_handle*/);

/*!
* \brief Функция для установки пары <ключ-значение> в защищенное хранилище
*/
typedef DWORD(*TFunProtectedStorePut)(TProvCallCtx, void * /*store_handle*/, BOOL /*isLM*/, const TCHAR * /*key*/, const BYTE * /*value*/, const size_t /*value_length*/);

/*!
* \brief Функция для получения значения из защищенного хранилища по ключу
*/
typedef DWORD(*TFunProtectedStoreGet)(TProvCallCtx, const void * /*store_handle*/, BOOL /*isLM*/, const TCHAR * /*key*/, BYTE * /*value*/, size_t * /*value_length*/);

/*!
* \brief Функция для удаления значения из защищенного хранилища по ключу
*/
typedef void(*TFunProtectedStoreRemove)(void * /*store_handle*/, BOOL /*isLM*/, const TCHAR * /*key*/);

typedef TRdrFkcRsaKey TRdrAsn1BlobType_RSA_pubkey_struct; /*struct for TRdrAsn1BlobType_RSA_pubkey blob type*/

/*поддерживаемые виды ASN.1-блобов*/
typedef enum {
  TRdrAsn1BlobType_RSA_pubkey /*PKCS#1 формат открытого ключа; разбирается в структуру TRdrAsn1BlobType_RSA_pubkey_struct*/
} TRdrAsn1BlobType;

/*!
* \brief Функция для разбора некоторых видов ASN.1-блобов
*/
typedef DWORD (*TFunDecodeASN1Blob)(TProvCallCtx, TRdrAsn1BlobType /*blob_type*/, const BYTE* /*asn1blob*/, DWORD /*asn1blob_size*/, void* /*decoded_struct_buf*/, DWORD* /*decoded_struct_buf_size*/);

/*!
* \brief Структура с функциями обратного вызова
*/
typedef struct {
    TFunEncrypt encrypt; //!< Функция шифрования для защищенного канала
    TFunDecrypt decrypt; //!< Функция расшифрования для защищенного канала
    TFunComputeMac compute_mac; //!< Функция вычисления имитовставки для защищенного канала
    TFunGetCachePassword get_password; //!< Функция получения пароля из кэша провайдера
    TFunShowMessage show_message; //!< Функция для вывода окна с сообщением
    TFunComputeHash compute_hash; //!< Функция для расчета хэша
    TFunComputeHMAC compute_hmac; //!< Функция для расчета HMAC
    TFunGenRandom gen_random; //!< Функция для генерации псевдослучайной последовательности заданной длины
    TFunProtectedStoreCreate create_store; //!< Функция создания временного защищенного хранилища произвольной информации
    TFunProtectedStoreDestroy destroy_store; //!< Функция уничтожения защищенного хранилища
    TFunProtectedStorePut put_to_store; //!< Функция для установки пары <ключ-значение> в защищенное хранилище
    TFunProtectedStoreGet get_from_store; //!< Функция для получения значения из защищенного хранилища по ключу
    TFunProtectedStoreRemove remove_from_store; //!< Функция для удаления значения из защищенного хранилища по ключу
    TFunDecodeASN1Blob decode_asn1_blob; //!< Функция для декодирования определенных ASN.1-блобов в структуры
} TCarrierCallbacks;

#endif /* !_READER_INDEPENDENT_RDR_H */
