Пример #1
0
static void camd35_process_ecm(uchar *buf, int buflen) {
    ECM_REQUEST er;
    if (!buf || buflen < 23)
        return;
    uint16_t ecmlen = (((buf[21] & 0x0f)<< 8) | buf[22])+3;
    if (ecmlen + 20 > buflen)
        return;
    er.ecmlen = ecmlen;
    er.srvid = b2i(2, buf+ 8);
    er.caid = b2i(2, buf+10);
    er.prid = b2i(4, buf+12);
    memcpy(er.ecm, buf + 20, er.ecmlen);

    if (!ProcessECM(er.caid,er.ecm,er.cw)) {
        er.rc = E_FOUND;
    } else er.rc = E_NOTFOUND;

    if (er.rc == E_NOTFOUND) {
        buf[0] = 0x08;
        buf[1] = 2;
        memset(buf + 20, 0, buf[1]);
        buf[22] = er.rc; //put rc in byte 22 - hopefully don't break legacy camd3
    } else {
        if (buf[0]==3)
            memmove(buf + 20 + 16, buf + 20 + buf[1], 0x34);
        buf[0]++;
        buf[1] = 16;
        memcpy(buf+20, er.cw, buf[1]);
    }
    camd35_send(buf, 0);
}
Пример #2
0
static void pandora_process_request(struct s_client *cl, uchar *buf, int32_t l) {
	int ecmlen;
	ECM_REQUEST *er;
	uchar md5tmp[MD5_DIGEST_LENGTH];

	if (!(er = get_ecmtask()))
		return;
	er->caid = b2i(2, buf + 1);
	er->srvid = b2i(2, buf + 3);
	er->prid = b2i(4, buf + 5);
	//er->ecmcrc32 = crc32(0L, buf+10, CS_ECMSTORESIZE);
	er->chid = b2i(2, buf + 10 + CS_ECMSTORESIZE);

	if (l > 12 + CS_ECMSTORESIZE + 16) {
		ecmlen = b2i(2, buf + 12 + CS_ECMSTORESIZE);
		if ((ecmlen > 320) || cl->pand_ignore_ecm)
			er->ecmlen = 0;
		else {
			if (!memcmp(buf + 10,
					MD5(buf + 14 + CS_ECMSTORESIZE, ecmlen, md5tmp),
					CS_ECMSTORESIZE)) {
				er->ecmlen = ecmlen;
				memcpy(er->ecm, buf + 14 + CS_ECMSTORESIZE, ecmlen);
				//set_ecmhash(cl, er);
			} else
				er->ecmlen = 0;
		}
	} else
		er->ecmlen = 0;

	if (!er->ecmlen)
		usleep(cl->pand_autodelay);
	get_cw(cl, er);
}
Пример #3
0
static int32_t griffin_card_info(struct s_reader *rdr)
{
	def_resp
	int i, r = 0;
	rdr_log(rdr, "Reading subscription info.");

	griffin_cmd(GRIFFIN_CMD_SUBSCRIPTION_INFO, NULL, 0, 16);

	if(cta_res[0] == 0x0b) // Old cards
	{
		for(i = 0; i < cta_lr - 8; i += 9)
		{
			rdr_log(rdr, " Subscription stream %d - %c%c%c%c%c%c",
					r++, cta_res[i + 2], cta_res[i + 3], cta_res[i + 4],
					cta_res[i + 5], cta_res[i + 6], cta_res[i + 7]);
		}
	}
	else if(cta_res[0] == 0x1b) // Newer cards
	{
		for(i = 0; i < cta_lr; i += 4)
		{
			rdr_log(rdr, " Subscription stream #%02d - 0x%04x",
					r++, b2i(2, cta_res + i + 2));
		}
	}

	rdr_log(rdr, "End subscription info.");
	return OK;
}
Пример #4
0
static void camd33_request_emm(void)
{
	uchar mbuf[20];
	struct s_reader *aureader = NULL, *rdr = NULL;

	//TODO: just take the first reader in list
	LL_ITER itr = ll_iter_create(cur_client()->aureader_list);
	while((rdr = ll_iter_next(&itr)))
	{
		aureader = rdr;
		break;
	}

	if(!aureader) { return; }

	if(aureader->hexserial[0])
	{
		cs_log("%s emm-request sent (reader=%s, caid=%04X, auprovid=%06X)",
			   username(cur_client()), aureader->label, aureader->caid,
			   aureader->auprovid ? aureader->auprovid : b2i(4, aureader->prid[0]));
		mbuf[0] = 0;
		mbuf[1] = aureader->caid >> 8;
		mbuf[2] = aureader->caid & 0xff;
		memcpy(mbuf + 3, aureader->hexserial, 4);
		memcpy(mbuf + 7, &aureader->prid[0][1], 3);
		memcpy(mbuf + 10, &aureader->prid[2][1], 3);
		camd33_send(mbuf, 13);
	}
Пример #5
0
static void ParsePMTData(emu_stream_client_data *cdata)
{
    uint8_t* data = cdata->data;

    uint16_t section_length = SCT_LEN(data);
    int32_t i;
    uint16_t program_info_length = 0, es_info_length = 0;
    uint8_t descriptor_tag = 0, descriptor_length = 0;
    uint8_t stream_type;
    uint16_t stream_pid, caid;

    program_info_length = b2i(2, data+10) &0xFFF;

    if(12+program_info_length >= section_length)
    {
        return;
    }

    for(i=12; i+1 < 12+program_info_length; i+=descriptor_length)
    {
        descriptor_tag = data[i];
        descriptor_length = data[i+1];

        if(descriptor_length < 1)
        {
            break;
        }

        if(i+1+descriptor_length >= 12+program_info_length)
        {
            break;
        }

        if(descriptor_tag == 0x09 && descriptor_length >= 4)
        {
            caid = b2i(2, data+i+2);

            if(caid>>8 == 0x0E)
            {
                cdata->ecm_pid = b2i(2, data+i+4) &0x1FFF;
                cs_log_dbg(D_READER, "[Emu] stream found ecm_pid: %X", cdata->ecm_pid);
                break;
            }
        }
    }
Пример #6
0
static void oscam_ser_process_pmt(uchar *buf, int32_t l)
{
  int32_t i;
  uchar sbuf[32];
  struct s_serial_client *serialdata=cur_client()->serialdata;
  switch(serialdata->connected)
  {
    case P_SSSP:
      serialdata->sssp_fix=0;
      memset(serialdata->sssp_tab, 0, sizeof(serialdata->sssp_tab));
      serialdata->sssp_srvid=b2i(2, buf+3);
      serialdata->sssp_num=0;


      for (i=9; (i<l) && (serialdata->sssp_num<SSSP_MAX_PID); i+=7)
      {
	if(chk_ser_srvid(cur_client(), b2i(2, buf+i), b2i(2, buf+3), b2i(3, buf+i+4))) { // check support for pid (caid, sid and provid in oscam.services)
            memcpy(sbuf+3+(serialdata->sssp_num<<1), buf+i+2, 2);
	    serialdata->sssp_tab[serialdata->sssp_num].caid=b2i(2, buf+i  );
    	    serialdata->sssp_tab[serialdata->sssp_num].pid =b2i(2, buf+i+2);
    	    serialdata->sssp_tab[serialdata->sssp_num].prid=b2i(3, buf+i+4);
    	    serialdata->sssp_num++;
        }
      }
      sbuf[0]=0xF1;
      sbuf[1]=0;
      sbuf[2]=(serialdata->sssp_num<<1);
      oscam_ser_send(cur_client(), sbuf, sbuf[2]+3);
      break;
  }
}
Пример #7
0
static int32_t camd35_recv(uchar *buf, int32_t rs)
{
	int32_t rc = 0, s, n=0, buflen=0, len=0;
	for (s=0; !rc; s++) {
		switch(s) {
			case 0:
				if (rs < 36) {
					rc = -1;
					goto out;
				}
				break;
			case 1:
				switch (camd35_auth_client(buf)) {
					case  0:        break;	// ok
					case  1: rc=-2; break;	// unknown user
				}
				memmove(buf, buf+4, rs-=4);
				break;
			case 2:
				aes_decrypt(&cl_aes_keys, buf, rs);
				if (rs!=boundary(4, rs))
					cs_log_debug("WARNING: packet size has wrong decryption boundary");

				n=(buf[0]==3) ? 0x34 : 0;

				//Fix for ECM request size > 255 (use ecm length field)
				if(buf[0]==0)
					buflen = (((buf[21]&0x0f)<< 8) | buf[22])+3;
				else
					buflen = buf[1];

				n = boundary(4, n+20+buflen);

				cs_log_debug("received %d bytes from client", rs);

				if (n<rs)
					cs_log_debug("ignoring %d bytes of garbage", rs-n);
				else
					if (n>rs) rc=-3;
				break;
			case 3:
				if (crc32(0L, buf+20, buflen)!=b2i(4, buf+4)) rc=-4;
				if (!rc) rc=n;
				break;
		}
	}

out:
	switch(rc) {
		case -2:	cs_log("unknown user");			break;
		case -3:	cs_log("incomplete request!");			break;
		case -4:	cs_log("checksum error (wrong password?)");	break;
	}

	return(rc);
}
Пример #8
0
int32_t emm_reader_match(struct s_reader *reader, uint16_t caid, uint32_t provid) {
	int32_t i;

	// if physical reader a card needs to be inserted
	if (!is_network_reader(reader) && reader->card_status != CARD_INSERTED)
		return 0;

	if (reader->audisabled)
		return 0;

	if (reader->caid != caid) {
		int caid_found = 0;
		for (i = 0; i < 2; i++) {
			if (reader->csystem.caids[i] == caid) {
				caid_found = 1;
				break;
			}
		}
		if (!caid_found) {
			rdr_debug_mask(reader, D_EMM, "reader_caid %04X != caid %04X", reader->caid, caid);
			return 0;
		}
	}

	//if (!hexserialset(reader)) { There are cards without serial, they should get emm of type global and shared!
	//	rdr_debug_mask(reader, D_EMM, "no hexserial is set");
	//	return 0;
	//}

	if (!provid) {
		rdr_debug_mask(reader, D_EMM, "caid %04X has no provider", caid);
		return 1;
	}

	if (reader->auprovid && reader->auprovid == provid) {
		rdr_debug_mask(reader, D_EMM, "matched auprovid %06X", reader->auprovid);
		return 1;
	}

	if (!reader->nprov) {
		rdr_debug_mask(reader, D_EMM, "no provider is set");
		return 1;
	}

	for (i=0; i<reader->nprov; i++) {
		uint32_t prid = b2i(4, reader->prid[i]);
		if (prid == provid || ( (reader->typ == R_CAMD35 || reader->typ == R_CS378X) && (prid & 0xFFFF) == (provid & 0xFFFF) )) {
			rdr_debug_mask(reader, D_EMM, "provider match %04X:%06X", caid, provid);
			return 1;
		}
	}
	rdr_debug_mask(reader, D_EMM, "skip provider %04X:%06X", caid, provid);
	return 0;
}
Пример #9
0
static void _set_pids_status(LLIST *ca_contexts, uint16_t onid, uint16_t tsid, uint16_t sid, uchar *buf, int len)
{
	int8_t offs = 0;
	uint16_t pid = 0;

	while(offs < len)
	{
		pid = b2i(2, buf + offs);
		offs += 2;
		_set_pid_status(ca_contexts, onid, tsid, sid, pid);
	}
}
Пример #10
0
static void camd35_process_ecm(uchar *buf, int buflen){
	ECM_REQUEST er;
	if (!buf || buflen < 23)
		return;
	uint16_t ecmlen = (((buf[21] & 0x0f)<< 8) | buf[22])+3;
	if (ecmlen + 20 > buflen)
		return;
	er.ecmlen = ecmlen;
	er.srvid = b2i(2, buf+ 8);
	er.caid = b2i(2, buf+10);
	er.prid = b2i(4, buf+12);
	er.rc = buf[3];
	
	ProcessECM(er.caid,buf + 20,er.cw);

	if (er.rc == E_STOPPED) {
		buf[0] = 0x08;
		buf[1] = 2;
		buf[20] = 0;
		/*
		* the second Databyte should be forseen for a sleeptime in minutes
		* whoever knows the camd3 protocol related to CMD08 - please help!
		* on tests this don't work with native camd3
		*/
		buf[21] = 0;
	}
	if ((er.rc == E_NOTFOUND) || (er.rc == E_INVALID)) {
		buf[0] = 0x08;
		buf[1] = 2;
		memset(buf + 20, 0, buf[1]);
		buf[22] = er.rc; //put rc in byte 22 - hopefully don't break legacy camd3
	} else {
		if (buf[0]==3)
			memmove(buf + 20 + 16, buf + 20 + buf[1], 0x34);
		buf[0]++;
		buf[1] = 16;
		memcpy(buf+20, er.cw, buf[1]);
	}
	camd35_send(buf, 0);
}
Пример #11
0
static void radegast_process_ecm(uchar *buf, int32_t l)
{
	int32_t i, n, sl;
	ECM_REQUEST *er;
	struct s_client *cl = cur_client();

	if(!(er = get_ecmtask()))
		{ return; }
	for(i = 0; i+1 < l; i += (sl + 2))
	{
		sl = buf[i + 1];
		
		switch(buf[i])
		{
		case  2:      // CAID (upper byte only, oldstyle)
			if(i+2 >= l)
				{ break; }
			er->caid = buf[i + 2] << 8;
			break;
		case 10:      // CAID
			if(i+3 >= l)
				{ break; }
			er->caid = b2i(2, buf + i + 2);
			break;
		case  3:      // ECM DATA
			if(i+4 >= l)
				{ break; }
				
			er->ecmlen = (((buf[i + 1 + 2] & 0x0F) << 8) | buf[i + 2 + 2]) + 3;
			
			if(er->ecmlen < 3 || er->ecmlen > MAX_ECM_SIZE || i+2+er->ecmlen > l)
				{ break; } 
			
			memcpy(er->ecm, buf + i + 2, er->ecmlen);
			break;
		case  6:      // PROVID (ASCII)
			if(i+2+sl > l)
				{ break; }
			n = (sl > 6) ? 3 : (sl >> 1);
			er->prid = cs_atoi((char *) buf + i + 2 + sl - (n << 1), n, 0);
			break;
		case  7:      // KEYNR (ASCII), not needed
			break;
		case  8:      // ECM PROCESS PID ?? don't know, not needed
			break;
		}
	}
	if(l != i)
		{ cs_log("WARNING: ECM-request corrupt"); }
	else
		{ get_cw(cl, er); }
}
Пример #12
0
static void ParsePATData(emu_stream_client_data *cdata)
{
	uint8_t* data = cdata->pat_data;
	uint16_t section_length = SCT_LEN(data);
	uint16_t srvid;
	int32_t i;

	for(i=8; i+7<section_length; i+=4)
	{
		srvid = b2i(2, data+i);
		
		if(srvid == 0)
			{ continue; }
		
		if(cdata->srvid == srvid)
		{
			cdata->pmt_pid = b2i(2, data+i+2) & 0x1FFF;
			cs_log_dbg(D_READER, "stream %i found pmt pid : 0x%04X (%i)",cdata->connid, cdata->pmt_pid, cdata->pmt_pid);
			break;
		}
	}
}
Пример #13
0
static void camd35_process_ecm(uchar *buf, int buflen){
	ECM_REQUEST er;
	if (!buf || buflen < 23)
		return;
	uint16_t ecmlen = (((buf[21] & 0x0f)<< 8) | buf[22])+3;
	if (ecmlen + 20 > buflen)
		return;
	er.ecmlen = ecmlen;
	er.srvid = b2i(2, buf+ 8);
	er.caid = b2i(2, buf+10);
	er.prid = b2i(4, buf+12);
	memcpy(er.ecm, buf + 20, er.ecmlen);
	
	// ========================================================================
	// HANDLE ECM HERE! Following 5 lines are just here for testing!
	// ========================================================================
	cs_log("SRVID: %04X", er.srvid);
	cs_log("CAID: %04X", er.caid);
	cs_log("PRID: %04X", er.prid);
	er.rc = E_FOUND;
	memset(&er.cw, 0x02, sizeof(er.cw));
	
	if (er.rc == E_NOTFOUND){
		buf[0] = 0x08;
		buf[1] = 2;
		memset(buf + 20, 0, buf[1]);
		buf[22] = er.rc; //put rc in byte 22 - hopefully don't break legacy camd3
	} else {
		if (buf[0]==3)
			memmove(buf + 20 + 16, buf + 20 + buf[1], 0x34);
		buf[0]++;
		buf[1] = 16;
		memcpy(buf+20, er.cw, buf[1]);
	}
	camd35_send(buf, 0);
}
Пример #14
0
static void radegast_process_ecm(uchar *buf, int32_t l)
{
  int32_t i, n, sl;
  ECM_REQUEST *er;
  struct s_client *cl = cur_client();

  if (!(er=get_ecmtask()))
    return;
  for (i=0; i<l; i+=(sl+2))
  {
    sl=buf[i+1];
    switch(buf[i])
    {
      case  2:		// CAID (upper byte only, oldstyle)
        er->caid=buf[i+2]<<8;
        break;
      case 10:		// CAID
        er->caid=b2i(2, buf+i+2);
        break;
      case  3:		// ECM DATA
        er->ecmlen = sl;
        memcpy(er->ecm, buf+i+2, er->ecmlen);
        break;
      case  6:		// PROVID (ASCII)
        n=(sl>6) ? 3 : (sl>>1);
        er->prid=cs_atoi((char *) buf+i+2+sl-(n<<1), n, 0);
        break;
      case  7:		// KEYNR (ASCII), not needed
        break;
      case  8:		// ECM PROCESS PID ?? don't know, not needed
        break;
    }
  }
  if (l!=i)
    cs_log("WARNING: ECM-request corrupt");
  else
    get_cw(cl, er);
}
Пример #15
0
uint32_t i2c_ds13x7_read() {
#ifdef CLOCK_DATETIME_SUPPORT
        ds13x7_reg_t rtc;
        struct clock_datetime_t d;
        uint32_t temp_time;

        i2c_ds13x7_get_block(0, (char *)&rtc, sizeof(rtc));
        d.sec     = b2i(rtc.sec);
        d.min     = b2i(rtc.min);
        d.hour    = b2i(rtc.hour);
        d.dow     = rtc.day;
        d.day     = b2i(rtc.date);
        d.month   = b2i(rtc.month&0x1f);
        d.year    = b2i(rtc.year);
        if (rtc.century) d.year+= 100;

        uint8_t cest=0;
#if TIMEZONE == TIMEZONE_CEST
        /* We must determine, if we have CET or CEST */
        int8_t last_sunday = last_sunday_in_month(d.day, d.dow);
        /* march until october can be summer time */
        if (d.month < 3 || d.month > 10) {
                cest=0;
        } else if (d.month == 3 && (last_sunday == -1 || (last_sunday == 0 && d.hour < 1))) {
                cest=0;
        } else if (d.month == 10 && (last_sunday == 1 || (last_sunday == 0 && d.hour > 1))) {
                cest=0;
        } else {
                cest=1;
        }
#endif
        temp_time = clock_utc2timestamp(&d,cest);
        return temp_time;
#else
	return 0;
#endif /* CLOCK_DATETIME_SUPPORT */

}
Пример #16
0
static int32_t oscam_ser_check_ecm(ECM_REQUEST *er, uchar *buf, int32_t l)
{
  int32_t i;
  struct s_serial_client *serialdata = cur_client()->serialdata;

  if (l<16)
  {
    cs_log(incomplete, l);
    return(1);
  }

  switch(serialdata->connected)
  {
    case P_HSIC:
      er->ecmlen = l-12;
      er->caid = b2i(2, buf+1 );
      er->prid = b2i(3, buf+3 );
      er->pid  = b2i(2, buf+6 );
      er->srvid= b2i(2, buf+10);
      memcpy(er->ecm, buf+12, er->ecmlen);
      break;
    case P_SSSP:
      er->pid=b2i(2, buf+3);
      for (i=0; (i<8) && (serialdata->sssp_tab[i].pid!=er->pid); i++);
      if (i>=serialdata->sssp_num)
      {
        cs_debug_mask(D_CLIENT, "illegal request, unknown pid=%04X", er->pid);
        return(2);
      }
      er->ecmlen = l-5;
      er->srvid= serialdata->sssp_srvid;
      er->caid = serialdata->sssp_tab[i].caid;
      er->prid = serialdata->sssp_tab[i].prid;
      memcpy(er->ecm, buf+5, er->ecmlen);
      break;
    case P_BOMBA:
      er->ecmlen = l;
      memcpy(er->ecm, buf, er->ecmlen);
      break;
    case P_DSR95:
      buf[l]='\0';	// prepare for trim
      trim((char *)buf+13);	// strip spc, nl, cr ...
      er->ecmlen = strlen((char *)buf+13)>>1;
      er->prid=cs_atoi((char *)buf+3, 3, 0);	// ignore errors
      er->caid=cs_atoi((char *)buf+9, 2, 0);	// ignore errors
      if (cs_atob(er->ecm, (char *)buf+13, er->ecmlen)<0)
      {
        cs_log("illegal characters in ecm-request");
        return(1);
      }
      if( serialdata->dsr9500type==P_DSR_WITHSID )
      {
        er->ecmlen -= 2;
        er->srvid=cs_atoi((char *)buf+13+(er->ecmlen << 1), 2, 0);
      }
      break;
    case P_GS:
      er->ecmlen = ((buf[3]<<8)|buf[2]) - 6;
      er->srvid =  (buf[5]<<8)|buf[4]; // sid
      er->caid  =  (buf[7]<<8)|buf[6];
      er->prid  = 0;
      if (er->ecmlen > 256) er->ecmlen = 256;
      memcpy(er->ecm, buf+10, er->ecmlen);
      break;
    case P_ALPHA:
      l=oscam_ser_alpha_convert(buf, l);
      er->ecmlen= b2i(2, buf+1 )-2;
      er->caid  = b2i(2, buf+3 );
      if ((er->ecmlen!=l-5) || (er->ecmlen>257))
      {
        cs_log(incomplete, l);
        return(1);
      }
      memcpy(er->ecm, buf+5, er->ecmlen);
      break;
    case P_GBOX:
      er->srvid = b2i(2, buf+serialdata->gbox_lens.cat_len+3+3);
      er->ecmlen = serialdata->gbox_lens.ecm_len+3;
      memcpy(er->ecm, buf+serialdata->gbox_lens.cat_len+3+serialdata->gbox_lens.pmt_len+3, er->ecmlen);
      break;
  }
  return(0);
}
Пример #17
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;
}
Пример #18
0
static void sha256_transform(sha256_context *ctx)
{
  uint32 W[64]; // Words of message schedule.
  uint32 v[8];  // FIPS a, b, c, d, e, f, g, h working variables.

  if (ctx == NULL) // Clean variables and return.
  {
    cleandata(v,sizeof(v));
    cleandata(W,sizeof(W));
    return;
  }

  // Prepare message schedule. Loop unrolling provides some small gain here.
  W[0] =  b2i(ctx->Data + 0 * 4 );   W[1] =  b2i(ctx->Data + 1 * 4 );
  W[2] =  b2i(ctx->Data + 2 * 4 );   W[3] =  b2i(ctx->Data + 3 * 4 );
  W[4] =  b2i(ctx->Data + 4 * 4 );   W[5] =  b2i(ctx->Data + 5 * 4 );
  W[6] =  b2i(ctx->Data + 6 * 4 );   W[7] =  b2i(ctx->Data + 7 * 4 );
  W[8] =  b2i(ctx->Data + 8 * 4 );   W[9] =  b2i(ctx->Data + 9 * 4 );
  W[10] = b2i(ctx->Data + 10 * 4 );  W[11] = b2i(ctx->Data + 11 * 4 );
  W[12] = b2i(ctx->Data + 12 * 4 );  W[13] = b2i(ctx->Data + 13 * 4 );
  W[14] = b2i(ctx->Data + 14 * 4 );  W[15] = b2i(ctx->Data + 15 * 4 );

  for (uint I = 16; I < 64; I++)
    W[I] = sg1(W[I-2]) + W[I-7] + sg0(W[I-15]) + W[I-16];

  uint32 *H=ctx->H;
  for (uint I = 0; I < 8; I++)
    v[I]=H[I];

  // MSVC -O2 partially unrolls this loop automatically.
  for (uint I = 0; I < 64; I++)
  {
    uint T1 = v[7] + Sg1(v[4]) + Ch(v[4], v[5], v[6]) + K[I] + W[I];

    // It is possible to eliminate variable copying if we unroll loop
    // and rename variables every time. But my test did not show any speed
    // gain on i7 for such full or partial unrolling.
    v[7] = v[6];
    v[6] = v[5];
    v[5] = v[4];
    v[4] = v[3] + T1;

    // It works a little faster when moved here from beginning of loop.
    uint T2 = Sg0(v[0]) + Maj(v[0], v[1], v[2]);

    v[3] = v[2];
    v[2] = v[1];
    v[1] = v[0];
    v[0] = T1 + T2;
  }

  for (uint I = 0; I < 8; I++)
    H[I]+=v[I];
}
Пример #19
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;
}
Пример #20
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;
}
Пример #21
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);
}
Пример #22
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;
}
Пример #23
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;
}
Пример #24
0
void cc_cacheex_filter_in(struct s_client *cl, uchar *buf)
{
	struct s_reader *rdr = (cl->typ == 'c') ? NULL : cl->reader;
	int i = 0, j;
	CECSPVALUETAB *filter;

	//mode==2 write filters to acc
	if(cl->typ == 'c' && cl->account && cl->account->cacheex.mode == 2
		&& cl->account->cacheex.allow_filter == 1)
	{
		filter = &cl->account->cacheex.filter_caidtab;
	}
	//mode==3 write filters to rdr
	else if(rdr && rdr->cacheex.mode == 3 && rdr->cacheex.allow_filter == 1)
	{
		filter = &rdr->cacheex.filter_caidtab;
	}
	else {
		return;
	}

	filter->n = b2i(2, buf + i);
	i += 2;

	int32_t max_filters = 30;
	for(j=0; j<max_filters; j++)
	{
		if(j<CS_MAXCAIDTAB)
		{
			filter->caid[j] = b2i(4, buf + i);
		}
		i += 4;
	}

	for(j=0; j<max_filters && j<CS_MAXCAIDTAB; j++)
	{
		if(j<CS_MAXCAIDTAB)
		{
			filter->cmask[j] = b2i(4, buf + i);
		}
		i += 4;
	}

	for(j=0; j<max_filters && j<CS_MAXCAIDTAB; j++)
	{
		if(j<CS_MAXCAIDTAB)
		{
			filter->prid[j] = b2i(4, buf + i);
		}
		i += 4;
	}

	for(j=0; j<max_filters && j<CS_MAXCAIDTAB; j++)
	{
		if(j<CS_MAXCAIDTAB)
		{
			filter->srvid[j] = b2i(4, buf + i);
		}
		i += 4;
	}

	cs_log_dbg(D_CACHEEX, "cacheex: received push filter request from %s", username(cl));
}
Пример #25
0
void cc_cacheex_push_in(struct s_client *cl, uchar *buf)
{
	struct cc_data *cc = cl->cc;
	ECM_REQUEST *er;
	if(!cc) { return; }

	if(cl->reader)
		{ cl->reader->last_s = cl->reader->last_g = time((time_t *)0); }
	if(cl) { cl->last = time(NULL); }

	int8_t rc = buf[14];
	if(rc != E_FOUND && rc != E_UNHANDLED)  //Maybe later we could support other rcs
		{ return; }
	uint16_t size = buf[12] | (buf[13] << 8);
	if(size != sizeof(er->ecmd5) + sizeof(er->csp_hash) + sizeof(er->cw))
	{
		cs_log_dbg(D_CACHEEX, "cacheex: %s received old cash-push format! data ignored!", username(cl));
		return;
	}
	if(!(er = get_ecmtask()))
		{ return; }

	er->caid = b2i(2, buf + 0);
	er->prid = b2i(4, buf + 2);
	er->srvid = b2i(2, buf + 10);
	er->ecm[0] = buf[19]!=0x80 && buf[19]!=0x81 ? 0 : buf[19]; //odd/even byte, usefull to send it over CSP and to check cw for swapping
	er->rc = rc;

	er->ecmlen = 0;

	if(buf[18])
	{
		if(buf[18] & (0x01 << 7))
		{
			er->cwc_cycletime = (buf[18] & 0x7F); // remove bit 8 to get cycletime
			er->cwc_next_cw_cycle = 1;
		}
		else
		{
			er->cwc_cycletime = buf[18];
			er->cwc_next_cw_cycle = 0;
		}
	}

	if (er->cwc_cycletime && er->cwc_next_cw_cycle < 2)
	{
		if(cl->typ == 'c' && cl->account && cl->account->cacheex.mode)
			{ cl->account->cwc_info++; }
		else if((cl->typ == 'p' || cl->typ == 'r') && (cl->reader && cl->reader->cacheex.mode))
			{ cl->cwc_info++; }
		cs_log_dbg(D_CWC, "CWC (CE) received from %s cycletime: %isek - nextcwcycle: CW%i for %04X@%06X:%04X", username(cl), er->cwc_cycletime, er->cwc_next_cw_cycle, er->caid, er->prid, er->srvid);
	}

	uint8_t *ofs = buf + 20;

	//Read ecmd5
	memcpy(er->ecmd5, ofs, sizeof(er->ecmd5)); //16
	ofs += sizeof(er->ecmd5);

	if(!check_cacheex_filter(cl, er))
		{ return; }

	//Read csp_hash:
	er->csp_hash = ntohl(b2i(4, ofs));
	ofs += 4;

	//Read cw:
	memcpy(er->cw, ofs, sizeof(er->cw)); //16
	ofs += sizeof(er->cw);

	//Read lastnode count:
	uint8_t count = *ofs;
	ofs++;

	//check max nodes:
	if(count > cacheex_maxhop(cl))
	{
			cs_log_dbg(D_CACHEEX, "cacheex: received %d nodes (max=%d), ignored! %s", (int32_t)count, cacheex_maxhop(cl), username(cl));
		NULLFREE(er);
		return;
	}
	cs_log_dbg(D_CACHEEX, "cacheex: received %d nodes %s", (int32_t)count, username(cl));
	//Read lastnodes:
	uint8_t *data;
	if (er){
		er->csp_lastnodes = ll_create("csp_lastnodes");
	}
	while(count)
	{
		if(!cs_malloc(&data, 8))
			{ break; }
		memcpy(data, ofs, 8);
		ofs += 8;
		ll_append(er->csp_lastnodes, data);
		count--;
		cs_log_dbg(D_CACHEEX, "cacheex: received node %" PRIu64 "X %s", cacheex_node_id(data), username(cl));
	}

	//for compatibility: add peer node if no node received:
	if(!ll_count(er->csp_lastnodes))
	{
		if(!cs_malloc(&data, 8))
			{ return; }
		memcpy(data, cc->peer_node_id, 8);
		ll_append(er->csp_lastnodes, data);
		cs_log_dbg(D_CACHEEX, "cacheex: added missing remote node id %" PRIu64 "X", cacheex_node_id(data));
	}

	cacheex_add_to_cache(cl, er);
}
Пример #26
0
static int32_t camd35_recv(struct s_client *client, uchar *buf, int32_t l)
{
	int32_t rc, s, rs, n = 0, buflen = 0, len = 0;
	for(rc = rs = s = 0; !rc; s++)
	{
		switch(s)
		{
		case 0:
			if(!client->udp_fd) { return (-9); }
			if(client->is_udp && client->typ == 'c')
			{
				rs = recv_from_udpipe(buf);
			}
			else
			{
				//read minimum packet size (4 byte ucrc + 32 byte data) to detect packet size (tcp only)

				//rs = cs_recv(client->udp_fd, buf, client->is_udp ? l : 36, 0);
				if(client->is_udp){
					while (1){
					rs = cs_recv(client->udp_fd, buf, l, 0);
						if (rs < 0){
							if(errno == EINTR) { continue; }  // try again in case of interrupt
							if(errno == EAGAIN) { continue; }  //EAGAIN needs select procedure again
							cs_log_dbg(client->typ == 'c' ? D_CLIENT : D_READER, "ERROR: %s (errno=%d %s)", __func__, errno, strerror(errno));
							break;
						}else {break;}
					}
				}else{
					int32_t tot=36, readed=0;
					rs = 0;
					do
					{
						readed = cs_recv(client->udp_fd, buf+rs, tot, 0);
						if (readed < 0){
							if(errno == EINTR) { continue; }  // try again in case of interrupt
							if(errno == EAGAIN) { continue; }  //EAGAIN needs select procedure again
							cs_log_dbg(client->typ == 'c' ? D_CLIENT : D_READER, "ERROR: %s (errno=%d %s)", __func__, errno, strerror(errno));
							break;
						}
						if (readed == 0){ // nothing to read left!
							rc = -5;
							break;
						}
						if (readed > 0){ // received something, add it!
							tot-=readed;
						rs+=readed;
						}
					}
					while(tot!=0);
				}

			}
			if(rs < 36)
			{	
				if(rc != -5)
					{ rc = -1; }
				goto out;
			}
			break;
		case 1:
			switch(camd35_auth_client(client, buf))
			{
			case  0:
				break;  // ok
			case  1:
				rc = -2;
				break; // unknown user
			default:
				rc = -9;
				break; // error's from cs_auth()
			}
			memmove(buf, buf + 4, rs -= 4);
			break;
		case 2:
			aes_decrypt(client->aes_keys, buf, rs);
			if(rs != boundary(4, rs))
				cs_log_dbg(client->typ == 'c' ? D_CLIENT : D_READER,
							  "WARNING: packet size has wrong decryption boundary");

			n = (buf[0] == 3) ? 0x34 : 0;

			//Fix for ECM request size > 255 (use ecm length field)
			if(buf[0] == 0)
				{ buflen = (((buf[21] & 0x0f) << 8) | buf[22]) + 3; }
			else if(buf[0] == 0x3d || buf[0] == 0x3e || buf[0] == 0x3f)  //cacheex-push
				{ buflen = buf[1] | (buf[2] << 8); }
			else
				{ buflen = buf[1]; }

			n = boundary(4, n + 20 + buflen);
			if(!(client->is_udp && client->typ == 'c') && (rs < n) && ((n - 32) > 0))
			{

				//len = cs_recv(client->udp_fd, buf+32, n-32, 0); // read the rest of the packet
				int32_t tot=n-32, readed=0;
				len = 0;
				do{
					readed = cs_recv(client->udp_fd, buf+32+len, tot, 0); // read the rest of the packet
					if (readed < 0){
						if(errno == EINTR) { continue; }  // try again in case of interrupt
						if(errno == EAGAIN) { continue; }  //EAGAIN needs select procedure again
						cs_log_dbg(client->typ == 'c' ? D_CLIENT : D_READER, "ERROR: %s (errno=%d %s)", __func__, errno, strerror(errno));
						break;
					}
					if (readed == 0){ // nothing to read left!
						break;
					}
					if (readed > 0){ // received something, add it!
					tot-=readed;
					len+=readed;
					}
				}
				while(tot!=0);


				if(len > 0)
				{
					rs += len;
					aes_decrypt(client->aes_keys, buf + 32, len);
				}
				if(len < 0)
				{
					rc = -1;
					goto out;
				}
			}

			cs_log_dump_dbg(client->typ == 'c' ? D_CLIENT : D_READER,
						  buf, rs, "received %d bytes from %s", rs, remote_txt());

			if(n < rs)
				cs_log_dbg(client->typ == 'c' ? D_CLIENT : D_READER,
							  "ignoring %d bytes of garbage", rs - n);
			else if(n > rs) { rc = -3; }
			break;
		case 3:
			if(crc32(0L, buf + 20, buflen) != b2i(4, buf + 4)) { rc = -4; }
			if(!rc) { rc = n; }
			break;
		}
	}

out:
	if((rs > 0) && ((rc == -1) || (rc == -2)))
	{
		cs_log_dump_dbg(client->typ == 'c' ? D_CLIENT : D_READER, buf, rs,
					  "received %d bytes from %s (native)", rs, remote_txt());
	}
	if(rc >= 0) { client->last = time(NULL); }  // last client action is now
	switch(rc)
	{
		//case 0:   break;
	case -1:
		cs_log("packet is too small (received %d bytes, expected %d bytes)", rs, l);
		break;
	case -2:
		if(cs_auth_client(client, 0, "unknown user"))
			{ cs_disconnect_client(client); }
		break;
	case -3:
		cs_log("incomplete request !");
		break;
	case -4:
		cs_log("checksum error (wrong password ?)");
		break;
	case -5:
		cs_log_dbg(client->typ == 'c' ? D_CLIENT : D_READER, "connection closed");
		break;		
		//default:  cs_log_dbg(D_TRACE, "camd35_recv returns rc=%d", rc); break;
	}

	return (rc);
}
Пример #27
0
void log_emm_request(struct s_reader *rdr){
	cs_log("%s emm-request sent (reader=%s, caid=%04X, auprovid=%06X)",
			username(cur_client()), rdr->label, rdr->caid,
			rdr->auprovid ? rdr->auprovid : b2i(4, rdr->prid[0]));
}
Пример #28
0
static void camd35_request_emm(ECM_REQUEST *er)
{
	int32_t i;
	time_t now;
	uchar mbuf[1024];
	struct s_client *cl = cur_client();
	struct s_reader *aureader = NULL, *rdr = NULL;

	if(er->selected_reader && !er->selected_reader->audisabled && ll_contains(cl->aureader_list, er->selected_reader))
		{ aureader = er->selected_reader; }

	if(!aureader && cl->aureader_list)
	{
		LL_ITER itr = ll_iter_create(cl->aureader_list);
		while((rdr = ll_iter_next(&itr)))
		{
			if(emm_reader_match(rdr, er->caid, er->prid))
			{
				aureader = rdr;
				break;
			}
		}
	}

	if(!aureader)
		{ return; }  // TODO

	uint16_t au_caid = aureader->caid;

	if(!au_caid && caid_is_bulcrypt(er->caid)) // Bulcrypt has 2 caids and aureader->caid can't be used. Use ECM_REQUEST caid for AU.
		{ au_caid = er->caid; }

	time(&now);
	if(!memcmp(cl->lastserial, aureader->hexserial, 8))
		if(llabs(now - cl->last) < 180) { return; }

	memcpy(cl->lastserial, aureader->hexserial, 8);
	cl->last = now;

	if(au_caid)
	{
		cl->disable_counter = 0;
		cs_log("%s emm-request sent (reader=%s, caid=%04X, auprovid=%06X)",
			   username(cur_client()), aureader->label, au_caid,
			   aureader->auprovid ? aureader->auprovid : b2i(4, aureader->prid[0]));
	}
	else if(cl->disable_counter > 2)
		{ return; }
	else
		{ cl->disable_counter++; }

	memset(mbuf, 0, sizeof(mbuf));
	mbuf[2] = mbuf[3] = 0xff;           // must not be zero
	i2b_buf(2, er->srvid, mbuf + 8);

	//override request provid with auprovid if set in CMD05
	if(aureader->auprovid)
	{
		if(aureader->auprovid != er->prid)
			{ i2b_buf(4, aureader->auprovid, mbuf + 12); }
		else
			{ i2b_buf(4, er->prid, mbuf + 12); }
	}
	else
	{
		i2b_buf(4, er->prid, mbuf + 12);
	}

	i2b_buf(2, er->pid, mbuf + 16);
	mbuf[0] = 5;
	mbuf[1] = 111;
	if(au_caid)
	{
		mbuf[39] = 1;                           // no. caids
		mbuf[20] = au_caid >> 8;        // caid's (max 8)
		mbuf[21] = au_caid & 0xff;
		memcpy(mbuf + 40, aureader->hexserial, 6);  // serial now 6 bytes
		mbuf[47] = aureader->nprov;
		for(i = 0; i < aureader->nprov; i++)
		{
			if((au_caid >= 0x1700 && au_caid <= 0x1799)  ||  // Betacrypt
					(au_caid >= 0x0600 && au_caid <= 0x0699))    // Irdeto (don't know if this is correct, cause I don't own a IRDETO-Card)
			{
				mbuf[48 + (i * 5)] = aureader->prid[i][0];
				memcpy(&mbuf[50 + (i * 5)], &aureader->prid[i][1], 3);
			}
			else
			{
				mbuf[48 + (i * 5)] = aureader->prid[i][2];
				mbuf[49 + (i * 5)] = aureader->prid[i][3];
				memcpy(&mbuf[50 + (i * 5)], &aureader->sa[i][0], 4); // for conax we need at least 4 Bytes
			}
		}
		//we think client/server protocols should deliver all information, and only readers should discard EMM
		mbuf[128] = (aureader->blockemm & EMM_GLOBAL && !(aureader->saveemm & EMM_GLOBAL)) ? 0 : 1;
		mbuf[129] = (aureader->blockemm & EMM_SHARED && !(aureader->saveemm & EMM_SHARED)) ? 0 : 1;
		mbuf[130] = (aureader->blockemm & EMM_UNIQUE && !(aureader->saveemm & EMM_UNIQUE)) ? 0 : 1;
		mbuf[127] = (aureader->blockemm & EMM_UNKNOWN && !(aureader->saveemm & EMM_UNKNOWN)) ? 0 : 1;
	}
	else        // disable emm
		{ mbuf[20] = mbuf[39] = mbuf[40] = mbuf[47] = mbuf[49] = 1; }
Пример #29
0
static int32_t dre_do_ecm(struct s_reader *reader, const ECM_REQUEST *er, struct s_ecm_answer *ea)
{
	def_resp;
	uint16_t overcryptId;
	uint8_t tmp[16];
	char tmp_dbg[256];
	struct dre_data *csystem_data = reader->csystem_data;
	if(reader->caid == 0x4ae0)
	{
		uchar ecmcmd41[] = { 0x41,
							 0x58, 0x1f, 0x00,     //fixed part, dont change
							 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,   //0x01 - 0x08: next key
							 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,   //0x11 - 0x18: current key
							 0x3b, 0x59, 0x11      //0x3b = keynumber, can be a value 56 ;; 0x59 number of package = 58+1 - Pay Package ;; 0x11 = provider
						   };
		ecmcmd41[22] = csystem_data->provider;
		memcpy(ecmcmd41 + 4, er->ecm + 8, 16);
		ecmcmd41[20] = er->ecm[6];  //keynumber
		ecmcmd41[21] = 0x58 + er->ecm[25];  //package number
		rdr_log_dbg(reader, D_READER, "unused ECM info front:%s", cs_hexdump(0, er->ecm, 8, tmp_dbg, sizeof(tmp_dbg)));
		rdr_log_dbg(reader, D_READER, "unused ECM info back:%s", cs_hexdump(0, er->ecm + 24, er->ecm[2] + 2 - 24, tmp_dbg, sizeof(tmp_dbg)));
		if((dre_cmd(ecmcmd41)))     //ecm request
		{
			if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
				{ return ERROR; }       //exit if response is not 90 00
			memcpy(ea->cw, cta_res + 11, 8);
			memcpy(ea->cw + 8, cta_res + 3, 8);

			return OK;
		}
	}

    else if(reader->caid == 0x4ae1)
    {
        if(csystem_data->provider == 0x11 || csystem_data->provider == 0x14)
        {
            uchar ecmcmd51[] = { 0x51, 0x02, 0x56, 0x05, 0x00, 0x4A, 0xE3,  //fixed header?
                                 0x9C, 0xDA,       //first three nibbles count up, fourth nibble counts down; all ECMs sent twice
                                 0xC1, 0x71, 0x21, 0x06, 0xF0, 0x14, 0xA7, 0x0E,   //next key?
                                 0x89, 0xDA, 0xC9, 0xD7, 0xFD, 0xB9, 0x06, 0xFD,   //current key?
                                 0xD5, 0x1E, 0x2A, 0xA3, 0xB5, 0xA0, 0x82, 0x11,   //key or signature?
                                 0x14          //provider
                               };
            memcpy(ecmcmd51 + 1, er->ecm + 5, 0x21);
            rdr_log_dbg(reader, D_READER, "unused ECM info front:%s", cs_hexdump(0, er->ecm, 5, tmp_dbg, sizeof(tmp_dbg)));
            rdr_log_dbg(reader, D_READER, "unused ECM info back:%s", cs_hexdump(0, er->ecm + 37, 4, tmp_dbg, sizeof(tmp_dbg)));
            ecmcmd51[33] = csystem_data->provider;  //no part of sig

            if((dre_cmd(ecmcmd51)))     //ecm request
            {
                if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
                    { return ERROR; }       //exit if response is not 90 00

                if(er->ecm[2] >= 46 && er->ecm[43] == 1 && csystem_data->provider == 0x11)
                {
                    memcpy(tmp, cta_res + 11, 8);
                    memcpy(tmp + 8, cta_res + 3, 8);
                    overcryptId = b2i(2, &er->ecm[44]);
                    rdr_log_dbg(reader, D_READER, "ICG ID: %04X", overcryptId);
                    Drecrypt2OverCW(overcryptId,tmp);
                    if(isValidDCW(tmp))
                    {
                        memcpy(ea->cw, tmp, 16);
                        return OK;
                    }
                    return ERROR;
                }

                DREover(reader, er->ecm, cta_res + 3);

                if(isValidDCW(cta_res + 3))
                {
                    memcpy(ea->cw, cta_res + 11, 8);
                    memcpy(ea->cw + 8, cta_res + 3, 8);
                    return OK;
                }
            }
        }
        else if((csystem_data->provider == 0x02 || csystem_data->provider == 0x03) && er->ecm[3] == 3)
        {
            // DRE 3

            if (er->ecm[4] == 2)
            {
                memcpy( ea->cw   , &er->ecm[42], 8);
                memcpy(&ea->cw[8], &er->ecm[34], 8);
                return OK;
            }

            uchar cmdlen;
            uchar crypted = er->ecm[8] & 1;
            uchar cryptkey = (er->ecm[8] & 6) >> 1;

            if (crypted == 0)
            {
                cmdlen = 50;
            }
            else
            {
                cmdlen = 57;
            }

            uchar ecmcmd[cmdlen];

            memcpy(ecmcmd, &er->ecm[17], cmdlen-1);
            ecmcmd[cmdlen-1] = csystem_data->provider;

            dre_cmd_c(ecmcmd, crypted, cryptkey);

            if(cta_res[2] == 0xD2 && isValidDCW(cta_res + 3))
            {
                memcpy(ea->cw, cta_res+11, 8);
                memcpy(ea->cw+8, cta_res+3, 8);
                return OK;
            }
        }
    }
    else if(reader->caid == 0x2710 && er->ecm[3] == 4)
Пример #30
0
static int32_t camd35_recv(uint8_t *buf, int32_t rs)
{
	int32_t rc, s, n = 0, buflen = 0;
	for(rc = s = 0; !rc; s++)
	{
		switch(s)
		{
		case 0:
			if(rs < 36)
			{
				rc = -1;
				goto out;
			}
			break;
		case 1:
			switch(camd35_auth_client(buf))
			{
			case  0:
				break;  // ok
			case  1:
				rc = -2;
				break; // unknown user
			default:
				rc = -9;
				break; // error's from cs_auth()
			}
			memmove(buf, buf + 4, rs -= 4);
			break;
		case 2:
			aes_decrypt(&cl_aes_keys, buf, rs);
			if(rs != boundary(4, rs))
			{ cs_log_dbg(0, "WARNING: packet size has wrong decryption boundary"); }

			n = (buf[0] == 3) ? 0x34 : 0;

			//Fix for ECM request size > 255 (use ecm length field)
			if(buf[0] == 0)
			{ buflen = (((buf[21] & 0x0f) << 8) | buf[22]) + 3; }
			else if(buf[0] == 0x3d || buf[0] == 0x3e || buf[0] == 0x3f)  //cacheex-push
			{ buflen = buf[1] | (buf[2] << 8); }
			else
			{ buflen = buf[1]; }

			n = boundary(4, n + 20 + buflen);

			cs_log_dbg(0, "received %d bytes from client", rs);

			if(n < rs)
			{ cs_log_dbg(0, "ignoring %d bytes of garbage", rs - n); }
			else if(n > rs) { rc = -3; }
			break;
		case 3:
			if(crc32(0, buf + 20, buflen) != b2i(4, buf + 4)) {
				rc = -4;
				cs_log_dump_dbg(buf, rs, "camd35 checksum failed for packet: ");
				cs_log_dbg(0, "checksum: %X", b2i(4, buf+4));
			}
			if(!rc) { rc = n; }
			break;
		}
	}

out:
	if((rs > 0) && ((rc == -1) || (rc == -2)))
	{
		cs_log_dbg(0, "received %d bytes from client (native)", rs);
	}
	switch(rc)
	{
	case -1:
		cs_log("packet is too small (received %d bytes, expected at least 36 bytes)", rs);
		break;
	case -2:
		cs_log("unknown user");
		break;
	case -3:
		cs_log("incomplete request !");
		break;
	case -4:
		cs_log("checksum error (wrong password ?)");
		break;
	}

	return (rc);
}