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

/*!
 * \file $RCSfile$
 * \version $Revision: 233004 $
 * \date $Date:: 2021-09-27 16:58:59 +0300#$
 * \author $Author: markova $
 * \brief Интерфейс ко всем считывателям (RDR).
 */

#if !defined( _READER_H )
#define _READER_H

#include <stdlib.h>
#include <tchar.h>

#include "reader/support.h" 
#include "reader/rdr_indie.h" 
#include "reader.kit/sup_sys.h"
#include "reader.kit/sup_lst.h"

#define READER_FUN_PASSWD_TERM 0x304
#define READER_FUN_CARRIER_TYPE 0x305
#define READER_FUN_CANCEL_CONSEQUENCES 0x1300
// 0x2300 удалён
#define READER_FUN_LOCK 0x2301
#define READER_FUN_UNLOCK 0x2302
#define READER_FUN_CONNECT_CARRIER 0x2303
#define READER_FUN_DISCONNECT_CARRIER 0x2304
// 0x2305 удалён
#define READER_FUN_LOCAL_MACHINE 0x2306
#define READER_FUN_GET_PARAM 0x2307
#define READER_FUN_FOLDER_PARAM_SET 0x2308
#define READER_FUN_AUTH_INFO 0x2309
#define READER_FUN_SET_APP 0x230A
#define READER_FUN_PASSWORD_TYPE 0x230B
#define READER_FUN_PROVIDER_INFO 0x230C
#define READER_FUN_ALGID_INFO 0x230D
#define READER_FUN_SET_AUTH_INFO 0x230E
#define READER_FUN_SET_SM_STATE 0x230F
#define READER_FUN_GET_APPLET_TEXT_INFO 0x2310
#define READER_FUN_GET_LIC_PERMISSIONS 0x2311
#define READER_FUN_UNIQUE_GET 0x3300
#define READER_FUN_USER_DEFINED_NAME_GET 0x3301
#define READER_FUN_FOLDER_ENUM_OPEN 0x3302
#define READER_FUN_FOLDER_ENUM_NEXT 0x3303
#define READER_FUN_FOLDER_ENUM_CLOSE 0x3304
#define READER_FUN_FOLDER_OPEN 0x3305
#define READER_FUN_FOLDER_CLOSE 0x3306
#define READER_FUN_PASSWD_PHRASE 0x3309
#define READER_FUN_RANDOM_GET 0x3310
#define READER_FUN_GET_DEFAULT_FOLDER 0x3311
#define READER_FUN_SET_DEFAULT_FOLDER 0x3312
#define READER_FUN_GET_HARDWARE_FLAGS 0x3313
#define READER_FUN_SET_HARDWARE_FLAGS 0x3314
#define READER_FUN_OID_INFO 0x3315

#define READER_FUN_SIMPLE_LOGIN_TEXT 0x5301
#if defined _MSC_VER
/* Макроопределение READER_FUN_SIMPLE_LOGIN является устаревшим.
 * Если пароль вашему устройству передается в виде строки char или BYTE, и вы проводите преобразование TCHAR*->char* при получении пароля,
 * следует использовать функцию READER_FUN_SIMPLE_LOGIN_ASCII, который пароль передается провайдером в виде char*. Если же вам по-прежнему
 * необходимо использование паролей в виде строки TCHAR, используйте макрос READER_FUN_SIMPLE_LOGIN_TEXT.
 * В не-Win операционных системах эти функции идентичны, однако преобразование следует провести для унификации кода.
 * При переводе модуля поддержки с READER_FUN_SIMPLE_LOGIN на READER_FUN_SIMPLE_LOGIN_ASCII не забудьте изменить местоположение функции в таблице 
 * функций модуля поддержки, так, чтобы номера шли строго по возрастанию.
 */
#define READER_FUN_SIMPLE_LOGIN __pragma(deprecated("READER_FUN_SIMPLE_LOGIN")) READER_FUN_SIMPLE_LOGIN_TEXT
#else
#define READER_FUN_SIMPLE_LOGIN READER_FUN_SIMPLE_LOGIN_TEXT
#endif 

#define READER_FUN_LOGOUT 0x5302
#define READER_FUN_SELF_LOGIN 0x5303
#define READER_FUN_AUTH_CHALLENGE 0x5304
#define READER_FUN_RESTORE_DEFAULT_ROOT 0x5305
#define READER_FUN_SEC_DESCR_READ 0x5307 
#define READER_FUN_HASH_INIT 0x5308
#define READER_FUN_HASH_DATA 0x5309
#define READER_FUN_HASH_GETVAL 0x530A
#define READER_FUN_HASH_DESTROY 0x530B
#define READER_FUN_SIMPLE_LOGIN_ASCII 0x530C
#define READER_FUN_FOLDER_CLEAR 0x6300

#define READER_FUN_PASSWD_CHANGE_TEXT 0x6301
/* Макроопределение READER_FUN_PASSWD_CHANGE является устаревшим.
 * Если пароль вашему устройству передается в виде строки char или BYTE, и вы проводите преобразование TCHAR*->char* при получении пароля,
 * следует использовать функцию READER_FUN_PASSWD_CHANGE_ASCII, который пароль передается провайдером в виде char*. Если же вам по-прежнему
 * необходимо использование паролей в виде строки TCHAR, используйте макрос READER_FUN_PASSWD_CHANGE_TEXT.
 * В не-Win операционных системах эти функции идентичны, однако преобразование следует провести для унификации кода.
 * При переводе модуля поддержки с READER_FUN_PASSWD_CHANGE на READER_FUN_PASSWD_CHANGE_ASCII не забудьте изменить местоположение функции в таблице
 * функций модуля поддержки, так, чтобы номера шли строго по возрастанию.
 */
#if defined _MSC_VER
#define READER_FUN_PASSWD_CHANGE __pragma(deprecated("READER_FUN_PASSWD_CHANGE")) READER_FUN_PASSWD_CHANGE_TEXT
#else
#define READER_FUN_PASSWD_CHANGE READER_FUN_PASSWD_CHANGE_TEXT
#endif 

#define READER_FUN_OPEN 0x6302
#define READER_FUN_CLOSE 0x6303
#define READER_FUN_UNLINK 0x6304
#define READER_FUN_SEC_DESCR_WRITE 0x6307
#define READER_FUN_CLEAR_TRIES 0x6308
#define READER_FUN_SELF_CHANGE 0x630A
#define READER_FUN_PASSWD_CHANGE_ASCII 0x630B
#define READER_FUN_READ 0x7300
#define READER_FUN_WRITE 0x7301
#define READER_FUN_CHSIZE 0x7302
#define READER_FUN_LENGTH 0x7303
#define READER_FUN_KEY_GEN 0x7304
#define READER_FUN_KEY_SET 0x7305
#define READER_FUN_SIGNATURE 0x7307
#define READER_FUN_AGREEMENT 0x7308
#define READER_FUN_GET_FREE_SPACE 0x7309
#define READER_FUN_AGREEMENT_FULL 0x730C
#define READER_FUN_PUBLIC_KEY 0x730D
#define READER_FUN_SET_2001 0x730E
#define READER_FUN_WEAK_SIGNATURE1 0x730F
#define READER_FUN_WEAK_SIGNATURE2 0x7310
#define READER_FUN_KEY_GEN_RSA 0x7311
#define READER_FUN_EXPTMOD_RSA 0x7312
#define READER_FUN_PUBLIC_KEY_RSA 0x7313
#define READER_FUN_AVAILABLE_LENGTH_RSA 0x7314
#define READER_IDS_BLOCK 0x400
#define READER_IDS_BASE 0x1300
#define READER_IDS_CARRIER_TYPE 2
#define READER_IDS_QUANT_V1 ( READER_IDS_CARRIER_TYPE + 1 )

#define READER_PASSWD_DEF_SIZE 0x20

#define READER_CONNECT_CARRIER_FLAG_FORMAT 0x1

#define READER_MODEFLAG_BITS 8

/*!
* \ingroup reader_types
* \defgroup reader_errors Коды ошибок, которые может вернуть модуль поддержки.
* <table>
* <tr><th>Код</th><th>Описание</th></tr>
* <tr><td>ERROR_SUCCESS</td><td>Операция завершилась успешно.</td></tr>
* <tr><td>ERROR_MORE_DATA</td><td>Для операции требуется больший массив, чем переданный.</td></tr>
* <tr><td>ERROR_FILE_NOT_FOUND</td><td>Указанный объект (файл, папка, апплет) не найден или отсутствует.</td></tr>
* <tr><td>ERROR_NOT_SUPPORTED</td><td>Требуемая функция не реализована. Чаще всего не является критической ошибкой.</td></tr>
* <tr><td>ERROR_NO_MORE_ITEMS</td><td>Больше не осталось элементов для перечисления.</td></tr>
* <tr><td>NTE_NOT_SUPPORTED</td><td>Указанная функция не поддерживается. Чаще всего является критической ошибкой.</td></tr>
* <tr><td>NTE_EXISTS</td><td>Создаваемый объект уже существует.</td></tr>
* <tr><td>NTE_BAD_KEYSET</td><td>Попытка выполнения операции на несуществующем ключе.</td></tr>
* <tr><td>NTE_BAD_KEY_STATE</td><td>Попытка выполнения операции в некорректном состоянии контейнера.</td></tr>
* <tr><td>NTE_NO_MEMORY</td><td>Не хватило памяти для аллокации.</td></tr>
* <tr><td>NTE_TOKEN_KEYSET_STORAGE_FULL</td><td>На носителе не достаточно места для создания объекта.</td></tr>
* <tr><td>NTE_SILENT_CONTEXT</td><td>Для операции требуется показать диалог, а провайдер запущен в CRYPT_SILENT.</td></tr>
* <tr><td>NTE_PERM</td><td>Выполнение указанной операции запрещено.</td></tr>
* <tr><td>ERROR_INVALID_PARAMETER, NTE_BAD_DATA</td><td>В функцию переданы неверные параметры.</td></tr>
* <tr><td>SCARD_W_CANCELLED_BY_USER</td><td>Пользователь прервал исполнение функции.</td></tr>
* <tr><td>SCARD_W_WRONG_CHV</td><td>Передан неверный пароль.</td></tr>
* <tr><td>SCARD_E_INVALID_CHV</td><td>Передан пароль неправильного формата.</td></tr>
* <tr><td>SCARD_W_CHV_BLOCKED</td><td>Карта заблокирована из-за превышения числа попыток ввода неверного пароля.</td></tr>
* <tr><td>SCARD_E_NOT_READY</td><td>Для работы со смарт-картой требуется выполнить ряд предварительных действий.</td></tr>
* <tr><td>SCARD_W_SECURITY_VIOLATION</td><td>Произошло нарушение безопасности защищенного канала.</td></tr>
* <tr><td>SCARD_E_READ_ONLY_CARD</td><td>В текущем состоянии на карте можно выполнять только базовые операции.</td></tr>
* </table>
* Также могут быть возвращены управляющие коды: для установления аутентификации (\ref rdr_auth_errs) и для выполнения какой-либо базовой операции (\ref rdr_return_errs).
*/

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

typedef BYTE * TReaderFkcOrderPtr; //!< Байтовый массив произвольной длины.
typedef BYTE * TReaderFkcUKMPtr; //!< Массив, содержащий UKM.
typedef BYTE * TReaderFkcRndmPtr; //!< Массив с рандомизатором.

//! Флаги, задающие режим открытия/создания файла/папки 
typedef struct 
{
    unsigned o_read : 1;      /*!< Объект открывается на чтение */
    unsigned o_write : 1;     /*!< Объект открывается на запись */
    unsigned o_create : 1;    /*!< Объект должен быть создан */
    unsigned o_private : 1;   /*!< Открывается/создаётся объект, чтение которого защищено паролем (применяется только для файлов) */
} TReaderInfoOpenFlags;

//! Фраза, выводимая при аутентификации
typedef struct
{
    TRdrLoginInfoType type;  /*!< Тип аутентификации, для которой запрашивается фраза*/
    TSupSysInfoText text;    /*!< Аутентификационная фраза */
} TReaderInfoPasswdText;

//! Тип считывателя
typedef struct 
{
    TSupSysNickname type; /*!< Тип считывателя */
    const TCHAR * path_to_item; /*!< Путь до объекта */
} TReaderInfoCarrierType;

//! Структура для получения поддерживаемых Algid'ов
typedef struct
{
    BOOL    forUserKey;		    /*!< TRUE - запрос на возможные алгоритмы ключа пользователя, FALSE - запрос на алгоритмы аутентификации (SESPAKE) */
    TRdrLoginInfoType auth_type;    /*!< если запрос на алгоритмы аутентификации, указывается, какая аутентификация имеется ввиду */
    size_t size;		    /*!< количество поддерживаемых алгоритмов */
    TRdrFkcEllipticPointParam * algs;   /*!< массив идентификаторов */
} TReaderInfoAlgIds; 

//! Структура для получения поддерживаемых длин RSA ключей
typedef struct
{
    DWORD min_key_bits; //минимальная длина RSA-ключа в битах
    DWORD max_key_bits; //максимальная длина RSA-ключа в битах

    /*Опциональный параметр. Если равен 0, то поддерживаются все длины в диапазоне min_key_bits, max_key_bits.
    Если не 0, то допустимые длины ключей равны 
    [min_key_bits, min_key_bits+1*increment_bits, min_key_bits+2*increment_bits,... max_key_bits]
    */
    DWORD increment_bits; 
} TReaderAvailableRsaLength;

//! Структура для установки состояния защищенного канала
typedef struct
{
    BOOL    isSM;		    /*!< TRUE - защищенный канал был установлен, FALSE - провайдер сбросил защищенный канал */
    TRdrLoginInfoType auth_type;    /*!< если iSM, то тип устанавливаемой аутентификации, иначе - 0 */
} TReaderInfoSmState;

#define READER_VALID_FUN_OK 0
#define READER_VALID_FUN_WRONG (-1)
#define READER_VALID_FUN_UNDEF 1

//! Структура для подключения к носителю
typedef struct 
{
    unsigned flags; /*!< [in] READER_CONNECT_CARRIER_FLAG_FORMAT для форматирования */
    TSupSysEList *media_list; /*!< [in] список зарегистрированных носителей */
    unsigned int applet_count; /*!< [out] число поддерживаемых приложений на данном носителе */
    TSupSysFindValidFun valid_fun; /*!< [in] колбэк для проверки того, что media из списка подходит для данного считывателя. Возвращает READER_VALID_FUN_-коды */
    TSupSysFindInfo* rdr_info; /*!< [in] valid_fun callback info*/
} TReaderInfoConnectCarrier;

//! Структура перечисления контейнеров в приложении
typedef struct 
{
    const TSupSysEContext *context; /*!< Внутренний контекст модуля (в функциях не должен использоваться) */
    TSupSysInfoText name; /*!< [out] На enum_open поле length должно быть проинициализировано максимальным значением длины имени контейнера в символах без учета \0.
			             На enum_next сюда помещается имя следующего контейнера на карте с указанием длины в символах без \0 */
    TSupSysInfoUntyped add_info; /*!< Дополнительный контекст перечисления, специфичный для модуля поддержки, провайдером не используется */ 
    TSupSysInfoText prototype; /*!< Шаблон перечисления: если флаг установлен RDR_FOLDER_ENUM_FLAG_NEW, то тут будет настоящее имя контейнера */ 
    unsigned flags; /*!< Флаги перечисления. (\ref rdr_enum_flags) */ 
} TReaderInfoFolderEnum;

//! Структура открытия/создания папки
typedef struct
{
    TSupSysInfoText name; /*!< Имя создаваемой папки (не равно имени контейнера для (long_names == 0) */
    size_t mode_bits; /*!< not used (depricated) */
    TReaderInfoOpenFlags mode; /*!< Режим открытия/создания папки*/
} TReaderInfoFolderOpen;

//! Структура проведения простой (SIMPLE) аутентификации в функции READER_FUN_SIMPLE_LOGIN_TEXT
typedef struct
{
    TRdrLoginInfoType auth_type; /*!< Тип проводимой аутентификации */
    TSupSysInfoText passwd; /*!< Значение пароля */
    int retries; /*!< [out] Число попыток ввода пароля. Инициализируется, только если есть возможность вернуть настоящее число попыток ввода пароля. */
} TReaderInfoLogin;

//! Структура проведения простой (SIMPLE) аутентификации в функции READER_FUN_SIMPLE_LOGIN_ASCII
typedef struct
{
    TRdrLoginInfoType auth_type; /*!< Тип проводимой аутентификации */
    TSupSysInfoAsciiText passwd; /*!< Значение пароля */
    int retries; /*!< [out] Число попыток ввода пароля. Инициализируется, только если есть возможность вернуть настоящее число попыток ввода пароля. */
} TReaderInfoLoginAscii;


//! Структура установки/запроса значения дескриптора безопасности контейнера
typedef struct 
{
    unsigned long sec_info; /*!< Информация с признаками информации о десктрипторе */
    TSupSysInfoUntyped sec_descr; /*!< Значение PSECURITY_DESCRIPTOR */
} TReaderInfoSecDescrRW;

//! Структура смены простой (SIMPLE) аутентификации в функции READER_FUN_PASSWD_CHANGE_TEXT
typedef struct
{
    TRdrLoginInfoType auth_type; /*!< Тип сменяемой аутентификации */
    TSupSysInfoText passwd; /*!< Значение нового пароля */
    TRdrLoginInfoType set_auth_type; /*!< Тип аутентификации, под которой меняется пароль. Если 0, то не установлена */
    TSupSysInfoText set_passwd; /*!< Значение пароля аутентификации, под которой меняется пароль */
} TReaderInfoPasswdChange;

//! Структура смены простой (SIMPLE) аутентификации в функции READER_FUN_PASSWD_CHANGE_ASCII
typedef struct
{
    TRdrLoginInfoType auth_type; /*!< Тип сменяемой аутентификации */
    TSupSysInfoAsciiText passwd; /*!< Значение нового пароля */
    TRdrLoginInfoType set_auth_type; /*!< Тип аутентификации, под которой меняется пароль. Если 0, то не установлена */
    TSupSysInfoAsciiText set_passwd; /*!< Значение пароля аутентификации, под которой меняется пароль */
} TReaderInfoPasswdChangeAscii;


//! Структура смены простой (SIMPLE) аутентификации
typedef struct
{
    size_t mode_bits; /*!< not used (depricated) */ 
    TReaderInfoOpenFlags mode;  /*!< Режим открытия/создания файла */
    TSupSysInfoText name; /*!< Имя создаваемого файла */
    TRdrFileNumber num; /*!< Номер создаваемого файла */
} TReaderInfoOpen;

//! Структура удаления файла
typedef struct
{
    TSupSysInfoText name; /*!< Имя удаляемого файла */
    TRdrFileNumber num; /*!< Номер удаляемого файла */
} TReaderInfoUnlink;

//! Структура чтения данных из файла
typedef struct
{
    size_t from; /*!< Смещение, начиная с которого начинается чтение. Прочитанные данные нужно всегда писать в info.info по нулевому смещению. */
    TSupSysInfoUntyped info; /*!< info.info - буфер под читаемые данные; info.length на входе в функцию - сколько нужно прочитать; на выходе из функции - сколько осталось прочитать. 
			          Провайдер реализует поблоковое чтение, поэтому, если носитель может читать только небольшими блоками, можно не усложнять реализацию циклами, а честно
				  вычитать из info.length, сколько было реально прочитано */
} TReaderInfoRead;

//! Структура записи данных в файл
typedef struct
{
    size_t from; /*!< Смещение, начиная с которого нужно писать. Смещаться нужно в файле-результате, а не info.info. */
    TSupSysInfoUntyped info; /*!< info.info - буфер с записываемыми данными; info.length на входе в функцию - сколько нужно записать; на выходе из функции - сколько осталось записать 
			     Провайдер реализует поблоковую запись, поэтому, если носитель может записывать только небольшими блоками, можно не усложнять реализацию циклами, а честно
			     вычитать из info.length, сколько было реально записано */
} TReaderInfoWrite;

//! Новый размер файла в байтах
typedef size_t TReaderInfoChSize;

//! Запрашиваемый текущий размер файла в байтах
typedef size_t TReaderInfoLength;

//! Размер свободного места
typedef size_t TReaderInfoFreeSpaceSize;

//! Запрашиваемое хэш-значение от считывателя
typedef BYTE TRdrHashValue[RDR_FKC_HASH_VALUE_SIZE_512];

//! Структура инициализации процесса хэширования на считывателе
typedef struct
{
    unsigned int hash_algid;	    //!< ALG_ID используемой хэш-функции (CALG_SHA1/CALG_GR3411/CALG_GR3411_2012_256/CALG_GR3411_2012_512) 
    TSupSysEContext * handle;	    //!< [out] Хэндл (ID) созданного объекта хэша на считывателе.
} TReaderFkcHashInit;

//! Структура хэширования данных на считывателе
typedef struct
{
    TSupSysEContext * handle;	    //!< Хэндл объекта хэша, полученный на инициализации
    TSupSysInfoUntyped info;	    //!< Хэшируемые данные
    size_t hashed_len;		    //!< [out] Количество реально прохэшированных данных
} TReaderFkcHashData;

//! Структура получения хэш-значения из считывателя
typedef struct
{
    TSupSysEContext * handle;	    //!< Хэндл объекта хэша, полученный на инициализации
    TRdrHashValue hashval;	    //!< [out] Хэш-значение, рассчитанное считывателем
    size_t hash_len;	            //!< [out] Длина хэш-значения
} TReaderFkcHashGetVal;


typedef TSupSysEContext * TReaderFkcHashDestroy; //!< Хэндл удаляемого объекта хэша
typedef TRdrFkcSespakeCounters TReaderInfoSespakeCounters; //!< Структура счетчиков SESPAKE
typedef TRdrFkcFolderEnumParam TReaderFkcFolderEnumParam; //!< Вид запрашиваемоего/устанавливаемого параметра

//! Структура с данными и функциями обратного вызова из провайдера
typedef struct
{
    TProvCallCtx context; //!< Текущий набор параметров для функций обратного вызова
    TCarrierCallbacks callbacks; //!< Набор колбэков, которыми могут пользоваться модули поддержки
} TReaderProviderInfo;

typedef enum {
    TRdrFkcSecureMessagingMode_CNT,
    TRdrFkcSecureMessagingMode_CBC
} TRdrFkcSecureMessagingMode;

typedef enum {
    TRdrFkcSecureMessagingCipher_28147,
    TRdrFkcSecureMessagingCipher_3412M
} TRdrFkcSecureMessagingCipher;

typedef enum {
    TRdrFkcSecureMessagingImit_28147,
    TRdrFkcSecureMessagingImit_3413M
} TRdrFkcSecureMessagingImit;

//! Структура параметров свойств защищенного канала
typedef struct _TRdrFkcSecureMessagingParams {
    BOOL padding; //!< дополнение до кратности 8 по ISO 7816-4
    TRdrFkcSecureMessagingType sm_type; //!< тип канала
    union {
	struct {
	    TRdrFkcSecureMessagingCipher cipher_algid; //!< используемый шифр
	    TRdrFkcSecureMessagingImit imit_algid; //!< используемая имитовставка
	    TRdrFkcSecureMessagingMode cipher_mode; //!<  используемый режим шифрования
	} iso_params;
	struct {
	    void* dummy;
	} fkc_params;
    } params;
} TRdrFkcSecureMessagingParams;

//! Структура получения параметров носителя/аутентификации/приложения
typedef struct
{
    TReaderFkcFolderEnumParam paramID; //!< идентификатор запрашиваемого параметра
    union {
	struct {
	    TRdrLoginInfoType auth_type; //!< идентификатор аутентификации, для которой запрашиваются счетчики
	    TReaderInfoSespakeCounters counters; //!< счетчики  в BE-формате последовательно: cSESPAKE, cFail, cCFail.
	    BOOL has_counters; //!< карта имеет настоящие счетчики
	} sespake_counters; //!< TCEP_sespake_counters
	struct {
	    TCHAR * password;
	    size_t max_length;
	} root_password;				//!< TCEP_default_password
	DWORD security_level;				//!< TCEP_fkc_csp_interface_container (\ref csp_interface)
	TRdrFkcCarrierFlags fkc_flags;			//!< TCEP_fkc_flags
	TRdrUniversalCarrierFlags uni_flags;		//!< TCEP_uni_flags
	unsigned int auth_types;			//!< TCEP_auth_types
	TRdrLoginInfoType is_auth_type_blocked;		//!< TCEP_auth_state. 
	struct {
	    TCHAR * password;
	    size_t max_length;
	    DWORD auth_type;
	} any_password;					//!< TCEP_default_password_auth_type
	struct {
	    char * password;
	    size_t max_length;
	    DWORD auth_type;
	} any_password_ascii;				//!< TCEP_default_password_auth_type_ascii
	TRdrFkcSecureMessagingParams sm_params;         //!< TCEP_sm_params
    } info;
} TReaderInfoGetParam;

//! Структура установления типизированных параметров носителя/аутентификации/приложения
typedef struct
{
    TReaderFkcFolderEnumParam paramID;
    union {
        TSupSysInfoUntyped hex_param;             //!< TCEP_header, TCEP_cloud_certificate, TCEP_cloud_extensions
	TSupSysInfoAsciiText string_param;        //!< TCEP_cloud_auth_server, TCEP_cloud_sign_server, TCEP_cloud_OAuth2_auth_token, TCEP_cloud_OAuth2_id_token
	DWORD dword_param;			  //!< TCEP_cloud_certificate_id, TCEP_cloud_permissions
    } info;
} TReaderInfoSetParam;

//! Возможные значения кодировки паролей на носителе
typedef enum {
    TReaderInfoPwdEncoding_default = 0,
    TReaderInfoPwdEncoding_UTF8 = 1
} TReaderInfoPwdEncoding;


//! Структура, описывающая свойства простой парольной аутентификации
typedef struct
{
    unsigned int uiRetries;	/*!< Счётчик оставшихся попыток, который отбражается пользователю перед вводом пароля */
    size_t max_pwd_length;	/*!< Максимальная поддерживаемая длина пароля */
    size_t min_pwd_length; 	/*!< Минимальная поддерживаемая длина пароля */
    TReaderInfoPwdEncoding password_encoding; /*!< Кодировка паролей*/
} TReaderInfoAuthInfoPwd;


//! Структура, описывающая свойства аутентификации по протоколу SESPAKE
typedef struct
{
    BYTE flags;		/*!< флаг 1 говорит о том, что используется group_id; 
			     флаг 2 говорит о том, что используется набор рандомизаторов (salt, ind); 
			     флаг 4 говорит о том, что используется точка Qpw.
			     флаг 8 говорит о том, что используются дополнительные свойства SESPAKE.
			     */

    TRdrFkcEllipticPointParam group_id;  //!< ID параметров алгоритма ключа
    TReaderFkcRndmPtr salt; /*!< рандомизатор salt*/
    BYTE ind;		    /*!< индекс точки ind*/
    TRdrFkcPoint * Qpw;	    /*!< точка Qpw*/
    BOOL prehash_password;  /*!< пароль перед использованием дополнительно хэшируется*/
    BOOL dont_use_mq;       /*!< при выводе ключа SESPAKE на кривых Эдвардса не используется умножение на m/q*/
} TReaderInfoAuthSESPAKE;

//! Обобщение структур, описывающих аутентификацию.
typedef union
{
    TReaderInfoAuthInfoPwd info_pwd;
    TReaderInfoAuthSESPAKE info_sespake;
} TReaderInfoAuthInfoUnion;

//! Информационная структура, предназначенная для получения свойств заданной аутентификации
typedef struct 
{
    TRdrLoginInfoType auth_type; /*!< Тип аутентификации, для которой запрашиваются свойства */
    TCHAR friendly_name[224]; /*!< unused */
    TReaderInfoAuthInfoUnion info; /*!< [out] Свойства запрошенной аутентификации. */
} TReaderInfoAuthInfo;

//! Перечисление шагов при выполнение SESPAKE
typedef enum
{
    TRECc_first = 1,		/*!< Первое сообщение SESPAKE. Провайдер передаёт носителю U1, ожидает U2. */
    TRECc_second = 2		/*!< Второе сообщение SESPAKE. Провайдер передаёт носителю HMACa, ожидает HMACb. */
} TReaderSespakeChallengeClass;

//! Объединение полей, используемых для передачи данных в криптопровайдер после первого и второго шагов SESPAKE
typedef union
{
    struct {
	TRdrFkcPoint * u2;		    //!< Значение U2, рассчитанное в соответствии с протоколом. Ожидается в форме Вейрштрасса. Если зажжен флаг #TRdrFkcCarrierFlags real_edwards_auth, то в форме Эдвардса.
    } first;
     struct {
	BYTE * hmacB;                       //!< Значение HMAC-B, рассчитанное в соответствии с протоколом.
    } second_12;
} TReaderSespakeChallenge2csp;


//! Объединение полей, используемых для передачи данных в носитель на первом и втором шаге SESPAKE
typedef union
{
    struct {
	TRdrFkcPoint * u1;		    //!< Значение U1, рассчитанное в соответствии с протоколом. Передаётся в форме Вейрштрасса. Если зажжен флаг #TRdrFkcCarrierFlags real_edwards_auth, то в форме Эдвардса.
    } first;
    struct {
	BYTE * hmacA;                       //!< Значение HMAC-A, рассчитанное в соответствии с протоколом.
    } second_12;
} TReaderSespakeChallenge2fkc;

//! Структура, передаваемая при выполнении аутентификации по SESPAKE 
typedef struct
{
    TRdrLoginInfoType auth_type;                     //!< Тип аутентификации (ROOT/PUK/CONT)
    TRdrFkcTrID	transaction_id;	                     //!< Уникальный идентификатор транзакции протокола SESPAKE
    TReaderSespakeChallengeClass challenge_class;    //!< Номер шага SESPAKE
    TReaderSespakeChallenge2csp to_CSP;              //!< [out] Данные, возвращаемые носителем после выполнения команды
    TReaderSespakeChallenge2fkc to_FKC;              //!< Данные, посылаемые носителю для выполнения команды
} TReaderInfoAuthChallenge;

/*! \} */

/*!
* \defgroup reader_external_interface Функции внешнего интерфейса библиотек
*/

/*! 
 * \ingroup reader_external_interface 
 * \defgroup Reader_RDR_12 Функции внешнего интерфейса библиотеки считывателей
 */

/*!
* \defgroup reader_interface Интерфейс подключения модулей поддержки
*/


/*!
* \ingroup reader_interface
* \defgroup reader_interface_fkc_fun Интерфейс подключения считывателей
*/  


/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_KEY_GEN
* \brief Функция генерации ключа.
*
* Функция должна создавать случайную ключевую пару средствами ключевого носителя. Вызывается, если выполнено условие (#TRdrUniversalCarrierFlags functional_container && #TRdrFkcCarrierFlags genKey).
* Должна вызываться только под основной аутентификацией. Если (#TRdrUniversalCarrierFlags folders), то вызывается в текущей папке.
*
* \sa \ref TReaderFkcKeyGen
*
*/  


/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_PASSWD_TERM
* \brief Функция получения термина пароля.
*
* Функция должна возвращать термин, которым описывается аутентификационная информация (пароль, ПИН-код, код и т.п.).
* Является опциональной и может быть не реализована. 
* \sa \ref TReaderInfoPasswdText
*
*/

/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_CARRIER_TYPE
* \brief Функция получения типа считывателя.
*
* Функция должна возвращать тип, к которому относится данный считыватель. Для модулях носителей (смарт-карт и токенов) может быть не реализована.
* \sa \ref TReaderInfoCarrierType
*
*/

/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_LOCK
* \brief Функция инициирует секцию работы со считывателем.
*
* Должна захватывать блокировку, если это применимо. Может вызывать последовательно несколько раз: в этом случае, если блокировка уже захвачена, может ничего не делать.
* Помимо установки блокировки может использоваться для настройки окружения, в котором будут выполняться дальнейшие команды: хэндла окна, признака "тихой" работы, сохранение аргументов для 
* передачи в колбэки организации защищенного канала. Параметры не могут использоваться на READER_FUN_DISCONNECT_CARRIER.
* Все команды, требующие функциональной работы со считывателем гарантированно выполняются после данной.
* \sa \ref TProvCallCtx 
*
*/

/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_UNLOCK
* \brief Функция завершения секции работы со считывателем. 
*
* В функции должны быть сняты все блокировки, открытые на предыдущих вызовах READER_FUN_LOCK. 
* Гарантированно вызывается в конце каждого существенного блока работы со считывателем.
* Может быть вызвана несколько раз. На всех вызовах кроме первого, может ничего не делать. 
*
*
*/

/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_CONNECT_CARRIER
* \brief Функция, устанавливающая соединение со считывателем. 
*
* Функция, устанавливающая соединение со считывателем. Возвращает количество апплетов, которые могут быть помещены на данный считыватель.
* Не должна передавать на считыватель функциональные команды. Реализуется только в считывателях, не носителях. 
* В модулях поддержки смарт-карт вместо неё должна быть реализована функция #RSCARD_FUN_CONNECT_CARRIER.
* \sa \ref TReaderInfoConnectCarrier
*/

/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_DISCONNECT_CARRIER
* \brief Функция, закрывающая соединение со считывателем.
*
* Вызывается в конце работы со считывателем, должна закрывать все открытые ранее ресурсы.
* Не рекомендуется передавать функциональные команды. Реализуется только в считывателях, не носителях.
* В данной функции нельзя использовать структуру контекста провайдера, переданную на READER_FUN_LOCK
* Из данной функции нельзя восстановиться - запрещено возвращать коды CPR_ERR_RDR.
*
*/

/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_LOCAL_MACHINE
* \brief  Функция, передающая признак машинного ключа. 
*
* Может быть реализована только в считывателях, подразумевающих возможность разделения ключей по пользователям.
*
*
*/

/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_GET_PARAM
* \brief Функция получения параметров носителя/апплета/аутентификации.
*
* Функция, используемая для получения большого количества параметров носителя/апплета/аутентификации.
* Запрашиваемый параметр определяется через поле paramID, которое может принимать значения из #TRdrFkcFolderEnumParam. Если реализация какого-либо параметра отсутствует, функция должна вернуть ERROR_NOT_SUPPORTED.
*
*
* \sa \ref TReaderInfoGetParam
*/

/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_FOLDER_PARAM_SET
* \brief Функция установки специфических параметров, передаваемых через CryptSetProvParam.
*
* В данный момент не используется нигде кроме CLOUD.
*
*
* \sa \ref TReaderInfoSetParam 
*/

/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_AUTH_INFO
* \brief Функция получения аутентификационной информации. 
*
* На вход получает указание аутентификации, у которой запрашиваются свойства.
* В зависимости от типа (SESPAKE или SIMPLE) возвращает либо свойства SESPAKE (в зависимости от флагов group_id, salt и ind, Qpw), либо ограничения на длину пароля (мин, макс), 
* и кодировку передаваемого носителю пароля. 
*
*
* \sa \ref TReaderInfoAuthInfo
*/

/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_SET_APP
* \brief Функция выбора апплета. 
*
* Получает на вход int, содержащий порядковый номер приложения. Провайдер может посылать значения из диапазона [0:n-1], где n - это максимально возможное
* число апплетов, которое модуль вернул на #READER_FUN_CONNECT_CARRIER или #RSCARD_FUN_CONNECT_CARRIER. Данная функция гарантированно вызывается перед любым началом работы с приложением.
* Если для считывателя/носителя применимо, то должна послать команду, которая инициализируем работу с указанным приложением. Если нет (например, n=1), то может быть не реализована. 
* Если конкретный считыватель/носитель не поддерживает работу с указанным приложением (не имеет апплета), то функция должна быть реализована и вернуть ERROR_FILE_NOT_FOUND.
*
*
*/

/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_PASSWORD_TYPE
* \brief Функция, возвращающая способ запрошенной аутентификации. 
*
* При вызове #READER_FUN_GET_PARAM c типом TCEP_auth_types модуль поддержки передают провайдеру информацию о типах аутентификации (\ref rdr_auth_flags), 
* тем самым указывая, что они есть. Конкретный способ (\ref rdr_auth_algs) указанной аутентификации провайдер получает через вызов функции #READER_FUN_PASSWORD_TYPE. 
* Реализация должна выглядеть примерно следующим образом: if ((*type & AUTH_TYPE_TYPE_MASK) == AUTH_TYPE_TYPE_ROOT) *type = AUTH_TYPE_TYPE_ROOT | AUTH_TYPE_AUTH_SIMPLE;
*
*
* \sa \ref TRdrLoginInfoType
*/

/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_PROVIDER_INFO
* \brief Функция установки колбэков шифрования.
*
* Функция установки колбэков шифрования и имитозащиты, используемых при реализации защищенного канала. 
*
*
* \sa \ref TReaderProviderInfo
*/

/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_ALGID_INFO
* \brief Функция получения перечня поддерживаемых параметров эллиптической кривой.
*
* Функция получения перечня поддерживаемых параметров эллиптической кривой для подписи (forUserKey == TRUE) и/или аутентификации по SESPAKE (forUserKey == FALSE).
* Перечень поддерживаемых алгоритмов формируется как массив, каждый элемент которого хранит значение из #TRdrFkcEllipticPointParam, с правильно установленной длиной.
* Если поле algs информационной структуры равно NULL, то функция устанавливает только длину. 
*
*
* \sa \ref TReaderInfoAlgIds 
*/

/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_OID_INFO
* \brief Функция для получения перечня поддерживаемых OID поддерживаемых параметров для эллиптических кривых. 
* 
* Может быть не реализована. Если она реализована, ее результат будет иметь приоритет перед 
* возвращаемым READER_FUN_ALGID_INFO значением при составлении списка поддерживаемых OID'ов носителя.
*/

/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_SET_AUTH_INFO
* \brief Функция установки новой аутентификации (смены) для SESPAKE.
*
* Принимает на вход новые Qpw, ind, salt, group_id для указанной SESPAKE-аутентификации. 
* Должна быть выполнена за одну APDU-команду. При установке нового значения аутентификации её счетчики должны быть сброшены в начальное положение. 
* Функция выполняется только под аутентификацией: либо той, которую меняют, либо под разблокирующей (администраторской), если носитель её поддерживает. 
* Функция может устанавливать параметры на кривой, отличающейся от той, которая использовалась ранее. 
*
* \sa TReaderInfoAuthInfo
*/

/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_SET_SM_STATE
* \brief Функция передает в модуль поддержки текущее состояние защищенного канала (SM) провайдера.
*
* Принимает на вход BOOL описывающий признак наличия SM. Гарантированно вызывается с FALSE при установке нового канала (перед SESPAKE) и в конце работы с носителем.
* Гарантированно вызывается с TRUE при успехе проведения SESPAKE (после второго шага) с точки зрения провайдера. Все посылаемые команды теперь должны быть зашифрованы.
* Функции запрещено посылать какие-либо сообщения карте. Сбросом аутентификации занимается #READER_FUN_LOGOUT. 
*
*
*/

/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_GET_APPLET_TEXT_INFO
* \brief Функция, получающая краткое описание апплета для окна выбора носителей. 
*
* Может быть не реализована. Если реализована, то должна корректно поддерживать как русский, 
* так и английский языки. 
*
* \sa \ref TSupSysInfoText
*/

/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_UNIQUE_GET
* \brief Функция запроса уникального идентификатора носителя.
*
* Unique должен содержать префикс, идентифицирующий вид носителя, и циферный уникальный номер носителя. Например: XTOKEN_11223344. 
* Если поле text == NULL, функция должна вернуть длину в символах без терминирующего нуля. Если длина меньше необходимой, то функция должна установить её в верную и вернуть ERROR_MORE_DATA.
* Если поле text != NULL, то провайдер гарантирует, что в буфере хватит места на (length + 1) TCHAR-символ. 
* Функция должна быть реализована для всех removable-носителей (смарт-карт и флеш-носителей).
*
* \sa \ref TSupSysInfoText
*/

/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_USER_DEFINED_NAME_GET
* \brief Функция запроса имени носителя, заданного пользователем.
*
* Если поле text == NULL, функция должна вернуть длину в символах без терминирующего нуля. Если длина меньше необходимой, то функция должна установить её в верную и вернуть ERROR_MORE_DATA.
* Если поле text != NULL, то провайдер гарантирует, что в буфере хватит места на (length + 1) TCHAR-символ. 
*
* \sa \ref TSupSysInfoText
*/

/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_FOLDER_ENUM_OPEN
* \brief Функция открытия контекста перечисления папок на носителе.
*
* Если у смарт-карты (USB-токена) в регистрации в реестре задан ключ Folders, где перечислены папки, то данная функция, а также #READER_FUN_FOLDER_ENUM_NEXT и 
* #READER_FUN_FOLDER_ENUM_CLOSE можно не реализовывать. Данная функция должна вернуть максимальную поддерживаемую длину папки, которая может быть возвращена на #READER_FUN_FOLDER_ENUM_NEXT.
* В информационной структуре передаётся add_info, которое может использовать модулем поддержки по своему усмотрению. Крайне желательно на данной функции выполнять настоящее перечисление папок и 
* сохранять их список в add_info, чтобы на #READER_FUN_FOLDER_ENUM_NEXT последовательно возвращать из него по одному имени без обращения к карте. 
* Данная функция может применяться в двух ситуациях: для перечисления существующих папок с ключами на носителе и для получения имени папки, в которой можно создать контейнера (если #TRdrUniversalCarrierFlags long_names == 0).
* В первом случае функция вызывается с флагом RDR_FOLDER_ENUM_FLAG_OPEN, во втором - с RDR_FOLDER_ENUM_FLAG_NEW. Если функция вызвана с RDR_FOLDER_ENUM_FLAG_NEW, то в prototype будет находиться настоящее полное имя 
* создаваемого контейнера. Его можно использовать для формирования имени папки. Как правило, в модулях смарт-карт данное поле не используется.
*
*
* \sa \ref TReaderInfoFolderEnum
*/

/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_FOLDER_ENUM_NEXT
* \brief Функция получения следующем папки из открытого контекста перечисления. 
*
* Должна копировать имя папки в поле name, правильно устанавливая длину имени. Рекомендуется реализовывать без взаимодействия с носителем, а возвращать элементы списка,
* построенно на #READER_FUN_FOLDER_ENUM_OPEN. Если были перечислены все носители, функция должна вернуть ошибку ERROR_NO_MORE_ITEMS.
*
*
* \sa \ref TReaderInfoFolderEnum
*/

/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_FOLDER_ENUM_CLOSE
* \brief Функция завершения перечисления.
*
* Гарантированно вызывается в конце перечисления при любом его результате. Используется для очистки ресурсов, выделенных на #READER_FUN_FOLDER_ENUM_OPEN. 
*
*  \sa \ref TReaderInfoFolderEnum
*/

/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_FOLDER_OPEN
* \brief Функция открытия/создания папки на носителе.
* 
* На вход приходит имя папки (в случае long_names совпадает с именем ключевого контейнера). Если установлен режим o_create, то папка должна быть создана. 
* В остальным случаях открывается в общем режиме. Если у носителя нет места для создания, то он должен вернуть NTE_TOKEN_KEYSET_STORAGE_FULL. Если такая папка уже есть, то NTE_EXISTS.
* Создание может выполняться только под аутентификацией. Для (long_names == FALSE) имя получается из функции #READER_FUN_FOLDER_ENUM_NEXT. После создания папки она должна быть открыта.
*
* 
* \sa \ref TReaderInfoFolderOpen
*/

/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_FOLDER_CLOSE
* \brief Функция закрытия папки.
* Данная функция вызывается в конце работы с ключевым контейнером. На ней может происходить освобождение ранее выделенных ресурсов в модуле поддержки, выделенных для открытой папки.
* В большинстве случаев может быть не реализована. Функция вызывается без транзакции, поэтому не должна посылать APDU-команды.
*
* \sa \ref TReaderInfoFolderOpen
*/

/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_PASSWD_PHRASE
* \brief Функция получения фразы для аутентификации.
* Возвращает строчку, которая позволяет пользователю убедиться, что он работает со своей картой. Как правило, не используется. Единственное применение было в картах УЭК.
*
* \sa \ref TReaderInfoPasswdText 
*/

/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_RANDOM_GET
* \brief Функция получения случайных значений.
* Обращается к встроенному ДСЧ носителя и получает некоторое количество случайных байт. Используется для тестирования ДСЧ, не для генерации. В данный момент не используется, но в будущем может потребоваться.
* \sa \ref TSupSysInfoUntyped
*/

/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_GET_DEFAULT_FOLDER
* \brief Функция получения имени папки с контейнером по умолчанию.
* Должна быть реализована, если носитель поддерживает возможность запоминания данного значения. Если нет, то контейнер по умолчанию реализуется через хранение файла def.key в корневой директории.
* \sa \ref TSupSysInfoText
*/

/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_SET_DEFAULT_FOLDER
* \brief  Функция установки имени папки с контейнером по умолчанию.
* Должна быть реализована, если носитель поддерживает возможность запоминания данного значения. Если нет, то контейнер по умолчанию реализуется через хранение файла def.key в корневой директории.
* \sa \ref TSupSysInfoText
*/

/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_SIMPLE_LOGIN
* \brief Функция аутентификации по простому парольному протоколу. Устаревшее макроопределение.
*
* Если пароль вашему устройству передается в виде строки char или BYTE, и вы проводите преобразование TCHAR*->char* при получении пароля,
* следует использовать функцию \ref READER_FUN_SIMPLE_LOGIN_ASCII, который пароль передается провайдером в виде char*. Если же вам по-прежнему
* необходимо использование паролей в виде строки TCHAR, используйте макрос \ref READER_FUN_SIMPLE_LOGIN_TEXT. В не-Win операционных системах эти функции идентичны, 
* однако преобразование следует провести для унификации кода.
*
* При переводе модуля поддержки с \ref READER_FUN_SIMPLE_LOGIN на \ref READER_FUN_SIMPLE_LOGIN_ASCII не забудьте изменить местоположение функции в таблице
* функций модуля поддержки, так, чтобы номера шли строго по возрастанию.
* \sa \ref TReaderInfoLogin
*/

/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_SIMPLE_LOGIN_ASCII
* \brief Функция аутентификации по простому парольному протоколу.
* Должна быть реализована, если в #READER_FUN_PASSWORD_TYPE было указано, что на носителе есть хоть одна SIMPLE-аутентификация. Проверка пароля должна происходит непосредственно на носителе.
* Если пароль неверный, а карта не заблокирована, функция должна вернуть SCARD_W_WRONG_CHV. В этом случае, если есть возможность, карта может установить число оставшихся попыток ввода пароля.
* Если карта заблокирована, функция должна вернуть SCARD_W_CHV_BLOCKED. Если аутентификация прошла успешно, функция должна вернуть ERROR_SUCCESS.
*
* При переводе модуля поддержки с \ref READER_FUN_SIMPLE_LOGIN на \ref READER_FUN_SIMPLE_LOGIN_ASCII не забудьте изменить местоположение функции в таблице
* функций модуля поддержки, так, чтобы номера шли строго по возрастанию.
*
* Получает пароль в виде ASCIIZ-строки (char*).
*
* \sa \ref TReaderInfoLoginAscii
*/

/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_SIMPLE_LOGIN_TEXT
* \brief Функция аутентификации по простому парольному протоколу.
* Должна быть реализована, если в #READER_FUN_PASSWORD_TYPE было указано, что на носителе есть хоть одна SIMPLE-аутентификация. Проверка пароля должна происходит непосредственно на носителе.
* Если пароль неверный, а карта не заблокирована, функция должна вернуть SCARD_W_WRONG_CHV. В этом случае, если есть возможность, карта может установить число оставшихся попыток ввода пароля.
* Если карта заблокирована, функция должна вернуть SCARD_W_CHV_BLOCKED. Если аутентификация прошла успешно, функция должна вернуть ERROR_SUCCESS.
*
* Получает пароль в виде строки символов TCHAR.
*
* Данное макроопределение равно \ref READER_FUN_SIMPLE_LOGIN, однако не помечено как устаревшее.
*
* \sa \ref TReaderInfoLogin
*/


/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_LOGOUT
* \brief Функция снятия аутентификации.
* Функция должна сбрасывать признак аутентифицированности на носителе. В случае SESPAKE в отличие от #READER_FUN_SET_SM_STATE должна послать APDU.
*
*/

/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_SELF_LOGIN
* \brief Функция самостоятельной аутентификации.
* Должна быть реализована, если в #READER_FUN_PASSWORD_TYPE было указано, что на носителе есть хоть одна SELF-аутентификация. Не принимает аргументов, должна самостоятельно доводить носитель до состояния
* аутентифицированности. Например, может потребовать предъявить отпечаток пальца. 
*
* \sa \ref TRdrLoginInfoType 
*/

/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_AUTH_CHALLENGE
* \brief Функция аутентификации по SESPAKE.
* Должна быть реализована, если в #READER_FUN_PASSWORD_TYPE было указано, что на носителе используется аутентификация по SESPAKE. Вызывается два раза (шаг указан в challenge_class). 
* На первом шаге передаёт в носитель U1, получает U2. На втором шаге передает в носитель HMACa, получает HMACb. Функции должна быть реализована в точном соответствии с Р 50.1.115–2016.
* Также на втором шаге носитель должен сперва убедиться, что transaction_id совпадает с тем, что был передан на первом шаге. 
*
* \sa \ref TReaderInfoAuthChallenge
*/

/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_RESTORE_DEFAULT_ROOT
* \brief Функция восстановления аутентификации в корне на значение по умолчанию, при котором не будет запрашиваться пароль.
* Должна быть реализована, если в #READER_FUN_GET_PARAM в параметре TCEP_auth_types был установлен флаг AUTH_FLAG_TYPE_CAN_RESET_ROOT_DEF. 
* Функция не принимает параметров. Должна выполняться только под аутентификацией. В результате работы функция аутентификация ROOT должна сбрасываться в 
* дефолтное значение, TCEP_auth_types должен возвращать флаг AUTH_FLAG_TYPE_IS_DEF_ROOT, а TCEP_default_password - значение этого пароля. 
* Если производится попытка сменить заблокированный пароль, но для этого необходим PUK (который не передан), функция должна вернуть ошибку CPR_ERR_RDR_NEED_PUK_AUTH.
*
* Особый режим данной функции - наличие флага AUTH_FLAG_TYPE_HARDWARE_RESET_ROOT_DEF. В этом случае реализации данной функции может сопутствовать ряд требований дополнительных действий.
* Например, некоторые токены при вызове функции дают 5 секунд на своё вынимание из USB-порта, что приводит к полному аппаратному сбросу носителя. 
*
*/
 
/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_SEC_DESCR_READ
* \brief Функция получения дескриптора безопасности в формате Microsoft.
* Может быть реализована только для Реестра Windows.
*                       
*  \sa \ref TReaderInfoSecDescrRW
*/

/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_HASH_INIT
* \brief  См.  описание функции \ref rdr_crypt_hash_init
*
* \sa \ref TReaderFkcHashInit
*/

/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_HASH_DATA
* \brief  См.  описание функции \ref rdr_crypt_hash_data
*
* \sa \ref TReaderFkcHashData
*/

/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_HASH_GETVAL
* \brief  См.  описание функции \ref rdr_crypt_hash_getval
*  \sa \ref TReaderFkcHashGetVal
*/

/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_HASH_DESTROY
* \brief  См.  описание функции \ref rdr_crypt_hash_destroy
*
*/

/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_FOLDER_CLEAR
* \brief Функция удаления открытой папки. 
* Может вызываться только под аутентификацией. Функция удаляет папку со всеми файлами, расположенными в ней, без возможности восстановления.
* Для функциональных контейнеров функция должна также удалять все связанные с папкой криптографические объекты (ключи, сертификаты, служебные файлы).
* При #TRdrUniversalCarrierFlags folders == 0 данная функция также вызывается для очистки объектов, связанных с контейнером, который хранился на носителе.
*
*/

/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_PASSWD_CHANGE
* \brief Функция смены SIMPLE-пароля.
* Устаревшее макроопределение.
*
* Если пароль вашему устройству передается в виде строки char или BYTE, и вы проводите преобразование TCHAR*->char* при получении пароля,
* следует использовать функцию \ref READER_FUN_PASSWD_CHANGE_ASCII, который пароль передается провайдером в виде char*. Если же вам по-прежнему
* необходимо использование паролей в виде строки TCHAR, используйте макрос \ref READER_FUN_PASSWD_CHANGE_TEXT.
* В не-Win операционных системах эти функции идентичны, однако преобразование следует провести для унификации кода.
*
* Если производится попытка сменить заблокированный пароль, но для этого необходим PUK (который не передан), функция должна вернуть ошибку CPR_ERR_RDR_NEED_PUK_AUTH.
*
* При переводе модуля поддержки с \ref READER_FUN_PASSWD_CHANGE на \ref READER_FUN_PASSWD_CHANGE_ASCII не забудьте изменить местоположение функции в таблице
* функций модуля поддержки, так, чтобы номера шли строго по возрастанию.
*
* \sa \ref TReaderInfoPasswdChange 
*/

/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_PASSWD_CHANGE_ASCII
* \brief Функция смены SIMPLE-пароля.
*
* Функция реализуется, если носитель поддерживает возмонжость смены простой парольной аутентификации.
* Функция принимает пароль текущей аутентификации (если требуется при смене) и новое значение пароля в виде ASCIIZ-строки (char*).
*
* Если производится попытка сменить заблокированный пароль, но для этого необходим PUK (который не передан), функция должна вернуть ошибку CPR_ERR_RDR_NEED_PUK_AUTH.
*
* При переводе модуля поддержки с \ref READER_FUN_PASSWD_CHANGE на \ref READER_FUN_PASSWD_CHANGE_ASCII не забудьте изменить местоположение функции в таблице
* функций модуля поддержки, так, чтобы номера шли строго по возрастанию.
*
* \sa \ref TReaderInfoPasswdChangeAscii
*/

/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_PASSWD_CHANGE_TEXT
* \brief Функция смены SIMPLE-пароля.
*
* Функция реализуется, если носитель поддерживает возмонжость смены простой парольной аутентификации.
* Функция принимает пароль текущей аутентификации (если требуется при смене) и новое значение пароля в виде строки символов TCHAR*.
*
* Данное макроопределение равно \ref READER_FUN_PASSWD_CHANGE, однако не помечено как устаревшее.
*
* \sa \ref TReaderInfoPasswdChange
*/


/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_OPEN
* \brief Функция открытия/создания файла на носителе.
* На вход приходят имя файла, его номер и режим открытия (создания). Ключевые файлы создаются с режимом o_private и должны быть в дальнейшем
* доступны для чтения только после аутентификации. Открытие файлов с разрешением o_write должно быть возможно только под аутентификацией. После создания файл должен быть открыт.
* <table>
* <tr><th>Номер файла</th><th>Имя файла</th><th>Рекомендуемый размер в байтах</th><th>Примечания</th></tr>
* <tr><td>1</td><td>masks.key</td><td>88</td><td>Ключевой файл</td></tr>
* <tr><td>2</td><td>primary.key</td><td>135</td><td>Ключевой файл</td></tr>
* <tr><td>3</td><td>header.key</td><td>10000+</td><td>Файл с открытой информацией и сертификатом</td></tr>
* <tr><td>4</td><td>masks2.key</td><td>88</td><td>Ключевой файл</td></tr>
* <tr><td>5</td><td>primary2.key</td><td>135</td><td>Ключевой файл</td></tr>
* <tr><td>6</td><td>name.key</td><td>260</td><td>Файл с именем</td></tr>
* <tr><td>7</td><td>def.key</td><td>260</td><td>Файл с именем дефолтного контейнера. Лежит в корневой папке. </td></tr>
* <tr><td>8</td><td>certificate_kx.key</td><td>5000+</td><td>Файл с сертификатом exchange-ключа. Используется только в csp_interface. (\ref csp_interface)</td></tr>
* <tr><td>9</td><td>certificate_sig.key</td><td>5000+</td><td>Файл с сертификатом signature-ключа. Используется только в csp_interface. (\ref csp_interface)</td></tr>
* <tr><td>10</td><td>extensions.key</td><td></td>5000+<td>Файл с расширениями. Используется только в csp_interface. (\ref csp_interface)</td></tr>
* </table>
*
* \sa \ref TReaderInfoOpen 
*/

/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_CLOSE
* \brief Функция закрытия файла.
* Может освобождать ресурсы, выделенные при открытии/создании файла. В большинстве случаев реализация не требуется.
*
*/

/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_UNLINK
* \brief Функция удаления файла.
* Должна удалять указанный файл без возможности восстановления. Выполнять требования по многократной перезаписи при удалении не нужно - это делает провайдер. Можно просто удалить объект.
*
* \sa \ref TReaderInfoUnlink 
*/

/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_SEC_DESCR_WRITE
* \brief Функция установки дескриптора безопасности в формате Microsoft.
* Может быть реализована только для Реестра Windows.
*
* \sa \ref TReaderInfoSecDescrRW
*/

/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_CLEAR_TRIES
* \brief Функция сброса попыток у указанной аутентификации.
* Должна быть реализована, если в #READER_FUN_GET_PARAM в параметре TCEP_auth_types был установлен флаг AUTH_FLAG_TYPE_CAN_RESET_COUNTERS. 
* Функция должна сбрасывать счетчик неуспешных аутентификаций у указанной аутентификации. Работает только под разблокирующей аутентификацией. 
*
* \sa \ref TRdrLoginInfoType 
*/

/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_SELF_CHANGE
* \brief Функция смены SELF-аутентификации.
* Может быть реализована, если у носителя есть самостоятельная аутентификация. Например, для инициации процесса смены хранимых отпечатков пальца.
*
* \sa \ref TRdrLoginInfoType 
*/

/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_READ
* \brief Функция чтения бинарных данных из открытого на чтение файла. 
* Функция читает info.length данных, начиная со смещения from. После чтения из info.length должно вычитаться количество прочитанных данных.
* Если носитель поддерживает только поблоковое чтение, то реализовывать цикл в функции не нужно: этим займется провайдер. from указывает на смещение
* в файле, а не в буфере. Записывать данные в буфер нужно всегда по смещению 0. 
* Для ключевых файлов должна проверять наличие аутентификации.
* \sa \ref TReaderInfoRead
*/

/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_WRITE
* \brief Функция записи бинарных данных в открытый на запись файл.
* Функция пишет info.length данных в файл, начиная со смещения from. После записи из info.length должно вычитаться количество реально записанных данных.
* Если носитель поддерживает только поблоковую запись, то реализовывать цикл в функции не нужно: этим займется провайдер. from указывает на смещение
* в файле, а не в буфере. Читать данные из буфера нужно всегда, начиная со смещения 0.
* \sa \ref TReaderInfoWrite
*/

/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_CHSIZE
* \brief Функция изменения размера файла. 
* Функция меняет реальный размер файла на переданный из провайдера. Чаще всего функция вызывается сразу после создания файла. Если все файлы создаются фиксированной длины, 
* функция может быть не реализована. 
* \sa \ref TReaderInfoChSize
*/

/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_LENGTH
* \brief Функция получения реальной длины открытого файла. 
* Должна либо возвращать "честное" значение, либо не быть реализована, тогда провайдер будет считать длину файлов максимальной.
* \sa \ref TReaderInfoLength
*/


/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_KEY_SET
* \brief Функция установления ключа в функциональный носитель. Должна быть реализована, если установлен флаг #TRdrFkcCarrierFlags setKey.
* Устанавливает ключ за два этапа. На первом устанавливается маскированное значение ключа k'=k+m. На втором передаётся значение аддитивной маски.
* Для снятия маски носитель должен выполнить вычитание по модулю 2^32 ("подвордовое" без учета переноса). 
* Например, так: for (j = 0; j < sign_params->secret_key_length / sizeof(uint32_t); j++) dfkc[j] -= mask[j];
* Помимо закрытого ключа в функцию также приходит и соответсвующий открытый ключ. Если носитель умеет формировать открытый ключ по закрытому самостоятельно,
* то настоятельно рекомендуется сравнить значения пришедшего открытого ключа и вычисленного после выполнения второго шага данной функции. 
*
* \sa \ref TReaderFkcKeySet
*/

/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_SIGNATURE
* \brief Функция электронной подписи.
* Должна быть реализована для функциональных носителей. На вход принимает хэш от сообщения (е), возвращает значение подписи (r,s).
* Если носитель поддерживает хэширование и визуализацию подписи, то на вход вместо хэша приходит контекст хэширования из #READER_FUN_HASH_INIT.
*
* \sa \ref TReaderFkcSignInfo
*/

/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_GET_FREE_SPACE
* \brief Функция возвращает количество свободного места на токене в байтах
* реализовывать необязательно.
* \sa \ref TReaderFkcSignInfo
*/

/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_WEAK_SIGNATURE1
* \brief Первый шаг протокола электронной подписи для слабодоверенных носителей.
* Аналогична функции \ref READER_FUN_SIGNATURE, но дополнительно принимает идентификатор сессии протокола, и возвращает контрольное значение w.
*
* \sa \ref TReaderFkcSignInfo, \ref READER_FUN_SIGNATURE, \ref READER_FUN_WEAK_SIGNATURE2
*/

/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_WEAK_SIGNATURE2
* \brief Второй шаг протокола электронной подписи для слабодоверенных носителей.
* Принимает идентификатор сессии протокола (который должен совпадать с переданным на первом шаге идентификатором), случайное значение l, 
* и возвращает контрольное значение v.
*
* \sa \ref TReaderFkcSignInfo, \ref READER_FUN_WEAK_SIGNATURE1, \ref READER_FUN_SIGNATURE
*/

/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_KEY_GEN_RSA
* \brief Функция генерации RSA-ключа.*
* Функция должна создавать случайную ключевую пару средствами ключевого носителя. Вызывается, если выполнено условие (#TRdrUniversalCarrierFlags functional_container && #TRdrFkcCarrierFlags genKey).
* Должна вызываться только под основной аутентификацией. Если (#TRdrUniversalCarrierFlags folders), то вызывается в текущей папке.
* \sa \ref TReaderFkcRsaKeyGen
*/

/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_EXPTMOD_RSA
* \brief Функция возведения в степень по модулю RSA.
* Должна быть реализована для функциональных носителей.
* В случае подписи на вход принимает хэш от сообщения (е), возвращает значение подписи (s).
* Если носитель поддерживает хэширование и визуализацию подписи, то на вход вместо хэша приходит контекст хэширования из #READER_FUN_HASH_INIT.
* В случае расшифрования на вход принимает зашифрованное сообщение (е), возвращает открытый текст (s).
* \sa \ref TReaderFkcRsaExptmodInfo
*/

/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_PUBLIC_KEY_RSA
* \brief Функция получения открытого ключа RSA.
* Должна быть реализована для csp_interface (\ref csp_interface). В остальных случаях не вызывается. 
* \sa \ref TReaderFkcRsaPublicKeyGet
*/

/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_AVAILABLE_LENGTH_RSA
* \brief  Функция получения перечня поддерживаемых длин модулей RSA.
* Перечень поддерживаемых длин формируется как массив, каждый элемент которого хранит длину модуля RSA в битах.
* \sa \ref TReaderAvailableRsaLength
*/

/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_AGREEMENT_FULL
* \brief Функция выполнения VKO.
* Может быть реализована для функциональных носителей. На вход принимает открытый ключ (Qb) и UKM(r,s). 
* На выходе получает ключ, вычисленный по формуле K=H(m/q * UKM * d * Qb), где d - ключ с указанным индексом, а H - функция хэширования,
* соответствующая алгоритму подписи ключа. Диверсификация ключа производиться не должна.
* Вызов данной функции управляется флагами #TRdrFkcCarrierFlags dh_supported_algid и #TRdrFkcCarrierFlags ableDH. Первый указывает, какие алгоритмы хэширования поддерживаются (ГОСТ Р 34.11-94/2012).
* Второй - какой вид VKO поддерживается: никакой, простой, маскированный (предпочтительный). В последнем режиме в данную функцию также передаётся маска, которая должна быть 
* наложена на ключ перед его получением из носителя. Наложение происходит путем сложения по модулю 2^32 без учета переноса. 
* Например, так: for (j = 0; j < EXCHANGE_KEY_LENGTH / sizeof(uint32_t); j++) VKO_key_out[j] += mask[j]. 
* Сформированный ключ VKO может быть удален после выполнения операции, т.к. более использоваться не будет.
*
* \sa \ref TReaderAgreeInfo
*/

/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_PUBLIC_KEY
* \brief Функция получения открытого ключа.
* Должна быть реализована для csp_interface (\ref csp_interface). В остальных случаях не вызывается. 
* \sa \ref TReaderFkcPublicKeyGet
*/

/*! \ingroup reader_interface_fkc_fun
* \def READER_FUN_SET_2001
* \brief Функция установки признака контейнера, что ключи 2001 года. В csp_interface (\ref csp_interface)
* все параметры ключа могут быть считаны из сертификата, а сведения, какого типа ключ (короткий 2012 года
* или 2001 года) могут вообще отсутствовать на носителе. Однако они могут понадобиться для вычисления хэша.
* Функция не передает никакой информации, сам факт вызова устанавливает работу с 2001 алгоритмами. Функция
* завершается ошибкой NTE_BAD_KEYSET, если носитель не поддерживает работу с 2001 годом, или есть сведения,
* что ключ все же 2012 года. Если функция не реализована, но вызов ее требуется, криптопровайдер считает,
* что данные из записанного сертификата противоречат возможностям носителя, и возвращает ошибку 
* NTE_BAD_KEYSET.
*/



/*! \ingroup rdr_ext_fkc_type
* \brief Информационная структура для генерации ключа.
*
* \ref READER_FUN_KEY_GEN
*/
typedef struct {
    TRdrFkcEllipticPointParam group_id;	//!< ID параметров алгоритма ключа
    int index;		    //!< номер ключа, возвращаемый при генерации. Должен быть 0 для первого ключа; 1 для второго, если поддерживается создание второго ключа.
    TRdrFkcPoint * public_key; //!< Точка - открытый ключ, возвращаемый при генерации
    TKeyAlgType alg_type; //!< Идентификатор алгоритма, для которого будет использован данный ключ
    DWORD key_type;	  //!< AT_KEYEXCHANGE или AT_SIGNATURE (\ref csp_interface)
    DWORD alg_id;	  //!< идентификатор алгоритма ключа (\ref csp_interface)
    BOOL  is_able_dh;     //!< Признак того, что ключ должен создавать с поддержкой операции Диффи-Хеллмана. 
    char * oid;		    //!< OID набора параметров кривой ключа (\ref csp_interface)
    const BYTE * add_random_data;    //!< Дополнительные данные для инициализации ДСЧ.
    DWORD random_data_length;	    //!< Длина данных инициализации ДСЧ
    DWORD permissions;	  //!< разрешения ключа (\ref csp_interface)
} TReaderFkcKeyGen;

/*! \ingroup rdr_ext_fkc_type
* \brief Информационная структура для генерации ключа RSA.
*
* \ref READER_FUN_KEY_GEN_RSA
*/
typedef struct {
    DWORD rsa_len;		    //!< длина модуля RSA ключа в байтах
    long public_exp;		    //!< открытая экспонента RSA
    int index;			    //!< номер ключа, возвращаемый при генерации. Должен быть 0 для первого ключа; 1 для второго, если поддерживается создание второго ключа.
    TRdrFkcRsaKey *public_key;	    //!< параметры и значение сгенерированного открытого ключа RSA
    DWORD key_type;		    //!< AT_KEYEXCHANGE или AT_SIGNATURE (\ref csp_interface)
    DWORD alg_id;		    //!< идентификатор алгоритма ключа (\ref csp_interface)
    BOOL  is_able_dh;		    //!< Признак того, что ключ должен создавать с поддержкой операции Диффи-Хеллмана. 
    const BYTE *add_random_data;    //!< Дополнительные данные для инициализации ДСЧ.
    DWORD random_data_length;	    //!< Длина данных инициализации ДСЧ
    DWORD permissions;		    //!< разрешения ключа (\ref csp_interface)
} TReaderFkcRsaKeyGen;

/*! \ingroup rdr_ext_fkc_type
* \brief Идентификатор шага установки неразделенного закрытого ключа
*
* \ref READER_FUN_KEY_SET
*/
typedef enum {
    TSetKeyStep_first = 1,	/*!< Первый шаг установки: устанавливается маскированное значение ключа*/
    TSetKeyStep_second = 2	/*!< Второй шаг установки: устанавливается маска закрытого ключа*/
} TSetKeyStep;


/*! \ingroup rdr_ext_fkc_type
* \brief Информационная структура для установки ключа.
*
* \ref READER_FUN_KEY_SET
*/
typedef struct
{
    TReaderFkcOrderPtr  dfkc; //!< Закрытый ключ, значение которого устанавливается в контейнер (на первом шаге маскированный ключ, на втором - аддитивная маска по модулю 2^32)
    TRdrFkcPoint * public_key; //!< Открытый ключ, значение которого устанавливается в контейнер.
    int index;	    //!< Номер записанного ключа в контейнере. Должен быть 0 для первого ключа; 1 для второго, если поддерживается создание второго ключа. Заполняется только на втором шаге.
    DWORD key_length; //!< Длина закрытого ключа.
    TRdrFkcEllipticPointParam group_id;	//!< ID параметров алгоритма ключа
    TSetKeyStep step; //!< Шаг установки закрытого ключа
    TKeyAlgType alg_type; //!< Идентификатор алгоритма, для которого будет использован данный ключ
    DWORD key_type;	  //!< AT_KEYEXCHANGE или AT_SIGNATURE (\ref csp_interface)
    DWORD alg_id;	  //!< идентификатор алгоритма ключа (\ref csp_interface)
    BOOL is_able_dh;	  //!< Признак того, что ключ должен создавать с поддержкой операции Диффи-Хеллмана. 
    char * oid;		  //!< OID набора параметров кривой ключа (\ref csp_interface)
    DWORD permissions;	  //!< разрешения ключа (\ref csp_interface)
} TReaderFkcKeySet;


/*! \ingroup rdr_ext_fkc_type
* \brief Структура передачи открытого ключа и его параметров. (\ref csp_interface)
*
*/
typedef struct
{
    DWORD key_type;		    //!< [in] AT_KEYEXCHANGE или AT_SIGNATURE
    struct {
	unsigned value : 1;
	unsigned id_g : 1;
	unsigned alg_id : 1;
	unsigned oid : 1;
	unsigned is_able_dh : 1;
	unsigned permissions : 1;
    } flags;			    //!< [in] Флаги, задающие параметры, которые запрашиваются. 
    TRdrFkcPoint * value;	    //!< [out] Открытый ключ, соответствующий закрытому указанного key_type
    TRdrFkcEllipticPointParam id_g; //!< [out] Параметры эллиптической кривой
    DWORD alg_id;		    //!< [out] Идентификатор алгоритма закрытого ключа - ALG_ID согласно CryptAPI.
    char * oid;			    //!< [out] OID параметров эллиптической кривой
    BOOL is_able_dh;		    //!< [out] Признак того, что ключ должен с поддержкой операции Диффи-Хеллмана. 
    DWORD permissions;		    //!< [out] разрешения ключа
} TReaderFkcPublicKeyGet;

/*! \ingroup rdr_ext_fkc_type
* \brief Структура передачи открытого ключа RSA и его параметров. (\ref csp_interface)
*
*/
typedef struct
{
    DWORD key_type;		    //!< [in] AT_KEYEXCHANGE или AT_SIGNATURE 
    TRdrFkcRsaKey *value;	    //!< [out] Открытый ключ RSA, соответствующий закрытому указанного key_type
} TReaderFkcRsaPublicKeyGet;


/*! \ingroup rdr_ext_fkc_type
* \brief Информационная структура для функции подписи
* \ref #READER_FUN_SIGNATURE
*/
typedef struct 
{
    int index;	//!< номер ключа
    struct {
	TReaderFkcOrderPtr e;  //!< in - хэш в big-endian
	size_t e_length;       //!< in - длина хэша в байтах
	TReaderFkcOrderPtr r;  //!< out - первая компонента подписи
	size_t r_length;       //!< out - длина r в байтах
	TReaderFkcOrderPtr s;  //!< out - вторая компонента подписи
	size_t s_length;       //!< out - длина s в байтах
    } Simple_Sign;
    TSupSysEContext * hash_ctx; //!< in - контекст хэширования, если носитель поддерживает хэширование, то используются данные из него
    DWORD key_type;		//!< тип ключа. 1 == AT_KEYEXCHANGE, 2 == AT_SIGNATURE. (\ref csp_interface) 
} TReaderFkcSignInfo;

/*! \ingroup rdr_ext_fkc_type
* \brief Информационная структура для функции возведения в степень по модулю RSA
* \ref #READER_FUN_EXPTMOD_RSA
*/
typedef struct
{
    int index;			//!< in - номер ключа
    struct {
	const BYTE* e;		//!< in - входные данные (закодированный хэш/зашифрованные данные) в big-endian
	size_t e_length;	//!< in - длина входных данных в байтах
	size_t pl_length;	//!< in - длина "чистого" хэша в байтах
	BYTE* s;		//!< out - выходные данные (подпись RSA/расшифрованные данные) в big-endian
	size_t s_length;	//!< out - длина выходных данных в байтах
    } Simple_Sign;
    TSupSysEContext *hash_ctx;	//!< in - контекст хэширования, если носитель поддерживает хэширование, то используются данные из него
    DWORD key_type;		//!< in - тип ключа. 1 == AT_KEYEXCHANGE, 2 == AT_SIGNATURE (\ref csp_interface)
    DWORD hash_alg;		//!< in - идентификатор алгоритма хэша - ALG_ID согласно CryptAPI
} TReaderFkcRsaExptmodInfo;

/*! \ingroup rdr_ext_fkc_type
* \brief Информационная структура для первого шага функции подписи с контролем случайности
* \ref #READER_FUN_WEAK_SIGNATURE1
*/
typedef struct
{
    TRdrFkcTrID transaction_id; //!< идентификатор транзации
    TReaderFkcSignInfo params;	//!< параметры подписи
    TReaderFkcOrderPtr w;	//!< out - значение w для контроля случайности
    size_t w_length;		//!< out - длина w в байтах
} TReaderFkcWeakSignFirstInfo;

/*! \ingroup rdr_ext_fkc_type
* \brief Информационная структура для второго шага функции подписи с контролем случайности
* \ref #READER_FUN_WEAK_SIGNATURE2
*/
typedef struct
{
    TRdrFkcTrID transaction_id; //!< идентификатор транзации
    TReaderFkcOrderPtr l;	//!< in - значение случайного l для контроля случайности
    size_t l_length;		//!< in - длина l в байтах
    TReaderFkcOrderPtr v;	//!< out - значение v для контроля случайности
    size_t v_length;		//!< out - длина v в байтах
    int index;         	        //!< номер ключа
} TReaderFkcWeakSignSecondInfo;


/*! \ingroup rdr_ext_fkc_type
* \brief Структура с параметрами для выполнения VKO
* 
* \ref #READER_FUN_AGREEMENT_FULL
*/
typedef struct 
{
    struct{
	int index;	    //!< Номер ключа. Значение,возвращенное из gen_key.
	TRdrFkcPoint *Qb;   //!< Открытый ключ, с которым выполняется выработка ключа обмена.
	size_t Qb_coord_size; //!< Длина координаты открытого ключа в байтах (#RDR_FKC_COORD_SIZE_256 или #RDR_FKC_COORD_SIZE_512)
	TReaderFkcUKMPtr ukm; //!< UKM
	size_t ukm_length; //!< Длина UKM в байтах (#RDR_FKC_UKM_SIZE_256 или #RDR_FKC_UKM_SIZE_512)
	TReaderFkcOrderPtr mask; //!< Значение аддитивной маски, которую нужно наложить на выработанный ключ
	size_t mask_length; //!< Длина маски в байтах (#RDR_EXCHANGE_KEY_LENGTH или #RDR_EXCHANGE_KEY_512_LENGTH)
    } to_FKC;
    struct {
	TReaderFkcOrderPtr key;	    //!< Маскированное значение выработанного ключа
	size_t key_length;          //!< Длина значения ключа в байтах (#RDR_EXCHANGE_KEY_LENGTH или #RDR_EXCHANGE_KEY_512_LENGTH)
    } to_CSP;
    DWORD key_type;		// Тип ключа. 1 == AT_KEYEXCHANGE, 2 == AT_SIGNATURE. (\ref csp_interface)
} TReaderAgreeInfo;

#endif /* !_READER_H */
