static void show_class(struct s_reader * reader, const char *p, const uchar *b, int32_t l) { int32_t i, j; // b -> via date (4 bytes) b+=4; l-=4; j=l-1; for (; j>=0; j--) for (i=0; i<8; i++) if (b[j] & (1 << (i&7))) { uchar cls; struct via_date vd; parse_via_date(b-4, &vd, 1); cls=(l-(j+1))*8+i; if (p) cs_log("%sclass: %02X, expiry date: %04d/%02d/%02d - %04d/%02d/%02d", p, cls, vd.year_s+1980, vd.month_s, vd.day_s, vd.year_e+1980, vd.month_e, vd.day_e); else cs_ri_log(reader, "class: %02X, expiry date: %04d/%02d/%02d - %04d/%02d/%02d", cls, vd.year_s+1980, vd.month_s, vd.day_s, vd.year_e+1980, vd.month_e, vd.day_e); } }
static int32_t dre_set_provider_info (struct s_reader * reader) { def_resp; int32_t i; uchar cmd59[] = { 0x59, 0x14 }; // subscriptions uchar cmd5b[] = { 0x5b, 0x00, 0x14 }; //validity dates cs_clear_entitlement(reader); cmd59[1] = reader->provider; if ((dre_cmd (cmd59))) { //ask subscription packages, returns error on 0x11 card uchar pbm[32]; tmp_dbg(65); memcpy (pbm, cta_res + 3, cta_lr - 6); cs_debug_mask(D_READER, "[dre-reader] pbm: %s", cs_hexdump(0, pbm, 32, tmp_dbg, sizeof(tmp_dbg))); if (pbm[0] == 0xff) cs_ri_log (reader, "[dre-reader] no active packages"); else for (i = 0; i < 32; i++) if (pbm[i] != 0xff) { cmd5b[1] = i; cmd5b[2] = reader->provider; dre_cmd (cmd5b); //ask for validity dates time_t start; time_t end; start = (cta_res[3] << 24) | (cta_res[4] << 16) | (cta_res[5] << 8) | cta_res[6]; end = (cta_res[7] << 24) | (cta_res[8] << 16) | (cta_res[9] << 8) | cta_res[10]; struct tm temp; localtime_r (&start, &temp); int32_t startyear = temp.tm_year + 1900; int32_t startmonth = temp.tm_mon + 1; int32_t startday = temp.tm_mday; localtime_r (&end, &temp); int32_t endyear = temp.tm_year + 1900; int32_t endmonth = temp.tm_mon + 1; int32_t endday = temp.tm_mday; cs_ri_log (reader, "[dre-reader] active package %i valid from %04i/%02i/%02i to %04i/%02i/%02i", i, startyear, startmonth, startday, endyear, endmonth, endday); cs_add_entitlement(reader, reader->caid, b2ll(4, reader->prid[0]), 0, 0, start, end, 1); } } return OK; }
int32_t ICC_Async_Activate (struct s_reader *reader, ATR * atr, uint16_t deprecated) { cs_debug_mask (D_IFD, "IFD: Activating card in reader %s\n", reader->label); reader->current_baudrate = DEFAULT_BAUDRATE; //this is needed for all readers to calculate work_etu for timings if (reader->atr[0] != 0) { cs_log("using ATR from reader config"); ATR_InitFromArray(atr, reader->atr, ATR_MAX_SIZE); } else { if (reader->crdr.active==1 && reader->crdr.activate) { call(reader->crdr.activate(reader, atr)); } else { switch(reader->typ) { case R_MP35: case R_DB2COM1: case R_DB2COM2: case R_SC8in1: case R_MOUSE: LOCK_SC8IN1; int32_t ret = Phoenix_Reset(reader, atr); UNLOCK_SC8IN1; if (ret) { cs_debug_mask(D_TRACE, "ERROR, function call Phoenix_Reset returns error."); return ERROR; } break; #if defined(LIBUSB) case R_SMART: call (SR_Reset(reader, atr)); break; #endif case R_INTERNAL: #if defined(SCI_DEV) call (Sci_Activate(reader)); call (Sci_Reset(reader, atr)); #elif defined(COOL) call (Cool_Reset(atr)); #elif defined(WITH_STAPI) call (STReader_Reset(reader->stsmart_handle, atr)); #elif defined(AZBOX) call (Azbox_Reset(reader, atr)); #endif break; #ifdef HAVE_PCSC case R_PCSC: { unsigned char atrarr[ATR_MAX_SIZE]; uint16_t atr_size = 0; if (pcsc_activate_card(reader, atrarr, &atr_size)) { if (ATR_InitFromArray (atr, atrarr, atr_size) == ATR_OK) return OK; else return ERROR; } else return ERROR; } break; #endif default: cs_log("ERROR ICC_Async_Activate: unknow reader type %i",reader->typ); return ERROR; } } } unsigned char atrarr[ATR_MAX_SIZE]; uint32_t atr_size; ATR_GetRaw(atr, atrarr, &atr_size); char tmp[atr_size*3+1]; cs_ri_log(reader, "ATR: %s", cs_hexdump(1, atrarr, atr_size, tmp, sizeof(tmp))); /* Get ICC reader->convention */ if (ATR_GetConvention (atr, &(reader->convention)) != ATR_OK) { cs_log("ERROR: Could not read reader->convention"); reader->convention = 0; reader->protocol_type = 0; return ERROR; } reader->protocol_type = ATR_PROTOCOL_TYPE_T0; LOCK_SC8IN1; int32_t ret = Parse_ATR(reader, atr, deprecated); UNLOCK_SC8IN1; //Parse_ATR and InitCard need to be included in lock because they change parity of serial port if (ret) cs_log("ERROR: Parse_ATR returned error"); if (ret) return ERROR; cs_debug_mask (D_IFD, "IFD: Card in reader %s succesfully activated\n", reader->label); return OK; }
static int32_t viaccess_card_info(struct s_reader * reader) { def_resp; int32_t i, l, scls, show_cls; 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}; time_t start_t, end_t; uchar via_cls = 0; show_cls=reader->show_cls; reader->last_geo.provid = 0; reader->last_geo.geo_len = 0; reader->last_geo.geo[0] = 0; cs_log("[viaccess-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 cs_log("[viaccess-reader] serial: %llu", b2ll(5, cta_res+2)); scls=0; 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 cs_ri_log(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 scls=0; 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) ) { int32_t fshow; l=cta_res[1]; //fshow=(client[cs_idx].dbglvl==D_DUMP)?1:(scls < show_cls)?1:0; fshow=(scls<show_cls); insb8[4]=l; write_cmd(insb8, NULL); // read class subs if( (cta_res[cta_lr-2]==0x90) && (fshow) && (cta_res[cta_lr-1]==0x00 || cta_res[cta_lr-1]==0x08) ) { show_class(reader, NULL, cta_res, cta_lr-2); get_via_data(cta_res, cta_lr-2, &start_t, &end_t, &via_cls); cs_add_entitlement(reader, reader->caid, (uint64_t)l_provid, (uint16_t)via_cls, (uint16_t)via_cls, start_t, end_t, 5); scls++; } } } insac[4]=0; insa4[2]=0x02; write_cmd(insa4, NULL); // select next provider } //return ERROR; return OK; }
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]); cs_log("[viaccess-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); // cs_log("[viaccess-reader] type: Viaccess, ver: %s serial: %llu", ver, b2ll(5, cta_res+2)); cs_ri_log(reader, "type: Viaccess (%sstandard atr), caid: %04X, serial: %llu", atr[9]==0x68?"":"non-",reader->caid, 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])); //cs_log("[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; cs_log("[viaccess-reader] name: %s", cta_res); */ insa4[2]=0x02; write_cmd(insa4, NULL); // select next issuer i++; } reader->nprov=i; cs_ri_log(reader, "providers: %d (%s)", reader->nprov, buf+1); if (cfg.ulparent) unlock_parental(reader); cs_log("[viaccess-reader] ready for requests"); return OK; }
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]) cs_log ("[dre-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; } //cs_ri_log("[dre-reader] type: DRE Crypt, caid: %04X, serial: %llu, card: v%x", cs_ri_log (reader, "[dre-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); cs_ri_log (reader, "[dre-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... cs_ri_log (reader, "[dre-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 cs_log ("[dre-reader] ready for requests"); return OK; }