Пример #1
0
static int32_t griffin_get_emm_type(EMM_PACKET *ep, struct s_reader *rdr)
{
	memcpy(ep->hexserial, ep->emm + 3, 4);
	switch(ep->emm[0])
	{
		case 0x82:
		case 0x83:
			if(memcmp(ep->hexserial, rdr->sa[0], 4) == 0)
			{
				if(DEBUG)
				{
					rdr_log_sensitive(rdr, "SHARED EMM TYPE:%02X SA:{%02X %02X %02X %02X}",
									ep->emm[0], ep->emm[3], ep->emm[4], ep->emm[5], ep->emm[6]);
				}
				ep->type = SHARED;
			}
			if(memcmp(ep->hexserial, rdr->sa[1], 4) == 0)
			{
				if(DEBUG)
				{
					rdr_log_sensitive(rdr, "UNIQUE EMM TYPE:%02X SA:{%02X %02X %02X %02X}",
									ep->emm[0], ep->emm[3], ep->emm[4], ep->emm[5], ep->emm[6]);
				}
				ep->type = UNIQUE;
			}
			break;

		default:
			ep->type = UNKNOWN;
			rdr_log_dbg(rdr, D_EMM, "UNKNOWN EMM TYPE:%02X SA:%02X %02X %02X %02X",
						ep->emm[0], ep->emm[3], ep->emm[4], ep->emm[5], ep->emm[6]);
	}
	return OK;
}
Пример #2
0
static int32_t bulcrypt_get_emm_type(EMM_PACKET *ep, struct s_reader *reader)
{
	char dump_emm_sn[64];
	int32_t emm_len = check_sct_len(ep->emm, 3);

	memset(ep->hexserial, 0, 8);

	if (emm_len < 176)
	{
		rdr_debug_mask(reader, D_TRACE | D_EMM, "emm_len < 176 (%u): %s",
			emm_len, cs_hexdump(1, ep->emm, 12, dump_emm_sn, sizeof(dump_emm_sn)));
		ep->type = UNKNOWN;
		return 0;
	}

	uint8_t mask_last = 0x00;
	ep->type = UNKNOWN;
	switch (ep->emm[0]) {
	case BULCRYPT_EMM_UNIQUE_82: ep->type = UNIQUE; mask_last = 0xF0; break; // Bulsatcom
	case BULCRYPT_EMM_UNIQUE_8a: ep->type = UNIQUE; mask_last = 0xF0; break; // Polaris
	case BULCRYPT_EMM_UNIQUE_85: ep->type = UNIQUE; mask_last = 0x00; break; // Bulsatcom
	case BULCRYPT_EMM_UNIQUE_8b: ep->type = UNIQUE; mask_last = 0x00; break; // Polaris
	case BULCRYPT_EMM_SHARED_84: ep->type = SHARED; break;
	}

	bool ret = false;
	if (ep->type == UNIQUE) {
		// The serial numbers looks like this:
		//   aa bb cc dd
		// To match EMM_82 and EMM_8a serial we compare (mask_last == 0xf0):
		//   aa bb cc d-
		// To match EMM_85 and EMM_8b serial we compare (mask_last == 0x00):
		//   aa bb cc --
		memcpy(ep->hexserial, ep->emm + 3, 4);
		ret = reader->hexserial[0] == ep->hexserial[0] &&
			  reader->hexserial[1] == ep->hexserial[1] &&
			  reader->hexserial[2] == ep->hexserial[2] &&
			  ((reader->hexserial[3] & mask_last) == (ep->hexserial[3] & mask_last));
	} else if (ep->type == SHARED) {
		// To match EMM_84
		//   aa bb -- --
		memcpy(ep->hexserial, ep->emm + 3, 2);
		ret = reader->hexserial[0] == ep->hexserial[0] &&
			  reader->hexserial[1] == ep->hexserial[1];
	}

	if (ret) {
		char dump_card_sn[64];
		cs_hexdump(1, reader->hexserial, 4, dump_card_sn, sizeof(dump_card_sn));
		cs_hexdump(1, ep->hexserial, 4, dump_emm_sn, sizeof(dump_emm_sn));
		rdr_log_sensitive(reader, "EMM_%s-%02x, emm_sn = {%s}, card_sn = {%s}",
			ep->type == UNIQUE ? "UNIQUE" :
			ep->type == SHARED ? "SHARED" : "??????",
			ep->emm[0],
			dump_emm_sn,
			dump_card_sn);
	}

	return ret;
}
Пример #3
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;
}
Пример #4
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;
}
Пример #5
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;
}
Пример #6
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;
}
Пример #7
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;
}
Пример #8
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;
}
Пример #9
0
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
    int32_t i;
    char *card;
    char tmp[9];

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

    reader->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 0x11:
        card = "Tricolor Centr";
        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 / Platforma HD new";
        reader->caid = 0x4ae1;
        break;			//59 type card
    case 0x15:
        card = "Platforma HD / DW old";
        reader->caid = 0x4ae1;
        break;			//59 type card
    default:
        card = "Unknown";
        reader->caid = 0x4ae1;
        break;
    }

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

    static const uchar cmd30[] =
    {   0x30, 0x81, 0x00, 0x81, 0x82, 0x03, 0x84, 0x05, 0x06, 0x87, 0x08, 0x09, 0x00, 0x81, 0x82, 0x03, 0x84, 0x05,
        0x00
    };
    dre_cmd (cmd30);		//unknown command, generates error on card 0x11 and 0x14
    /*
    response:
    59 03 E2 E3
    FE 48 */

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

    providers[1] = reader->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] = reader->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

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

    int32_t low_dre_id = ((cta_res[4] << 16) | (cta_res[5] << 8) | cta_res[6]) - 48608;
    int32_t dre_chksum = 0;
    uchar buf[32];
    snprintf ((char *)buf, sizeof(buf), "%i%i%08i", reader->provider - 16, major_version + 1, 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%i%i%08i, geocode %i, card: %s v%i.%i",
             reader->caid, cs_hexdump(0, reader->hexserial + 2, 4, tmp, sizeof(tmp)), dre_chksum, reader->provider - 16,
             major_version + 1, 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;

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

    rdr_log(reader, "ready for requests");
    return OK;
}
Пример #10
0
static int32_t bulcrypt_get_emm_type(EMM_PACKET *ep, struct s_reader *reader)
{
	char dump_emm_sn[64], dump_card_sn[64];
	unsigned int emm_len = check_sct_len(ep->emm, 3);
	int32_t ret = FALSE;

	memset(ep->hexserial, 0, 8);

	if (emm_len < 176)
	{
		rdr_debug_mask(reader, D_EMM, "emm_len < 176 (%u): %s",
			emm_len, cs_hexdump(1, ep->emm, 12, dump_emm_sn, sizeof(dump_emm_sn)));
		ep->type = UNKNOWN;
		return FALSE;
	}

	cs_hexdump(1, reader->hexserial, 3, dump_card_sn, sizeof(dump_card_sn));

#define compare_hex_serial(serial_len) \
	do { \
		cs_hexdump(1, ep->hexserial, serial_len, dump_emm_sn, sizeof(dump_emm_sn)); \
		ret = memcmp(ep->hexserial, reader->hexserial, serial_len) == 0; \
	} while(0)

#define check_serial(serial_len) \
	do { \
		memcpy(ep->hexserial, ep->emm + 3, serial_len); \
		compare_hex_serial(serial_len); \
	} while(0)

#define check_serial_skip_first(serial_len) \
	do { \
		memcpy(ep->hexserial, ep->emm + 4, serial_len); \
		compare_hex_serial(serial_len); \
	} while(0)

	switch (ep->emm[0]) {
	case BULCRYPT_EMM_UNIQUE_82:
	case BULCRYPT_EMM_UNIQUE_85:
		ep->type = UNIQUE;
		check_serial(3);
		if (ret)
			rdr_log_sensitive(reader, "EMM_UNIQUE-%02x-{%02x}, emm_sn = {%s}, card_sn = {%s}",
				ep->emm[0], ep->emm[6], dump_emm_sn, dump_card_sn);
		break;
	case BULCRYPT_EMM_SHARED_84:
		ep->type = SHARED;
		check_serial(2);
		if (ret)
			rdr_log_sensitive(reader, "EMM_SHARED-%02x-{%02x-%02x}, emm_sn = {%s}, card_sn = {%s}",
				ep->emm[0], ep->emm[5], ep->emm[6], dump_emm_sn, dump_card_sn);
		break;
	case BULCRYPT_EMM_8a:
		ep->type = UNKNOWN;
		check_serial_skip_first(2);
		if (ret)
			rdr_log_sensitive(reader, "EMM_UNKNOWN-%02x-{%02x-%02x}, emm_sn = {%s}, card_sn = {%s}",
				ep->emm[0], ep->emm[5], ep->emm[6], dump_emm_sn, dump_card_sn);
		break;
	case BULCRYPT_EMM_8b:
		ep->type = GLOBAL;
		check_serial_skip_first(1);
		if (ret)
			rdr_log_sensitive(reader, "EMM_GLOBAL-%02x-{%02x-%02x}, emm_sn = {%s}, card_sn = {%s}",
				ep->emm[0], ep->emm[5], ep->emm[6], dump_emm_sn, dump_card_sn);
		break;
	case BULCRYPT_EMM_FILLER:
		ep->type = UNKNOWN;
		break;
	default:
		ep->type = UNKNOWN;
		rdr_log(reader, "UNKNOWN_EMM len: %u, %s..", emm_len,
			cs_hexdump(1, ep->emm, 12, dump_emm_sn, sizeof(dump_emm_sn)));
		break;
	}

	return ret;
}