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

/*!
 * \file $RCSfile$
 * \version $Revision: 61931 $
 * \date $Date: 2010-05-21 19:24:23 +0400 (РџС‚, 21 РјР°Р№ 2010) $
 * \author $Author: borodin $
 * \brief Параметры папки (носителя).
 */

#include "rdr_prj.h"

DWORD rdr_exist_default_password(const TSupSysEContext *context, DWORD auth_type, BOOL * exist)
{
    DWORD code;
    DWORD flags = 0;
    if ((auth_type & AUTH_TYPE_TYPE_MASK) != AUTH_TYPE_TYPE_PUK && (auth_type & AUTH_TYPE_TYPE_MASK) != AUTH_TYPE_TYPE_ROOT)
	LOGRETURN((DWORD)ERROR_INVALID_PARAMETER);
    code = rdr_all_password_flags(context, &flags);
    if (code) 
	LOGRETURN(code);
    if ((auth_type & AUTH_TYPE_TYPE_MASK) == AUTH_TYPE_TYPE_PUK)
	*exist = (flags & AUTH_FLAG_TYPE_IS_DEF_PUK) ? TRUE : FALSE;
    else 
	*exist = (flags & AUTH_FLAG_TYPE_IS_DEF_ROOT) ? TRUE : FALSE;
    LOGRETURN(code);
}

DWORD rdr_get_default_password(const TSupSysEContext *context, DWORD auth_type, char * password, size_t max_length)
{
    DWORD code;
    TReaderInfoGetParam info;
    SUPSYS_PRE(max_length);
    SUPSYS_PRE_WRITE_PTRS(password, (max_length*sizeof (TCHAR)));
    
    info.paramID = TCEP_default_password_auth_type_ascii;
    info.info.any_password_ascii.password = password;
    info.info.any_password_ascii.max_length = max_length;
    info.info.any_password_ascii.auth_type = auth_type;
    code = supsys_call(context, READER_FUN_GET_PARAM, &info); 
    if (code == (DWORD)ERROR_NOT_SUPPORTED || code == (DWORD)NTE_NOT_SUPPORTED) {
	TCHAR tpassword[CRYPT_MAX_PIN_LENGTH + 1];
	info.paramID = TCEP_default_password_auth_type;
	info.info.any_password.password = tpassword;
	info.info.any_password.max_length = CRYPT_MAX_PIN_LENGTH;
	info.info.any_password.auth_type = auth_type;
	code = supsys_call(context, READER_FUN_GET_PARAM, &info);
	if ((code == (DWORD)ERROR_NOT_SUPPORTED || code == (DWORD)NTE_NOT_SUPPORTED) && ((auth_type & AUTH_TYPE_TYPE_MASK) == AUTH_TYPE_TYPE_ROOT)) {
	    info.paramID = TCEP_default_password;
	    info.info.root_password.password = tpassword;
	    info.info.root_password.max_length = CRYPT_MAX_PIN_LENGTH;
	    code = supsys_call(context, READER_FUN_GET_PARAM, &info);
	}
	if (code == ERROR_SUCCESS) {
	    if (_tcslen(tpassword) > max_length)
		code = ERROR_MORE_DATA;
	    else if (password) {
		_2asciicpy(password, tpassword);
	    }
	}
	support_zero_memory(tpassword, CRYPT_MAX_PIN_LENGTH*sizeof(TCHAR));
    }
    LOGRETURN(code);
}

DWORD rdr_get_universal_flags(const TSupSysEContext *context, TRdrUniversalCarrierFlags * flags) 
{
    DWORD code;
    TReaderInfoGetParam info;
    memset(&info.info.uni_flags, 0, sizeof(TRdrUniversalCarrierFlags));
    info.paramID = TCEP_uni_flags;
    code = supsys_call(context, READER_FUN_GET_PARAM, &info);
    if (code)
	LOGRETURN(code);
    *flags = info.info.uni_flags;
    LOGRETURN(ERROR_SUCCESS);
}

DWORD rdr_get_fkc_flags(const TSupSysEContext *context, TRdrFkcCarrierFlags * flags)
{
    DWORD code;
    TReaderInfoGetParam info;
    memset(&info.info.fkc_flags, 0, sizeof(TRdrFkcCarrierFlags));
    info.paramID = TCEP_fkc_flags;
    code = supsys_call(context, READER_FUN_GET_PARAM, &info);
    if (code)
	LOGRETURN(code);
    *flags = info.info.fkc_flags;
    LOGRETURN(ERROR_SUCCESS);
}

DWORD rdr_get_sm_params(const TSupSysEContext* context, TRdrFkcSecureMessagingType* type, unsigned int* algid, DWORD* cipher_mode, unsigned int* imit_key_algid, BOOL* padding)
{
    DWORD code;
    TReaderInfoGetParam info;
    TRdrFkcSecureMessagingParams* smp;

    info.paramID = TCEP_sm_params;
    memset(&info.info.sm_params, 0, sizeof(TRdrFkcSecureMessagingParams));

    code = supsys_call(context, READER_FUN_GET_PARAM, &info);
    if (code == (DWORD)ERROR_NOT_SUPPORTED) {
	*type = TRdrFkcSecureMessagingType_FKC;
	*algid = CALG_G28147;
	*cipher_mode = CRYPT_MODE_CNT;
	*imit_key_algid = CALG_G28147;
	*padding = FALSE;
	LOGRETURN(ERROR_SUCCESS);
    }
    if (code) {
	LOGRETURN(code);
    }
    smp = &info.info.sm_params;

    *type = smp->sm_type;
    *padding = smp->padding;

    if (smp->sm_type == TRdrFkcSecureMessagingType_ISO) {
	switch (smp->params.iso_params.cipher_algid) {
	    case TRdrFkcSecureMessagingCipher_28147:
		*algid = CALG_G28147;
		break;
	    case TRdrFkcSecureMessagingCipher_3412M:
		*algid = CALG_GR3412_2015_M;
		break;
	    default:
		LOGRETURN((DWORD)NTE_NOT_SUPPORTED);
	}

	switch (smp->params.iso_params.cipher_mode) {
	    case TRdrFkcSecureMessagingMode_CNT:
		*cipher_mode = CRYPT_MODE_CNT;
		break;
	    case TRdrFkcSecureMessagingMode_CBC:
		*cipher_mode = CRYPT_MODE_CBC;
		break;
	    default:
		LOGRETURN((DWORD)NTE_NOT_SUPPORTED);
	}

	switch (smp->params.iso_params.imit_algid) {
	    case TRdrFkcSecureMessagingImit_28147:
		*imit_key_algid = CALG_G28147;
		break;
	    case TRdrFkcSecureMessagingImit_3413M:
		*imit_key_algid = CALG_GR3412_2015_M;
		break;
	    default:
		LOGRETURN((DWORD)NTE_NOT_SUPPORTED);
	}
    }
    else if (smp->sm_type == TRdrFkcSecureMessagingType_FKC) {
    }
    LOGRETURN(ERROR_SUCCESS);
}

DWORD rdr_get_container_level(const TSupSysEContext *context, DWORD * security_level)
{
    DWORD code;
    TReaderInfoGetParam info;
    info.info.security_level = 0;
    info.paramID = TCEP_fkc_csp_interface_container;
    code = supsys_call(context, READER_FUN_GET_PARAM, &info);
    if (code)
	LOGRETURN(code);
    *security_level = info.info.security_level;
    LOGRETURN(ERROR_SUCCESS);
}

DWORD rdr_get_license_permissions(const TSupSysEContext *context, unsigned * permissions) 
{
    DWORD code;
    DWORD dw_perm = 0;
    code = supsys_call(context, READER_FUN_GET_LIC_PERMISSIONS, &dw_perm);
    if (code)
	LOGRETURN(code);
    *permissions = (unsigned)dw_perm;
    LOGRETURN(ERROR_SUCCESS);
}

DWORD rdr_get_support_flag (const TSupSysEContext *context, size_t flag, int * value)
{
    LOGRETURN(supsys_flag(context, RDR_FLAG_BLOCK_RDR, flag, value));
}

DWORD rdr_get_auth_state(const TSupSysEContext *context, TRdrLoginInfoType auth_type)
{
    TReaderInfoGetParam info;
    info.paramID = TCEP_auth_state;
    info.info.is_auth_type_blocked = auth_type;
    LOGRETURN(supsys_call(context, READER_FUN_GET_PARAM, &info));
}

static void makecounter(DWORD * dest, DWORD src)
{
    *dest = ((src & 0xFF000000) >> 24) | ((src & 0xFF0000) >> 8) | ((src & 0xFF00) << 8) | ((src & 0xFF) << 24);
}
DWORD rdr_get_sespake_counters(const TSupSysEContext *context, TRdrLoginInfoType auth_type, TRdrFkcSespakeCounters counters, BOOL* has_counters)
{
    DWORD code;
    TReaderInfoGetParam info;
    SUPSYS_PRE_WRITE_PTRS(counters, sizeof(TRdrFkcSespakeCounters));
    info.paramID = TCEP_sespake_counters;
    info.info.sespake_counters.auth_type = auth_type & AUTH_TYPE_TYPE_MASK;
    info.info.sespake_counters.has_counters = TRUE;
    code = supsys_call(context, READER_FUN_GET_PARAM, &info);
    if (code)
	LOGRETURN(code);

    *has_counters = info.info.sespake_counters.has_counters;
    if (info.info.sespake_counters.has_counters) {
	makecounter(&counters[TSespakeCounterType_SESPAKE], info.info.sespake_counters.counters[TSespakeCounterType_SESPAKE]);
	makecounter(&counters[TSespakeCounterType_fail], info.info.sespake_counters.counters[TSespakeCounterType_fail]);
	makecounter(&counters[TSespakeCounterType_cfail], info.info.sespake_counters.counters[TSespakeCounterType_cfail]);
    }
    LOGRETURN(code);

}

DWORD rdr_get_applet_text_info(const TSupSysEContext *context, size_t * text_info_length, TCHAR * text_info)
{
    DWORD code;
    TSupSysInfoText text_info_str;
    if (!context || !text_info_length)
	LOGRETURN((DWORD)ERROR_NOT_SUPPORTED);

    text_info_str.text = text_info;
    text_info_str.length = *text_info_length;
    code = supsys_call(context, READER_FUN_GET_APPLET_TEXT_INFO, &text_info_str);
    if (code == (DWORD)ERROR_MORE_DATA) {
	*text_info_length = text_info_str.length;
	LOGRETURN(code);
    }
    if (code)
	LOGRETURN(code);    

    *text_info_length = text_info_str.length;
    LOGRETURN(0);
}

DWORD rdr_all_password_flags(const TSupSysEContext *context, DWORD * auth_flags)
{
    DWORD code;
    TReaderInfoGetParam info;
    info.paramID = TCEP_auth_types;
    code = supsys_call(context, READER_FUN_GET_PARAM, &info);
    if (code)
	LOGRETURN(code);
    
    *auth_flags = info.info.auth_types;
    LOGRETURN(code);
}

DWORD rdr_set_container_param(const TSupSysEContext *context, TRdrFkcFolderEnumParam param_type, BYTE * pbData, DWORD dwData)
{
    TReaderInfoSetParam info;
    info.paramID = param_type;
    switch (param_type) {
	case TCEP_header:
	case TCEP_cloud_certificate:
	case TCEP_cloud_extensions:
	    info.info.hex_param.info = pbData;
	    info.info.hex_param.length = (size_t)dwData;
	    break;
	case TCEP_cloud_auth_server:
	case TCEP_cloud_sign_server:
	case TCEP_cloud_OAuth2_auth_token:
	case TCEP_cloud_OAuth2_id_token:
	case TCEP_cloud_username:
	case TCEP_cloud_password:
	    info.info.string_param.text = (char*)pbData;
	    info.info.string_param.length = dwData - 1;
	    break;
	case TCEP_cloud_certificate_id:
	case TCEP_cloud_permissions:
	    if (dwData != sizeof(DWORD))
		LOGRETURN((DWORD)ERROR_INVALID_PARAMETER);
	    info.info.dword_param = *(DWORD*)pbData;
	    break;
	default:
	    LOGRETURN((DWORD)ERROR_INVALID_PARAMETER);
    }
    LOGRETURN(supsys_call(context, READER_FUN_FOLDER_PARAM_SET, &info));
}

DWORD rdr_get_hardware_store_flags(const TSupSysEContext *context, DWORD* hardware_flags)
{
    LOGRETURN(supsys_call(context, READER_FUN_GET_HARDWARE_FLAGS, (TSupSysInfo*)hardware_flags));
}

DWORD rdr_set_hardware_store_flags(const TSupSysEContext *context, DWORD hardware_flags)
{
    LOGRETURN(supsys_call(context, READER_FUN_SET_HARDWARE_FLAGS, (TSupSysInfo*)&hardware_flags));
}

/* end of file: $Id: rfprm.c 61931 2010-05-21 15:24:23Z borodin $ */
