#ifndef _DSS_MOBILE_FUNCTIONS_H
#define _DSS_MOBILE_FUNCTIONS_H

#define FUNCTION_SUCCEDED		    (int)0x00
#define FUNCTION_FAILED			    (int)0x01
#define INVALID_PARAMETER		    (int)0x02
#define NO_MEMORY			    (int)0x03
#define MORE_DATA_NEEDED		    (int)0x04
#define INVALID_BLOB_HEADER		    (int)0x05
#define INVALID_PASSWORD		    (int)0x06
#define FUNCTION_NOT_IMPLEMENTED	    (int)0x07

#define CALG_AES_128_CMAC            0x00008014
#define CALG_HMAC_SHA1		     0x80098004
#define CALG_HMAC_GR3411_2012_256    0x00008034

// Версия блоба с конкатенацией ключа под маской и маски
#define DSS_BLOB_VERSION	3
// Версия блоба с флагами защиты ключа и конкатенацией ключа под маской и маски
#define DSS_PF_BLOB_VERSION	4

// Размер буфера с флагами защиты ключа
#define KEY_PROTECTION_FLAGS_SIZE   4

// Размер буфера со случайными данными для замешивания энтропии ПДСЧ
#define RANDOM_DATA_LENGTH	32

// Размер буфера с nonce
#define NONCE_DATA_LENGTH	32

#if defined(__cplusplus)
extern "C" {
#endif // defined(__cplusplus)

#include <string.h>

// Функции для мобильных платформ

/// Функция импорта ключей на фиксированном пароле
/*
 *	\param[in]	user_id - идентификатор пользователя, используется в качестве seed для выработки ключа шифрования ключа
 *	\param[in]	user_id_len - длина идентификатора пользователя
 *	\param[in]	keys - ключи, пригодные для импорта в мобильном без ввода пароля. Передаются через QR
 *	\param[out]	handle_hmac - handle ключа HMAC в CSP для дальнейшего использования
 *	\param[out]	handle_auth - handle ключа AUTH в CSP для дальнейшего использования
 *	\return		код ошибки, 0 - выполнение успешно
 */
int importRawKeys(char* user_id,
                  int user_id_len,
                  char* keys,
                  void **handle_hmac,
                  void **handle_auth);

/// Функция импорта ключа на фиксированном пароле
/*
 *	\param[in]	user_id - идентификатор пользователя, используется в качестве seed для выработки ключа шифрования ключа
 *	\param[in]	user_id_len - длина идентификатора пользователя
 *	\param[in]	key - ключ, пригодный для импорта в мобильном без ввода пароля. Передаются через QR
 *	\param[out]	handle_key - handle ключа в CSP для дальнейшего использования
 *	\param[out]	key_protection_flags - флаги защиты ключа
 *	\return		код ошибки, 0 - выполнение успешно
 */
int importRawKey(char* user_id,
                 int user_id_len,
                 char* key,
                 void **handle_key,
                 char key_protection_flags[KEY_PROTECTION_FLAGS_SIZE]);

/// Функция импорта ключей в зашифрованном виде, в процессе импорта должна проверяться целостность ключа (успешность расшифрования на пароле)
/*
 *	\param[in]	user_id - идентификатор пользователя, используется в качестве seed для выработки ключа шифрования ключа
 *	\param[in]	user_id_len - длина идентификатора пользователя
 *	\param[in]	encrypted_keys - зашифрованные на secure_password ключи, без загловков блобов и пр., в соответствии с алгоримом в ТЗ (включая padding, хэш и пр.)
 *	\param[in]	secure_password - пароль для импорта
 *	\param[in]	secure_password_len - длина пароля
 *	\param[out]	handle_hmac - handle ключа HMAC в CSP для дальнейшего использования
 *	\param[out]	handle_auth - handle ключа AUTH в CSP для дальнейшего использования
 *	\return		код ошибки, 0 - выполнение успешно
 */
int importEncryptedKeys(char* user_id,
                        int user_id_len,
                        char* encrypted_keys,
                        char* secure_password,
                        int secure_password_len,
                        void **handle_hmac,
                        void **handle_auth);

/// Функция импорта ключа в зашифрованном виде, в процессе импорта должна проверяться целостность ключа (успешность расшифрования на пароле)
/*
 *	\param[in]	user_id - идентификатор пользователя, используется в качестве seed для выработки ключа шифрования ключа
 *	\param[in]	user_id_len - длина идентификатора пользователя
 *	\param[in]	encrypted_key - зашифрованные на secure_password ключи, без загловков блобов и пр., в соответствии с алгоримом в ТЗ (включая padding, хэш и пр.)
 *	\param[in]	secure_password - пароль для импорта
 *	\param[in]	secure_password_len - длина пароля
 *	\param[out]	handle_key - handle ключа в CSP для дальнейшего использования
 *	\param[out]	key_protection_flags - флаги защиты ключа
 *	\return		код ошибки, 0 - выполнение успешно
 */
int importEncryptedKey(char* user_id,
                       int user_id_len,
                       char* encrypted_key,
                       char* secure_password,
                       int secure_password_len,
                       void **handle_key,
                       char key_protection_flags[KEY_PROTECTION_FLAGS_SIZE]);

/// Функция экспорта ключей в зашифрованном виде с типом блоба 0x03
/*
 *	\param[in]	handle_hmac - handle ключа HMAC в CSP
 *	\param[in]	handle_auth - handle ключа AUTH в CSP
 *	\param[in]	user_id - идентификатор пользователя, используется в качестве seed для выработки ключа шифрования ключа
 *	\param[in]	user_id_len - длина идентификатора пользователя
 *	\param[in]	secure_password - пароль для экспорта
 *	\param[in]	secure_password_len - длина пароля
 *	\param[in]	prf_algid - идентификатор алгоритма PRF
 *	\param[out]	encrypted_keys - зашифрованные на secure_password ключи, без загловков блобов и пр., в соответствии с алгоримом в ТЗ (включая padding, хэш и пр.)
 *	\param[out]	encrypted_keys_len
 *	\return		код ошибки, 0 - выполнение успешно
 */
int exportKeys(void *handle_hmac,
               void *handle_auth,
               char* user_id,
               int user_id_len,
               char* secure_password,
               int secure_password_len,
               int prf_algid,
               char* encrypted_keys,
               int *encrypted_keys_len);

/// Функция экспорта ключа в зашифрованном виде с типом блоба 0x04
/*
 *	\param[in]	handle_key - handle ключа в CSP
 *	\param[in]	user_id - идентификатор пользователя, используется в качестве seed для выработки ключа шифрования ключа
 *	\param[in]	user_id_len - длина идентификатора пользователя
 *	\param[in]	secure_password - пароль для экспорта
 *	\param[in]	secure_password_len - длина пароля
 *	\param[in]	prf_algid - идентификатор алгоритма PRF
 *	\param[in]	key_protection_flags - флаги защиты ключа
 *	\param[out]	encrypted_key - зашифрованные на secure_password ключи, без загловков блобов и пр., в соответствии с алгоримом в ТЗ (включая padding, хэш и пр.)
 *	\param[out]	encrypted_key_len
 *	\return		код ошибки, 0 - выполнение успешно
 */
int exportKey(void *handle_key,
              char* user_id,
              int user_id_len,
              char* secure_password,
              int secure_password_len,
              int prf_algid,
              char key_protection_flags[KEY_PROTECTION_FLAGS_SIZE],
              char *encrypted_key,
              int *encrypted_key_len);

/// Функция освобождения ключа
/*
 *	\param[in]	handle - handle ключа в CSP
 *	\return		код ошибки, 0 - выполнение успешно
 */
int freeHandle(void *handle);

/// Функция генерации кода подтверждения HMAC
/*
 *	\param[in]	handle - handle ключа в CSP
 *	\param[in]	data - данные для проверки в hex-формате
 *	\param[in]	data_len - длина данных для проверки
 *	\param[in]	HMAC_len - длина HMAC для генерации (параметр D). При значении, отличном от 0, выполняется функция Truncate в соответствии с ТЗ. В противном случае возвращается полное значение в hex-формате
 *	\param[out]	HMAC - сформированный HMAC
 *	\return		код ошибки, 0 - выполнение успешно
 */
int generateHMAC(void *handle,
                 char* data,
                 int data_len,
                 int HMAC_len,
                 char* HMAC);

/// Функция замешивания энтропии в ПДСЧ
/*
 *	\param[in]	random_data - случайные данные для замешивания
 *	\return		код ошибки, 0 - выполнение успешно
 */
int addEntropy(char random_data[RANDOM_DATA_LENGTH]);

/// Функция для создания эфемерной пары для шифрования/расшифрования
/*
 *	\param[out]	handle_transport_key - хэндл ключа
 *	\return		код ошибки, 0 - выполнение успешно
 */
int getTransportKey(void **handle_transport_key);

/// Функция экспорта открытого ключа
/*
 *	\param[in]	handle_key - хэндл ключа
 *	\param[out]	pub_key - блоб с экспортированным открытым ключом
 *	\param[out]	pub_key_len - длина блоба с экспортированным ключом
 *	\return		код ошибки, 0 - выполнение успешно
 */
int getPublicKeyInfo(void *handle_key,
                     char* pub_key,
                     int* pub_key_len);

/// Функция расшифрования ключевых блобов с ключом на результате VKO - transport ключа и server_pub_key
/*
 *	\param[in]	handle_transport_key - хэндл транспортного ключа
 *	\param[in]	server_pub_key - блоб с открытым ключом сервера
 *	\param[in]	server_pub_key_len - длина блоба с открытым ключом сервера
 *	\param[in]	double_encrypted_keys - буфер с зашифрованными ключами
 *	\param[in]	double_encrypted_keys_len - длина буфера с зашифрованными ключами
 *	\param[out]	encrypted_key_1 - расшифрованный блоб с первым ключом
 *	\param[out]	encrypted_key_2 - расшифрованный блоб со вторымключом
 *	\param[out]	encrypted_key_len - длина блобов с расшифрованными ключами
 *	\return		код ошибки, 0 - выполнение успешно
 */
int decryptEncryptedKey(void *handle_transport_key,
                        char* server_pub_key,
                        int server_pub_key_len,
                        char* double_encrypted_keys,
                        int double_encrypted_keys_len,
                        char* encrypted_key_1,
                        char* encrypted_key_2,
                        int* encrypted_key_len);

/// Функция генерация случайных 32 байт
/*
 *	\param[out]	nonce - буфер для сгенерированных данных
 *	\return		код ошибки, 0 - выполнение успешно
 */
int genNonce(char nonce[NONCE_DATA_LENGTH]);


#if defined(__cplusplus)
} // extern "C"
#endif // defined(__cplusplus)

#endif // _DSS_MOBILE_FUNCTIONS_H
