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

/*!
 * \file $RCSfile$
 * \version $Revision: 226608 $
 * \date $Date:: 2021-03-31 13:09:05 +0300#$
 * \author $Author: borodin $
 * \brief Функция соединения с носителем.
 */

#include "ric_prj.h"

DWORD ric_get_param(TSupSysContext *context, TSupSysInfo *info) {
    TReaderFkcFolderEnumParam paramID;
    TReaderInfoGetParam * inf = (TReaderInfoGetParam*)info;
    DWORD code = ERROR_SUCCESS;
    TRICContext *ctx = (TRICContext*)context;

    SUPSYS_PRE_CCONTEXT(ctx, TRICContext);
    paramID = inf->paramID;

    switch (paramID) {
	case TCEP_auth_types:
	    inf->info.auth_types = AUTH_FLAG_TYPE_ROOT_CONT | AUTH_FLAG_TYPE_ROOT;
	    if (ctx->card_type == CardType_Magistra)
		inf->info.auth_types |= AUTH_FLAG_TYPE_CAN_RESET_ROOT_DEF;
	    break;
	case TCEP_uni_flags:
	    inf->info.uni_flags.folders = 1;
	    inf->info.uni_flags.long_names = 0;
	    inf->info.uni_flags.can_create_folder = 0;
	    inf->info.uni_flags.functional_container = 0;
	    inf->info.uni_flags.premapped_files = 1;
	    break;
	default:
	    code = (DWORD)NTE_NOT_SUPPORTED;
	    break;
    }
    return code;
}
DWORD ric_get_password_type(TSupSysContext *context, TSupSysInfo *info) {
    TRdrLoginInfoType * type = (TRdrLoginInfoType*)info;
    UNUSED(context);

    if ((*type & AUTH_TYPE_TYPE_MASK) == AUTH_TYPE_TYPE_ROOT)
	*type = AUTH_TYPE_TYPE_ROOT | AUTH_TYPE_AUTH_SIMPLE;
    else
	return ERROR_INVALID_PARAMETER;

    return ERROR_SUCCESS;
}

DWORD ric_get_auth_info(TSupSysContext *context, TSupSysInfo *info) {
    TReaderInfoAuthInfo * tpwd = (TReaderInfoAuthInfo *)info;
    UNUSED(context);

    if (tpwd->auth_type != AUTH_TYPE_TYPE_ROOT)
	return (DWORD)ERROR_INVALID_PARAMETER;
    tpwd->info.info_pwd.max_pwd_length = 8;
    tpwd->info.info_pwd.min_pwd_length = 0;
    tpwd->info.info_pwd.uiRetries = 5;
    return 0;
}

/*! 
 * \ingroup ric_fun
 * \brief Функция соединения с носителем.
 */
DWORD ric_connect_carrier(
    TSupSysContext *context, 
    TSupSysInfo *info )
{
    TSCardInfoConnectCarrier *inf = (TSCardInfoConnectCarrier*)info;
    TRICContext *ctx = (TRICContext*)context;
    DWORD code;

    SUPSYS_PRE_INFO( info, TSCardInfoConnectCarrier );
    SUPSYS_PRE_CCONTEXT( ctx, TRICContext );
    
    ctx->apdu = inf->apdu_cmd;
    ctx->apdu_full = inf->simple_apdu_cmd;
    ctx->reader = inf->reader;
    ctx->ber_tlv_search = inf->ber_tlv_search;
    ctx->simple_tlv_search = inf->simple_tlv_search;
    ctx->connect_name = (inf->connect && (_tcscmp(inf->connect, KCHANNEL_CONNECT) == 0)) ? KCHANNEL_CONNECT : DEFAULT_CONNECT;
    code = ric_unique_num( ctx, ctx->unique );
    if( code )
	return code;
    inf->app_count = 1;
    return ERROR_SUCCESS;
}

DWORD select_app (TRICContext * ctx) {
    BYTE apdu_sel[] = { 0, 0xA4, 0x00, 0x00 };
    unsigned char data[2] = { 0, 1 };
    BYTE response[255];
    size_t len = 255;
    /* Select pin file. */
    return send_apdu( ctx, apdu_sel, data, sizeof (data), response, &len );
}

static DWORD ric_error(unsigned short sw, DWORD * retries_out)
{
    if ((sw & 0xFFF0) == 0x63C0) {
	int retries = sw & 0xf;
	if (retries) {
	    *retries_out = retries;
	    return (DWORD)SCARD_W_WRONG_CHV;
	}
	else
	    return (DWORD)SCARD_W_CHV_BLOCKED;
    }
    switch (sw) {
	case 0x6983: return (DWORD)SCARD_W_CHV_BLOCKED;
	case 0x62F3: return (DWORD)NTE_TOKEN_KEYSET_STORAGE_FULL;
	case 0x6b00: return (DWORD)NTE_TOKEN_KEYSET_STORAGE_FULL;
	case 0x65F0: return (DWORD)SCARD_W_UNSUPPORTED_CARD;
	case 0x6982: return (DWORD)CPR_ERR_RDR_NEED_ROOT_AUTH;
	case 0x6a82: return (DWORD)ERROR_FILE_NOT_FOUND;
	case 0x6985: return (DWORD)CPR_ERR_RDR_NEED_OPEN_FOLDER;
	case 0x6a86:
	case 0x6d00:
	case 0x6989: return (DWORD)SCARD_E_UNSUPPORTED_FEATURE;
	default:     return (DWORD)SCARD_W_UNSUPPORTED_CARD;
    }
}

DWORD send_apdu(TRICContext * ctx, const BYTE * apdu, const BYTE * in, size_t in_len, BYTE * out, size_t * out_len)
{
    DWORD tries = 0;
    DWORD code = ctx->apdu_full(ctx->reader, FALSE, ric_error, apdu, in, in_len, out, out_len, &tries);
    if (code == (DWORD)SCARD_W_WRONG_CHV)
	ctx->retries = (int)tries;
    return code;
}


/* end of file: $Id: ric_con.c 226608 2021-03-31 10:09:05Z borodin $ */
