Ejemplo n.º 1
0
static int32_t ICC_Async_GetPLL_Divider(struct s_reader *reader)
{
	if(reader->divider != 0) { return reader->divider; }

	if(reader->cardmhz != 8300)  /* Check dreambox is not DM7025 */
	{
		float divider;
		rdr_log(reader," TEST tempo mhz check = %u mhz", reader->mhz);
		divider = ((float) reader->cardmhz) / ((float) reader->mhz);
		if (tempfi == 9) reader->divider = (int32_t) divider; // some card's runs only when slightly oveclocked like HD02
		else {
		reader->divider = (int32_t) divider;
		if(divider > reader->divider) { reader->divider++; }  /* to prevent over clocking, ceil (round up) the divider */
		}
		rdr_debug_mask(reader, D_DEVICE, "PLL maxmhz = %.2f, wanted mhz = %.2f, divider used = %d, actualcardclock=%.2f", (float) reader->cardmhz / 100, (float) reader->mhz / 100,
					   reader->divider, (float) reader->cardmhz / reader->divider / 100);
		reader->mhz = reader->cardmhz / reader->divider;
	}
	else /* STB is DM7025 */
	{
		int32_t i, dm7025_clock_freq[] = {518, 461, 395, 360, 319, 296, 267, 244, 230, 212, 197},
										 dm7025_PLL_setting[] = {6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, t_cardmhz = reader->mhz;

		for(i = 0; i < 11; i++)
			if(t_cardmhz >= dm7025_clock_freq[i]) { break; }

		if(i > 10) { i = 10; }

		reader->mhz = dm7025_clock_freq[i];
		reader->divider = dm7025_PLL_setting[i]; /*Nicer way of codeing is: reader->divider = i + 6;*/

		rdr_debug_mask(reader, D_DEVICE, "DM7025 PLL maxmhz = %.2f, wanted mhz = %.2f, PLL setting used = %d, actualcardclock=%.2f", (float) reader->cardmhz / 100, (float) t_cardmhz / 100,
					   reader->divider, (float) reader->mhz / 100);
	}

	return reader->divider;
}
Ejemplo n.º 2
0
static int32_t Cool_Reset (struct s_reader *reader, ATR * atr)
{
	int32_t ret;

	if (!reader->ins7e11_fast_reset) {
		//set freq to reader->cardmhz if necessary
		uint32_t clk;

		ret = cnxt_smc_get_clock_freq (specdev()->handle, &clk);
		coolapi_check_error("cnxt_smc_get_clock_freq", ret);
		if (clk/10000 != (uint32_t)reader->cardmhz) {
			rdr_debug_mask(reader, D_DEVICE, "COOL: clock freq: %i, scheduling change to %i for card reset",
					clk, reader->cardmhz*10000);
			call (Cool_SetClockrate(reader, reader->cardmhz));
		}
	}
	else {
		rdr_debug_mask(reader, D_DEVICE, "fast reset needed, restoring transmit parameter for coolstream device %s", reader->device);
		call(Cool_Set_Transmit_Timeout(reader, 0));
		rdr_log(reader, "Doing fast reset");
	}

	//reset card
	ret = cnxt_smc_reset_card (specdev()->handle, ATR_TIMEOUT, NULL, NULL);
	coolapi_check_error("cnxt_smc_reset_card", ret);
	cs_sleepms(50);
	int32_t n = ATR_MAX_SIZE;
	unsigned char buf[ATR_MAX_SIZE];
	ret = cnxt_smc_get_atr (specdev()->handle, buf, &n);
	coolapi_check_error("cnxt_smc_get_atr", ret);

	call (!ATR_InitFromArray (atr, buf, n) != ERROR);
	{
		cs_sleepms(50);
		return OK;
	}
}
Ejemplo n.º 3
0
static void reader_log_emm(struct s_reader * reader, EMM_PACKET *ep, int32_t i, int32_t rc, struct timeb *tps) {
	char *rtxt[] = {
		"error",
		is_cascading_reader(reader) ? "sent" : "written",
		"skipped",
		"blocked" };
	char *typedesc[] = { "unknown", "unique", "shared", "global" };
	struct s_client *cl = reader->client;
	struct timeb tpe;

	if (reader->logemm & (1 << rc)) {
		cs_ftime(&tpe);
		if (!tps)
			tps = &tpe;

		rdr_log(reader, "%s emmtype=%s, len=%d, idx=%d, cnt=%d: %s (%ld ms)",
				username(ep->client), typedesc[cl->emmcache[i].type], ep->emm[2],
				i, cl->emmcache[i].count, rtxt[rc],
				1000 * (tpe.time - tps->time) + tpe.millitm - tps->millitm);
	}

	if (rc) {
		cl->lastemm = time(NULL);
		led_status_emm_ok();
	}

#if defined(WEBIF) || defined(LCDSUPPORT)
	//counting results
	switch (rc) {
	case 0: reader->emmerror[ep->type]++; break;
	case 1: reader->emmwritten[ep->type]++; break;
	case 2: reader->emmskipped[ep->type]++; break;
	case 3: reader->emmblocked[ep->type]++; break;
	}
#endif
}
Ejemplo n.º 4
0
void do_emm(struct s_client * client, EMM_PACKET *ep)
{
	char *typtext[]={"unknown", "unique", "shared", "global"};
	char tmp[17];
	int32_t emmnok=0;

	struct s_reader *aureader = NULL;
	cs_ddump_mask(D_EMM, ep->emm, ep->emmlen, "emm:");

	int8_t cl_dvbapi = 0, assemble = 0;
#ifdef HAVE_DVBAPI
	cl_dvbapi = streq(cfg.dvbapi_usr, client->account->usr);
#endif
	if (client->account->emm_reassembly > 1 || (client->account->emm_reassembly && cl_dvbapi))
		assemble = 1;

	LL_ITER itr = ll_iter_create(client->aureader_list);
	while ((aureader = ll_iter_next(&itr))) {
		if (!aureader->enable)
			continue;

		uint16_t caid = b2i(2, ep->caid);
		uint32_t provid = b2i(4, ep->provid);

		if (aureader->audisabled) {
			rdr_debug_mask(aureader, D_EMM, "AU is disabled");
			/* we have to write the log for blocked EMM here because
			 this EMM never reach the reader module where the rest
			 of EMM log is done. */
			if (aureader->logemm & 0x10)  {
				rdr_log(aureader, "%s emmtype=%s, len=%d, idx=0, cnt=1: audisabled (0 ms)",
						client->account->usr,
						typtext[ep->type],
						ep->emm[2]);
			}
			continue;
		}

		if (!(aureader->grp & client->grp)) {
			rdr_debug_mask(aureader, D_EMM, "skip emm, group mismatch");
			continue;
		}

		//TODO: provider possibly not set yet, this is done in get_emm_type()
		if (!emm_reader_match(aureader, caid, provid))
			continue;

		struct s_cardsystem *cs = NULL;

		if (is_cascading_reader(aureader)) { // network reader (R_CAMD35 R_NEWCAMD R_CS378X R_CCCAM)
			if (!aureader->ph.c_send_emm) // no emm support
				continue;

			cs = get_cardsystem_by_caid(caid);
			if (!cs) {
				rdr_debug_mask(aureader, D_EMM, "unable to find cardsystem for caid %04X", caid);
				continue;
			}
		} else { // local reader
			if (aureader->csystem.active)
				cs=&aureader->csystem;
		}

		if (cs && cs->get_emm_type) {
			if (!cs->get_emm_type(ep, aureader)) {
				rdr_debug_mask(aureader, D_EMM, "emm skipped, get_emm_type() returns error");
				emmnok++;
				continue;
			}
		}

		if (cs && cs->get_emm_filter) {
			if (!do_simple_emm_filter(aureader, cs, ep)) {
				rdr_debug_mask(aureader, D_EMM, "emm skipped, emm_filter() returns invalid");
				emmnok++;
				continue;
			}
		}

		if (cs && cs->do_emm_reassembly) {
			if (assemble) {
				if (!cs->do_emm_reassembly(client, ep))
					return;
			} else {
				rdr_debug_mask(aureader, D_EMM, "processing raw emm");
			}
		}

		rdr_debug_mask_sensitive(aureader, D_EMM, "emmtype %s. Reader serial {%s}.", typtext[ep->type],
			cs_hexdump(0, aureader->hexserial, 8, tmp, sizeof(tmp)));
		rdr_debug_mask_sensitive(aureader, D_EMM, "emm UA/SA: {%s}.",
			cs_hexdump(0, ep->hexserial, 8, tmp, sizeof(tmp)));

		client->last = time(NULL);
		saveemm(aureader, ep);

		int32_t is_blocked = 0;
		switch (ep->type) {
			case UNKNOWN: is_blocked = (aureader->blockemm & EMM_UNKNOWN) == EMM_UNKNOWN; break;
			case UNIQUE : is_blocked = (aureader->blockemm & EMM_UNIQUE ) == EMM_UNIQUE;  break;
			case SHARED : is_blocked = (aureader->blockemm & EMM_SHARED ) == EMM_SHARED;  break;
			case GLOBAL : is_blocked = (aureader->blockemm & EMM_GLOBAL ) == EMM_GLOBAL;  break;
		}

		// if not already blocked we check for block by len
		if (!is_blocked) is_blocked = cs_emmlen_is_blocked( aureader, ep->emm[2] ) ;

		if (is_blocked != 0) {
#ifdef WEBIF
			aureader->emmblocked[ep->type]++;
			is_blocked = aureader->emmblocked[ep->type];
#endif
			/* we have to write the log for blocked EMM here because
			 this EMM never reach the reader module where the rest
			 of EMM log is done. */
			if (aureader->logemm & 0x08)  {
				rdr_log(aureader, "%s emmtype=%s, len=%d, idx=0, cnt=%d: blocked (0 ms)",
						client->account->usr,
						typtext[ep->type],
						ep->emm[2],
						is_blocked);
			}
			continue;
		}

		client->lastemm = time((time_t*)0);

		client->emmok++;
		if (client->account)
			client->account->emmok++;
		first_client->emmok++;

		//Check emmcache early:
		int32_t i;
		unsigned char md5tmp[CS_EMMSTORESIZE];
		struct s_client *au_cl = aureader->client;

		MD5(ep->emm, ep->emm[2], md5tmp);
		ep->client = client;

		for (i=0; i<CS_EMMCACHESIZE; i++) {
			if (!memcmp(au_cl->emmcache[i].emmd5, md5tmp, CS_EMMSTORESIZE)) {
				rdr_debug_mask(aureader, D_EMM, "emm found in cache: count %d rewrite %d",
					au_cl->emmcache[i].count, aureader->rewritemm);
				if (aureader->cachemm && (au_cl->emmcache[i].count > aureader->rewritemm)) {
					reader_log_emm(aureader, ep, i, 2, NULL);
					return;
				}
				break;
			}
		}

		EMM_PACKET *emm_pack;
		if (cs_malloc(&emm_pack, sizeof(EMM_PACKET))) {
			rdr_debug_mask(aureader, D_EMM, "emm is being sent to reader");
			memcpy(emm_pack, ep, sizeof(EMM_PACKET));
			add_job(aureader->client, ACTION_READER_EMM, emm_pack, sizeof(EMM_PACKET));
		}
	}
	if (emmnok > 0 && emmnok == ll_count(client->aureader_list)) {
		client->emmnok++;
		if (client->account)
			client->account->emmnok++;
		first_client->emmnok++;
	}
}
Ejemplo n.º 5
0
/*
static void cmd_test(struct s_reader *reader)
{
    def_resp;
    int i;
    uchar drecmd[] = { 0x00, 0x02 };
    char tmp[64];

    for(i = 0; i <= 0xFF; i++)
    {
        if(i == 0x45) continue;
        drecmd[0] = i;
        dre_cmd(drecmd);
        if(cta_res[2] == 0xE2)
        {
            if(cta_res[3] != 0xE3) rdr_log(reader, "cmd %02X error %02X",i ,cta_res[3]);
        }
        else
        {
            rdr_log(reader, "cmd %02X answer %s",i ,cs_hexdump(0, cta_res, cta_res[1]+2, tmp, sizeof(tmp)));
        }
    }

    uchar drecmd[64];

    //memset(drecmd, 0, 64);
    //drecmd[0] = 0x71;
    for(i = 2; i <= 64; i++)
    {
        memset(drecmd, 0, 64);
        drecmd[i-1] = 0x02;
        drecmd[0] = 0x71;

        dre_script(drecmd, i, 0, 0, 0);

        if(cta_res[2] == 0xE2)
        {
            if((cta_res[3] != 0xE2) & (cta_res[3] != 0xED)) rdr_log(reader, "Len %02X error %02X",i ,cta_res[3]);
            if((cta_res[3] & 0xF0) != 0xE0) rdr_log(reader, "Len %02X answer %s",i ,cs_hexdump(0, cta_res, cta_res[1]+2, tmp, sizeof(tmp)));
        }
        else
        {
            rdr_log(reader, "Len %02X answer %s",i ,cs_hexdump(0, cta_res, cta_res[1]+2, tmp, sizeof(tmp)));
        }
    }
}
*/
static int32_t dre_card_init(struct s_reader *reader, ATR *newatr)
{
	get_atr;
	def_resp;
	uchar ua[] = { 0x43, 0x15 };  // get serial number (UA)
	uchar providers[] = { 0x49, 0x15 };   // get providers
	uchar cmd56[] = { 0x56, 0x00 };
	int32_t i;
	char *card;
	char tmp[9];

	if((atr[0] != 0x3b) || (atr[1] != 0x15) || (atr[2] != 0x11) || (atr[3] != 0x12) || (
				((atr[4] != 0x01) || (atr[5] != 0x01)) &&
				((atr[4] != 0xca) || (atr[5] != 0x07)) &&
                ((atr[4] != 0xcb) || (atr[5] != 0x07)) &&
                ((atr[4] != 0xcc) || (atr[5] != 0x07)) &&
                ((atr[4] != 0xcd) || (atr[5] != 0x07))
			))
		{ return ERROR; }

	if(!cs_malloc(&reader->csystem_data, sizeof(struct dre_data)))
		{ return ERROR; }
	struct dre_data *csystem_data = reader->csystem_data;

	csystem_data->provider = atr[6];
	uchar checksum = xor(atr + 1, 6);

	if(checksum != atr[7])
		{ rdr_log(reader, "warning: expected ATR checksum %02x, smartcard reports %02x", checksum, atr[7]); }

	switch(atr[6])
	{
        case 0:

            if(!(dre_cmd(cmd56))) { return ERROR; }
            if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00)) { return ERROR; }

            switch(cta_res[4])
            {
                case 0x02:
                    card = "Tricolor Centr DRE3";
                    reader->caid = 0x4ae1;
                    break;
                case 0x03:
                    card = "Tricolor Syberia DRE3";
                    reader->caid = 0x4ae1;  
                    break;
                case 0x18:
                case 0x19:
                    card = "Tricolor Centr DRE4";
                    reader->caid = 0x2710;
                    break;
                case 0x1A:
                    card = "Tricolor Syberia DRE4";
                    reader->caid = 0x2710;
                    break;
                default:
                    return ERROR;
            }
            csystem_data->provider = cta_res[4];
            providers[0] = 0x83;
            break;
        case 0x11:
            card = "Tricolor Centr DRE2";
            reader->caid = 0x4ae1;
            break;          //59 type card = MSP (74 type = ATMEL)
        case 0x12:
            card = "Cable TV";
            reader->caid = 0x4ae1;  //TODO not sure about this one
            break;
        case 0x14:
            card = "Tricolor Syberia DRE2";
            reader->caid = 0x4ae1;
            break;          //59 type card
        case 0x15:
            card = "Platforma HD / DW old";
            reader->caid = 0x4ae1;
            break;          //59 type card
        default:
            return ERROR;
	}

	memset(reader->prid, 0x00, 8);

    if(atr[6] > 0)
    {
        reader->prid[0][3] = atr[6];
    }
    else
    {
        reader->prid[0][3] = csystem_data->provider;
    }

	uchar cmd54[] = { 0x54, 0x14 };   // geocode
	cmd54[1] = csystem_data->provider;
	uchar geocode = 0;
	if((dre_cmd(cmd54)))      //error would not be fatal, like on 0x11 cards
		{ geocode = cta_res[3]; }

	providers[1] = csystem_data->provider;
	if(!(dre_cmd(providers)))
		{ return ERROR; }           //fatal error
	if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
		{ return ERROR; }

	uchar provname[128];
	for(i = 0; ((i < cta_res[2] - 6) && (i < 128)); i++)
	{
		provname[i] = cta_res[6 + i];
		if(provname[i] == 0x00)
			{ break; }
	}

	int32_t major_version = cta_res[3];
	int32_t minor_version = cta_res[4];

	ua[1] = csystem_data->provider;
	dre_cmd(ua);          //error would not be fatal

	int32_t hexlength = cta_res[1] - 2;   //discard first and last byte, last byte is always checksum, first is answer code

    if(reader->force_ua)
    {
        rdr_log(reader, "WARNING!!!! used UA from force_ua %08X", reader->force_ua);
        memcpy(cta_res + 3, &reader->force_ua, 4);
    }

	reader->hexserial[0] = 0;
	reader->hexserial[1] = 0;
	memcpy(reader->hexserial + 2, cta_res + 3, hexlength);

	int32_t low_dre_id, dre_chksum;
	uchar buf[32];

    if(major_version < 0x3)
    {
        low_dre_id = ((cta_res[4] << 16) | (cta_res[5] << 8) | cta_res[6]) - 48608;
        dre_chksum = 0;
        snprintf((char *)buf, sizeof(buf), "%i%i%08i", csystem_data->provider - 16, major_version + 1, low_dre_id);

        for(i = 0; i < 32; i++)
        {
            if(buf[i] == 0x00)
                { break; }
            dre_chksum += buf[i] - 48;
        }

        if(major_version < 2)
        {
            reader->caid = 0x4ae0;
            card = csystem_data->provider == 0x11 ? "Tricolor Centr DRE1" : "Tricolor Syberia DRE1";
        }

        rdr_log(reader, "type: DRE Crypt, caid: %04X, serial: {%s}, dre id: %i%i%i%08i, geocode %i, card: %s v%i.%i",
                reader->caid, cs_hexdump(0, reader->hexserial + 2, 4, tmp, sizeof(tmp)), dre_chksum, csystem_data->provider - 16,
                major_version + 1, low_dre_id, geocode, card, major_version, minor_version);
    }
    else
    {
        low_dre_id = ((cta_res[4] << 16) | (cta_res[5] << 8) | cta_res[6]);
        dre_chksum = 0;
        snprintf((char *)buf, sizeof(buf), "%i%i%08i", csystem_data->provider, major_version, low_dre_id);

        for(i = 0; i < 32; i++)
        {
            if(buf[i] == 0x00)
                { break; }
            dre_chksum += buf[i] - 48;
        }
        rdr_log(reader, "type: DRE Crypt, caid: %04X, serial: {%s}, dre id: %i%03i%i%08i, geocode %i, card: %s v%i.%i",
                reader->caid, cs_hexdump(0, reader->hexserial + 2, 4, tmp, sizeof(tmp)), dre_chksum, csystem_data->provider,
                major_version, low_dre_id, geocode, card, major_version, minor_version);
    }

	rdr_log(reader, "Provider name:%s.", provname);

	memset(reader->sa, 0, sizeof(reader->sa));
	memcpy(reader->sa[0], reader->hexserial + 2, 1);  //copy first byte of unique address also in shared address, because we dont know what it is...

	rdr_log_sensitive(reader, "SA = %02X%02X%02X%02X, UA = {%s}", reader->sa[0][0], reader->sa[0][1], reader->sa[0][2],
					  reader->sa[0][3], cs_hexdump(0, reader->hexserial + 2, 4, tmp, sizeof(tmp)));

	reader->nprov = 1;

//  cmd_test(reader);

    // exec user script, wicardd format
    if(reader->userscript != NULL)
    {
        uint8_t *usercmd = NULL;
        int cmd_len;
        int n;
        char *tempbuf = malloc(2048);
        trim2(reader->userscript);
        FILE *pFile = fopen(reader->userscript, "rt");

        if(pFile != NULL)
        {
            uchar ignoreProvid = 0;
            uchar crypted = 0;
            uchar cryptkey = 0;
            do
            {
                tempbuf[0] = '\0';
                if(usercmd != NULL) free(usercmd);

                if(fgets(tempbuf, 2048, pFile) == NULL) continue;

                if(strlen(tempbuf) < 10) continue;

                trim2(tempbuf);

                ignoreProvid = 0;
                crypted = 0;
                cryptkey = 0;

                if(tempbuf[0] == '8' && tempbuf[1] == '6' && csystem_data->provider == 0x11) ignoreProvid = 1;
                else if(strncmp(tempbuf ,"REG2" ,4) == 0)
                {
                    dre_read_ee(reader, &tempbuf[4] ,csystem_data->provider);
                    continue;
                }
                else if(strncmp(tempbuf ,"CR" ,2) == 0)
                {
                    crypted = 1;
                    cryptkey = ((tempbuf[2] - (tempbuf[2] > 0x39 ? 0x37:0x30)) << 4) + ((tempbuf[3] - (tempbuf[3] > 0x39 ? 0x37:0x30)) & 0xF);
                }
                else if(tempbuf[0] != '5' && tempbuf[1] != '9') continue;

                strtoupper(tempbuf);

                cmd_len = strlen(tempbuf) / 2 - 3 + ignoreProvid - (crypted * 2);
                usercmd = malloc(cmd_len);

                for(i=0,n= 4+(crypted * 4);i<cmd_len;i++,n+=2)
                {
                    usercmd[i] = ((tempbuf[n] - (tempbuf[n] > 0x39 ? 0x37:0x30)) << 4) + ((tempbuf[n+1] - (tempbuf[n+1] > 0x39 ? 0x37:0x30)) & 0xF);
                }

                /*if(usercmd[cmd_len-1] != csystem_data->provider && !ignoreProvid)
                {
                    rdr_log(reader, "Skip script: current provid %02X , script provid %02X", csystem_data->provider, usercmd[cmd_len-1]);
                    continue;
                }
                */
                rdr_log(reader, "User script: %s", tempbuf);

                /*ret =*/ 

                rdr_log(reader, "Script %s", (dre_script(usercmd, cmd_len, ignoreProvid, crypted, cryptkey)) ? "done" : "error");
            }
            while(!feof(pFile));
        }
        else
        {
            rdr_log(reader, "Can't open script file (%s)", reader->userscript);
        }

        //if(usercmd != NULL) free(usercmd);
        if(tempbuf != NULL) free(tempbuf);
    }

    if(csystem_data->provider == 0x11)
    {
        memset(reader->prid[1], 0x00, 8);
        reader->prid[1][3] = 0xFE;
        reader->nprov = 2;
    }

	if(!dre_set_provider_info(reader))
		{ return ERROR; }           //fatal error

	rdr_log(reader, "ready for requests");
	return OK;
}
Ejemplo n.º 6
0
static int32_t viaccess_card_info(struct s_reader * reader)
{
	def_resp;
	int32_t i, l;
	uchar insac[] = { 0xca, 0xac, 0x00, 0x00, 0x00 }; // select data
	uchar insb8[] = { 0xca, 0xb8, 0x00, 0x00, 0x00 }; // read selected data
	uchar insa4[] = { 0xca, 0xa4, 0x00, 0x00, 0x00 }; // select issuer
	uchar insc0[] = { 0xca, 0xc0, 0x00, 0x00, 0x00 }; // read data item
	static const uchar ins24[] = { 0xca, 0x24, 0x00, 0x00, 0x09 }; // set pin

	static const uchar cls[] = { 0x00, 0x21, 0xff, 0x9f};
	static const uchar pin[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04};

	reader->last_geo.provid  = 0;
	reader->last_geo.geo_len = 0;
	reader->last_geo.geo[0]  = 0;

	rdr_log(reader, "card detected");

	cs_clear_entitlement(reader); //reset the entitlements

	// set pin
	write_cmd(ins24, pin);

	insac[2]=0xa4; write_cmd(insac, NULL); // request unique id
	insb8[4]=0x07; write_cmd(insb8, NULL); // read unique id
	rdr_log_sensitive(reader, "serial: {%llu}", (unsigned long long) b2ll(5, cta_res+2));

	insa4[2]=0x00; write_cmd(insa4, NULL); // select issuer 0
	for (i=1; (cta_res[cta_lr-2]==0x90) && (cta_res[cta_lr-1]==0); i++)
	{
		uint32_t l_provid, l_sa;
		uchar l_name[64];
		insc0[4]=0x1a; write_cmd(insc0, NULL); // show provider properties
		cta_res[2]&=0xF0;
		l_provid=b2i(3, cta_res);

		insac[2]=0xa5; write_cmd(insac, NULL); // request sa
		insb8[4]=0x06; write_cmd(insb8, NULL); // read sa
		l_sa=b2i(4, cta_res+2);

		insac[2]=0xa7; write_cmd(insac, NULL); // request name
		insb8[4]=0x02; write_cmd(insb8, NULL); // read name nano + len
		l=cta_res[1];
		insb8[4]=l; write_cmd(insb8, NULL); // read name
		cta_res[l]=0;
		trim((char *)cta_res);
		if (cta_res[0])
			snprintf((char *)l_name, sizeof(l_name), ", name: %s", cta_res);
		else
			l_name[0]=0;

		// read GEO
		insac[2]=0xa6; write_cmd(insac, NULL); // request GEO
		insb8[4]=0x02; write_cmd(insb8, NULL); // read GEO nano + len
		l=cta_res[1];
		char tmp[l*3+1];
		insb8[4]=l; write_cmd(insb8, NULL); // read geo
		rdr_log_sensitive(reader, "provider: %d, id: {%06X%s}, sa: {%08X}, geo: %s",
			i, l_provid, l_name, l_sa, (l<4) ? "empty" : cs_hexdump(1, cta_res, l, tmp, sizeof(tmp)));

		// read classes subscription
		insac[2]=0xa9; insac[4]=4;
		write_cmd(insac, cls); // request class subs
		while( (cta_res[cta_lr-2]==0x90) && (cta_res[cta_lr-1]==0) )
		{
			insb8[4]=0x02; write_cmd(insb8, NULL); // read class subs nano + len
			if( (cta_res[cta_lr-2]==0x90) && (cta_res[cta_lr-1]==0) )
			{
				l=cta_res[1];
				insb8[4]=l; write_cmd(insb8, NULL); // read class subs
				if( (cta_res[cta_lr-2]==0x90) &&
					(cta_res[cta_lr-1]==0x00 || cta_res[cta_lr-1]==0x08) )
				{
					show_class(reader, NULL, l_provid, cta_res, cta_lr-2);
				}
			}
		}

		insac[4]=0;
		insa4[2]=0x02;
		write_cmd(insa4, NULL); // select next provider
	}
	//return ERROR;
	return OK;
}
Ejemplo n.º 7
0
static int32_t viaccess_do_ecm(struct s_reader * reader, const ECM_REQUEST *er, struct s_ecm_answer *ea)
{
	def_resp;
	static const unsigned char insa4[] = { 0xca,0xa4,0x04,0x00,0x03 }; // set provider id
	unsigned char ins88[] = { 0xca,0x88,0x00,0x00,0x00 }; // set ecm
	unsigned char insf8[] = { 0xca,0xf8,0x00,0x00,0x00 }; // set geographic info
	static const unsigned char insc0[] = { 0xca,0xc0,0x00,0x00,0x12 }; // read dcw

	// //XXX what is the 4th byte for ??
	int32_t ecm88Len = MIN(MAX_ECM_SIZE-4, SCT_LEN(er->ecm)-4);
	if(ecm88Len < 1){
		rdr_log(reader, "ECM: Size of ECM couldn't be correctly calculated.");
		return ERROR;
	}
	uchar ecmData[ecm88Len];
	memset(ecmData, 0, ecm88Len);
	memcpy(ecmData, er->ecm+4, ecm88Len);
	uchar *ecm88Data = &ecmData[0];
	uint32_t provid=0;
	int32_t rc=0;
	int32_t hasD2 = 0;
	int32_t curEcm88len=0;
	int32_t nanoLen=0;
	uchar *nextEcm;
	uchar DE04[256];
	int32_t D2KeyID=0;
	int32_t curnumber_ecm=0;
	//nanoD2 d2 02 0d 02 -> D2 nano, len 2
	// 0d -> post AES decrypt CW
	// 0b -> pre AES decrypt CW
	int32_t nanoD2 = 0; //   0x0b = 1  0x0d = 2

	memset(DE04, 0, sizeof(DE04)); //fix dorcel de04 bug

	nextEcm=ecm88Data;



	while (ecm88Len>0 && !rc) {

		if(ecm88Data[0] ==0x00 &&  ecm88Data[1] == 0x00) {
			// nano 0x00  and len 0x00 aren't valid ... something is obviously wrong with this ecm.
			rdr_log(reader, "ECM: Invalid ECM structure. Rejecting");
			return ERROR;
		}

		// 80 33 nano 80 (ecm) + len (33)
		if(ecm88Data[0]==0x80) { // nano 80, give ecm len
			curEcm88len=ecm88Data[1];
			nextEcm=ecm88Data+curEcm88len+2;
			ecm88Data += 2;
			ecm88Len -= 2;
		}

		if(!curEcm88len) { //there was no nano 80 -> simple ecm
			curEcm88len=ecm88Len;
		}

		// d2 02 0d 02 -> D2 nano, len 2,  select the AES key to be used
		if(ecm88Data[0]==0xd2) {
			// test if need post or pre AES decrypt
			if(ecm88Data[2]==0x0b)
			{
				nanoD2 = 1;
				rdr_debug_mask(reader, D_READER, "ECM: nano D2 0x0b");
			}
			if(ecm88Data[2]==0x0d)
			{
				nanoD2 = 2;
				rdr_debug_mask(reader, D_READER, "ECM: nano D2 0x0d");
			}
			// use the d2 arguments to get the key # to be used
			int32_t len = ecm88Data[1] + 2;
			D2KeyID=ecm88Data[3];
			ecm88Data += len;
			ecm88Len -= len;
			curEcm88len -=len;
			hasD2 = 1;
		}
		else
			hasD2 = 0;


		// 40 07 03 0b 00  -> nano 40, len =7  ident 030B00 (tntsat), key #0  <== we're pointing here
		// 09 -> use key #9
		// 05 67 00
		if ((ecm88Data[0]==0x90 || ecm88Data[0]==0x40) && (ecm88Data[1]==0x03 || ecm88Data[1]==0x07 ) )
		{
			uchar ident[3], keynr;
			uchar *ecmf8Data=0;
			int32_t ecmf8Len=0;

			nanoLen=ecm88Data[1] + 2;
			keynr=ecm88Data[4]&0x0F;

			// 40 07 03 0b 00  -> nano 40, len =7  ident 030B00 (tntsat), key #0  <== we're pointing here
			// 09 -> use key #9
			if(nanoLen>5) {
				curnumber_ecm =(ecm88Data[6]<<8) | (ecm88Data[7]);
				rdr_debug_mask(reader, D_READER, "checking if the ecm number (%x) match the card one (%x)",curnumber_ecm,reader->last_geo.number_ecm);
				// if we have an ecm number we check it.
				// we can't assume that if the nano len is 5 or more we have an ecm number
				// as some card don't support this
            if( reader->last_geo.number_ecm > 0 ) {
                if (reader->last_geo.number_ecm == curnumber_ecm && !( ecm88Data[nanoLen-1] == 0x01 && (ecm88Data[2] == 0x03 && ecm88Data[3] == 0x0B && ecm88Data[4] == 0x00 ) )) {
                    keynr=ecm88Data[5];
                    rdr_debug_mask(reader, D_READER, "keyToUse = %02x, ECM ending with %02x",ecm88Data[5], ecm88Data[nanoLen-1]);
                } else {
                    if( ecm88Data[nanoLen-1] == 0x01 && (ecm88Data[2] == 0x03 && ecm88Data[3] == 0x0B && ecm88Data[4] == 0x00 ) )
                    {
                        rdr_debug_mask(reader, D_READER, "Skip ECM ending with = %02x for ecm number (%x) for provider %02x%02x%02x",ecm88Data[nanoLen-1], curnumber_ecm, ecm88Data[2], ecm88Data[3], ecm88Data[4]);
                    }
                    rdr_debug_mask(reader, D_READER, "Skip ECM ending with = %02x for ecm number (%x)",ecm88Data[nanoLen-1], curnumber_ecm);
                    ecm88Data=nextEcm;
                    ecm88Len-=curEcm88len;
                    continue; //loop to next ecm
                }
            }
            else { // long ecm but we don't have an ecm number so we have to try them all.
                keynr=ecm88Data[5];
                rdr_debug_mask(reader, D_READER, "keyToUse = %02x",ecm88Data[5]);
            }
        }

			memcpy (ident, &ecm88Data[2], sizeof(ident));
			provid = b2i(3, ident);
			ident[2]&=0xF0;

			if(hasD2 && reader->aes_list) {
				// check that we have the AES key to decode the CW
				// if not there is no need to send the ecm to the card
				if(!aes_present(reader->aes_list, 0x500, (uint32_t) (provid & 0xFFFFF0) , D2KeyID))
					return ERROR;
			}


			if (!chk_prov(reader, ident, keynr))
			{
				rdr_debug_mask(reader, D_READER, "ECM: provider or key not found on card");
				snprintf( ea->msglog, MSGLOGSIZE, "provider(%02x%02x%02x) or key(%d) not found on card", ident[0],ident[1],ident[2], keynr );
				return ERROR;
			}

			ecm88Data+=nanoLen;
			ecm88Len-=nanoLen;
			curEcm88len-=nanoLen;

			// DE04
			if (ecm88Data[0]==0xDE && ecm88Data[1]==0x04)
			{
				memcpy (DE04, &ecm88Data[0], 6);
				ecm88Data+=6;
			}
			//

			if( reader->last_geo.provid != provid )
			{
				reader->last_geo.provid = provid;
				reader->last_geo.geo_len = 0;
				reader->last_geo.geo[0]  = 0;
				write_cmd(insa4, ident); // set provider
			}

			//Nano D2 0x0b Pre AES decrypt CW
			if ( hasD2 && nanoD2 == 1)
			{
				uchar *ecm88DataCW = ecm88Data;
				int32_t cwStart = 0;
				//int32_t cwStartRes = 0;
				int32_t must_exit = 0;
				// find CW start
				while(cwStart < curEcm88len -1 && !must_exit)
				{
					if(ecm88Data[cwStart] == 0xEA && ecm88Data[cwStart+1] == 0x10)
					{
						ecm88DataCW = ecm88DataCW + cwStart + 2;
						must_exit = 1;
					}
					cwStart++;
				}
				// use AES from list to decrypt CW
				rdr_debug_mask(reader, D_READER, "Decoding CW : using AES key id %d for provider %06x",D2KeyID, (provid & 0xFFFFF0));
				if (aes_decrypt_from_list(reader->aes_list,0x500, (uint32_t) (provid & 0xFFFFF0), D2KeyID, &ecm88DataCW[0], 16) == 0)
					snprintf( ea->msglog, MSGLOGSIZE, "AES Decrypt : key id %d not found for CAID %04X , provider %06x", D2KeyID, 0x500, (provid & 0xFFFFF0) );
			}

			while(ecm88Len>1 && ecm88Data[0]<0xA0)
			{
				nanoLen=ecm88Data[1]+2;
				if (!ecmf8Data)
					ecmf8Data=(uchar *)ecm88Data;
				ecmf8Len+=nanoLen;
				ecm88Len-=nanoLen;
				curEcm88len-=nanoLen;
				ecm88Data+=nanoLen;
			}
			if(ecmf8Len)
			{
				if( reader->last_geo.geo_len!=ecmf8Len ||
					memcmp(reader->last_geo.geo, ecmf8Data, reader->last_geo.geo_len))
				{
					memcpy(reader->last_geo.geo, ecmf8Data, ecmf8Len);
					reader->last_geo.geo_len= ecmf8Len;
					insf8[3]=keynr;
					insf8[4]=ecmf8Len;
					write_cmd(insf8, ecmf8Data);
				}
			}
			ins88[2]=ecmf8Len?1:0;
			ins88[3]=keynr;
			ins88[4]= curEcm88len;
			//
			// we should check the nano to make sure the ecm is valid
			// we should look for at least 1 E3 nano, 1 EA nano and the F0 signature nano
			//
			// DE04
			if (DE04[0]==0xDE)
			{
				uint32_t l = curEcm88len-6;
				if (l > 256 || curEcm88len <= 6) { //don't known if this is ok...
					rdr_log(reader, "ecm invalid/too long! len=%d", curEcm88len);
					return ERROR;
				}
				memcpy(DE04+6, (uchar *)ecm88Data, l);
				write_cmd(ins88, DE04); // request dcw
			}
			else
			{
				write_cmd(ins88, (uchar *)ecm88Data); // request dcw
			}
			//
			write_cmd(insc0, NULL);	// read dcw
			switch(cta_res[0])
			{
			case 0xe8: // even
				if(cta_res[1]==8) { memcpy(ea->cw,cta_res+2,8); rc=1; }
				break;
			case 0xe9: // odd
				if(cta_res[1]==8) { memcpy(ea->cw+8,cta_res+2,8); rc=1; }
				break;
			case 0xea: // complete
				if(cta_res[1]==16) { memcpy(ea->cw,cta_res+2,16); rc=1; }
				break;
			default :
				ecm88Data=nextEcm;
				ecm88Len-=curEcm88len;
				rdr_debug_mask(reader, D_READER, "ECM: key to use is not the current one, trying next ECM");
				snprintf( ea->msglog, MSGLOGSIZE, "key to use is not the current one, trying next ECM" );
			}
		}
		else {
			//ecm88Data=nextEcm;
			//ecm88Len-=curEcm88len;
			rdr_debug_mask(reader, D_READER, "ECM: Unknown ECM type");
			snprintf( ea->msglog, MSGLOGSIZE, "Unknown ECM type" );
			return ERROR; /*Lets interupt the loop and exit, because we don't know this ECM type.*/
		}
	}

	if ( hasD2 && !dcw_crc(ea->cw) && nanoD2 == 2) {
		rdr_debug_mask(reader, D_READER, "Decoding CW : using AES key id %d for provider %06x",D2KeyID, (provid & 0xFFFFF0));
		rc=aes_decrypt_from_list(reader->aes_list,0x500, (uint32_t) (provid & 0xFFFFF0), D2KeyID,ea->cw, 16);
		if( rc == 0 )
			snprintf( ea->msglog, MSGLOGSIZE, "AES Decrypt : key id %d not found for CAID %04X , provider %06x", D2KeyID, 0x500, (provid & 0xFFFFF0) );
	}

	return(rc?OK:ERROR);
}
Ejemplo n.º 8
0
static int32_t conax_card_info(struct s_reader * reader)
{
	def_resp;
	int32_t type, i, j, k=0, n=0, l;
	uint16_t provid = 0;
	char provname[32], pdate[32], chid[32];
	static const uchar insC6[] = {0xDD, 0xC6, 0x00, 0x00, 0x03, 0x1C, 0x01, 0x00};
	static const uchar ins26[] = {0xDD, 0x26, 0x00, 0x00, 0x03, 0x1C, 0x01, 0x01};
	uchar insCA[] = {0xDD, 0xCA, 0x00, 0x00, 0x00};
	char *txt[] = { "Package", "PPV-Event" };
	static const uchar *cmd[] = { insC6, ins26 };
	time_t start_t = 0, end_t = 0;
	uint32_t cxclass = 0;

	cs_clear_entitlement(reader); // reset the entitlements

	for (type=0; type<2; type++) {
		n=0;
		write_cmd(cmd[type], cmd[type]+5);
		while (cta_res[cta_lr-2]==0x98) {
			insCA[4]=cta_res[cta_lr-1];		// get len
			write_cmd(insCA, NULL);		// read
			if ((cta_res[cta_lr-2]==0x90) || (cta_res[cta_lr-2]==0x98)) {
				for (j=0; j<cta_lr-2; j+=cta_res[j+1]+2) {
					provid=(cta_res[j+2+type]<<8) | cta_res[j+3+type];
					chid[0] = '\0';
					for (k=0, i=j+4+type; (i<j+cta_res[j+1]); i+=cta_res[i+1]+2) {
						switch(cta_res[i]) {
							case 0x01:
								l=(cta_res[i+1]<(sizeof(provname)-1)) ? cta_res[i+1] : sizeof(provname)-1;
								memcpy(provname, cta_res+i+2, l);
								provname[l]='\0';
								break;
							case 0x30:
								if (k > 1) {
									rdr_log(reader, "%s: %d, id: %04X%s, date: %s - %s, name: %s", txt[type], ++n, provid, chid, pdate, pdate+16, trim(provname));

									// add entitlements to list
									cs_add_entitlement(reader, reader->caid, b2ll(4, reader->prid[0]), provid, cxclass, start_t, end_t, type + 1);

									k = 0;
									chid[0] = '\0';
								}
								if(k == 0) start_t = chid_date(cta_res+i+2, pdate, 15);
								else end_t = chid_date(cta_res+i+2, pdate+16, 15) /* add 23:59:59 here: */ + 0x1517F;
								++k;
								break;
							case 0x20: // Provider classes
							case 0x90: // (?) not sure what this is, saw it once in log
								snprintf(chid, sizeof(chid), ", classes: %02X%02X%02X%02X", cta_res[i+2], cta_res[i+3], cta_res[i+4] ,cta_res[i+5]);
								cxclass = b2ll(4, &cta_res[i+2]);
								break;
						}
					}
					rdr_log(reader, "%s: %d, id: %04X%s, date: %s - %s, name: %s", txt[type], ++n, provid, chid, pdate, pdate+16, trim(provname));

					// add entitlements to list
					cs_add_entitlement(reader, reader->caid, b2ll(4, reader->prid[0]), provid, cxclass, start_t, end_t, type + 1);
				}
			}
		}
	}
	rdr_log(reader, "ready for requests");
	return OK;
}
Ejemplo n.º 9
0
static int32_t conax_card_init(struct s_reader * reader, ATR *newatr)
{
  unsigned char cta_res[CTA_RES_LEN];
  int32_t i, j, n;
  static const uchar ins26[] = {0xDD, 0x26, 0x00, 0x00, 0x03, 0x10, 0x01, 0x40};
  uchar ins82[] = {0xDD, 0x82, 0x00, 0x00, 0x11, 0x11, 0x0f, 0x01, 0xb0, 0x0f, 0xff, \
                   0xff, 0xfb, 0x00, 0x00, 0x09, 0x04, 0x0b, 0x00, 0xe0, 0x30, 0x2b };

  uchar cardver=0;

  get_hist;
  if ((hist_size < 4) || (memcmp(hist,"0B00",4)))
    return ERROR;

  reader->caid=0xB00;

  if ((n=read_record(reader, ins26, ins26+5, cta_res))<=0) return ERROR;   // read caid, card-version

  for (i=0; i<n; i+=cta_res[i+1]+2)
    switch(cta_res[i])
    {
      case 0x20: cardver=cta_res[i+2]; break;
      case 0x28: reader->caid=(cta_res[i+2]<<8)|cta_res[i+3];
    }

  // Ins82 command needs to use the correct CAID reported in nano 0x28
  ins82[17]=(reader->caid>>8)&0xFF;
  ins82[18]=(reader->caid)&0xFF;

  if ((n=read_record(reader, ins82, ins82+5, cta_res))<=0) return ERROR; // read serial

  reader->nprov = 0;

  for (j=0, i=2; i<n; i+=cta_res[i+1]+2)
    switch(cta_res[i])
    {
      case 0x23:
        if (cta_res[i+5] != 0x00) {
          memcpy(reader->hexserial, &cta_res[i+3], 6);
        }
        else {
          memcpy(reader->sa[j], &cta_res[i+5], 4);
          j++;
          reader->nprov++;
        }
        break;
    }

  memset(reader->prid, 0x00, sizeof(reader->prid));

  rdr_log_sensitive(reader, "type: Conax, caid: %04X, serial: {%llu}, hex serial: {%02x%02x%02x%02x}, card: v%d",
         reader->caid, (unsigned long long) b2ll(6, reader->hexserial), reader->hexserial[2],
         reader->hexserial[3], reader->hexserial[4], reader->hexserial[5], cardver);

  rdr_log(reader, "Providers: %d", reader->nprov);

  for (j=0; j<reader->nprov; j++)
  {
    rdr_log(reader, "Provider: %d  Provider-Id: %06X", j+1, b2i(4, reader->prid[j]));
    rdr_log_sensitive(reader, "Provider: %d  SharedAddress: {%08X}", j+1, b2i(4, reader->sa[j]));
  }

  return OK;
}
Ejemplo n.º 10
0
bool IO_Serial_Read (struct s_reader * reader, uint32_t delay, uint32_t timeout, uint32_t size, unsigned char * data)
{
	uint32_t count = 0;
	
	if (timeout == 0){ // General fix for readers not communicating timeout and delay
		if (reader->read_timeout != 0) timeout = reader->read_timeout; else timeout = 9990000; // hope 99990000 is long enough!
		rdr_debug_mask(reader, D_DEVICE,"Warning: read timeout 0 changed to %d us", timeout);
	}
	
	rdr_debug_mask(reader, D_DEVICE,"Read timeout %d us, read delay %d us, to read %d char(s), chunksize %d char(s)", timeout, delay, size, size);
	
	if (reader->crdr.read_written && reader->written > 0) { // these readers need to read all transmitted chars before they can receive!
		unsigned char buf[256];
		rdr_debug_mask(reader, D_DEVICE,"Reading %d echoed transmitted chars...", reader->written); 
		int32_t n = reader->written;
		reader->written=0;
		if(IO_Serial_Read (reader, 0, 9990000, n, buf)) // use 9990000 = aprox 10 seconds (since written chars could be hughe!)
			return ERROR;
		rdr_debug_mask(reader, D_DEVICE,"Reading of echoed transmitted chars done!");
	}

#if defined(WITH_STAPI) || defined(__SH4__)	//internal stapi and sh4 readers need special treatment as they don't respond correctly to poll and some sh4 boxes only can read 1 byte at once
	if(reader->typ == R_INTERNAL){
		int32_t readed;
#if defined(WITH_STAPI)
		const int32_t chunksize = INT_MAX;
#elif defined(__SH4__)
		const int32_t chunksize = 1;
#endif
		struct timeval tv, tv_spent;
		gettimeofday(&tv,0);
		memcpy(&tv_spent,&tv,sizeof(struct timeval));
		readed=0;

		while((((tv_spent.tv_sec-tv.tv_sec)*1000000) + ((tv_spent.tv_usec-tv.tv_usec)/1000000L)) < (time_t)(timeout))
		{		
	 		readed = read(reader->handle, &data[count], size-count>=chunksize?chunksize:size-count);
	 		gettimeofday(&tv_spent,0);
			if(readed > 0) count +=readed;
			if(count < size){
				if(readed < chunksize) cs_sleepus(1);
				continue;
			} else break;
		}	
		if(count < size) {
			rdr_ddump_mask(reader, D_DEVICE, data, count, "Receiving:");
			return ERROR;
		}
	} else	
#endif  // read all chars at once for all other boxes
	{
		while(count < size){
			int32_t readed = -1, errorcount=0;
			AGAIN:
			if(IO_Serial_WaitToRead (reader, delay, timeout)) {
				rdr_debug_mask(reader, D_DEVICE, "Timeout in IO_Serial_WaitToRead, timeout=%d us", timeout);
				return ERROR;
			}
				
			while (readed <0 && errorcount < 10) {
				readed = read (reader->handle, &data[count], size-count);
				if (readed < 0) {
					if (errno == EINTR) continue; // try again in case of interrupt
					if (errno == EAGAIN) goto AGAIN; //EAGAIN needs select procedure again
					rdr_log(reader, "ERROR: %s (errno=%d %s)", __func__, errno, strerror(errno));
					errorcount++;
				}
			} 
				
			if (readed == 0) {
				rdr_ddump_mask(reader, D_DEVICE, data, count, "Receiving:");
				rdr_debug_mask(reader, D_DEVICE, "Received End of transmission");
				return ERROR;
			}
			count +=readed;
		}
	}
	rdr_ddump_mask(reader, D_DEVICE, data, count, "Receiving:");
	return OK;
}
Ejemplo n.º 11
0
int32_t MP35_Init(struct s_reader * reader)
{
  MP35_info reader_info;
  BYTE rec_buf[32];
  BYTE parameter;
  int32_t original_mhz;

  rdr_debug_mask(reader, D_IFD, "Initializing MP35 reader");

  current_product = 0;
  original_mhz = reader->mhz; // MP3.5 commands should be always be written using 9600 baud at 3.58MHz
  reader->mhz = 357;
  
  call(IO_Serial_SetParams(reader, 9600, 8, PARITY_NONE, 1, IO_SERIAL_HIGH, IO_SERIAL_HIGH));

  IO_Serial_Sendbreak(reader, MP35_BREAK_LENGTH);
  IO_Serial_DTR_Clr(reader);
  IO_Serial_DTR_Set(reader);
  cs_sleepms(200);
  IO_Serial_Flush(reader);

  memset(rec_buf, 0x00, sizeof(rec_buf));
  call(IO_Serial_Write(reader, MP35_WRITE_DELAY, 2, fw_version));
  call(IO_Serial_Read(reader, MP35_READ_DELAY, 4, rec_buf));
  if(rec_buf[3] != ACK)
  {
    rdr_debug_mask(reader, D_IFD, "Failed MP35 command: fw_version");
    return ERROR;
  }

  if (MP35_product_info(reader, rec_buf[1], rec_buf[0], rec_buf[2], &reader_info) != OK)
  {
    rdr_log(reader, "MP35_Init: unknown product code");
    return ERROR;
  }

  if(reader_info.current_product == 0x10) // USB Phoenix
  {
    if(original_mhz == 357)
    {
      rdr_log(reader, "MP35_Init: Using oscillator 1 (3.57MHz)");
      parameter = 0x01;
    }
    else if(original_mhz == 368)
    {
      rdr_log(reader, "MP35_Init: Using oscillator 2 (3.68MHz)");
      parameter = 0x02;
    }
    else if(original_mhz == 600)
    {
      rdr_log(reader, "MP35_Init: Using oscillator 3 (6.00MHz)");
      parameter = 0x03;
    }
    else
    {
      rdr_log(reader, "MP35_Init: MP35 support only mhz=357, mhz=368 or mhz=600");
      rdr_log(reader, "MP35_Init: Forced oscillator 1 (3.57MHz)");
      parameter = 0x01;
      original_mhz = 357;
    }
    memset(rec_buf, 0x00, sizeof(rec_buf));
    call(IO_Serial_Write(reader, MP35_WRITE_DELAY, 2, set_mode_osc));
    call(IO_Serial_Write(reader, MP35_WRITE_DELAY, 1, &parameter));
    call(IO_Serial_Read(reader, MP35_READ_DELAY, 1, rec_buf)); // Read ACK from previous command
    if(rec_buf[0] != ACK)
    {
      rdr_debug_mask(reader, D_IFD, "Failed MP35 command: set_mode_osc");
      return ERROR;
    }
    rdr_log(reader, "MP35_Init: Leaving programming mode");
    memset(rec_buf, 0x00, sizeof(rec_buf));
    call(IO_Serial_Write(reader, MP35_WRITE_DELAY, 2, exit_program_mode));
    call(IO_Serial_Read(reader, MP35_READ_DELAY, 1, rec_buf));
    if(rec_buf[0] != ACK)
    {
      rdr_debug_mask(reader, D_IFD, "Failed MP35 command: exit_program_mode");
      return ERROR;
    }
  }
  else //MP3.5 or MP3.6
  {
    if(reader_info.product_fw_version >= 0x0500)
    {
      int32_t info_len;
      char info[sizeof(rec_buf) - 2];

      memset(rec_buf, 0x00, sizeof(rec_buf));
      call(IO_Serial_Write(reader, MP35_WRITE_DELAY, 2,  fw_info));
      call(IO_Serial_Read(reader, MP35_READ_DELAY, 1, rec_buf));
      info_len = rec_buf[0];
      call(IO_Serial_Read(reader, MP35_READ_DELAY, info_len + 1, rec_buf));
      if(rec_buf[info_len] != ACK)
      {
        rdr_debug_mask(reader, D_IFD, "Failed MP35 command: fw_info");
        return ERROR;
      }
      memcpy(info, rec_buf, info_len);
      info[info_len] = '\0';
      rdr_log(reader, "MP35_Init: FW Info - %s", info);
    }

    memset(rec_buf, 0x00, sizeof(rec_buf));
    if(original_mhz == 357)
    {
      rdr_log(reader, "MP35_Init: Using oscillator 1 (3.57MHz)");
      call(IO_Serial_Write(reader, MP35_WRITE_DELAY, 2, phoenix_mode));
    }
    else if(original_mhz == 600)
    {
      rdr_log(reader, "MP35_Init: Using oscillator 2 (6.00MHz)");
      call(IO_Serial_Write(reader, MP35_WRITE_DELAY, 2, phoenix_6mhz_mode));
    }
    else
    {
      rdr_log(reader, "MP35_Init: MP35 support only mhz=357 or mhz=600");
      rdr_log(reader, "MP35_Init: Forced oscillator 1 (3.57MHz)");
      call(IO_Serial_Write(reader, MP35_WRITE_DELAY, 2, phoenix_mode));
      original_mhz = 357;
    }
  }

  reader->mhz = original_mhz; // We might have switched oscillator here
  current_product = reader_info.current_product;
  IO_Serial_Flush(reader);

  return OK;
}
Ejemplo n.º 12
0
bool IO_Serial_Write (struct s_reader * reader, uint32_t delay, uint32_t timeout, uint32_t size, const unsigned char * data)
{
	if (timeout == 0){ // General fix for readers not communicating timeout and delay
		if (reader->char_delay != 0) timeout = reader->char_delay; else timeout = 1000000;
		rdr_debug_mask(reader, D_DEVICE,"Warning: write timeout 0 changed to %d us", timeout);
	}
	uint32_t count, to_send, i_w;
	unsigned char data_w[512];
	
	to_send = (delay? 1: size); // calculate chars to send at one
	rdr_debug_mask(reader, D_DEVICE,"Write timeout %d us, write delay %d us, to send %d char(s), chunksize %d char(s)", timeout, delay, size, to_send);
	
	for (count = 0; count < size; count += to_send)
	{
		if (count + to_send > size){
			to_send = size - count;
			}
		uint16_t errorcount=0, to_do=to_send;
		for (i_w=0; i_w < to_send; i_w++)
				data_w [i_w] = data [count + i_w];
		rdr_ddump_mask(reader, D_DEVICE, data_w+(to_send-to_do), to_do, "Sending:");
		AGAIN:		
		if (!IO_Serial_WaitToWrite (reader, delay, timeout))
		{
			while (to_do !=0){
				int32_t u = write (reader->handle, data_w+(to_send-to_do), to_do);
				if (u < 1) {
					if (errno==EINTR) continue; //try again in case of Interrupted system call
					if (errno==EAGAIN) goto AGAIN; //EAGAIN needs a select procedure again
					errorcount++;
					int16_t written = count + to_send - to_do;
					if (u != 0) {
						rdr_log(reader, "ERROR: %s: Written=%d of %d (errno=%d %s)",
							__func__, written , size, errno, strerror(errno));
					}
					if (errorcount > 10){ //exit if more than 10 errors
						return ERROR;
					}
				}
				else {
					to_do -= u;
					errorcount = 0;
					if (reader->crdr.read_written)
						reader->written += u; // these readers echo transmitted chars
					}
			}
		}
		else
		{
			rdr_log(reader, "Timeout in IO_Serial_WaitToWrite, delay=%d us, timeout=%d us", delay, timeout);
			if (reader->crdr.read_written && reader->written > 0) { // these readers need to read all transmitted chars before they can receive!
				unsigned char buf[256];
				rdr_debug_mask(reader, D_DEVICE,"Reading %d echoed transmitted chars...", reader->written); 
				int32_t n = reader->written;
				if(IO_Serial_Read (reader, 0, 9990000, n, buf)) // use 9990000 = aprox 10 seconds (since written chars could be hughe!)
					return ERROR;
				reader->written=0;
				rdr_debug_mask(reader, D_DEVICE,"Reading of echoed transmitted chars done!");
			}
			return ERROR;
		}
	}
	if (reader->crdr.read_written && reader->written > 0) { // these readers need to read all transmitted chars before they can receive!
		unsigned char buf[256];
		rdr_debug_mask(reader, D_DEVICE,"Reading %d echoed transmitted chars...", reader->written); 
		int32_t n = reader->written;
		if(IO_Serial_Read (reader, 0, 9990000, n, buf)) // use 9990000 = aprox 10 seconds (since written chars could be hughe!)
			return ERROR;
		reader->written=0;
		rdr_debug_mask(reader, D_DEVICE,"Reading of echoed transmitted chars done!");
	}
	return OK;
}
Ejemplo n.º 13
0
bool cardreader_init(struct s_reader *reader)
{
	struct s_client *client = reader->client;
	client->typ = 'r';
	int8_t i = 0;
	set_localhost_ip(&client->ip);
	while((cardreader_device_init(reader) == 2) && i < 10)
	{
		cs_sleepms(2000);
		if(!ll_contains(configured_readers, reader) || !is_valid_client(client) || reader->enable != 1)
			{ return false; }
		i++;
	}
	if (i >= 10)
	{
		reader->card_status = READER_DEVICE_ERROR;
		cardreader_close(reader);
		reader->enable = 0;
		return false;
	}
	else 
	{
		if(reader->typ == R_INTERNAL)
		{
			if(boxtype_is("dm8000") || boxtype_is("dm800") || boxtype_is("dm800se"))
				{reader->cardmhz = 2700;}
			if(boxtype_is("dm500") || boxtype_is("dm600pvr"))
				{reader->cardmhz = 3150;}
			if(boxtype_is("dm7025"))
				{reader->cardmhz = 8300;}
			if((!strncmp(boxtype_get(), "vu", 2 ))||(boxtype_is("ini-8000am")))
				{reader->cardmhz = 2700; reader->mhz = 450;} // only one speed for vu+ and Atemio Nemesis due to usage of TDA8024
		}
		if((reader->cardmhz > 2000) && (reader->typ != R_SMART))
		{
			rdr_log(reader, "Reader initialized (device=%s, detect=%s%s, pll max=%.2f MHz, wanted mhz=%.2f MHz)",
					reader->device,
					reader->detect & 0x80 ? "!" : "",
					RDR_CD_TXT[reader->detect & 0x7f],
					(float)reader->cardmhz / 100,
					(float)reader->mhz / 100);
			rdr_log(reader,"Reader sci internal, detected box type: %s", boxtype_get());
		}
		else
		{
			if (reader->typ == R_SMART || is_smargo_reader(reader))
			{
				rdr_log_dbg(reader, D_IFD, "clocking for smartreader with smartreader or smargo protocol");
				if (reader->cardmhz >= 2000) reader->cardmhz =  369; else
				if (reader->cardmhz >= 1600) reader->cardmhz = 1600; else
				if (reader->cardmhz >= 1200) reader->cardmhz = 1200; else
				if (reader->cardmhz >= 961)  reader->cardmhz =  961; else
				if (reader->cardmhz >= 800)  reader->cardmhz =  800; else
				if (reader->cardmhz >= 686)  reader->cardmhz =  686; else
				if (reader->cardmhz >= 600)  reader->cardmhz =  600; else
				if (reader->cardmhz >= 534)  reader->cardmhz =  534; else
				if (reader->cardmhz >= 480)  reader->cardmhz =  480; else
				if (reader->cardmhz >= 436)  reader->cardmhz =  436; else
				if (reader->cardmhz >= 400)  reader->cardmhz =  400; else
				if (reader->cardmhz >= 369)  reader->cardmhz =  369; else
				if (reader->cardmhz == 357)  reader->cardmhz =  369; else // 357 not a default smartreader setting
				if (reader->cardmhz >= 343)  reader->cardmhz =  343; else 
				reader->cardmhz =  320;
				if (reader->mhz >= 1600) reader->mhz = 1600; else
				if (reader->mhz >= 1200) reader->mhz = 1200; else
				if (reader->mhz >= 961)  reader->mhz =  961; else
				if (reader->mhz >= 900)  reader->mhz =  900; else
				if (reader->mhz >= 800)  reader->mhz =  800; else
				if (reader->mhz >= 686)  reader->mhz =  686; else
				if (reader->mhz >= 600)  reader->mhz =  600; else
				if (reader->mhz >= 534)  reader->mhz =  534; else
				if (reader->mhz >= 480)  reader->mhz =  480; else
				if (reader->mhz >= 436)  reader->mhz =  436; else
				if (reader->mhz >= 400)  reader->mhz =  369; else
				if (reader->mhz >= 369)  reader->mhz =  369; else
				if (reader->mhz == 357)  reader->mhz =  369; else // 357 not a default smartreader setting
				if (reader->mhz >= 343)  reader->mhz =  343; else 
				reader->mhz =  320;
	    	}
			if ((reader->typ == R_SMART || is_smargo_reader(reader)) && reader->autospeed == 1)
			{
				rdr_log(reader, "Reader initialized (device=%s, detect=%s%s, mhz= AUTO, cardmhz=%d)",
						reader->device,
						reader->detect & 0x80 ? "!" : "",
						RDR_CD_TXT[reader->detect & 0x7f],
						reader->cardmhz);
			} else {
				rdr_log(reader, "Reader initialized (device=%s, detect=%s%s, mhz=%d, cardmhz=%d)",
						reader->device,
						reader->detect & 0x80 ? "!" : "",
						RDR_CD_TXT[reader->detect & 0x7f],
						reader->mhz,
						reader->cardmhz);
				if (reader->typ == R_INTERNAL && !(reader->cardmhz > 2000))
					rdr_log(reader,"Reader sci internal, detected box type: %s", boxtype_get());
			}
		}
		return true;
	}
}
Ejemplo n.º 14
0
static int32_t pcsc_init(struct s_reader *pcsc_reader)
{
	ULONG rv;
	DWORD dwReaders = 0;
	LPSTR mszReaders = NULL;
	char *ptr, **readers = NULL;
	char *device = pcsc_reader->device;
	int32_t nbReaders;
	int32_t reader_nb;

	rdr_log_dbg(pcsc_reader, D_DEVICE, "PCSC establish context for PCSC pcsc_reader %s", device);
	SCARDCONTEXT hContext;
	memset(&hContext, 0, sizeof(hContext));
	rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
	if(rv == SCARD_S_SUCCESS)
	{
		if(!cs_malloc(&pcsc_reader->crdr_data, sizeof(struct pcsc_data)))
			{ return ERROR; }
		struct pcsc_data *crdr_data = pcsc_reader->crdr_data;
		crdr_data->hContext = hContext;

		// here we need to list the pcsc readers and get the name from there,
		// the pcsc_reader->device should contain the pcsc_reader number
		// and after the actual device name is copied in crdr_data->pcsc_name .
		rv = SCardListReaders(crdr_data->hContext, NULL, NULL, &dwReaders);
		if(rv != SCARD_S_SUCCESS)
		{
			rdr_log_dbg(pcsc_reader, D_DEVICE, "PCSC failed listing readers [1] : (%lx)", (unsigned long)rv);
			return ERROR;
		}
		if(!cs_malloc(&mszReaders, dwReaders))
			{ return ERROR; }
		rv = SCardListReaders(crdr_data->hContext, NULL, mszReaders, &dwReaders);
		if(rv != SCARD_S_SUCCESS)
		{
			rdr_log_dbg(pcsc_reader, D_DEVICE, "PCSC failed listing readers [2]: (%lx)", (unsigned long)rv);
			NULLFREE(mszReaders);
			return ERROR;
		}
		/* Extract readers from the null separated string and get the total
		 * number of readers
		 */
		nbReaders = 0;
		ptr = mszReaders;
		while(*ptr != '\0')
		{
			ptr += strlen(ptr) + 1;
			nbReaders++;
		}

		if(nbReaders == 0)
		{
			rdr_log(pcsc_reader, "PCSC : no pcsc_reader found");
			NULLFREE(mszReaders);
			return ERROR;
		}

		if(!cs_malloc(&readers, nbReaders * sizeof(char *)))
		{
			NULLFREE(mszReaders);
			return ERROR;
		}

		char* device_line;
		char* device_first;
		char* device_second;

		device_line = strdup((const char *)&pcsc_reader->device);
		device_first = strsep(&device_line, ":");
		device_second = strsep(&device_line, ":");
		reader_nb = atoi(device_first);

		/* fill the readers table */
		nbReaders = 0;
		ptr = mszReaders;
		while(*ptr != '\0')
		{
			rdr_log_dbg(pcsc_reader, D_DEVICE, "PCSC pcsc_reader %d: %s", nbReaders, ptr);
			readers[nbReaders] = ptr;
			if ((reader_nb == -1) && (device_second != NULL) && strstr(ptr,device_second)){
				reader_nb = nbReaders;
			}
			ptr += strlen(ptr) + 1;
			nbReaders++;
		}

		if(reader_nb < 0 || reader_nb >= nbReaders)
		{
			rdr_log(pcsc_reader, "Wrong pcsc_reader index: %d", reader_nb);
			NULLFREE(mszReaders);
			NULLFREE(readers);
			NULLFREE(device_line);
			return ERROR;
		}

		if (readers)
		{
		snprintf(crdr_data->pcsc_name, sizeof(crdr_data->pcsc_name), "%s", readers[reader_nb]);
		NULLFREE(readers);
		}
		NULLFREE(mszReaders);
		NULLFREE(device_line);
	}
	else
	{
		rdr_log(pcsc_reader, "PCSC failed establish context (%lx)", (unsigned long)rv);
		return ERROR;
	}
	return OK;
}
Ejemplo n.º 15
0
static int32_t pcsc_check_card_inserted(struct s_reader *pcsc_reader)
{
	struct pcsc_data *crdr_data = pcsc_reader->crdr_data;
	DWORD dwState, dwAtrLen, dwReaderLen;
	unsigned char pbAtr[64];
	SCARDHANDLE rv;

	dwAtrLen = sizeof(pbAtr);
	rv = 0;
	dwState = 0;
	dwReaderLen = 0;

	// Do we have a card ?
	if(!crdr_data->pcsc_has_card && !crdr_data->hCard)
	{
		// try connecting to the card
		rv = SCardConnect(crdr_data->hContext, crdr_data->pcsc_name, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &crdr_data->hCard, &crdr_data->dwActiveProtocol);
		if(rv == (SCARDHANDLE)SCARD_E_NO_SMARTCARD)
		{
			// no card in pcsc_reader
			crdr_data->pcsc_has_card = 0;
			if(crdr_data->hCard)
			{
				SCardDisconnect(crdr_data->hCard, SCARD_RESET_CARD);
				crdr_data->hCard = 0;
			}
			// rdr_log_dbg(pcsc_reader, D_DEVICE, "PCSC card in %s removed / absent [dwstate=%lx rv=(%lx)]", crdr_data->pcsc_name, dwState, (unsigned long)rv );
			return OK;
		}
		else if(rv == (SCARDHANDLE)SCARD_W_UNRESPONSIVE_CARD)
		{
			// there is a problem with the card in the pcsc_reader
			crdr_data->pcsc_has_card = 0;
			crdr_data->hCard = 0;
			rdr_log(pcsc_reader, "PCSC card in %s is unresponsive. Eject and re-insert please.", crdr_data->pcsc_name);
			return ERROR;
		}
		else if(rv == SCARD_S_SUCCESS)
		{
			// we have a card
			crdr_data->pcsc_has_card = 1;
			rdr_log(pcsc_reader, "PCSC was opened with handle: %ld", (long)crdr_data->hCard);
		}
		else
		{
			// if we get here we have a bigger problem -> display status and debug
			// rdr_log_dbg(pcsc_reader, D_DEVICE, "PCSC pcsc_reader %s status [dwstate=%lx rv=(%lx)]", crdr_data->pcsc_name, dwState, (unsigned long)rv );
			return ERROR;
		}

	}

	// if we get there the card is ready, check its status
	rv = SCardStatus(crdr_data->hCard, NULL, &dwReaderLen, &dwState, &crdr_data->dwActiveProtocol, pbAtr, &dwAtrLen);

	if(rv == SCARD_S_SUCCESS && (dwState & (SCARD_PRESENT | SCARD_NEGOTIABLE | SCARD_POWERED)))
	{
		return OK;
	}
	else
	{
		SCardDisconnect(crdr_data->hCard, SCARD_RESET_CARD);
		crdr_data->hCard = 0;
		crdr_data->pcsc_has_card = 0;
	}

	return ERROR;
}
Ejemplo n.º 16
0
void do_emm_from_file(struct s_reader * reader)
{
	if (!reader->emmfile)
		return;

	char token[256];
	FILE *fp;

	if (reader->emmfile[0] == '/')
		snprintf(token, sizeof(token), "%s", reader->emmfile); //pathname included
	else
		get_config_filename(token, sizeof(token), reader->emmfile); //only file specified, look in confdir for this file

	if (!(fp = fopen (token, "rb"))) {
		rdr_log(reader, "ERROR: Cannot open EMM file '%s' (errno=%d %s)\n", token, errno, strerror(errno));
		return;
	}

	EMM_PACKET *eptmp;
	if (!cs_malloc(&eptmp, sizeof(EMM_PACKET))) {
		fclose (fp);
		return;
	}

	size_t ret = fread(eptmp, sizeof(EMM_PACKET), 1, fp);
	if (ret < 1 && ferror(fp)) {
		rdr_log(reader, "ERROR: Can't read EMM from file '%s' (errno=%d %s)", token, errno, strerror(errno));
		free(eptmp);
		fclose(fp);
		return;
	}
	fclose (fp);

	eptmp->caid[0] = (reader->caid >> 8) & 0xFF;
	eptmp->caid[1] = reader->caid & 0xFF;
	if (reader->nprov > 0)
		memcpy(eptmp->provid, reader->prid[0], sizeof(eptmp->provid));
	eptmp->emmlen = eptmp->emm[2] + 3;

	struct s_cardsystem *cs = get_cardsystem_by_caid(reader->caid);
	if (cs && cs->get_emm_type && !cs->get_emm_type(eptmp, reader)) {
		rdr_debug_mask(reader, D_EMM, "emm skipped, get_emm_type() returns error");
		free(eptmp);
		return;
	}

	//save old b_nano value
	//clear lsb and lsb+1, so no blocking, and no saving for this nano
	uint16_t save_s_nano = reader->s_nano;
	uint16_t save_b_nano = reader->b_nano;
	uint32_t save_saveemm = reader->saveemm;

	reader->s_nano = reader->b_nano = 0;
	reader->saveemm = 0;

	int32_t rc = cardreader_do_emm(reader, eptmp);
	if (rc == OK)
		rdr_log(reader, "EMM from file %s was successful written.", token);
	else
		rdr_log(reader, "ERROR: EMM read from file %s NOT processed correctly! (rc=%d)", token, rc);

	//restore old block/save settings
	reader->s_nano = save_s_nano;
	reader->b_nano = save_b_nano;
	reader->saveemm = save_saveemm;

	free(eptmp);
}
Ejemplo n.º 17
0
static void Azbox_SetMode(struct s_reader *reader, int32_t mode)
{
  sc_mode = mode;
  rdr_log(reader, "openxcas sc: set mode %d", sc_mode);
}
Ejemplo n.º 18
0
static int32_t bulcrypt_card_init(struct s_reader *reader, ATR *newatr)
{
	int i;
	char tmp[1024];
	char card_serial[16];
	const uchar *set_key_command;
	uchar card_type;

	get_atr
	def_resp

	reader->bulcrypt_version = 0;

	if (memcmp(atr, atr_carpet, MIN(sizeof(atr_carpet), atr_size)) != 0)
	{
		if (atr_size == 3) {
			rdr_log(reader, "ATR_len=3 but ATR is unknown: %s",
				cs_hexdump(1, atr, atr_size, tmp, sizeof(tmp)));
		}
		return ERROR;
	}

	reader->nprov = 1;
	memset(reader->prid, 0, sizeof(reader->prid));
	memset(reader->hexserial, 0, sizeof(reader->hexserial));
	memset(card_serial, 0, sizeof(card_serial));

	rdr_log(reader, "Bulcrypt card detected, checking card version.");

	// Do we have Bulcrypt V2 card?
	write_cmd(cmd_card_v2_key1, NULL);
	write_cmd(cmd_card_v2_key2, NULL);
	if (cta_lr < 18 || (cta_res[0] != 0x11 && cta_res[1] != 0x10))
	{
		// The card is v1
		reader->bulcrypt_version = 1;
		set_key_command = cmd_set_key;
	} else {
		// The card is v2
		reader->bulcrypt_version = 2;
		set_key_command = cmd_set_key_v2;
	}

	// Set CW obfuscation key
	write_cmd(set_key_command, set_key_command + 5);
	if (cta_lr < 2 || (cta_res[0] != 0x90 && cta_res[1] != 0x00))
	{
		rdr_log(reader, "(cmd_set_key) Unexpected card answer: %s",
			cs_hexdump(1, cta_res, cta_lr, tmp, sizeof(tmp)));
		return ERROR;
	}

	rdr_log(reader, "Bulcrypt v%d card detected.%s", reader->bulcrypt_version,
		reader->bulcrypt_version != 1 ? " *UNSUPPORTED CARD VERSION*" : "");

	// Read card type
	write_cmd(cmd_cardtype1, NULL);
	write_cmd(cmd_cardtype2, NULL);
	if (cta_lr < 5 || (cta_res[0] != 0x01 && cta_res[1] != 0x01))
	{
		rdr_log(reader, "(cmd_cardtype) Unexpected card answer: %s",
			cs_hexdump(1, cta_res, cta_lr, tmp, sizeof(tmp)));
		return ERROR;
	}
	card_type = cta_res[2]; // We have seen 0x4c and 0x75

	// *FIXME* Unknown command
	write_cmd(cmd_unkn_0a1, NULL);
	write_cmd(cmd_unkn_0a2, NULL);

	// Read card HEX serial
	write_cmd(cmd_cardsn1, NULL);
	write_cmd(cmd_cardsn2, NULL);
	if (cta_lr < 6 || (cta_res[0] != 0x02 && cta_res[1] != 0x04))
	{
		rdr_log(reader, "(card_sn) Unexpected card answer: %s",
			cs_hexdump(1, cta_res, cta_lr, tmp, sizeof(tmp)));
		return ERROR;
	}
	memcpy(reader->hexserial, cta_res + 2, 4);
	// Skip bottom four bits (they are 0x0b on our cards)
	reader->hexserial[3] = reader->hexserial[3] & 0xF0;

	// Read card ASCII serial
	write_cmd(cmd_ascsn1, NULL);
	write_cmd(cmd_ascsn2, NULL);
	if (cta_lr < 15 || (cta_res[0] != 0x05 && cta_res[1] != 0x0d))
	{
		rdr_log(reader, "(asc_sn) Unexpected card answer: %s",
			cs_hexdump(1, cta_res, cta_lr, tmp, sizeof(tmp)));
		return ERROR;
	}
	memcpy(card_serial, cta_res + 2, 13);
	cta_lr = strlen(card_serial);
	for (i = 0; i < cta_lr; i++)
	{
		if (card_serial[i] == ' ')
			continue;
		// Sanity check
		if (!isdigit(card_serial[i]))
			card_serial[i] = '*';
	}

	// Write empty ECM, *FIXME* why are we doing this? To prepare the card somehow?
	write_cmd(cmd_ecm_empty, NULL);

	// The HEX serial have nothing to do with Serial (they do not match)
	rdr_log_sensitive(reader, "CAID: 0x4AEE|0x5581, CardType: 0x%02x, Serial: {%s}, HexSerial: {%02X %02X %02X %02X}",
		card_type,
		card_serial,
		reader->hexserial[0], reader->hexserial[1], reader->hexserial[2], reader->hexserial[3]);

	rdr_log(reader, "Ready for requests.");

	return OK;
}
Ejemplo n.º 19
0
/*
Bulcrypt ECM structure:

  80 70       - ECM header (80 | 81)
  4c          - ECM length after this field (0x4c == 76 bytes)
  4f 8d 87 0b - unixts == 1334675211 == Tue Apr 17 18:06:51 EEST 2012
  00 66       - *FIXME* Program number?
  00 7d       - *FIXME*
  ce 70       - ECM counter
  0b 88       - ECM type
  xx yy zz .. - Encrypted ECM payload (64 bytes)

*/
static int32_t bulcrypt_do_ecm(struct s_reader * reader, const ECM_REQUEST *er, struct s_ecm_answer *ea)
{
	char tmp[512];
	uchar ecm_cmd[256];

	def_resp

	int32_t ecm_len = check_sct_len(er->ecm, 3);
	if (ecm_len < 64 || ecm_len > 188)
	{
		rdr_log(reader, "Wrong ECM length: %d", ecm_len);
		return ERROR;
	}

	// CMD: DE 20 00 00 4C
	memcpy(ecm_cmd, cmd_ecm, sizeof(cmd_ecm));
	ecm_cmd[4] = er->ecm[2]; // Set ECM length
	memcpy(ecm_cmd + sizeof(cmd_ecm), er->ecm + 3, ecm_cmd[4]);

	// Send ECM
	write_cmd(ecm_cmd, ecm_cmd + 5);
	if (cta_lr != 2)
	{
		rdr_log(reader, "(ecm_cmd) Unexpected card answer: %s",
			cs_hexdump(1, cta_res, cta_lr, tmp, sizeof(tmp)));
		return ERROR;
	}

	if (cta_res[0] == 0x90 && cta_res[1] == 0x03)
	{
		rdr_log(reader, "No active subscription.");
		return ERROR;
	}

	if ( !(cta_res[0] == 0x90 && cta_res[1] == 0x13) )
	{
		rdr_log(reader, "(ecm_cmd) Unexpected card answer: %s",
			cs_hexdump(1, cta_res, cta_lr, tmp, sizeof(tmp)));
		return ERROR;
	}

	// Call get_cw
	write_cmd(cmd_ecm_get_cw, NULL);

	// rdr_log(reader, "CW_LOG: %s", cs_hexdump(1, cta_res, cta_lr, tmp, sizeof(tmp)));
	if (cta_lr < 20 || (cta_res[0] != 0x0a && cta_res[1] != 0x11))
	{
		rdr_log(reader, "(get_cw) Unexpected card answer: %s",
			cs_hexdump(1, cta_res, cta_lr, tmp, sizeof(tmp)));
		return ERROR;
	}

	// *FIXME* is the bellow info true?
	//   0x80 (ver 1) is supported
	//   0xc0 (ver 2) is *NOT* supported currently
	if (cta_res[2] == 0xc0)
	{
		rdr_log(reader, "Possibly unsupported codeword (bulcrypt v2): %s",
			cs_hexdump(1, cta_res, cta_lr, tmp, sizeof(tmp)));
		// *FIXME* commented for testing, this really should be an error
		//return ERROR;
	}

	// Remove code word obfuscation
	uchar *cw = cta_res + 3;
	if (reader->bulcrypt_version == 1) {
		int i;
		for (i = 0 ; i < 16; i++) {
			cw[i] = cw[i] ^ sess_key[i];
		}
	}

	if (er->ecm[0] == 0x81)
	{
		// Even/Odd CWs should be exchanged
		memcpy(ea->cw, cw + 8, 8);
		memcpy(ea->cw + 8, cw, 8);
	} else {
		memcpy(ea->cw, cw, 8);
		memcpy(ea->cw + 8, cw + 8, 8);
	}

	// Check if DCW is valid
	if (!cw_is_valid(reader, ea->cw) || !cw_is_valid(reader, ea->cw + 8))
		return ERROR;

	return OK;
}
Ejemplo n.º 20
0
static int32_t bulcrypt_card_info(struct s_reader *reader)
{
	char tmp[512];
	time_t last_upd_ts, subs_end_ts;
	struct tm tm;
	def_resp

	rdr_log(reader, "Reading subscription info.");

	cs_clear_entitlement(reader);

	write_cmd(cmd_sub_info1, NULL);
	write_cmd(cmd_sub_info2, NULL);

	if (cta_lr < 45)
	{
		rdr_log(reader, "(info_cmd) Unexpected card answer: %s",
			cs_hexdump(1, cta_res, cta_lr, tmp, sizeof(tmp)));
		return ERROR;
	}

	// Response contains:
	//  13 29 0B
	//  4F 8F 00 E9 - Unix ts set by UNIQUE_EMM_82
	//  3C 65 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 BF
	//  3C 84 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 BF
	//  90 2B

	last_upd_ts = b2i(4, cta_res + 3);
	subs_end_ts = last_upd_ts + (31 * 86400); // *FIXME* this is just a guess

	reader->card_valid_to = subs_end_ts;

	gmtime_r(&last_upd_ts, &tm);
	memset(tmp, 0, sizeof(tmp));
	strftime(tmp, sizeof(tmp), "%Y-%m-%d %H:%M:%S %Z", &tm);
	rdr_log(reader, "Subscription data last update    : %s", tmp);

	gmtime_r(&subs_end_ts, &tm);
	memset(tmp, 0, sizeof(tmp));
	strftime(tmp, sizeof(tmp), "%Y-%m-%d %H:%M:%S %Z", &tm);
	rdr_log(reader, "Subscription should be active to : %s", tmp);

	unsigned int subs1 = b2i(2, cta_res + 3 + 4 + 16);
	unsigned int subs2 = b2i(2, cta_res + 3 + 4 + 16 + 18);

	if (subs1 == 0xffff) {
		rdr_log(reader, "No active subscriptions (0x%04x, 0x%04x)", subs1, subs2);
	} else {
		unsigned int i;
		rdr_log(reader, "Subscription data 1 (0x%04x): %s",
			subs1, dec2bin_str(subs1, tmp));
		rdr_log(reader, "Subscription data 2 (0x%04x): %s",
			subs2, dec2bin_str(subs2, tmp));

		// Configure your tiers to get subscription packets name resolution
// # Example oscam.tiers file
// 5581:0001|Economic
// 5581:0002|Standard
// 5581:0004|Premium
// 5581:0008|HBO
// 5581:0010|Unknown Package 10
// 5581:0020|Unknown Package 20
// 5581:0040|Unknown Package 40
// 5581:0080|Unknown Package 80
		for (i = 1; i < 256; i <<= 1)
		{
			if ((subs1 & i) == i) {
				cs_add_entitlement(reader, 0x4AEE,
					0, /* provid */
					i, /* id  */
					0, /* class */
					last_upd_ts, /* start_ts */
					subs_end_ts, /* end_ts */
					4 /* type: Tier */
				);
				cs_add_entitlement(reader, 0x5581,
					0, /* provid */
					i, /* id  */
					0, /* class */
					last_upd_ts, /* start_ts */
					subs_end_ts, /* end_ts */
					4 /* type: Tier */
				);
				get_tiername(i, 0x4aee, tmp);
				if (tmp[0] == 0x00)
					get_tiername(i, 0x5581, tmp);
				rdr_log(reader, "  Package %02x is active: %s", i, tmp);
			}
		}
	}

	return OK;
}
Ejemplo n.º 21
0
static int32_t conax_do_ecm(struct s_reader * reader, const ECM_REQUEST *er, struct s_ecm_answer *ea)
{
  def_resp;
  int32_t i,j,n,num_dw=0, rc=0;
  unsigned char insA2[]  = { 0xDD,0xA2,0x00,0x00,0x00 };
  unsigned char insCA[]  = { 0xDD,0xCA,0x00,0x00,0x00 };

  unsigned char exp[] = {0x01, 0x00, 0x01};
  unsigned char buf[256];

  if ((n=check_sct_len(er->ecm, 3))<0)
    return ERROR;

  buf[0]=0x14;
  buf[1]=n+1;
  if(0x0 != PairingECMRotation(reader, er, n))
    buf[2]=2; // card will answer with encrypted dw
  else
    buf[2]=0;

  memcpy(buf+3, er->ecm, n);
  insA2[4]=n+3;

  write_cmd(insA2, buf);  // write Header + ECM

  while ((cta_res[cta_lr-2]==0x98) &&   // Antwort
  ((insCA[4]=cta_res[cta_lr-1])>0) && (insCA[4]!=0xFF))
  {
    write_cmd(insCA, NULL);  //Codeword auslesen

    if ((cta_res[cta_lr-2]==0x98) ||
    ((cta_res[cta_lr-2]==0x90) ))
    {
      /*checks if answer is encrypted with RSA algo and decrypts it if needed*/
      if(0x81 == cta_res[0] && 2 == cta_res[2] >> 5) /*81 XX 5X*/
      {
        if(0x00 == cta_res[cta_lr-1])
          rc = RSA_CNX(reader, cta_res, reader->rsa_mod, exp, cta_lr, 64u, 3u);
        else
          rc = -4; /*card has no right to decode this channel*/
      }

      if(0 == rc)
      for(i = 0;  i < cta_lr-2 && num_dw < 2; i+=cta_res[i+1]+2)
      {
        switch (cta_res[i])
        {
          case 0x25:
            if ( (cta_res[i+1]>=0xD) && !((n=cta_res[i+4])&0xFE) )
            {
              rc|=(1<<n);
              memcpy(ea->cw+(n<<3), cta_res+i+7, 8);
              ++num_dw;
            }
            break;
          case 0x31:
            if ( (cta_res[i+1]==0x02  && cta_res[i+2]==0x00  && cta_res[i+3]==0x00) || \
            (cta_res[i+1]==0x02  && cta_res[i+2]==0x40  && cta_res[i+3]==0x00) )
              break;
            else if (strcmp(reader->pincode, "none"))
            {
              conax_send_pin(reader);
              write_cmd(insA2, buf);  // write Header + ECM

              while ((cta_res[cta_lr-2]==0x98) &&   // Antwort
                      ((insCA[4]=cta_res[cta_lr-1])>0) && (insCA[4]!=0xFF))
              {
                write_cmd(insCA, NULL);  //Codeword auslesen

                if ((cta_res[cta_lr-2]==0x98) ||
                    ((cta_res[cta_lr-2]==0x90) && (!cta_res[cta_lr-1])))
                {
                  for(j=0;j<cta_lr-2; j+=cta_res[j+1]+2)
                    if ((cta_res[j]==0x25) &&       // access: is cw
                        (cta_res[j+1]>=0xD) &&      // 0xD: 5 header + 8 cw
                        !((n=cta_res[j+4])&0xFE))   // cw idx must be 0 or 1
                    {
                      rc|=(1<<n);
                      memcpy(ea->cw+(n<<3), cta_res+j+7, 8);
                      ++num_dw;
                    }
                }
              }
            }
            break;
        }
      }
    }
  }

  switch(rc)
  {
    case -1:
      rdr_log(reader, "conax decode ECM problem - RSA key is probably faulty");
    break;
    case -2:
      rdr_log(reader, "conax RSA pairing - wrong size of data");
    break;
    case -3:
      rdr_log(reader, "conax RSA pairing- wrong size of data for second round");
    case -4:
      rdr_log(reader, "card has no right to decode this channel");
    break;
  }

  /* answer 9011 - conax smart card need reset */
  if(2<=cta_lr && 0x90==cta_res[cta_lr-2] &&
     0x11==cta_res[cta_lr-1])
  {
    rdr_log(reader, "conax card hangs - reset is required");
    reader->card_status = UNKNOWN;
  }

  if (rc==3)
    return OK;
  else
    return ERROR;
}
Ejemplo n.º 22
0
bool cardreader_init(struct s_reader *reader)
{
	struct s_client *client = reader->client;
	client->typ = 'r';
	int8_t i = 0;
	set_localhost_ip(&client->ip);
	while((cardreader_device_init(reader) == 2) && i < 10)
	{
		cs_sleepms(2000);
		if(!ll_contains(configured_readers, reader) || !is_valid_client(client) || reader->enable != 1)
			{ return false; }
		i++;
	}
	if (i >= 10)
	{
		reader->card_status = READER_DEVICE_ERROR;
		cardreader_close(reader);
		reader->enable = 0;
		return false;
	}
	else 
	{
		if((reader->cardmhz > 2000) && (reader->typ != R_SMART))
		{
			rdr_log(reader, "Reader initialized (device=%s, detect=%s%s, pll max=%.2f MHz, wanted mhz=%.2f MHz)",
					reader->device,
					reader->detect & 0x80 ? "!" : "",
					RDR_CD_TXT[reader->detect & 0x7f],
					(float)reader->cardmhz / 100,
					(float)reader->mhz / 100);
			rdr_log(reader,"Reader sci internal, detected box type: %s", stb_boxtype ? stb_boxtype : "generic");
		}
		else
		{
			if ((reader->typ == R_SMART) || (!strcasecmp(reader->crdr.desc, "smargo")) ){
				rdr_debug_mask(reader, D_IFD, "clocking for smartreader with smartreader or smargo protocol");
				if (reader->cardmhz >= 2000) reader->cardmhz =  369; else
				if (reader->cardmhz >= 1600) reader->cardmhz = 1600; else
				if (reader->cardmhz >= 1200) reader->cardmhz = 1200; else
				if (reader->cardmhz >= 961)  reader->cardmhz =  961; else
				if (reader->cardmhz >= 800)  reader->cardmhz =  800; else
				if (reader->cardmhz >= 686)  reader->cardmhz =  686; else
				if (reader->cardmhz >= 600)  reader->cardmhz =  600; else
				if (reader->cardmhz >= 534)  reader->cardmhz =  534; else
				if (reader->cardmhz >= 480)  reader->cardmhz =  480; else
				if (reader->cardmhz >= 436)  reader->cardmhz =  436; else
				if (reader->cardmhz >= 400)  reader->cardmhz =  400; else
				if (reader->cardmhz >= 369)  reader->cardmhz =  369; else
				if (reader->cardmhz == 357)  reader->cardmhz =  369; else // 357 not a default smartreader setting
				if (reader->cardmhz >= 343)  reader->cardmhz =  343; else 
				reader->cardmhz =  320;
				if (reader->mhz >= 1600) reader->mhz = 1600; else
				if (reader->mhz >= 1200) reader->mhz = 1200; else
				if (reader->mhz >= 961)  reader->mhz =  961; else
				if (reader->mhz >= 900)  reader->mhz =  900; else
				if (reader->mhz >= 800)  reader->mhz =  800; else
				if (reader->mhz >= 686)  reader->mhz =  686; else
				if (reader->mhz >= 600)  reader->mhz =  600; else
				if (reader->mhz >= 534)  reader->mhz =  534; else
				if (reader->mhz >= 480)  reader->mhz =  480; else
				if (reader->mhz >= 436)  reader->mhz =  436; else
				if (reader->mhz >= 400)  reader->mhz =  369; else
				if (reader->mhz >= 369)  reader->mhz =  369; else
				if (reader->mhz == 357)  reader->mhz =  369; else // 357 not a default smartreader setting
				if (reader->mhz >= 343)  reader->mhz =  343; else 
				reader->mhz =  320;
	    	}
			if (((reader->typ == R_SMART) && (reader->autospeed == 1)) || ((!strcasecmp(reader->crdr.desc, "smargo")) && (reader->autospeed == 1))) { 
				rdr_log(reader, "Reader initialized (device=%s, detect=%s%s, mhz= AUTO, cardmhz=%d)",
						reader->device,
						reader->detect & 0x80 ? "!" : "",
						RDR_CD_TXT[reader->detect & 0x7f],
						reader->cardmhz);
			} else {
				rdr_log(reader, "Reader initialized (device=%s, detect=%s%s, mhz=%d, cardmhz=%d)",
						reader->device,
						reader->detect & 0x80 ? "!" : "",
						RDR_CD_TXT[reader->detect & 0x7f],
						reader->mhz,
						reader->cardmhz);
			}
		}
		return true;
	}
}
Ejemplo n.º 23
0
static int32_t viaccess_card_init(struct s_reader * reader, ATR *newatr)
{
	get_atr;
	def_resp;
	int32_t i;
	uchar buf[256];
	uchar insac[] = { 0xca, 0xac, 0x00, 0x00, 0x00 }; // select data
	uchar insb8[] = { 0xca, 0xb8, 0x00, 0x00, 0x00 }; // read selected data
	uchar insa4[] = { 0xca, 0xa4, 0x00, 0x00, 0x00 }; // select issuer
	uchar insc0[] = { 0xca, 0xc0, 0x00, 0x00, 0x00 }; // read data item
	static const uchar insFAC[] = { 0x87, 0x02, 0x00, 0x00, 0x03 }; // init FAC
	static const uchar FacDat[] = { 0x00, 0x00, 0x28 };
	static unsigned char ins8702_data[] = { 0x00, 0x00, 0x11};
	static unsigned char ins8704[] = { 0x87, 0x04, 0x00, 0x00, 0x07 };
	static unsigned char ins8706[] = { 0x87, 0x06, 0x00, 0x00, 0x04 };


	if ((atr[1]!=0x77) || ((atr[2]!=0x18) && (atr[2]!=0x11) && (atr[2]!=0x19)) || ((atr[9]!=0x68) && (atr[9]!=0x6C)))
		return ERROR;

	write_cmd(insFAC, FacDat);
	if( !(cta_res[cta_lr-2]==0x90 && cta_res[cta_lr-1]==0) )
		return ERROR;

	memset(&reader->last_geo, 0, sizeof(reader->last_geo));
	write_cmd(insFAC, ins8702_data);
	if ((cta_res[cta_lr-2]==0x90) && (cta_res[cta_lr-1]==0x00)) {
		write_cmd(ins8704, NULL);
		if ((cta_res[cta_lr-2]==0x90) && (cta_res[cta_lr-1]==0x00)) {
			write_cmd(ins8706, NULL);
			if ((cta_res[cta_lr-2]==0x90) && (cta_res[cta_lr-1]==0x00)) {
				reader->last_geo.number_ecm =(cta_res[2]<<8) | (cta_res[3]);
				rdr_log(reader,  "using ecm #%x for long viaccess ecm",reader->last_geo.number_ecm);
			}
		}
	}


	//  switch((atr[atrsize-4]<<8)|atr[atrsize-3])
	//  {
	//    case 0x6268: ver="2.3"; break;
	//    case 0x6668: ver="2.4(?)"; break;
	//    case 0xa268:
	//    default: ver="unknown"; break;
	//  }

	reader->caid=0x500;
	memset(reader->prid, 0xff, sizeof(reader->prid));
	insac[2]=0xa4; write_cmd(insac, NULL); // request unique id
	insb8[4]=0x07; write_cmd(insb8, NULL); // read unique id
	memcpy(reader->hexserial, cta_res+2, 5);
	//  rdr_log(reader, "[viaccess-reader] type: Viaccess, ver: %s serial: %llu", ver, b2ll(5, cta_res+2));
	rdr_log_sensitive(reader, "type: Viaccess (%sstandard atr), caid: %04X, serial: {%llu}",
		atr[9]==0x68?"":"non-",reader->caid, (unsigned long long) b2ll(5, cta_res+2));

	i=0;
	insa4[2]=0x00; write_cmd(insa4, NULL); // select issuer 0
	buf[0]=0;
	while((cta_res[cta_lr-2]==0x90) && (cta_res[cta_lr-1]==0))
	{
		insc0[4]=0x1a; write_cmd(insc0, NULL); // show provider properties
		cta_res[2]&=0xF0;
		reader->prid[i][0]=0;
		memcpy(&reader->prid[i][1], cta_res, 3);
		memcpy(&reader->availkeys[i][0], cta_res+10, 16);
		snprintf((char *)buf+strlen((char *)buf), sizeof(buf)-strlen((char *)buf), ",%06X", b2i(3, &reader->prid[i][1]));
		//rdr_log(reader, "[viaccess-reader] buf: %s", buf);

		insac[2]=0xa5; write_cmd(insac, NULL); // request sa
		insb8[4]=0x06; write_cmd(insb8, NULL); // read sa
		memcpy(&reader->sa[i][0], cta_res+2, 4);

		/*
		insac[2]=0xa7; write_cmd(insac, NULL); // request name
		insb8[4]=0x02; write_cmd(insb8, NULL); // read name nano + len
		l=cta_res[1];
		insb8[4]=l; write_cmd(insb8, NULL); // read name
		cta_res[l]=0;
		rdr_log(reader, "[viaccess-reader] name: %s", cta_res);
		*/

		insa4[2]=0x02;
		write_cmd(insa4, NULL); // select next issuer
		i++;
	}
	reader->nprov=i;
	rdr_log(reader, "providers: %d (%s)", reader->nprov, buf+1);

	if (cfg.ulparent)
		unlock_parental(reader);

	rdr_log(reader, "ready for requests");
	return OK;
}
Ejemplo n.º 24
0
static int32_t pcsc_init(struct s_reader *pcsc_reader)
{
    ULONG rv;
    DWORD dwReaders;
    LPSTR mszReaders = NULL;
    char *ptr, **readers = NULL;
    char *device = pcsc_reader->device;
    int32_t nbReaders;
    int32_t reader_nb;

    pcsc_reader->pcsc_has_card=0;
    pcsc_reader->hCard=0;
    pcsc_reader->hContext=0;

    rdr_debug_mask(pcsc_reader, D_DEVICE, "PCSC establish context for PCSC pcsc_reader %s", device);
    rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &pcsc_reader->hContext);
    if ( rv == SCARD_S_SUCCESS ) {
        // here we need to list the pcsc readers and get the name from there,
        // the pcsc_reader->device should contain the pcsc_reader number
        // and after the actual device name is copied in pcsc_reader->pcsc_name .
        rv = SCardListReaders(pcsc_reader->hContext, NULL, NULL, &dwReaders);
        if( rv != SCARD_S_SUCCESS ) {
            rdr_debug_mask(pcsc_reader, D_DEVICE, "PCSC failed listing readers [1] : (%lx)", (unsigned long)rv);
            return ERROR;
        }
        if (!cs_malloc(&mszReaders, dwReaders))
            return ERROR;
        rv = SCardListReaders(pcsc_reader->hContext, NULL, mszReaders, &dwReaders);
        if( rv != SCARD_S_SUCCESS ) {
            rdr_debug_mask(pcsc_reader, D_DEVICE, "PCSC failed listing readers [2]: (%lx)", (unsigned long)rv);
            free(mszReaders);
            return ERROR;
        }
        /* Extract readers from the null separated string and get the total
         * number of readers
         */
        nbReaders = 0;
        ptr = mszReaders;
        while (*ptr != '\0') {
            ptr += strlen(ptr)+1;
            nbReaders++;
        }

        if (nbReaders == 0) {
            rdr_log(pcsc_reader, "PCSC : no pcsc_reader found");
            free(mszReaders);
            return ERROR;
        }

        if (!cs_malloc(&readers, nbReaders * sizeof(char *)))
            return ERROR;

        /* fill the readers table */
        nbReaders = 0;
        ptr = mszReaders;
        while (*ptr != '\0') {
            rdr_debug_mask(pcsc_reader, D_DEVICE, "PCSC pcsc_reader %d: %s", nbReaders, ptr);
            readers[nbReaders] = ptr;
            ptr += strlen(ptr)+1;
            nbReaders++;
        }

        reader_nb=atoi((const char *)&pcsc_reader->device);
        if (reader_nb < 0 || reader_nb >= nbReaders) {
            rdr_log(pcsc_reader, "Wrong pcsc_reader index: %d", reader_nb);
            free(mszReaders);
            free(readers);
            return ERROR;
        }

        snprintf(pcsc_reader->pcsc_name,sizeof(pcsc_reader->pcsc_name),"%s",readers[reader_nb]);
        free(mszReaders);
        free(readers);
    }
    else {
        rdr_log(pcsc_reader, "PCSC failed establish context (%lx)", (unsigned long)rv);
        return ERROR;
    }
    return OK;
}
Ejemplo n.º 25
0
static int32_t viaccess_do_emm(struct s_reader * reader, EMM_PACKET *ep)
{
	def_resp;
	static const unsigned char insa4[] = { 0xca,0xa4,0x04,0x00,0x03 }; // set provider id
	unsigned char insf0[] = { 0xca,0xf0,0x00,0x01,0x22 }; // set adf
	unsigned char insf4[] = { 0xca,0xf4,0x00,0x01,0x00 }; // set adf, encrypted
	unsigned char ins18[] = { 0xca,0x18,0x01,0x01,0x00 }; // set subscription
	unsigned char ins1c[] = { 0xca,0x1c,0x01,0x01,0x00 }; // set subscription, encrypted
	static const unsigned char insc8[] = { 0xca,0xc8,0x00,0x00,0x02 }; // read extended status
	// static const unsigned char insc8Data[] = { 0x00,0x00 }; // data for read extended status

	int32_t emmdatastart=7;


	if (ep->type == UNIQUE) emmdatastart++;
	int32_t emmLen=SCT_LEN(ep->emm)-emmdatastart;
	int32_t rc=0;

	///cs_dump(ep->emm, emmLen+emmdatastart, "RECEIVED EMM VIACCESS");

	int32_t emmUpToEnd;
	uchar *emmParsed = ep->emm+emmdatastart;
	int32_t provider_ok = 0;
	uint32_t emm_provid;
	uchar keynr = 0;
	int32_t ins18Len = 0;
	uchar ins18Data[512];
	uchar insData[512];
	uchar *nano81Data = 0;
	uchar *nano91Data = 0;
	uchar *nano92Data = 0;
	uchar *nano9EData = 0;
	uchar *nanoF0Data = 0;

	for (emmUpToEnd=emmLen; (emmParsed[1] != 0) && (emmUpToEnd > 0); emmUpToEnd -= (2 + emmParsed[1]), emmParsed += (2 + emmParsed[1])) {
		///cs_dump (emmParsed, emmParsed[1] + 2, "NANO");

		if (emmParsed[0]==0x90 && emmParsed[1]==0x03) {
			/* identification of the service operator */

			uchar soid[3], ident[3], i;

			for (i=0; i<3; i++) {
				soid[i]=ident[i]=emmParsed[2+i];
			}
			ident[2]&=0xF0;
			emm_provid=b2i(3, ident);
			keynr=soid[2]&0x0F;
			if (chk_prov(reader, ident, keynr)) {
				provider_ok = 1;
			} else {
				rdr_log(reader, "EMM: provider or key not found on card (%x, %x)", emm_provid, keynr);
				return ERROR;
			}

			// check if the provider changes. If yes, set the new one. If not, don't .. card will return an error if we do.
			if( reader->last_geo.provid != emm_provid ) {
				write_cmd(insa4, ident);
				if( cta_res[cta_lr-2]!=0x90 || cta_res[cta_lr-1]!=0x00 ) {
					cs_dump(insa4, 5, "set provider cmd:");
					cs_dump(soid, 3, "set provider data:");
					rdr_log(reader, "update error: %02X %02X", cta_res[cta_lr-2], cta_res[cta_lr-1]);
					return ERROR;
				}
			}
			// as we are maybe changing the used provider, clear the cache, so the next ecm will re-select the correct one
			reader->last_geo.provid = 0;
			reader->last_geo.geo_len = 0;
			reader->last_geo.geo[0]  = 0;

		}
		else if (emmParsed[0]==0x9e && emmParsed[1]==0x20) {
			/* adf */

			if (!nano91Data) {
				/* adf is not crypted, so test it */

				uchar custwp;
				uchar *afd;

				custwp=reader->sa[0][3];
				afd=(uchar*)emmParsed+2;

				if( afd[31-custwp/8] & (1 << (custwp & 7)) )
					rdr_debug_mask(reader, D_READER, "emm for our card %08X", b2i(4, &reader->sa[0][0]));
				else
					return SKIPPED;
			}

			// memorize
			nano9EData = emmParsed;

		} else if (emmParsed[0]==0x81) {
			nano81Data = emmParsed;
		} else if (emmParsed[0]==0x91 && emmParsed[1]==0x08) {
			nano91Data = emmParsed;
		} else if (emmParsed[0]==0x92 && emmParsed[1]==0x08) {
			nano92Data = emmParsed;
		} else if (emmParsed[0]==0xF0 && emmParsed[1]==0x08) {
			nanoF0Data = emmParsed;
		} else {
			/* other nanos */
			show_subs(reader, emmParsed);

			memcpy(ins18Data+ins18Len, emmParsed, emmParsed[1] + 2);
			ins18Len += emmParsed [1] + 2;
		}
	}

	if (!provider_ok) {
		rdr_debug_mask(reader, D_READER, "provider not found in emm, continue anyway");
		// force key to 1...
		keynr = 1;
		///return ERROR;
	}

	if (!nanoF0Data) {
		cs_dump(ep->emm, ep->emmlen, "can't find 0xf0 in emm...");
		return ERROR; // error
	}

	if (nano9EData) {
		if (!nano91Data) {
			// set adf
			insf0[3] = keynr;  // key
			insf0[4] = nano9EData[1] + 2;
			write_cmd(insf0, nano9EData);
			if( cta_res[cta_lr-2]!=0x90 || cta_res[cta_lr-1]!=0x00 ) {
				cs_dump(insf0, 5, "set adf cmd:");
				cs_dump(nano9EData, insf0[4] , "set adf data:");
				rdr_log(reader, "update error: %02X %02X", cta_res[cta_lr-2], cta_res[cta_lr-1]);
				return ERROR;
			}
		} else {
			// set adf crypte
			insf4[3] = keynr;  // key
			insf4[4] = nano91Data[1] + 2 + nano9EData[1] + 2;
			memcpy (insData, nano91Data, nano91Data[1] + 2);
			memcpy (insData + nano91Data[1] + 2, nano9EData, nano9EData[1] + 2);
			write_cmd(insf4, insData);
			if(( cta_res[cta_lr-2]!=0x90 && cta_res[cta_lr-2]!=0x91) || cta_res[cta_lr-1]!=0x00 ) {
				cs_dump(insf4, 5, "set adf encrypted cmd:");
				cs_dump(insData, insf4[4], "set adf encrypted data:");
				rdr_log(reader, "update error: %02X %02X", cta_res[cta_lr-2], cta_res[cta_lr-1]);
				return ERROR;
			}
		}
	}

	if (!nano92Data) {
		// send subscription
		ins18[2] = nano9EData ? 0x01: 0x00; // found 9E nano ?
		ins18[3] = keynr;  // key
		ins18[4] = ins18Len + nanoF0Data[1] + 2;
		memcpy (insData, ins18Data, ins18Len);
		memcpy (insData + ins18Len, nanoF0Data, nanoF0Data[1] + 2);
		write_cmd(ins18, insData);
		if( (cta_res[cta_lr-2]==0x90 || cta_res[cta_lr-2]==0x91) && cta_res[cta_lr-1]==0x00 ) {
			rdr_debug_mask(reader, D_READER, "update successfully written");
			rc=1; // written
		} else {
			cs_dump(ins18, 5, "set subscription cmd:");
			cs_dump(insData, ins18[4], "set subscription data:");
			rdr_log(reader, "update error: %02X %02X", cta_res[cta_lr-2], cta_res[cta_lr-1]);
		}

	} else {
		// send subscription encrypted

		if (!nano81Data) {
			cs_dump(ep->emm, ep->emmlen, "0x92 found, but can't find 0x81 in emm...");
			return ERROR; // error
		}

		ins1c[2] = nano9EData ? 0x01: 0x00; // found 9E nano ?
		if (ep->type == UNIQUE) ins1c[2] = 0x02;
		ins1c[3] = keynr;  // key
		ins1c[4] = nano92Data[1] + 2 + nano81Data[1] + 2 + nanoF0Data[1] + 2;
		memcpy (insData, nano92Data, nano92Data[1] + 2);
		memcpy (insData + nano92Data[1] + 2, nano81Data, nano81Data[1] + 2);
		memcpy (insData + nano92Data[1] + 2 + nano81Data[1] + 2, nanoF0Data, nanoF0Data[1] + 2);
		write_cmd(ins1c, insData);

		if( (cta_res[cta_lr-2]==0x90 && cta_res[cta_lr-1]==0x00) ) {
			rdr_log(reader, "update successfully written");
			rc=1; // written
		}
		else {
			if( cta_res[cta_lr-2]&0x1 )
				rdr_log(reader, "update not written. Data already exists or unknown address");

			//if( cta_res[cta_lr-2]&0x8 ) {
			write_cmd(insc8, NULL);
			if( (cta_res[cta_lr-2]==0x90 && cta_res[cta_lr-1]==0x00) ) {
				rdr_log(reader, "extended status  %02X %02X", cta_res[0], cta_res[1]);
			}
			//}
			return ERROR;
		}

	}

	/*
	Sub Main()
	Sc.Write("CA A4 04 00 03")
	RX
	Sc.Write("02 07 11")
	RX
	Sc.Write("CA F0 00 01 22")
	RX
	Sc.Write("9E 20")
	Sc.Write("10 10 08 8A 80 00 04 00 10 10 26 E8 54 80 1E 80")
	Sc.Write("00 01 00 00 00 00 00 50 00 00 80 02 22 00 08 50")
	RX
	Sc.Write("CA 18 01 01 11")
	RX
	Sc.Write("A9 05 34 DE 34 FF 80")
	Sc.Write("F0 08 1A 3E AF B5 2B EE E3 3B")
	RX

	End Sub
	*/
	return rc;
}
Ejemplo n.º 26
0
int32_t ICC_Async_Activate(struct s_reader *reader, ATR *atr, uint16_t deprecated)
{
	rdr_debug_mask(reader, D_IFD, "Activating card");

	reader->current_baudrate = DEFAULT_BAUDRATE;
	if(reader->atr[0] != 0 && !reader->ins7e11_fast_reset)
	{
		rdr_log(reader, "Using ATR from reader config");
		ATR_InitFromArray(atr, reader->atr, ATR_MAX_SIZE);
	}
	else
	{
		call(reader->crdr.activate(reader, atr));
		if(reader->crdr.skip_extra_atr_parsing)
			{ return OK; }
	}

	unsigned char atrarr[ATR_MAX_SIZE];
	uint32_t atr_size;
	ATR_GetRaw(atr, atrarr, &atr_size);
	char tmp[atr_size * 3 + 1];
	// dirty hack for seca cards on Golden Interstar Xspeed internal reader 
	char *hack_golden_interstar = cs_hexdump(1, atrarr, atr_size, tmp, sizeof(tmp));
	int result = strncmp(hack_golden_interstar, "18 40 D8 ", sizeof(tmp));
	if (!result)
	{
		rdr_log(reader, "Disabling rom rev detection. Golden Star internal reader dirty hack");
		reader->ins7e11_fast_reset = 2;
	}
	// end dirty hack If a solution to the stb's sci driver is found remove this hack
	rdr_log(reader, "ATR: %s", cs_hexdump(1, atrarr, atr_size, tmp, sizeof(tmp)));
	memcpy(reader->card_atr, atrarr, atr_size);
	reader->card_atr_length = atr_size;

	/* Get ICC reader->convention */
	if(ATR_GetConvention(atr, &(reader->convention)) != ATR_OK)
	{
		rdr_log(reader, "ERROR: Could not read reader->convention");
		reader->convention = 0;
		reader->protocol_type = 0;
		return ERROR;
	}

	reader->protocol_type = ATR_PROTOCOL_TYPE_T0;

	// Parse_ATR and InitCard need to be included in lock because they change parity of serial port
	if(reader->crdr.lock)
		{ reader->crdr.lock(reader); }

	int32_t ret = Parse_ATR(reader, atr, deprecated);

	if(reader->crdr.unlock)
		{ reader->crdr.unlock(reader); }

	if(ret)
		{ rdr_log(reader, "ERROR: Parse_ATR returned error"); }
	if(ret)
		{ return ERROR; }
	rdr_debug_mask(reader, D_IFD, "Card succesfully activated");

	return OK;
}
Ejemplo n.º 27
0
static int32_t dre_set_provider_info(struct s_reader *reader)
{
	def_resp;
	int32_t i;
    int subscr_cmd_len = 4;
    uchar subscr[4];// = { 0x59, 0x14 };   // subscriptions
    uchar dates[] = { 0x5b, 0x00, 0x14 }; //validity dates
    uchar subscr_len = 0, n = 0;
	struct dre_data *csystem_data = reader->csystem_data;

	cs_clear_entitlement(reader);

    switch(csystem_data->provider)
    {
        case 0x02:
        case 0x03:
            subscr[0] = 0x84;
            subscr[1] = 0;
            subscr[2] = 0x5F;
            subscr[3] = csystem_data->provider;
            dates[0] = 0x85;
            subscr_len = 0x5F;
            break;
        case 0x18:
        case 0x19:
        case 0x1A:
            subscr[0] = 0x94;
            subscr[1] = 0;
            subscr[2] = 0x5F;
            subscr[3] = csystem_data->provider;
            dates[0] = 0x95;
            subscr_len = 0x5F;
            break;
        default:
            subscr[0] = 0x59;
            subscr[1] = csystem_data->provider;
            subscr_len = 0x20;
            subscr_cmd_len = 2;
    }

chk_subscr:
    
    if((dre_script(subscr, subscr_cmd_len, 0, 0, 0)))      //ask subscription packages, returns error on 0x11 card
    {
        uchar pbm[subscr_len];
        char tmp_dbg[subscr_len*2+1];
		memcpy(pbm, cta_res + 3, cta_lr - 6);
        rdr_log_dbg(reader, D_READER, "pbm: %s", cs_hexdump(0, pbm, subscr_len, tmp_dbg, sizeof(tmp_dbg)));

        for(i = 0; i < subscr_len; i++)
            if(pbm[i] != 0xff)
            {
                dates[1] = i;
                dates[2] = csystem_data->provider;
                dre_cmd(dates);   //ask for validity dates

                time_t start;
                time_t end;
                start = (cta_res[3] << 24) | (cta_res[4] << 16) | (cta_res[5] << 8) | cta_res[6];
                end = (cta_res[7] << 24) | (cta_res[8] << 16) | (cta_res[9] << 8) | cta_res[10];

                struct tm temp;

                localtime_r(&start, &temp);
                int32_t startyear = temp.tm_year + 1900;
                int32_t startmonth = temp.tm_mon + 1;
                int32_t startday = temp.tm_mday;
                localtime_r(&end, &temp);
                int32_t endyear = temp.tm_year + 1900;
                int32_t endmonth = temp.tm_mon + 1;
                int32_t endday = temp.tm_mday;
                rdr_log(reader, "active package %i valid from %04i/%02i/%02i to %04i/%02i/%02i", i+n, startyear, startmonth, startday,
                        endyear, endmonth, endday);
                cs_add_entitlement(reader, reader->caid, b2ll(4, reader->prid[0]), 0, i+n, start, end, 5, 1);
            }
    }
    
    if(subscr_len == 0x5F) // read second part subscription packages, for DRE3 and DRE4
    {
        subscr[1] = 0x5F;
        subscr[2] = 0x21;
        subscr_len = 0x21;
        n = 0x5F;
        goto chk_subscr;
    }

	return OK;
}
Ejemplo n.º 28
0
int32_t ICC_Async_CardWrite(struct s_reader *reader, unsigned char *command, uint16_t command_len, unsigned char *rsp, uint16_t *lr)
{
	int32_t ret;

	*lr = 0; //will be returned in case of error
	if(reader->crdr.card_write)
	{
		call(reader->crdr.card_write(reader, command, rsp, lr, command_len));
		return OK;
	}

	if(reader->crdr.lock)
		{ reader->crdr.lock(reader); }

	int32_t try = 1;
	uint16_t type = 0;
	do
	{
		switch(reader->protocol_type)
		{
			if(try > 1)
					rdr_log(reader, "Warning: needed try nr %i, next ECM has some delay", try);
		case ATR_PROTOCOL_TYPE_T0:
			ret = Protocol_T0_Command(reader, command, command_len, rsp, lr);
			type = 0;
			break;
		case ATR_PROTOCOL_TYPE_T1:
			ret = Protocol_T1_Command(reader, command, command_len, rsp, lr);
			type = 1;
			if(ret != OK && !reader->crdr.skip_t1_command_retries)
			{
				//try to resync
				rdr_log(reader, "Resync error: readtimeouts %d/%d (max/min) us, writetimeouts %d/%d (max/min) us", reader->maxreadtimeout, reader->minreadtimeout, reader->maxwritetimeout, reader->minwritetimeout);
				unsigned char resync[] = { 0x21, 0xC0, 0x00, 0xE1 };
				ret = Protocol_T1_Command(reader, resync, sizeof(resync), rsp, lr);
				if(ret == OK)
				{
					//reader->ifsc = DEFAULT_IFSC; //tryfix cardtimeouts: ifsc is setup at card init, on resync it should not return to default_ifsc
					rdr_log(reader, "T1 Resync command succesfull ifsc = %i", reader->ifsc);
					ret = ERROR;
				}
				else
				{
					rdr_log(reader, "T1 Resync command error, trying to reactivate!");
					ATR atr;
					ICC_Async_Activate(reader, &atr, reader->deprecated);
					if(reader->crdr.unlock)
						{ reader->crdr.unlock(reader); }
					return ERROR;
				}
			}
			break;
		case ATR_PROTOCOL_TYPE_T14:
			ret = Protocol_T14_ExchangeTPDU(reader, command, command_len, rsp, lr);
			type = 14;
			break;
		default:
			rdr_log(reader, "ERROR: Unknown protocol type %i", reader->protocol_type);
			type = 99; // use 99 for unknown.
			ret = ERROR;
		}
		try++;
	}
	while((try < 3) && (ret != OK));    //always do one retry when failing

	if(reader->crdr.unlock)
		{ reader->crdr.unlock(reader); }

	if(ret)
	{
		rdr_debug_mask(reader, D_TRACE, "ERROR: Protocol_T%d_Command returns error", type);
		return ERROR;
	}

	rdr_ddump_mask(reader, D_READER, rsp, *lr, "Answer from cardreader:");
	return OK;
}

int32_t ICC_Async_GetTimings(struct s_reader *reader, uint32_t wait_etu)
{
	int32_t timeout = ETU_to_us(reader, wait_etu);
	rdr_debug_mask(reader, D_IFD, "Setting timeout to %i ETU (%d us)", wait_etu, timeout);
	return timeout;
}
Ejemplo n.º 29
0
static int32_t dre_command(struct s_reader *reader, const uchar *cmd, int32_t cmdlen, unsigned char *cta_res, uint16_t *p_cta_lr, 
                                                            uint8_t crypted, uint8_t keynum, uint8_t dre_v, uint8_t cmd_type)
                                                            //attention: inputcommand will be changed!!!! answer will be in cta_res, length cta_lr ; returning 1 = no error, return ERROR = err
{
	uchar startcmd[] = { 0x80, 0xFF, 0x10, 0x01, 0x05 };  //any command starts with this,
	//last byte is nr of bytes of the command that will be sent
	//after the startcmd
	//response on startcmd+cmd:     = { 0x61, 0x05 }  //0x61 = "OK", last byte is nr. of bytes card will send
	uchar reqans[] = { 0x00, 0xC0, 0x00, 0x00, 0x08 };    //after command answer has to be requested,
	//last byte must be nr. of bytes that card has reported to send
	uchar command[256];
	uchar checksum;
	char tmp[256];
	int32_t headerlen = sizeof(startcmd);

    if(dre_v > 0)
    {
        startcmd[1] = 0;
        startcmd[2] = crypted;
        startcmd[3] = keynum;
    }

    startcmd[4] = cmdlen + 3 - cmd_type; //commandlength + type + len + checksum bytes
	memcpy(command, startcmd, headerlen);
    command[headerlen++] = cmd_type ? 0x86 : CMD_BYTE;  //type
    command[headerlen++] = cmdlen + (cmd_type == 1 ? 0 : 1);    //len = command + 1 checksum byte
	memcpy(command + headerlen, cmd, cmdlen);

    if(!cmd_type)
    {
        checksum = ~xor(cmd, cmdlen);
        //rdr_log_dbg(reader, D_READER, "Checksum: %02x", checksum);
        cmdlen += headerlen;
        command[cmdlen++] = checksum;
    }
    else cmdlen += headerlen;

	reader_cmd2icc(reader, command, cmdlen, cta_res, p_cta_lr);

	if((*p_cta_lr != 2) || (cta_res[0] != OK_RESPONSE))
	{
		rdr_log(reader, "command sent to card: %s", cs_hexdump(0, command, cmdlen, tmp, sizeof(tmp)));
		rdr_log(reader, "unexpected answer from card: %s", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
		return ERROR;           //error
	}

    rdr_log_dbg(reader, D_READER, "command sent to card: %s", cs_hexdump(0, command, cmdlen, tmp, sizeof(tmp)));
    rdr_log_dbg(reader, D_READER, "answer from card: %s", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));

	reqans[4] = cta_res[1];   //adapt length byte
	reader_cmd2icc(reader, reqans, 5, cta_res, p_cta_lr);

	if(cta_res[0] != CMD_BYTE)
	{
		rdr_log(reader, "unknown response: cta_res[0] expected to be %02x, is %02x", CMD_BYTE, cta_res[0]);
		return ERROR;
	}

	if((cta_res[1] == 0x03) && (cta_res[2] == 0xe2))
	{
		switch(cta_res[3+dre_v])
		{
		case 0xe1:
			rdr_log(reader, "checksum error: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
			break;
		case 0xe2:
			rdr_log(reader, "wrong cmd len: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
			break;
		case 0xe3:
			rdr_log(reader, "illegal command: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
			break;
        case 0xe4:
            rdr_log(reader, "wrong adress type: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
            break;
        case 0xe5:
            rdr_log(reader, "wrong CMD param: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
            break;
        case 0xe6:
            rdr_log(reader, "wrong UA: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
            break;
        case 0xe7:
            rdr_log(reader, "wrong group: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
            break;
        case 0xe8:
            rdr_log(reader, "wrong key num: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
            break;
        case 0xeb:
            rdr_log(reader, "No key or subscribe : %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
            break;
		case 0xec:
			rdr_log(reader, "wrong signature: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
			break;
        case 0xed:
            rdr_log(reader, "wrong provider: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
            break;
        case 0xef:
            rdr_log(reader, "wrong GEO code: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
            break;
		default:
			rdr_log_dbg(reader, D_READER, "unknown error: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
			break;
		}
		return ERROR;           //error
	}

	int32_t length_excl_leader = *p_cta_lr;

	if((cta_res[*p_cta_lr - 2] == 0x90) && (cta_res[*p_cta_lr - 1] == 0x00))
		{ length_excl_leader -= 2; }

	checksum = ~xor(cta_res + 2, length_excl_leader - 3);

	if(cta_res[length_excl_leader - 1] != checksum)
	{
		rdr_log(reader, "checksum does not match, expected %02x received %02x:%s", checksum,
				cta_res[length_excl_leader - 1], cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
		return ERROR;           //error
	}
	return OK;
}
Ejemplo n.º 30
0
static int32_t griffin_card_init(struct s_reader *rdr, ATR *newatr)
{
	int32_t i;
	get_atr
	def_resp

	if(atr_size < 10)
	{
		return ERROR;
	}

	//       0  1  2  3  4  5  6  7  8  9
	// ATR: 3B 08 yy 01 xx xx xx xx 10 00
	if(atr[0] != 0x3b || atr[1] != 0x08 || atr[3] != 0x01 || atr[9] != 0x00)
	{
		return ERROR;
	}

	if(!cs_malloc(&rdr->csystem_data, sizeof(struct griffin_data)))
	{
		return ERROR;
	}

	struct griffin_data *csystem_data = rdr->csystem_data;

	rdr->nprov = 1;
	memset(rdr->sa, 0, sizeof(rdr->sa));
	memset(rdr->prid, 0, sizeof(rdr->prid));
	memset(rdr->hexserial, 0, sizeof(rdr->hexserial));

	rdr->caid = (0x55 << 8) | atr[2];
	memcpy(rdr->hexserial, atr + 4, 4);
	csystem_data->cmd_base = atr[8];

	rdr_log_sensitive(rdr, "[griffin-reader] card detected, cmd_base: %02X caid: %04X hexserial: {%02X %02X %02X %02X}",
			csystem_data->cmd_base, rdr->caid, rdr->hexserial[0], rdr->hexserial[1], rdr->hexserial[2], rdr->hexserial[3]);

	griffin_cmd(GRIFFIN_CMD_INIT, NULL, 0, 2);
	csystem_data->cmd_base = cta_res[2]; // already set from ATR

	griffin_cmd(GRIFFIN_CMD_GET_HEX_SERIAL, NULL, 0, 6);
	memcpy(rdr->hexserial, cta_res + 2, 4);

	char serial[16];
	memset(serial, 0, sizeof(serial));
	griffin_cmd(GRIFFIN_CMD_GET_ASCII_SERIAL, NULL, 0, 14);
	memcpy(serial, cta_res + 2, 12);

	griffin_cmd(GRIFFIN_CMD_GET_CAID, NULL, 0, 4);
	rdr->caid = (cta_res[2] << 8) | cta_res[3];

	griffin_cmd(GRIFFIN_CMD_GET_CARD_ADDRESS, NULL, 0, 48);

	for(i = 1 ; i < CS_MAXPROV; i++)
	{
		if(3 + (i * 16) + 4 > cta_lr)
		{
			break;
		}
		memcpy(rdr->sa[i - 1], cta_res + 3 + (i * 16), 4);
	}

	// Unknown commands
	griffin_cmd(0x22, NULL, 0, 2);
	griffin_cmd(0x10, NULL, 0, 2);
	griffin_cmd(0x14, NULL, 0, 2);
	//griffin_cmd(0x2a, NULL, 0, 2);
	//griffin_cmd(0x30, NULL, 0, 2);

	for(i = 0 ; i < CS_MAXPROV; i++)
	{
		if(array_has_nonzero_byte(rdr->sa[i], 4))
		{
			rdr_log_sensitive(rdr, "CAID: 0x%04X, Serial: {%s}, HexSerial: {%02X %02X %02X %02X} Addr: {%02X %02X %02X %02X}",
					rdr->caid, serial, rdr->hexserial[0], rdr->hexserial[1], rdr->hexserial[2], rdr->hexserial[3],
					rdr->sa[i][0], rdr->sa[i][1], rdr->sa[i][2], rdr->sa[i][3]);
		}
	}

	rdr_log(rdr, "Ready for requests.");
	return OK;
}