/* vim:set sw=4 ts=8 fileencoding=cp1251::Кодировка:WINDOWS-1251[АБЁЪЯабёъя] */
#ifdef _WIN32
    #pragma setlocale("rus")
#endif
/*
 * Copyright(C) 2013 Проект ИОК
 *
 * Этот файл содержит информацию, являющуюся
 * собственностью компании Крипто Про.
 *
 * Любая часть этого файла не может быть скопирована,
 * исправлена, переведена на другие языки,
 * локализована или модифицирована любым способом,
 * откомпилирована, передана по сети с или на
 * любую компьютерную систему без предварительного
 * заключения соглашения с компанией Крипто Про.
 */
/*!
 * \version $Revision: 89611 $
 * \date $Date: 2013-05-29 23:43:11 +0400 (СЃСЂ, 29 РјР°Р№ 2013) $
 * \author $Author: lse $
 *
 * \brief Интерфейс реализации TLS уровня ядра
 */

#ifndef __KTLS_h__
#define __KTLS_h__

#if !defined(_MSC_VER)
    #include "CSP_WinDef.h"
    #include "ntstatus.h"
    typedef ULONG NTSTATUS;
#endif

#include "wincspc.h"
#include "CSP_Sspi.h"
#include "ipsec/include/sadb.h"
/*! \defgroup ProKTLS Структуры данных и функции TLS уровня ядра
  \ingroup ProUKTLS
  \note На данный момент модуль ядра реализован для Linux-систем
*/


/*! Прототип функции протоколирования
*\ingroup ProKTLS */
typedef void CAPI_EXTC
KTLSLogDecl(void *pUfnAgr, 
	   log_severity_t severity, unsigned uFlags, 
	   const char *fmt, ...);

/*! Прототип функции установления уровня протоколирования 
*\ingroup ProKTLS */
typedef void CAPI_EXTC
KTLSSetLogLvlDecl(void *pUfnAgr, log_severity_t severity, unsigned uFlags);

/*! Структура в которой передается данные для создания ktls_gost_handle 
*\ingroup ProKTLS */
typedef struct ktls_gost_in_st {
    void             *pUfnArg;
    /*!< \brief Пользовательский аргумент функции протоколирования.*/
    KTLSLogDecl	     *LogUfn;
    /*!< \brief Функция протоколирования , может быть 0.*/
    KTLSSetLogLvlDecl *SetLogLvlUfn;
    /*!< \brief Функция управления протоколированием, устанавливается при использовании #LogUfn.*/
    unsigned         allocatedMem;
    /*!< \brief Размер выделенной под ktls_gost_handle памяти (не менее requiredMem в #ktls_gost_out_st).*/
    void*            reserved[4];
    /*!< \brief Зарезервировано, не используется, заполняется нулями.*/
    LPCPC_CONFIG pConfig;/*!< указатель на конфигурацию, с которой был создан провайдер */
    HCRYPTMODULE hCSP;/*!< указатель на провайдер, в котором будет работать TLS */
} ktls_gost_in;

/*! Структура в которой возвращаются данные для создания ktls_gost_handle 
*\ingroup ProKTLS */
typedef struct ktls_gost_out_st {
    unsigned requiredMem;
    /*!< \brief Необходимый для ktls_gost_handle размер памяти.*/
   void*    reserved[7];
    /*!< \brief Зарезервировано, не используется, заполняется нулями.*/
} ktls_gost_out;


/*! Хендл на контекст уровня ядра 
\ingroup ProKTLS*/
typedef struct 
{
    int dummy;
} *CPKTLS_HANDLE; 

/*! Хендл TLS уровня ядра
* \ingroup ProKTLS
*/
typedef struct _CPKTLS_vtbl_ CPKTLS_VTBL, * ktls_gost_handle;

/*! \ingroup ProKTLS
* экспорт сессионных ключей
*/
#define CPKTLS_CONTEXT_EXPORT_TO_USER    (0x10000)
#define CPKTLS_CONTEXT_EXPORT_DELETE_OLD (0x20000)  // удалить сессию после экспорта

/*! \ingroup ProKTLS
* \brief Функция cpktls_init_gost() предназначена для инициализации библиотеки TLS уровня ядра
* \param h [in/out]- указатель на область памяти, где будут размещены указатели на функции TLS уровня ядра и таблица указателей на функции SADB
* \param in [in] - структура, в которой передаются параметры для инициализации таблицы (размер памяти, выделенный под нее)
* \param uFlags [in] - в настоящей версии не используется и должен быть установлен в 0
* \param out [out] - структура, в которой возвращается размер памяти, необходимый для резервирования структуры
* \returns в случае успеха возвращается STATUS_SUCCESS
* \retval STATUS_SUCCESS \e операция прошла успешно. Если в качестве параметра h передается NULL, в поле out возвращается количество памяти, которую необходимо зарезервировать.
* \retval STATUS_NO_MEMORY \e выделено недостаточно памяти под структуру
* \retval STATUS_INTERNAL_ERROR \e заданы неверные параметры вызова функции
*/
DWORD CAPI_EXTC cpktls_init_gost(
    ktls_gost_handle h,
    const ktls_gost_in *in,
    unsigned uFlags,
    ktls_gost_out *out
);

/*! \ingroup ProKTLS
* \brief cpktls_shutdown_gosti() - функция завершения работы библиотеки TLS.
* \param h [in/out] - указатель на хендл TLS
* \param uFlags - не используются, должен быть равен 0
* \returns STATUS_SUCCESS
*/
DWORD CAPI_EXTC cpktls_shutdown_gost (
    ktls_gost_handle h,
    unsigned uFlags
);

typedef DWORD CAPI_EXTC ImportContext_t (
    ktls_gost_handle h,
    PSecBuffer pPackedContext, 
    PRIVKEY *hPriv,
    PUBKEY_2012 *hPub,
    unsigned uFlags, 
    CPKTLS_HANDLE *phCtx
);

typedef DWORD CAPI_EXTC ExportContext_t (
    ktls_gost_handle h,
    CPKTLS_HANDLE hCtx,
    PRIVKEY *hPriv,
    PUBKEY_2012 *hPub,
    unsigned uFlags,
    PSecBuffer pPackedContext
);

/*
Seal()
Функция зашифровывает сообщение с использованием сессионного ключа, выработанного совместно с удалённой стороной, и вычисляет имитовставку (аналог EncryptMessage() уровня пользователя).
*/
typedef DWORD CAPI_EXTC Seal_t (
    ktls_gost_handle h,
    CPKTLS_HANDLE hCtx,
    IN ULONG fQOP,
    IN OUT PSecBufferDesc Message,
    IN ULONG MessageSeqNo 
);

/*
UnSeal()
Функция расшифровывает сообщение, проверяет его целостность и уведомляет о получении запроса на переустановку связи или разрыв соединения (аналог DecryptMessage() уровня пользователя).
*/
typedef DWORD CAPI_EXTC UnSeal_t (
    ktls_gost_handle h,
    CPKTLS_HANDLE hCtx,
    IN OUT PSecBufferDesc Message,
    IN ULONG MessageSeqNo,
    OUT PULONG pfQOP 
);

/*
QueryAttributes()
Функция возвращает информацию о свойствах данного контекста (аналог QueryContextAttributes() уровня пользователя).
*/
typedef DWORD CAPI_EXTC QueryAttributes_t (
    ktls_gost_handle h,
    CPKTLS_HANDLE hCtx,
    IN ULONG Attribute,
    IN OUT PVOID Buffer
);

/*
CompleteToken()
Функция используется для управления контекстом соединения (аналог ApplyControlToken() уровня пользователя).
*/
typedef DWORD CAPI_EXTC CompleteToken_t (
    ktls_gost_handle h,
    CPKTLS_HANDLE hCtx,
    IN PSecBufferDesc Token
);

/*
Функция освобождает структуры данных, связанные с данным соединением (аналог DeleteSecurityContext() уровня пользователя).
*/
typedef DWORD CAPI_EXTC DeleteContext_t (
    ktls_gost_handle h,
    unsigned uFlags,
    CPKTLS_HANDLE hCtx
);
/*! \ingroup ProKTLS 
 * \brief Структура, содержащая указатели на функции TLS в ядре и таблицу функций SADB
*/
struct _CPKTLS_vtbl_
{
    ImportContext_t * ImportContext; /*!< Указатель на #ImportContext */
    ExportContext_t * ExportContext; /*!< Указатель на #ExportContext */
    Seal_t * Seal;/*!< Указатель на #Seal */ 
    UnSeal_t * UnSeal;/*!< Указатель на #UnSeal */ 
    QueryAttributes_t * QueryAttributes;/*!< Указатель на #QueryAttributes */ 
    CompleteToken_t * CompleteToken;/*!< Указатель на #CompleteToken */ 
    DeleteContext_t * DeleteContext;/*!< Указатель на #DeleteContext */ 
    GEN_SADB tlsdb; /*!< Таблица функций SADB */
};

#endif
