/*
*******************************************************************************
\file belt.h
\brief STB 34.101.31 (belt): data encryption and integrity algorithms
\project bee2 [cryptographic library]
\created 2012.12.18
\version 2023.02.02
\copyright The Bee2 authors
\license Licensed under the Apache License, Version 2.0 (see LICENSE.txt).
*******************************************************************************
*/

/*!
*******************************************************************************
\file belt.h
\brief Алгоритмы СТБ 34.101.31 (belt)
*******************************************************************************
*/

#ifndef __BEE2_BELT_H
#define __BEE2_BELT_H

#ifdef __cplusplus
extern "C" {
#endif

#include "bee2/defs.h"

/*!
*******************************************************************************
\file belt.h

Реализованы алгоритмы СТБ 34.101.31 (belt). 
Дополнительно реализованы алгоритм ключезависимого хэширования (HMAC),
основанный на функции хэширования belt-hash, и алгоритм построения ключа
по паролю, основанный на HMAC[belt-hash]. Эти алгоритмы определены
соответственно в СТБ 34.101.47 и в СТБ 34.101.45.

Основные алгоритмы объединяются в группы, которые определяют следующие
криптографические механизмы:
-	ECB ---  шифрование в режиме простой замены;
-	CBC ---  шифрование в режиме сцепления блоков;
-	CFB ---  шифрование в режиме гаммирования с обратной связью;
-	CTR ---  шифрование в режиме счетчика;
-	MAC ---  имитозащита на основе шифрования;
-	DWP ---  аутентифицированное шифрование данных, схема DWP;
-	CHE ---  аутентифицированное шифрование данных, схема CHE;
-	KWP ---  аутентифицированное шифрование ключей;
-	Hash --- хэширование;
-	BDE ---	 блоковое дисковое шифрование;
-	SDE ---	 секторное дисковое шифрование;
-	FMT ---	 шифрование с сохранением формата;
-	KRP ---  преобразование ключей;
-	HMAC --- имитозащита на основе хэширования.

Механизмы построены на базовых криптографических алгоритмах шифрования 
блока (Block), шифрования широкого блока (WBL) и сжатия (Compr). 
Механизм WBL определен в новой редакции СТБ 34.101.31 и представляет 
собой ядро KWP. 

В механизмах ECB, CBC, CFB, CTR, MAC, DWP, CHE, KWP, BDE, SDE, FMT, KRP
используется ключ из 32 октетов. Ключ такой длины может быть построен
по ключу из 16 или 24 октетов с помощью функции beltExpand().

В механизме HMAC используется ключ произвольной длины. Рекомендуется
использовать ключ из 32 октетов.

В механизмах ECB, CBC, CFB, CTR, MAC, DWP, CHE, KWP, BDE данные
обрабатываются блоками по 16 октетов.

В механизмах Hash, HMAC данные обрабатываются блоками по 32 октета.

В механизме SDE обрабатываются секторы. Сектор состоит из двух или более полных 
16-октетных блоков.

В механизме FMT обрабатываются строки длины count в алфавите 
ZZ_mod = {0, 1,..., mod - 1}. Здесь mod -- размер алфавита или модуль.
Должны выполняться следующие ограничения:
-	2 <= mod && mod <= 65536;
-	2 <= count && count <= 600.
Последнее ограничение -- ограничение реализации.

На вход основных и вспомогательных функций данные и ключи подаются
либо как void-массивы (неформатированные данные, по умолчанию),
либо как массивы u32 (форматированные данные). Внутри функций
неформатированные данные форматируются перед использованием.
На платформах с соглашениями BIG_ENDIAN форматирование требует
дополнительного времени.

Каждый механизм реализуется связкой из нескольких функций. Эти функции 
используют общее состояние, указатель на которое передается в функции 
как дополнительный параметр. Имеются функция определения объема памяти 
для состояния (_keep). Память для состояния готовит вызывающая программа 
и она же отвечает за очистку памяти.

Состояние можно копировать как фрагмент памяти.

В связке обязательно имеется функция инициализации механизма (Start)
и одна или несколько функций обработки фрагментов данных и получения
результатов обработки (StepX).

Логика суффиксов функций StepX:
-	E -- encrypt (зашифровать);
-	D -- decrypt (расшифровать);
-	A -- authenticate (имитозащита);
-	I -- имитозащита открытых данных в режиме DWP;
-	H -- hashing (хэширование);
-	G -- get (получить имитовставку, хэш-значение или новый ключ);
-	V -- verify (проверить хэш-значение, имитовставку);
-	R -- random (псевдослучайная генерация).

Функции связки спроектированы как максимально простые и эффективные.
В частности, в этих функциях не проверяются входные данные.

Каждая связка покрывается высокоуровневой функцией, которая
обрабатывает все данные целиком. В высокоуровневых функциях есть
проверка входных данных.

Механизмы MAC, Hash, HMAC, DWP, CHE реализованы с поддержкой принципа 
get-then-continue. Это означает, что после обработки определенной порции данных
можно вызвать функцию типа StepG, а затем продолжить обработку.

\expect Общее состояние связки функций не изменяется вне этих функций.

\expect{ERR_BAD_INPUT} Все входные указатели высокоуровневых функций 
действительны.

\pre Все входные указатели низкоуровневых функций действительны.

\pre Если не оговорено противное, то входные буферы функций связки 
не пересекаются.
*******************************************************************************
*/

/*
*******************************************************************************
Долговременные параметры
*******************************************************************************
*/

/*!	\brief Блок подстановки H

	Возвращается таблица значений блока подстановки H.
	\return Указатель на таблицу H.
	\remark Таблица используется для формирования начальных значений
	переменных некоторых алгоритмов, а также в тестовых примерах.
*/
const octet* beltH();

/*
*******************************************************************************
Расширение ключа (belt-keyexpand)
*******************************************************************************
*/

/*!	\brief Расширение ключа

	Ключ [len]key расширяется до ключа key_.
	\pre len == 16 || len == 24 || len == 32.
	\remark Буферы key и key_ могут пересекаться.
*/
void beltKeyExpand(
	octet key_[32],		/*!< [out] расширенный ключ */
	const octet key[],	/*!< [in] первоначальный ключ */
	size_t len			/*!< [in] длина key в октетах */
);

/*!	\brief Расширение и форматирование ключа

	Ключ [len]key форматируется и расширяется до ключа key_.
	\pre len == 16 || len == 24 || len == 32.
	\remark Буферы key и key_ могут пересекаться.
*/
void beltKeyExpand2(
	u32 key_[8],		/*!< [out] расширенный форматированный ключ */
	const octet key[],	/*!< [in] первоначальный ключ */
	size_t len			/*!< [in] длина ключа в октетах */
);


/*
*******************************************************************************
Шифрование блока (belt-block)
*******************************************************************************
*/

/*!	\brief Зашифрование блока

	Выполняется зашифрование блока данных block на форматированном ключе key.
	Результат зашифрования возвращается по адресу block.
	\pre memIsAligned(block, 4) == TRUE.
*/
void beltBlockEncr(
	octet block[16],		/*!< [in,out] блок */
	const u32 key[8]		/*!< [in] ключ */
);

/*!	\brief Зашифрование форматированного блока

	Выполняется зашифрование форматированного блока данных block
	на форматированном ключе key. Результат зашифрования возвращается
	по адресу block.
*/
void beltBlockEncr2(
	u32 block[4],			/*!< [in,out] блок */
	const u32 key[8]		/*!< [in] ключ */
);

/*!	\brief Зашифрование блока из четверки слов

	Выполняется зашифрование форматированного блока (a, b, c, d), заданного 
	четверкой последовательных 32-разрядных слов, на форматированном ключе key.
	Результат зашифрования возвращается через входные слова.
*/
void beltBlockEncr3(
	u32* a,				/*!< [in,out] слово a */
	u32* b,				/*!< [in,out] слово b */
	u32* c,				/*!< [in,out] слово c */
	u32* d,				/*!< [in,out] слово d */
	const u32 key[8]	/*!< [in] ключ */
);

/*!	\brief Расшифрование блока

	Выполняется расшифрование блока данных block на форматированном ключе key.
	Результат расшифрования возвращается по адресу block.
	\pre memIsAligned(block, 4) == TRUE.
*/
void beltBlockDecr(
	octet block[16],		/*!< [in,out] блок */
	const u32 key[8]		/*!< [in] ключ */
);

/*!	\brief Расшифрование форматированного блока

	Выполняется расшифрование форматированного блока данных block
	на форматированном ключе key. Результат расшифрования возвращается
	по адресу block.
*/
void beltBlockDecr2(
	u32 block[4],			/*!< [in,out] блок */
	const u32 key[8]		/*!< [in] ключ */
);

/*!	\brief Расшифрование блока из четверки слов

	Выполняется расшифрование форматированного блока (a, b, c, d), заданного 
	четверкой последовательных 32-разрядных слов, на форматированном ключе key.
	Результат расшифрования возвращается через входные слова.
*/
void beltBlockDecr3(
	u32* a,				/*!< [in,out] слово a */
	u32* b,				/*!< [in,out] слово b */
	u32* c,				/*!< [in,out] слово c */
	u32* d,				/*!< [in,out] слово d */
	const u32 key[8]	/*!< [in] ключ */
);

/*
*******************************************************************************
Шифрование широкого блока (belt-wbl, WBL)
*******************************************************************************
*/

/*!	\brief Длина состояния функций WBL

	Возвращается длина состояния (в октетах) функций WBL.
	\return Длина состояния.
*/
size_t beltWBL_keep();

/*!	\brief Инициализация функций WBL

	По ключу [len]key в state формируются структуры данных,
	необходимые для шифрования в режиме WBL.
	\pre len == 16 || len == 24 || len == 32.
	\pre По адресу state зарезервировано beltWBL_keep() октетов.
	\remark Буферы key и state могут пересекаться.
*/
void beltWBLStart(
	void* state,			/*!< [out] состояние */
	const octet key[],		/*!< [in] ключ */
	size_t len				/*!< [in] длина ключа в октетах */
);

/*!	\brief Зашифрование в режиме WBL

	Буфер [count]buf зашифровывается на ключе, размещенном в state.
	Результат зашифрования сохраняется в buf.
	\pre count >= 32.
	\expect beltWBLStart() < beltWBLStepE()*.
*/
void beltWBLStepE(
	void* buf,			/*!< [in,out] открытый текст / шифртекст */
	size_t count,		/*!< [in] число октетов текста */
	void* state			/*!< [in,out] состояние */
);

/*!	\brief Расшифрование в режиме WBL

	Буфер [count]buf расшифровывается на ключе, размещенном в state.
	Результат расшифрования сохраняется в buf.
	\pre count >= 32.
	\expect beltWBLStart() < beltWBLStepD()*.
*/
void beltWBLStepD(
	void* buf,			/*!< [in,out] шифртекст / открытый текст */
	size_t count,		/*!< [in] число октетов данных */
	void* state			/*!< [in,out] состояние */
);

/*!	\brief Расшифрование в режиме WBL с двумя частями

	Буфер [count - 16]buf1 || [16]buf2 расшифровывается в режиме WBL на ключе, 
	размещенном в state. Результат расшифрования сохраняется в buf1 || buf2.
	\pre count >= 32.
	\pre Буферы buf1 и buf2 не пересекаются.
	\expect beltWBLStart() < beltWBLStepD2()*.
	\remark С помощью beltWBLStepD2() снятие защиты с ключа в механизме KWP
	может быть организовано по следующей схеме:
	-	первая часть защищенного ключа помещается в buf1;
	-	вторая часть защищенного ключа помещается в buf2;
	-	применяется beltWBLStepD2();
	-	если buf2 совпадает с заголовком ключа, то buf1 принимается как ключ.
	.
*/
void beltWBLStepD2(
	void* buf1,		/*!< [in,out] первая часть шифртекста / открытого текста */
	void* buf2,		/*!< [in,out] вторая часть шифртекста / открытого текста */
	size_t count,	/*!< [in] длина текста */
	void* state		/*!< [in,out] состояние */
);

/*!	\brief Продолженное зашифрование в режиме WBL

	Буфер [count]buf зашифровывается на ключе, размещенном в state.
	Результат зашифрования сохраняется в buf. При первом обращении счетчик i 
	меняется от 1 до 2n, при втором --- от 2n + 1 до 4n, и так далее. 
	\pre count >= 32.
	\expect beltWBLStart() < beltWBLStepR()*.
	\remark Многократное зашифрование в режиме WBL используется для генерации 
	одноразового ключа в СТБ 34.101.45. Поэтому функции назначен суффикс R.
*/
void beltWBLStepR(
	void* buf,			/*!< [in,out] открытый текст / шифртекст */
	size_t count,		/*!< [in] число октетов текста */
	void* state			/*!< [in,out] состояние */
);

/*
*******************************************************************************
Сжатие (belt-compress)
*******************************************************************************
*/

/*!	\brief Глубина стека функций сжатия

	Возвращается глубина стека (в октетах) функций сжатия.
	\return Глубина стека.
*/
size_t beltCompr_deep();

/*!	\brief Сжатие форматированных данных

	Форматированный буфер h || X сжимается до форматированного буфера h.
	\pre Буферы X и h не пересекаются.
	\deep{stack} beltCompr_deep().
*/
void beltCompr(
	u32 h[8],			/*!< [in,out] первая часть входа/выход */
	const u32 X[8],		/*!< [in] вторая часть входа */
	void* stack			/*!< [in,out] стек */
);

/*!	\brief Сжатие форматированных данных со сложением

	Форматированный буфер h || X сжимается до форматированного буфера h.
	Внутренняя переменная S belt-compress добавдяется поразрядно 
	по модулю 2 к буферу s.
	\pre Буферы s и h, X и s, X и h не пересекаются.
	\deep{stack} beltCompr_deep().
*/
void beltCompr2(
	u32 s[4],			/*!< [in,out] сумма */
	u32 h[8],			/*!< [in,out] первая часть входа/выход */
	const u32 X[8],		/*!< [in] вторая часть входа */
	void* stack			/*!< [in,out] стек */
);

/*
*******************************************************************************
Шифрование в режиме простой замены (belt-ecb, ECB)
*******************************************************************************
*/

/*!	\brief Длина состояния функций ECB

	Возвращается длина состояния (в октетах) функций шифрования в режиме ECB.
	\return Длина состояния.
*/
size_t beltECB_keep();

/*!	\brief Инициализация шифрования в режиме ECB

	По ключу [len]key в state формируются структуры данных, необходимые для 
	шифрования в режиме ECB.
	\pre len == 16 || len == 24 || len == 32.
	\pre По адресу state зарезервировано beltECB_keep() октетов.
	\remark Буферы key и state могут пересекаться.
*/
void beltECBStart(
	void* state,			/*!< [out] состояние */
	const octet key[],		/*!< [in] ключ */
	size_t len				/*!< [in] длина ключа в октетах */
);

/*!	\brief Зашифрование фрагмента в режиме ECB

	Буфер [count]buf зашифровывается в режиме ECB на ключе, размещенном 
	в state.
	\pre count >= 16.
	\expect beltECBStart() < beltECBStepE()*.
	\remark К функции можно обратиться несколько раз, передавая buf из полных
	блоков. Неполный блок можно передать только при последнем обращении.
	В этом случае выполняется "кража" блока (ciphertext stealing, CTS).
	\remark При организации последовательных обращений к функции следует
	учитывать, что буфер buf должен содержать не менее одного блока.
	Например для зашифрования 33 октетов можно зашифровать сначала 16 октетов,
	а затем еще 17. Но нельзя зашифровать сначала 32 октета, а затем еще 1.
*/
void beltECBStepE(
	void* buf,			/*!< [in,out] открытый текст / шифртекст */
	size_t count,		/*!< [in] число октетов текста */
	void* state			/*!< [in,out] состояние */
);

/*!	\brief Расшифрование в режиме ECB

	Буфер [count]buf расшифровывается в режиме ECB на ключе, размещенном 
	в state.
	\pre count >= 16.
	\expect beltECBStart() < beltECBStepD()*.
	\remark Сохраняются замечания по функции beltECBStepE().
*/
void beltECBStepD(
	void* buf,			/*!< [in,out] шифртекст / открытый текст */
	size_t count,		/*!< [in] число октетов текста */
	void* state			/*!< [in,out] состояние */
);

/*!	\brief Зашифрование в режиме ECB

	Буфер [count]src зашифровывается на ключе [len]key октетов.
	Результат зашифрования размещается в буфере [count]dest.
	\expect{ERR_BAD_INPUT}
	-	len == 16 || len == 24 || len == 32;
	-	count >= 16.
	.
	\return ERR_OK, если данные успешно зашифрованы, и код ошибки
	в противном случае.
*/
err_t beltECBEncr(
	void* dest,				/*!< [out] шифртекст */
	const void* src,		/*!< [in] открытый текст */
	size_t count,			/*!< [in] число октетов текста */
	const octet key[],		/*!< [in] ключ */
	size_t len				/*!< [in] длина ключа */
);

/*!	\brief Расшифрование в режиме ECB

	Буфер src из count октетов расшифровывается на ключе [len]key.
	Результат расшифрования размещается в буфере dest.
	\expect{ERR_BAD_INPUT}
	-	len == 16 || len == 24 || len == 32;
	-	count >= 16.
	.
	\return ERR_OK, если данные успешно расшифрованы, и код ошибки
	в противном случае.
*/
err_t beltECBDecr(
	void* dest,				/*!< [out] открытый текст */
	const void* src,		/*!< [in] шифртекст */
	size_t count,			/*!< [in] число октетов текста */
	const octet key[],		/*!< [in] ключ */
	size_t len				/*!< [in] длина ключа */
);

/*
*******************************************************************************
Шифрование в режиме сцепления блоков (belt-cbc, CBC)
*******************************************************************************
*/

/*!	\brief Длина состояния функций CBC

	Возвращается длина состояния (в октетах) функций шифрования в режиме CBC.
	\return Длина состояние.
*/
size_t beltCBC_keep();

/*!	\brief Инициализация шифрования в режиме CBC

	По ключу [len]key и синхропосылке iv в state формируются
	структуры данных, необходимые для шифрования в режиме CBC.
	\pre len == 16 || len == 24 || len == 32.
	\pre По адресу state зарезервировано beltCBC_keep() октетов.
	\remark Буферы key и state могут пересекаться.
*/
void beltCBCStart(
	void* state,			/*!< [out] состояние */
	const octet key[],		/*!< [in] ключ */
	size_t len,				/*!< [in] длина ключа в октетах */
	const octet iv[16]		/*!< [in] синхропосылка */
);

/*!	\brief Зашифрование в режиме CBC

	Буфер [count]buf зашифровывается в режиме CBC на ключе, размещенном 
	в state.
	\pre count >= 16.
	\expect beltCBCStart() < beltCBCStepE()*.
	\remark К функции можно обратиться несколько раз, передавая buf из полных
	блоков. Неполный блок можно передать только при последнем обращении.
	В этом случае выполняется "кража" блока (ciphertext stealing, CTS).
	\remark При организации последовательных обращений к функции следует
	учитывать, что буфер buf должен содержать не менее одного блока.
	Например для зашифрования 33 октетов можно зашифровать сначала 16 октетов,
	а затем еще 17. Но нельзя зашифровать сначала 32 октета, а затем еще 1.
*/
void beltCBCStepE(
	void* buf,			/*!< [in,out] открытый текст / шифртекст */
	size_t count,		/*!< [in] число октетов текста */
	void* state			/*!< [in,out] состояние */
);

/*!	\brief Расшифрование в режиме CBC

	Буфер [count]buf расшифровывается в режиме CBC на ключе, размещенном 
	в state.
	\pre count >= 16.
	\expect beltCBCStart() < beltCBCStepD()*.
	\remark Сохраняются замечания по функции beltCBCStepE().
*/
void beltCBCStepD(
	void* buf,			/*!< [in,out] шифртекст / открытый текст */
	size_t count,		/*!< [in] число октетов текста */
	void* state			/*!< [in,out] состояние */
);

/*!	\brief Зашифрование в режиме CBC

	Буфер [count]src зашифровывается на ключе [len]key с использованием 
	синхропосылки iv. Результат зашифрования размещается в буфере [count]dest.
	\expect{ERR_BAD_INPUT}
	-	len == 16 || len == 24 || len == 32;
	-	count >= 16.
	.
	\return ERR_OK, если данные успешно зашифрованы, и код ошибки
	в противном случае.
	\remark Буферы могут пересекаться.
*/
err_t beltCBCEncr(
	void* dest,				/*!< [out] шифртекст */
	const void* src,		/*!< [in] открытый текст */
	size_t count,			/*!< [in] число октетов текста */
	const octet key[],		/*!< [in] ключ */
	size_t len,				/*!< [in] длина ключа */
	const octet iv[16]		/*!< [in] синхропосылка */
);

/*!	\brief Расшифрование в режиме CBC

	Буфер [count]src расшифровывается на ключе [len]key с использованием 
	синхропосылки iv. Результат расшифрования размещается в буфере [count]dest.
	\expect{ERR_BAD_INPUT}
	-	len == 16 || len == 24 || len == 32;
	-	count >= 16.
	.
	\return ERR_OK, если данные успешно расшифрованы, и код ошибки
	в противном случае.
	\remark Буферы могут пересекаться.
*/
err_t beltCBCDecr(
	void* dest,				/*!< [out] открытый текст */
	const void* src,		/*!< [in] шифртекст */
	size_t count,			/*!< [in] число октетов текста */
	const octet key[],		/*!< [in] ключ */
	size_t len,				/*!< [in] длина ключа */
	const octet iv[16]		/*!< [in] синхропосылка */
);

/*
*******************************************************************************
Шифрование в режиме гаммирования с обратной связью (belt-cfb, CFB)
*******************************************************************************
*/

/*!	\brief Длина состояния функций CFB

	Возвращается длина состояния (в октетах) функций шифрования в режиме CFB.
	\return Длина состояния.
*/
size_t beltCFB_keep();

/*!	\brief Инициализация шифрования в режиме CFB

	По ключу [len]key и синхропосылке iv в state формируются
	структуры данных, необходимые для шифрования в режиме CFB.
	\pre len == 16 || len == 24 || len == 32.
	\pre По адресу state зарезервировано beltCFB_keep() октетов.
	\remark Буферы key и state могут пересекаться.
*/
void beltCFBStart(
	void* state,			/*!< [out] состояние */
	const octet key[],		/*!< [in] ключ */
	size_t len,				/*!< [in] длина ключа в октетах */
	const octet iv[16]		/*!< [in] синхропосылка */
);

/*!	\brief Зашифрование в режиме CFB

	Буфер [count]buf зашифровывается в режиме CFB на ключе, размещенном 
	в state.
	\expect beltCFBStart() < beltCFBStepE()*.
*/
void beltCFBStepE(
	void* buf,			/*!< [in,out] открытый текст / шифртекст */
	size_t count,		/*!< [in] число октетов текста */
	void* state			/*!< [in,out] состояние */
);

/*!	\brief Расшифрование в режиме CFB

	Буфер [count]buf расшифровывается в режиме CFB на ключе, размещенном 
	в state.
	\expect beltCFBStart() < beltCFBStepD()*.
*/
void beltCFBStepD(
	void* buf,			/*!< [in,out] шифртекст / открытый текст */
	size_t count,		/*!< [in] число октетов текста */
	void* state			/*!< [in,out] состояние */
);

/*!	\brief Зашифрование в режиме CFB

	Буфер [count]src зашифровывается на ключе [len]key с использованием 
	синхропосылки iv. Результат зашифрования размещается в буфере [count]dest.
	\expect{ERR_BAD_INPUT} len == 16 || len == 24 || len == 32.
	\return ERR_OK, если данные успешно зашифрованы, и код ошибки
	в противном случае.
	\remark Буферы могут пересекаться.
*/
err_t beltCFBEncr(
	void* dest,				/*!< [out] шифртекст */
	const void* src,		/*!< [in] открытый текст */
	size_t count,			/*!< [in] число октетов текста */
	const octet key[],		/*!< [in] ключ */
	size_t len,				/*!< [in] длина ключа */
	const octet iv[16]		/*!< [in] синхропосылка */
);

/*!	\brief Расшифрование в режиме CFB

	Буфер [count]src расшифровывается на ключе [len]key с использованием 
	синхропосылки iv. Результат расшифрования размещается в буфере [count]dest.
	\expect{ERR_BAD_INPUT} len == 16 || len == 24 || len == 32.
	\return ERR_OK, если данные успешно расшифрованы, и код ошибки
	в противном случае.
	\remark Буферы могут пересекаться.
*/
err_t beltCFBDecr(
	void* dest,				/*!< [out] открытый текст */
	const void* src,		/*!< [in] шифртекст */
	size_t count,			/*!< [in] число октетов текста */
	const octet key[],		/*!< [in] ключ */
	size_t len,				/*!< [in] длина ключа */
	const octet iv[16]		/*!< [in] синхропосылка */
);

/*
*******************************************************************************
Шифрование в режиме счетчика (belt-ctr, CTR)
*******************************************************************************
*/

/*!	\brief Длина состояния функций CTR

	Возвращается длина состояния (в октетах) функций шифрования в режиме CTR.
	\return Длина состояния.
*/
size_t beltCTR_keep();

/*!	\brief Инициализация шифрования в режиме CTR

	По ключу [len]key и синхропосылке iv в state формируются
	структуры данных, необходимые для шифрования в режиме CTR.
	\pre len == 16 || len == 24 || len == 32.
	\pre По адресу state зарезервировано beltCTR_keep() октетов.
	\remark Буферы key и state могут пересекаться.
*/
void beltCTRStart(
	void* state,			/*!< [out] состояние */
	const octet key[],		/*!< [in] ключ */
	size_t len,				/*!< [in] длина ключа в октетах */
	const octet iv[16]		/*!< [in] синхропосылка */
);

/*!	\brief Зашифрование фрагмента в режиме CTR

	Буфер [count]buf зашифровывается в режиме CTR на ключе, размещенном 
	в state.
	\expect beltCTRStart() < beltCTRStepE()*.
*/
void beltCTRStepE(
	void* buf,			/*!< [in,out] открытый текст / шифртекст */
	size_t count,		/*!< [in] число октетов текста */
	void* state			/*!< [in,out] состояние */
);

/*!	\brief Расшифрование фрагмента в режиме CTR
	\remark Зашифрование в режиме CTR не отличается от расшифрования.
*/
#define beltCTRStepD beltCTRStepE

/*!	\brief Шифрование в режиме CTR

	Буфер [count]src зашифровывается или расшифровывается на ключе
	[len]key с использованием синхропосылки iv. Результат шифрования 
	размещается в буфере [count]dest.
	\expect{ERR_BAD_INPUT} len == 16 || len == 24 || len == 32.
	\return ERR_OK, если шифрование завершено успешно, и код ошибки
	в противном случае.
	\remark Буферы могут пересекаться.
*/
err_t beltCTR(
	void* dest,				/*!< [out] шифртекст / открытый текст */
	const void* src,		/*!< [in] открытый текст / шифртекст */
	size_t count,			/*!< [in] число октетов текста */
	const octet key[],		/*!< [in] ключ */
	size_t len,				/*!< [in] длина ключа */
	const octet iv[16]		/*!< [in] синхропосылка */
);

/*
*******************************************************************************
Имитозащита (belt-mac, MAC)
*******************************************************************************
*/

/*!	\brief Длина состояния функций MAC

	Возвращается длина состояния (в октетах) функций имитозащиты в режиме MAC.
	\return Длина состояния.
*/
size_t beltMAC_keep();

/*!	\brief Инициализация функций MAC

	По ключу [len]key в state формируются структуры данных, необходимые для 
	имитозащиты в режиме MAC.
	\pre len == 16 || len == 24 || len == 32.
	\pre По адресу state зарезервировано beltMAC_keep() октетов.
	\remark Буферы key и state могут пересекаться.
*/
void beltMACStart(
	void* state,			/*!< [out] состояние */
	const octet key[],		/*!< [in] ключ */
	size_t len				/*!< [in] длина ключа в октетах */
);

/*!	\brief Имитозащита фрагмента данных в режиме MAC

	Текущая имитовставка, размещенная в state, пересчитывается с учетом нового
	фрагмента данных [count]buf. Пересчет выполняется на ключе, также 
	размещенном в state.
	\expect beltMACStart() < beltMACStepA()*.
*/
void beltMACStepA(
	const void* buf,	/*!< [in] данные */
	size_t count,		/*!< [in] число октетов данных */
	void* state			/*!< [in,out] состояние */
);

/*!	\brief Определение имитовставки в режиме MAC

	Определяется окончательная имитовставка mac всех данных,
	обработанных до этого функцией beltMACStepA().
	\expect (beltMACStepA()* < beltMACStepG())*.
	\remark Если продолжение имитозащиты не предполагается, то буферы 
	mac и state могут пересекаться.
*/
void beltMACStepG(
	octet mac[8],		/*!< [out] имитовставка */
	void* state			/*!< [in,out] состояние */
);

/*!	\brief Определение усеченной имитовставки в режиме MAC

	Определяется окончательная имитовставка [mac_len]mac всех данных,
	обработанных до этого функцией beltMACStepA(). Возвращаемая имитовставка 
	состоит из первых mac_len октетов полной имитовставки.
	\pre mac_len <= 8.
	\expect (beltMACStepA()* < beltMACStepG2())*.
	\remark Если продолжение имитозащиты не предполагается, то буферы 
	mac и state могут пересекаться.
*/
void beltMACStepG2(
	octet mac[],		/*!< [out] имитовставка */
	size_t mac_len,		/*!< [in] длина имитовставки */
	void* state			/*!< [in,out] состояние */
);

/*!	\brief Проверка имитовставки в режиме MAC

	Проверяется, что окончательная имитовставка всех данных,
	обработанных до этого функцией beltMACStepA(), совпадает с mac.
	\expect (beltMACStepA()* < beltMACStepV())*.
	\return Признак успеха.
*/
bool_t beltMACStepV(
	const octet mac[8],	/*!< [in] контрольная имитовставка */
	void* state			/*!< [in,out] состояние */
);

/*!	\brief Проверка усеченной имитовставки

	Проверяется, что первые mac_len октетов окончательной имитовставки
	всех данных, обработанных до этого функцией beltMACStepA(), совпадают
	с [mac_len]mac.
	\pre mac_len <= 8.
	\expect (beltMACStepA()* < beltMACStepV2())*.
*/
bool_t beltMACStepV2(
	const octet mac[],	/*!< [in] контрольная имитовставка */
	size_t mac_len,		/*!< [out] длина mac */
	void* state			/*!< [in,out] состояние */
);

/*!	\brief Имитозащита в режиме MAC

	На ключе [len]key определяется имитовставка mac буфера [count]src.
	\expect{ERR_BAD_INPUT} len == 16 || len == 24 || len == 32.
	\return ERR_OK, если имитовставка успешно вычислена, и код ошибки
	в противном случае.
	\remark Буферы могут пересекаться.
*/
err_t beltMAC(
	octet mac[8],			/*!< [out] имитовставка */
	const void* src,		/*!< [in] данные */
	size_t count,			/*!< [in] число октетов данных */
	const octet key[],		/*!< [in] ключ */
	size_t len				/*!< [in] длина ключа */
);

/*
*******************************************************************************
Аутентифицированное шифрование по схеме DWP (belt-dwp, DWP)
*******************************************************************************
*/

/*!	\brief Длина состояния функций DWP

	Возвращается длина состояния (в октетах) функций DWP.
	\return Длина состояния.
*/
size_t beltDWP_keep();

/*!	\brief Инициализация функций DWP

	По ключу [len]key и синхропосылке iv в state формируются
	структуры данных, необходимые для аутентифицированного шифрования
	в режиме DWP.
	\pre len == 16 || len == 24 || len == 32.
	\pre По адресу state зарезервировано beltDWP_keep() октетов.
	\remark Буферы key и state могут пересекаться.
*/
void beltDWPStart(
	void* state,			/*!< [out] состояние */
	const octet key[],		/*!< [in] ключ */
	size_t len,				/*!< [in] длина ключа в октетах */
	const octet iv[16]		/*!< [in] синхропосылка */
);

/*!	\brief Зашифрование критического фрагмента в режиме DWP

	Фрагмент критических данных [count]buf зашифровывается на ключе,
	размещенном в state. Результат зашифрования сохраняется в buf.
	\expect beltDWPStart() < beltDWPStepE()*.
*/
void beltDWPStepE(
	void* buf,			/*!< [in,out] критические данные */
	size_t count,		/*!< [in] число октетов данных */
	void* state			/*!< [in,out] состояние */
);

/*!	\brief Имитозащита открытого фрагмента в режиме DWP

	Текущая имитовставка, размещенная в state, пересчитывается с учетом нового
	фрагмента открытых данных [count]buf. Пересчет выполняется на ключе, 
	также размещенном в state.
	\expect beltDWPStart() < beltDWPStepI()*.
*/
void beltDWPStepI(
	const void* buf,	/*!< [in] открытые данные */
	size_t count,		/*!< [in] число октетов данных */
	void* state			/*!< [in,out] состояние */
);

/*!	\brief Имитозащита критического фрагмента в режиме DWP

	Текущая имитовставка, размещенная в state, пересчитывается с учетом нового
	фрагмента зашифрованных критических данных [count]buf. Пересчет выполняется 
	на ключе, также размещенном в state.
	\expect По адресу state зарезервировано beltDWP_keep() октетов.
	\expect beltDWPStepI()* < beltDWPStepA()*.
	\expect beltDWPStepE()* < beltDWPStepA()*.
*/
void beltDWPStepA(
	const void* buf,	/*!< [in] критические данные */
	size_t count,		/*!< [in] число октетов данных */
	void* state			/*!< [in,out] состояние */
);

/*!	\brief Определение имитовставки в режиме DWP

	Определяется окончательная имитовставка mac всех данных,
	обработанных до этого функциями beltDWPStepI() и beltDWPStepA().
	\expect beltDWPStepI()* < beltDWPStepG().
	\expect beltDWPStepA()* < beltDWPStepG().
	\warning При выполнении функции состояние state изменяется так, 
	что продолжение имитозащиты становится некорректным.
*/
void beltDWPStepG(
	octet mac[8],		/*!< [out] имитовставка */
	void* state			/*!< [in,out] состояние */
);

/*!	\brief Проверка имитовставки в режиме DWP

	Проверяется, что окончательная имитовставка всех данных,
	обработанных до этого функциями beltDWPStepI() и beltDWPStepA(),
	совпадает с mac.
	\expect beltDWPStepI()* < beltDWPStepV().
	\expect beltDWPStepA()* < beltDWPStepV().
	\return Признак успеха.
	\warning При выполнении функции состояние state изменяется так, 
	что продолжение имитозащиты становится некорректным.
*/
bool_t beltDWPStepV(
	const octet mac[8],	/*!< [in] контрольная имитовставка */
	void* state			/*!< [in,out] состояние */
);

/*!	\brief Расшифрование критического фрагмента в режиме DWP

	Фрагмент зашифрованных критических данных [count]buf расшифровывается 
	на ключе, размещенном в state.
	Результат расшифрования сохраняется в buf.
	\expect beltDWPStepG() < beltDWPStepD().
	\expect beltDWPStepA()* < beltDWPStepD().
*/
void beltDWPStepD(
	void* buf,			/*!< [in,out] критические данные */
	size_t count,		/*!< [in] число октетов данных */
	void* state			/*!< [in,out] состояние */
);

/*!	\brief Установка защиты в режиме DWP

	На ключе [len]key с использованием имитовставки iv устанавливается 
	защита критических данных [count1]src1 и открытых данных [count2]src2. 
	При установке защиты критические данные зашифровываются и сохраняются 
	в буфере [count1]dest. Кроме этого определяется имитовставка mac 
	пары (src1, src2).
	\expect{ERR_BAD_INPUT}
	-	len == 16 || len == 24 || len == 32;
	-	буферы dest и mac не пересекаются.
	.
	\return ERR_OK, если защита успешно установлена, и код ошибки
	в противном случае.
	\remark Буферы могут пересекаться, за исключением пересечения dest и mac.
*/
err_t beltDWPWrap(
	void* dest,				/*!< [out] зашифрованные критические данные */
	octet mac[8],			/*!< [out] имитовставка */
	const void* src1,		/*!< [in] критические данные */
	size_t count1,			/*!< [in] число октетов критических данных */
	const void* src2,		/*!< [in] открытые данные */
	size_t count2,			/*!< [in] число октетов открытых данных */
	const octet key[],		/*!< [in] ключ */
	size_t len,				/*!< [in] длина ключа */
	const octet iv[16]		/*!< [in] синхропосылка */
);

/*!	\brief Снятие защиты в режиме DWP

	На ключе [len]key октетов с использованием имитовставки iv
	снимается защита зашифрованных критических данных [count1]src1 
	и открытых данных [count2]src2. При снятии защиты проверяется
	целостность пары (src1, src2) с помощью имитовставки mac. Если
	целостность не нарушена, то данные src1 расшифровываются в буфер 
	[count1]dest.
	\expect{ERR_BAD_INPUT} len == 16 || len == 24 || len == 32.
	\return ERR_OK, если защита успешно снята, и код ошибки
	в противном случае.
	\remark Буферы могут пересекаться.
*/
err_t beltDWPUnwrap(
	void* dest,				/*!< [out] расшифрованные критические данные */
	const void* src1,		/*!< [in] зашифрованные критические данные */
	size_t count1,			/*!< [in] число октетов критических данных */
	const void* src2,		/*!< [in] открытые данные */
	size_t count2,			/*!< [in] число октетов открытых данных */
	const octet mac[8],		/*!< [in] имитовставка */
	const octet key[],		/*!< [in] ключ */
	size_t len,				/*!< [in] длина ключа */
	const octet iv[16]		/*!< [in] синхропосылка */
);

/*
*******************************************************************************
Аутентифицированное шифрование по схеме CHE (belt-che, CHE)
*******************************************************************************
*/

/*!	\brief Длина состояния функций CHE

	Возвращается длина состояния (в октетах) функций CHE.
	\return Длина состояния.
*/
size_t beltCHE_keep();

/*!	\brief Инициализация функций CHE

	По ключу [len]key и синхропосылке iv в state формируются
	структуры данных, необходимые для аутентифицированного шифрования
	в режиме CHE.
	\pre len == 16 || len == 24 || len == 32.
	\pre По адресу state зарезервировано beltCHE_keep() октетов.
	\remark Буферы key и state могут пересекаться.
*/
void beltCHEStart(
	void* state,			/*!< [out] состояние */
	const octet key[],		/*!< [in] ключ */
	size_t len,				/*!< [in] длина ключа в октетах */
	const octet iv[16]		/*!< [in] синхропосылка */
);

/*!	\brief Зашифрование критического фрагмента в режиме CHE

	Фрагмент критических данных [count]buf зашифровывается на ключе,
	размещенном в state. Результат зашифрования сохраняется в buf.
	\expect beltCHEStart() < beltCHEStepE()*.
*/
void beltCHEStepE(
	void* buf,			/*!< [in,out] критические данные */
	size_t count,		/*!< [in] число октетов данных */
	void* state			/*!< [in,out] состояние */
);

/*!	\brief Имитозащита открытого фрагмента в режиме CHE

	Текущая имитовставка, размещенная в state, пересчитывается с учетом нового
	фрагмента открытых данных [count]buf. Пересчет выполняется на ключе,
	также размещенном в state.
	\expect beltCHEStart() < beltCHEStepI()*.
*/
void beltCHEStepI(
	const void* buf,	/*!< [in] открытые данные */
	size_t count,		/*!< [in] число октетов данных */
	void* state			/*!< [in,out] состояние */
);

/*!	\brief Имитозащита критического фрагмента в режиме CHE

	Текущая имитовставка, размещенная в state, пересчитывается с учетом нового
	фрагмента зашифрованных критических данных [count]buf. Пересчет выполняется
	на ключе, также размещенном в state.
	\expect По адресу state зарезервировано beltCHE_keep() октетов.
	\expect beltCHEStepI()* < beltCHEStepA()*.
	\expect beltCHEStepE()* < beltCHEStepA()*.
*/
void beltCHEStepA(
	const void* buf,	/*!< [in] критические данные */
	size_t count,		/*!< [in] число октетов данных */
	void* state			/*!< [in,out] состояние */
);

/*!	\brief Определение имитовставки в режиме CHE

	Определяется окончательная имитовставка mac всех данных,
	обработанных до этого функциями beltCHEStepI() и beltCHEStepA().
	\expect beltCHEStepI()* < beltCHEStepG().
	\expect beltCHEStepA()* < beltCHEStepG().
	\warning При выполнении функции состояние state изменяется так,
	что продолжение имитозащиты становится некорректным.
*/
void beltCHEStepG(
	octet mac[8],		/*!< [out] имитовставка */
	void* state			/*!< [in,out] состояние */
);

/*!	\brief Проверка имитовставки в режиме CHE

	Проверяется, что окончательная имитовставка всех данных,
	обработанных до этого функциями beltCHEStepI() и beltCHEStepA(),
	совпадает с mac.
	\expect beltCHEStepI()* < beltCHEStepV().
	\expect beltCHEStepA()* < beltCHEStepV().
	\return Признак успеха.
	\warning При выполнении функции состояние state изменяется так,
	что продолжение имитозащиты становится некорректным.
*/
bool_t beltCHEStepV(
	const octet mac[8],	/*!< [in] контрольная имитовставка */
	void* state			/*!< [in,out] состояние */
);

/*!	\brief Расшифрование критического фрагмента в режиме CHE

	Фрагмент зашифрованных критических данных [count]buf расшифровывается
	на ключе, размещенном в state.
	Результат расшифрования сохраняется в buf.
	\expect beltCHEStepG() < beltCHEStepD().
	\expect beltCHEStepA()* < beltCHEStepD().
*/
void beltCHEStepD(
	void* buf,			/*!< [in,out] критические данные */
	size_t count,		/*!< [in] число октетов данных */
	void* state			/*!< [in,out] состояние */
);

/*!	\brief Установка защиты в режиме CHE

	На ключе [len]key с использованием имитовставки iv устанавливается
	защита критических данных [count1]src1 и открытых данных [count2]src2.
	При установке защиты критические данные зашифровываются и сохраняются
	в буфере [count1]dest. Кроме этого определяется имитовставка mac
	пары (src1, src2).
	\expect{ERR_BAD_INPUT}
	-	len == 16 || len == 24 || len == 32;
	-	буферы dest и mac не пересекаются.
	.
	\return ERR_OK, если защита успешно установлена, и код ошибки
	в противном случае.
	\remark Буферы могут пересекаться, за исключением пересечения dest и mac.
*/
err_t beltCHEWrap(
	void* dest,				/*!< [out] зашифрованные критические данные */
	octet mac[8],			/*!< [out] имитовставка */
	const void* src1,		/*!< [in] критические данные */
	size_t count1,			/*!< [in] число октетов критических данных */
	const void* src2,		/*!< [in] открытые данные */
	size_t count2,			/*!< [in] число октетов открытых данных */
	const octet key[],		/*!< [in] ключ */
	size_t len,				/*!< [in] длина ключа */
	const octet iv[16]		/*!< [in] синхропосылка */
);

/*!	\brief Снятие защиты в режиме CHE

	На ключе [len]key октетов с использованием имитовставки iv
	снимается защита зашифрованных критических данных [count1]src1
	и открытых данных [count2]src2. При снятии защиты проверяется
	целостность пары (src1, src2) с помощью имитовставки mac. Если
	целостность не нарушена, то данные src1 расшифровываются в буфер
	[count1]dest.
	\expect{ERR_BAD_INPUT} len == 16 || len == 24 || len == 32.
	\return ERR_OK, если защита успешно снята, и код ошибки
	в противном случае.
	\remark Буферы могут пересекаться.
*/
err_t beltCHEUnwrap(
	void* dest,				/*!< [out] расшифрованные критические данные */
	const void* src1,		/*!< [in] зашифрованные критические данные */
	size_t count1,			/*!< [in] число октетов критических данных */
	const void* src2,		/*!< [in] открытые данные */
	size_t count2,			/*!< [in] число октетов открытых данных */
	const octet mac[8],		/*!< [in] имитовставка */
	const octet key[],		/*!< [in] ключ */
	size_t len,				/*!< [in] длина ключа */
	const octet iv[16]		/*!< [in] синхропосылка */
);

/*
*******************************************************************************
Шифрование и имитозащита ключей (belt-kwp, KWP)
*******************************************************************************
*/

/*!	@{
	\brief Низкоуровневые функции KWP
	\remark Повторяются функции механизма WBL.
*/
#define beltKWP_keep beltWBL_keep
#define beltKWPStart beltWBLStart
#define beltKWPStepE beltWBLStepE
#define beltKWPStepD beltWBLStepD
#define beltKWPStepD2 beltWBLStepD2
/*!	@} */


/*!	\brief Установка защиты в режиме KWP

	На ключе [len]key устанавливается защита ключа [count]src с заголовком 
	header. В результате определяется защищенный ключ [count + 16]dest.
	\expect{ERR_BAD_INPUT}
	-	len == 16 || len == 24 || len == 32;
	-	count >= 16.
	.
	\return ERR_OK, если защита успешно установлена, и код ошибки 
	в противном случае.
	\remark При нулевом указателе header используется нулевой заголовок.
	\remark Буферы могут пересекаться.
*/
err_t beltKWPWrap(
	octet dest[],			/*!< [out] защищенный ключ */
	const octet src[],		/*!< [in] защищаемый ключ */
	size_t count,			/*!< [in] длина src в октетах */
	const octet header[16],	/*!< [in] заголовок ключа */
	const octet key[],		/*!< [in] ключ защиты */
	size_t len				/*!< [in] длина key в октетах */
);

/*!	\brief Снятие защиты в режиме KWP

	На ключе [len]key снимается защита с ключа [count]src. В результате 
	определяется первоначальный ключ [count - 16]dest с заголовком header.
	\expect{ERR_BAD_INPUT} 
	-	len == 16 || len == 24 || len == 32;
	-	count >= 32.
	.
	\return ERR_OK, если защита успешно снята, и код ошибки в противном случае.
	\remark При нулевом указателе header используется нулевой заголовок.
	\remark Буферы могут пересекаться.
*/
err_t beltKWPUnwrap(
	octet dest[],			/*!< [out] ключ */
	const octet src[],		/*!< [in] защищенный ключ */
	size_t count,			/*!< [in] длина src в октетах */
	const octet header[16],	/*!< [in] заголовок ключа */
	const octet key[],		/*!< [in] ключ защиты */
	size_t len				/*!< [in] длина key в октетах */
);

/*
*******************************************************************************
Хэширование (belt-hash, Hash)
*******************************************************************************
*/

/*!	\brief Длина состояния функции хэширования

	Возвращается длина состояния (в октетах) функции хэширования.
	\return Длина состояния.
*/
size_t beltHash_keep();

/*!	\brief Инициализация функции хэширования

	В state формируются структуры данных, необходимые для хэширования.
	\pre По адресу state зарезервировано beltHash_keep() октетов.
*/
void beltHashStart(
	void* state			/*!< [out] состояние */
);

/*!	\brief Хэширование фрагмента данных

	Текущее хэш-значение, размещенное в state, пересчитывается с учетом нового
	фрагмента данных [count]buf.
	\expect beltHashStart() < beltHashStepH()*.
*/
void beltHashStepH(
	const void* buf,	/*!< [in] данные */
	size_t count,		/*!< [in] число октетов данных */
	void* state			/*!< [in,out] состояние */
);

/*!	\brief Определение хэш-значения

	Определяется окончательное хэш-значение hash всех данных,
	обработанных до этого функцией beltHashStepH().
	\expect (beltHashStepH()* < beltHashStepG())*.
	\remark Если продолжение хэширования не предполагается, то буферы 
	hash и state могут пересекаться.
*/
void beltHashStepG(
	octet hash[32],		/*!< [out] хэш-значение */
	void* state			/*!< [in,out] состояние */
);

/*!	\brief Определение усеченного хэш-значения

	Определяется окончательное хэш-значение [hash_len]hash 
	всех данных, обработанных до этого функцией beltHashStepH().
	Возвращаемое хэш-значение состоит из первых hash_len октетов 
	полного хэш-значения.
	\pre hash_len <= 32.
	\expect (beltHashStepH()* < beltHashStepG2())*.
	\remark Если продолжение хэширования не предполагается, то буферы 
	hash и state могут пересекаться.
*/
void beltHashStepG2(
	octet hash[],		/*!< [out] хэш-значение */
	size_t hash_len,	/*!< [out] длина hash */
	void* state			/*!< [in,out] состояние */
);

/*!	\brief Проверка хэш-значения

	Проверяется, что окончательное хэш-значение всех данных,
	обработанных до этого функцией beltHashStepH(), совпадает с hash.
	\expect (beltHashStepH()* < beltHashStepV())*.
*/
bool_t beltHashStepV(
	const octet hash[32],	/*!< [in] контрольные хэш-значение */
	void* state				/*!< [in,out] состояние */
);

/*!	\brief Проверка усеченного хэш-значения

	Проверяется, что первые hash_len октетов окончательного хэш-значения
	всех данных, обработанных до этого функцией beltHashStepH(), совпадают
	с [hash_len]hash.
	\pre hash_len <= 32.
	\expect (beltHashStepH()* < beltHashStepV2())*.
*/
bool_t beltHashStepV2(
	const octet hash[],	/*!< [in] контрольное хэш-значение */
	size_t hash_len,	/*!< [out] длина hash */
	void* state			/*!< [in,out] состояние */
);

/*!	\brief Хэширование

	Определяется хэш-значение hash буфера [count]src.
	\return ERR_OK, если хэширование успешно завершено, и код ошибки
	в противном случае.
	\remark Буферы могут пересекаться.
*/
err_t beltHash(
	octet hash[32],		/*!< [out] хэш-значение */
	const void* src,	/*!< [in] данные */
	size_t count		/*!< [in] число октетов данных */
);

/*
*******************************************************************************
Блоковое дисковое шифрование (belt-bde, BDE)
*******************************************************************************
*/

/*!	\brief Длина состояния функций BDE

	Возвращается длина состояния (в октетах) функций шифрования в режиме BDE.
	\return Длина состояние.
*/
size_t beltBDE_keep();

/*!	\brief Инициализация шифрования в режиме BDE

	По ключу [len]key и синхропосылке iv в state формируются
	структуры данных, необходимые для шифрования в режиме BDE.
	\pre len == 16 || len == 24 || len == 32.
	\pre По адресу state зарезервировано beltBDE_keep() октетов.
	\remark Буферы key и state могут пересекаться.
*/
void beltBDEStart(
	void* state,			/*!< [out] состояние */
	const octet key[],		/*!< [in] ключ */
	size_t len,				/*!< [in] длина ключа в октетах */
	const octet iv[16]		/*!< [in] синхропосылка */
);

/*!	\brief Шаг зашифрования в режиме BDE

	Буфер [count]buf зашифровывается в режиме BDE на ключе, размещенном 
	в state.
	\pre count % 16 == 0.
	\expect beltBDEStart() < beltBDEStepE()*.
*/
void beltBDEStepE(
	void* buf,			/*!< [in,out] открытый текст / шифртекст */
	size_t count,		/*!< [in] число октетов текста */
	void* state			/*!< [in,out] состояние */
);

/*!	\brief Шаг расшифрования в режиме BDE

	Буфер [count]buf расшифровывается в режиме BDE на ключе, размещенном 
	в state.
	\pre count % 16 == 0.
	\expect beltBDEStart() < beltBDEStepD()*.
*/
void beltBDEStepD(
	void* buf,			/*!< [in,out] шифртекст / открытый текст */
	size_t count,		/*!< [in] число октетов текста */
	void* state			/*!< [in,out] состояние */
);

/*!	\brief Зашифрование в режиме BDE

	Буфер [count]src зашифровывается на ключе [len]key с использованием 
	синхропосылки iv. Результат зашифрования размещается в буфере [count]dest.
	\expect{ERR_BAD_INPUT}
	-	len == 16 || len == 24 || len == 32;
	-	count % 16 == 0 && count >= 16.
	.
	\return ERR_OK, если данные успешно зашифрованы, и код ошибки
	в противном случае.
	\remark Буферы могут пересекаться.
*/
err_t beltBDEEncr(
	void* dest,				/*!< [out] шифртекст */
	const void* src,		/*!< [in] открытый текст */
	size_t count,			/*!< [in] число октетов текста */
	const octet key[],		/*!< [in] ключ */
	size_t len,				/*!< [in] длина ключа */
	const octet iv[16]		/*!< [in] синхропосылка */
);

/*!	\brief Расшифрование в режиме BDE

	Буфер [count]src расшифровывается на ключе [len]key с использованием 
	синхропосылки iv. Результат расшифрования размещается в буфере [count]dest.
	\expect{ERR_BAD_INPUT}
	-	len == 16 || len == 24 || len == 32;
	-	count % 16 == 0 && count >= 16.
	.
	\return ERR_OK, если данные успешно расшифрованы, и код ошибки
	в противном случае.
	\remark Буферы могут пересекаться.
*/
err_t beltBDEDecr(
	void* dest,				/*!< [out] открытый текст */
	const void* src,		/*!< [in] шифртекст */
	size_t count,			/*!< [in] число октетов текста */
	const octet key[],		/*!< [in] ключ */
	size_t len,				/*!< [in] длина ключа */
	const octet iv[16]		/*!< [in] синхропосылка */
);

/*
*******************************************************************************
Секторное дисковое шифрование (belt-sde, SDE)
*******************************************************************************
*/

/*!	\brief Длина состояния функций SDE

	Возвращается длина состояния (в октетах) функций шифрования в режиме SDE.
	\return Длина состояние.
*/
size_t beltSDE_keep();

/*!	\brief Инициализация шифрования в режиме SDE

	По ключу [len]key и синхропосылке iv в state формируются
	структуры данных, необходимые для шифрования в режиме SDE.
	\pre len == 16 || len == 24 || len == 32.
	\pre По адресу state зарезервировано beltSDE_keep() октетов.
	\remark Буферы key и state могут пересекаться.
*/
void beltSDEStart(
	void* state,			/*!< [out] состояние */
	const octet key[],		/*!< [in] ключ */
	size_t len				/*!< [in] длина ключа в октетах */
);

/*!	\brief Шаг зашифрования в режиме SDE

	Сектор [count]buf зашифровывается в режиме SDE на ключе, размещенном 
	в state, и синхропосылке iv.
	\pre count % 16 == 0 && count >= 32.
	\expect beltSDEStart() < beltSDEStepE()*.
*/
void beltSDEStepE(
	void* buf,			/*!< [in,out] открытый текст / шифртекст */
	size_t count,		/*!< [in] число октетов текста */
	const octet iv[16],	/*!< [in] синхропосылка */
	void* state			/*!< [in,out] состояние */
);

/*!	\brief Шаг расшифрования в режиме SDE

	Сектор [count]buf расшифровывается в режиме SDE на ключе, размещенном 
	в state, и синхропосылке iv.
	\pre count % 16 == 0 && count >= 32.
	\expect beltSDEStart() < beltSDEStepD()*.
*/
void beltSDEStepD(
	void* buf,			/*!< [in,out] шифртекст / открытый текст */
	size_t count,		/*!< [in] число октетов текста */
	const octet iv[16],	/*!< [in] синхропосылка */
	void* state			/*!< [in,out] состояние */
);

/*!	\brief Зашифрование в режиме SDE

	Сектор [count]src зашифровывается на ключе [len]key с использованием 
	синхропосылки iv. Результат зашифрования размещается в буфере [count]dest.
	\expect{ERR_BAD_INPUT}
	-	len == 16 || len == 24 || len == 32;
	-	count % 16 == 0 && count >= 32.
	.
	\return ERR_OK, если данные успешно зашифрованы, и код ошибки
	в противном случае.
	\remark Буферы могут пересекаться.
*/
err_t beltSDEEncr(
	void* dest,				/*!< [out] шифртекст */
	const void* src,		/*!< [in] открытый текст */
	size_t count,			/*!< [in] число октетов текста */
	const octet key[],		/*!< [in] ключ */
	size_t len,				/*!< [in] длина ключа */
	const octet iv[16]		/*!< [in] синхропосылка */
);

/*!	\brief Расшифрование в режиме SDE

	Сектор [count]src расшифровывается на ключе [len]key с использованием 
	синхропосылки iv. Результат расшифрования размещается в буфере [count]dest.
	\expect{ERR_BAD_INPUT}
	-	len == 16 || len == 24 || len == 32;
	-	count % 16 == 0 && count >= 32.
	.
	\return ERR_OK, если данные успешно расшифрованы, и код ошибки
	в противном случае.
	\remark Буферы могут пересекаться.
*/
err_t beltSDEDecr(
	void* dest,				/*!< [out] открытый текст */
	const void* src,		/*!< [in] шифртекст */
	size_t count,			/*!< [in] число октетов текста */
	const octet key[],		/*!< [in] ключ */
	size_t len,				/*!< [in] длина ключа */
	const octet iv[16]		/*!< [in] синхропосылка */
);

/*
*******************************************************************************
Шифрование с сохранением формата (belt-fmt, FMT)
*******************************************************************************
*/

/*!	\brief Длина состояния функций FMT

	Возвращается длина состояния (в октетах) функций шифрования при обработке
	слов длины count в алфавите {0, 1,..., mod - 1}.
	\pre 2 <= mod && mod <= 65536.
	\pre 2 <= count && count <= 600.
	\return Длина состояния.
*/
size_t beltFMT_keep(
	u32 mod,			/*!< [in] размер алфавита */
	size_t count		/*!< [in] длина слов */
);

/*!	\brief Инициализация шифрования в режиме FMT

	По размеру алфавита mod, длине слов count и ключу [len]key в state 
	формируются структуры данных, необходимые для шифрования в режиме FMT.
	\pre 2 <= mod && mod <= 65536.
	\pre 2 <= count && count <= 600.
	\pre len == 16 || len == 24 || len == 32.
	\pre По адресу state зарезервировано beltFMT_keep() октетов.
	\remark Буферы key и state могут пересекаться.
*/
void beltFMTStart(
	void* state,		/*!< [in,out] состояние */
	u32 mod,			/*!< [in] размер алфавита */
	size_t count,		/*!< [in] длина слов */
	const octet key[],	/*!< [in] ключ */
	size_t len			/*!< [in] длина key в октетах */
);

/*!	\brief Шаг зашифрования в режиме FMT

	Строка [count]buf зашифровывается на ключе, размещенном в state,
	и синхропосылке iv. Здесь count -- длина строки, предварительно 
	установленная в state функцией beltFMTStart(). Результат зашифрования 
	сохраняется в buf.
	\expect beltFMTStart() < beltFMTStepE()*.
	\expect Символы строки принадлежат алфавиту {0,1,..., mod - 1}, размер 
	mod которого предварительно установлен в state функцией beltFMTStart().
	\remark При нулевом указателе iv используется нулевая синхропосылка.
*/
void beltFMTStepE(
	u16 buf[],				/*!< [in,out] открытый текст / шифртекст */
	const octet iv[16],		/*!< [in] синхропосылка */
	void* state				/*!< [in,out] состояние */
);

/*!	\brief Шаг расшифрования в режиме FMT

	Строка [count]buf расшифровывается на ключе, размещенном в state,
	и синхропосылке iv. Здесь count -- длина строки, предварительно 
	установленная в state функцией beltFMTStart(). Результат расшифрования 
	сохраняется в buf.
	\expect beltFMTStart() < beltFMTStepD()*.
	\expect Символы строки принадлежат алфавиту {0,1,..., mod - 1}, размер 
	mod которого предварительно установлен в state функцией beltFMTStart().
	\remark При нулевом указателе iv используется нулевая синхропосылка.
*/
void beltFMTStepD(
	u16 buf[],				/*!< [in,out] шифртекст / открытый текст */
	const octet iv[16],		/*!< [in] синхропосылка */
	void* state				/*!< [in,out] состояние */
);

/*!	\brief Зашифрование в режиме FMT

	Строка [count]src в алфавите {0, 1,..., mod - 1} зашифровывается на ключе 
	[len]key и синхропосылке iv. Результат зашифрования размещается в буфере 
	[count]dest. При нулевом указателе iv используется нулевая синхропосылка.
	\expect{ERR_BAD_INPUT}
	- 2 <= mod && mod <= 65536;
	- 2 <= count;
	- len == 16 || len == 24 || len == 32;
	- если iv ненулевой, то буферы iv и [count]dest не пересекаются.
	.
	\expect{ERR_NOT_IMPLEMENTED} count <= 600.
	\expect Символы src принадлежат алфавиту {0, 1,..., mod - 1}.
	\return ERR_OK, если зашифрование успешно выполнено, и код ошибки в 
	противном случае.
	\remark Все буферы, кроме iv и [count]dest, могут пересекаться.
*/
err_t beltFMTEncr(
	u16 dest[],				/*!< [out] шифртекст */
	u32 mod,				/*!< [in] размер алфавита */
	const u16 src[],		/*!< [in] открытый текст */
	size_t count,			/*!< [in] длина открытого текста / шифртекста */
	const octet key[],		/*!< [in] ключ */
	size_t len,				/*!< [in] длина key в октетах */
	const octet iv[16]		/*!< [in] синхропосылка */
);

/*!	\brief Расшифрование в режиме FMT

	Строка [count]src в алфавите {0, 1,..., mod - 1} расшифровывается на ключе
	[len]key и синхропосылке iv. Результат расшифрования размещается в буфере 
	[count]dest. При нулевом указателе iv используется нулевая синхропосылка.
	\expect{ERR_BAD_INPUT}
	- 2 <= mod && mod <= 65536;
	- 2 <= count;
	- len == 16 || len == 24 || len == 32;
	- если iv ненулевой, то буферы iv и [count]dest не пересекаются.
	.
	\expect{ERR_NOT_IMPLEMENTED} count <= 600.
	\expect Символы src принадлежат алфавиту {0, 1,..., mod - 1}.
	\return ERR_OK, если расшифрование успешно выполнено, и код ошибки в 
	противном случае.
	\remark Все буферы, кроме iv и [count]dest, могут пересекаться.
*/
err_t beltFMTDecr(
	u16 dest[],				/*!< [out] открытый текст */
	u32 mod,				/*!< [in] размер алфавита */
	const u16 src[],		/*!< [in] шифртекст */
	size_t count,			/*!< [in] длина шифртекста / открытого текста */
	const octet key[],		/*!< [in] ключ */
	size_t len,				/*!< [in] длина key в октетах */
	const octet iv[16]		/*!< [in] синхропосылка */
);

/*
*******************************************************************************
Преобразование ключа (belt-keyrep, KRP)
*******************************************************************************
*/

/*!	\brief Длина состояния функций преобразования ключа

	Возвращается длина состояния (в октетах) функций преобразования ключа.
	\return Длина состояния.
*/
size_t beltKRP_keep();

/*!	\brief Инициализация функций преобразования ключа

	По ключу [len]key, который принадлежит уровню level, в state формируются 
	структуры данных, необходимые для преобразования этого ключа.
	\pre len == 16 || len == 24 || len == 32.
	\pre По адресу state зарезервировано beltKRP_keep() октетов.
	\remark Буферы key и state могут пересекаться.
*/
void beltKRPStart(
	void* state,			/*!< [out] состояние */
	const octet key[],		/*!< [in] ключ */
	size_t len,				/*!< [in] длина ключа в октетах */
	const octet level[12]	/*!< [in] уровень */
);

/*!	\brief Тиражирование ключа

	Ключ [len]key, размещенный в state функцией beltKRPStart(), 
	преобразуется в ключ [key_len]key_, который имеет заголовок header.
	\pre (key_len == 16 || key_len == 24 || key_len == 32) && key_len <= len.
	\expect beltKRPStart() < beltKRPStepG()*.
*/
void beltKRPStepG(
	octet key_[],			/*!< [out] преобразованный ключ */
	size_t key_len,			/*!< [in] длина key в октетах */
	const octet header[16],	/*!< [in] заголовок key_ */
	void* state				/*!< [in,out] состояние */
);

/*!	\brief Преобразование ключа

	По ключу [n]src, который имеет уровень level, строится ключ [m]dest, 
	который имеет заголовок header.
	\expect{ERR_BAD_INPUT} 
	-	n == 16 || n == 24 || n == 32;
	-	m == 16 || m == 24 || m == 32;
	-	m <= n.
	.
	\return ERR_OK, если преобразование успешно завершено, и код ошибки
	в противном случае.
	\remark Буферы могут пересекаться.
*/
err_t beltKRP(
	octet dest[],				/*!< [out] преобразованный ключ */
	size_t m,					/*!< [in] длина dest в октетах */
	const octet src[],			/*!< [in] исходный ключ */
	size_t n,					/*!< [in] длина src в октетах */
	const octet level[12],		/*!< [in] уровень ключа src */
	const octet header[16]		/*!< [in] заголовок ключа dest */
);

/*
*******************************************************************************
Ключезавимое хэширование (hmac-hbelt, HMAC, алгоритм 6.1.4 СТБ 34.101.47)
*******************************************************************************
*/

/*!	\brief Длина состояния функций HMAC

	Возвращается длина состояния (в октетах) функций имитозащиты в режиме MAC.
	\return Длина состояния.
*/
size_t beltHMAC_keep();

/*!	\brief Инициализация функций HMAC

	По ключу [len]key в state формируются структуры данных, необходимые для 
	имитозащиты в режиме HMAC.
	\pre По адресу state зарезервировано beltHMAC_keep() октетов.
	\remark Рекомендуется использовать ключ из 32 октетов.
*/
void beltHMACStart(
	void* state,			/*!< [out] состояние */
	const octet key[],		/*!< [in] ключ */
	size_t len				/*!< [in] длина ключа в октетах */
);

/*!	\brief Имитозащита фрагмента данных в режиме HMAC

	Текущая имитовставка, размещенная в state, пересчитывается с учетом нового
	фрагмента данных [count]buf. Пересчет выполняется на ключе,
	также размещенном в state.
	\expect beltHMACStart() < beltHMACStepA()*.
*/
void beltHMACStepA(
	const void* buf,	/*!< [in] данные */
	size_t count,		/*!< [in] число октетов данных */
	void* state			/*!< [in,out] состояние */
);

/*!	\brief Определение имитовставки в режиме HMAC

	Определяется окончательная имитовставка mac всех данных,
	обработанных до этого функцией beltHMACStepA().
	\expect (beltHMACStepA()* < beltHMACStepG())*.
*/
void beltHMACStepG(
	octet mac[32],		/*!< [out] имитовставка */
	void* state			/*!< [in,out] состояние */
);

/*!	\brief Определение усеченной имитовставки в режиме HMAC

	Определяется окончательная имитовставка [mac_len]mac всех данных,
	обработанных до этого функцией beltHMACStepA(). Возвращаемая имитовставка 
	состоит из первых mac_len октетов полной имитовставки.
	\pre mac_len <= 32.
	\expect (beltHMACStepA()* < beltHMACStepG2())*.
	\remark Если продолжение имитозащиты не предполагается, то буферы 
	mac и state могут пересекаться.
*/
void beltHMACStepG2(
	octet mac[],		/*!< [out] имитовставка */
	size_t mac_len,		/*!< [in] длина имитовставки */
	void* state			/*!< [in,out] состояние */
);

/*!	\brief Проверка имитовставки в режиме HMAC

	Проверяется, что окончательная имитовставка всех данных,
	обработанных до этого функцией beltHMACStepA(), совпадает с mac.
	\expect (beltHMACStepA()* < beltHMACStepV())*.
*/
bool_t beltHMACStepV(
	const octet mac[32],	/*!< [in] контрольная имитовставка */
	void* state				/*!< [in,out] состояние */
);

/*!	\brief Проверка усеченной имитовставки

	Проверяется, что первые mac_len октетов окончательной имитовставки
	всех данных, обработанных до этого функцией beltHMACStepA(), совпадают
	с [mac_len]mac.
	\pre mac_len <= 32.
	\expect (beltHMACStepA()* < beltHMACStepV2())*.
*/
bool_t beltHMACStepV2(
	const octet mac[],	/*!< [in] контрольная имитовставка */
	size_t mac_len,		/*!< [out] длина mac */
	void* state			/*!< [in,out] состояние */
);

/*!	\brief Имитозащита в режиме HMAC

	На ключе [len]key определяется имитовставка mac буфера [count]src.
	\return ERR_OK, если имитовставка успешно вычислена, и код ошибки
	в противном случае.
	\remark Буферы могут пересекаться.
*/
err_t beltHMAC(
	octet mac[32],			/*!< [out] имитовставка */
	const void* src,		/*!< [in] данные */
	size_t count,			/*!< [in] число октетов данных */
	const octet key[],		/*!< [in] ключ */
	size_t len				/*!< [in] длина ключа */
);

/*
*******************************************************************************
Построение ключа по паролю
*******************************************************************************
*/

/*!	\brief Построение ключа по паролю

	По паролю [pwd_len]pwd строится ключ key. Для усложнения словарных атак 
	используется синхропосылка [salt_len]salt. Для усложнения перебора паролей 
	ключ пересчитывается iter > 0 раз.
	\expect{ERR_BAD_INPUT} iter != 0.
	\return ERR_OK, если ключ успешно построен, и код ошибки в противном 
	случае.
	\remark Рекомендуется использовать iter >= 10000 и salt_len >= 8.
	\remark Реализована упрощенная редакция алгоритма PBKDF2 
	(Password-Based Key Derivation Function version 2), определенного в PKCS#5.
	Редакция описана в СТБ 34.101.45 (приложение E).
*/
err_t beltPBKDF2(
	octet key[32],			/*!< [out] ключ */
	const octet pwd[],		/*!< [in] пароль */
	size_t pwd_len,			/*!< [in] длина пароля (в октетах) */
	size_t iter,			/*!< [in] число итераций */
	const octet salt[],		/*!< [in] синхропосылка ("соль") */
	size_t salt_len			/*!< [in] длина синхропосылки (в октетах) */
);


#ifdef __cplusplus
} /* extern "C" */
#endif

#endif /* __BEE2_BELT_H */
