static int32_t ICC_Async_GetPLL_Divider(struct s_reader *reader) { if(reader->divider != 0) { return reader->divider; } if(reader->cardmhz != 8300) /* Check dreambox is not DM7025 */ { float divider; rdr_log(reader," TEST tempo mhz check = %u mhz", reader->mhz); divider = ((float) reader->cardmhz) / ((float) reader->mhz); if (tempfi == 9) reader->divider = (int32_t) divider; // some card's runs only when slightly oveclocked like HD02 else { reader->divider = (int32_t) divider; if(divider > reader->divider) { reader->divider++; } /* to prevent over clocking, ceil (round up) the divider */ } rdr_debug_mask(reader, D_DEVICE, "PLL maxmhz = %.2f, wanted mhz = %.2f, divider used = %d, actualcardclock=%.2f", (float) reader->cardmhz / 100, (float) reader->mhz / 100, reader->divider, (float) reader->cardmhz / reader->divider / 100); reader->mhz = reader->cardmhz / reader->divider; } else /* STB is DM7025 */ { int32_t i, dm7025_clock_freq[] = {518, 461, 395, 360, 319, 296, 267, 244, 230, 212, 197}, dm7025_PLL_setting[] = {6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, t_cardmhz = reader->mhz; for(i = 0; i < 11; i++) if(t_cardmhz >= dm7025_clock_freq[i]) { break; } if(i > 10) { i = 10; } reader->mhz = dm7025_clock_freq[i]; reader->divider = dm7025_PLL_setting[i]; /*Nicer way of codeing is: reader->divider = i + 6;*/ rdr_debug_mask(reader, D_DEVICE, "DM7025 PLL maxmhz = %.2f, wanted mhz = %.2f, PLL setting used = %d, actualcardclock=%.2f", (float) reader->cardmhz / 100, (float) t_cardmhz / 100, reader->divider, (float) reader->mhz / 100); } return reader->divider; }
static int32_t Cool_Reset (struct s_reader *reader, ATR * atr) { int32_t ret; if (!reader->ins7e11_fast_reset) { //set freq to reader->cardmhz if necessary uint32_t clk; ret = cnxt_smc_get_clock_freq (specdev()->handle, &clk); coolapi_check_error("cnxt_smc_get_clock_freq", ret); if (clk/10000 != (uint32_t)reader->cardmhz) { rdr_debug_mask(reader, D_DEVICE, "COOL: clock freq: %i, scheduling change to %i for card reset", clk, reader->cardmhz*10000); call (Cool_SetClockrate(reader, reader->cardmhz)); } } else { rdr_debug_mask(reader, D_DEVICE, "fast reset needed, restoring transmit parameter for coolstream device %s", reader->device); call(Cool_Set_Transmit_Timeout(reader, 0)); rdr_log(reader, "Doing fast reset"); } //reset card ret = cnxt_smc_reset_card (specdev()->handle, ATR_TIMEOUT, NULL, NULL); coolapi_check_error("cnxt_smc_reset_card", ret); cs_sleepms(50); int32_t n = ATR_MAX_SIZE; unsigned char buf[ATR_MAX_SIZE]; ret = cnxt_smc_get_atr (specdev()->handle, buf, &n); coolapi_check_error("cnxt_smc_get_atr", ret); call (!ATR_InitFromArray (atr, buf, n) != ERROR); { cs_sleepms(50); return OK; } }
static void reader_log_emm(struct s_reader * reader, EMM_PACKET *ep, int32_t i, int32_t rc, struct timeb *tps) { char *rtxt[] = { "error", is_cascading_reader(reader) ? "sent" : "written", "skipped", "blocked" }; char *typedesc[] = { "unknown", "unique", "shared", "global" }; struct s_client *cl = reader->client; struct timeb tpe; if (reader->logemm & (1 << rc)) { cs_ftime(&tpe); if (!tps) tps = &tpe; rdr_log(reader, "%s emmtype=%s, len=%d, idx=%d, cnt=%d: %s (%ld ms)", username(ep->client), typedesc[cl->emmcache[i].type], ep->emm[2], i, cl->emmcache[i].count, rtxt[rc], 1000 * (tpe.time - tps->time) + tpe.millitm - tps->millitm); } if (rc) { cl->lastemm = time(NULL); led_status_emm_ok(); } #if defined(WEBIF) || defined(LCDSUPPORT) //counting results switch (rc) { case 0: reader->emmerror[ep->type]++; break; case 1: reader->emmwritten[ep->type]++; break; case 2: reader->emmskipped[ep->type]++; break; case 3: reader->emmblocked[ep->type]++; break; } #endif }
void do_emm(struct s_client * client, EMM_PACKET *ep) { char *typtext[]={"unknown", "unique", "shared", "global"}; char tmp[17]; int32_t emmnok=0; struct s_reader *aureader = NULL; cs_ddump_mask(D_EMM, ep->emm, ep->emmlen, "emm:"); int8_t cl_dvbapi = 0, assemble = 0; #ifdef HAVE_DVBAPI cl_dvbapi = streq(cfg.dvbapi_usr, client->account->usr); #endif if (client->account->emm_reassembly > 1 || (client->account->emm_reassembly && cl_dvbapi)) assemble = 1; LL_ITER itr = ll_iter_create(client->aureader_list); while ((aureader = ll_iter_next(&itr))) { if (!aureader->enable) continue; uint16_t caid = b2i(2, ep->caid); uint32_t provid = b2i(4, ep->provid); if (aureader->audisabled) { rdr_debug_mask(aureader, D_EMM, "AU is disabled"); /* we have to write the log for blocked EMM here because this EMM never reach the reader module where the rest of EMM log is done. */ if (aureader->logemm & 0x10) { rdr_log(aureader, "%s emmtype=%s, len=%d, idx=0, cnt=1: audisabled (0 ms)", client->account->usr, typtext[ep->type], ep->emm[2]); } continue; } if (!(aureader->grp & client->grp)) { rdr_debug_mask(aureader, D_EMM, "skip emm, group mismatch"); continue; } //TODO: provider possibly not set yet, this is done in get_emm_type() if (!emm_reader_match(aureader, caid, provid)) continue; struct s_cardsystem *cs = NULL; if (is_cascading_reader(aureader)) { // network reader (R_CAMD35 R_NEWCAMD R_CS378X R_CCCAM) if (!aureader->ph.c_send_emm) // no emm support continue; cs = get_cardsystem_by_caid(caid); if (!cs) { rdr_debug_mask(aureader, D_EMM, "unable to find cardsystem for caid %04X", caid); continue; } } else { // local reader if (aureader->csystem.active) cs=&aureader->csystem; } if (cs && cs->get_emm_type) { if (!cs->get_emm_type(ep, aureader)) { rdr_debug_mask(aureader, D_EMM, "emm skipped, get_emm_type() returns error"); emmnok++; continue; } } if (cs && cs->get_emm_filter) { if (!do_simple_emm_filter(aureader, cs, ep)) { rdr_debug_mask(aureader, D_EMM, "emm skipped, emm_filter() returns invalid"); emmnok++; continue; } } if (cs && cs->do_emm_reassembly) { if (assemble) { if (!cs->do_emm_reassembly(client, ep)) return; } else { rdr_debug_mask(aureader, D_EMM, "processing raw emm"); } } rdr_debug_mask_sensitive(aureader, D_EMM, "emmtype %s. Reader serial {%s}.", typtext[ep->type], cs_hexdump(0, aureader->hexserial, 8, tmp, sizeof(tmp))); rdr_debug_mask_sensitive(aureader, D_EMM, "emm UA/SA: {%s}.", cs_hexdump(0, ep->hexserial, 8, tmp, sizeof(tmp))); client->last = time(NULL); saveemm(aureader, ep); int32_t is_blocked = 0; switch (ep->type) { case UNKNOWN: is_blocked = (aureader->blockemm & EMM_UNKNOWN) == EMM_UNKNOWN; break; case UNIQUE : is_blocked = (aureader->blockemm & EMM_UNIQUE ) == EMM_UNIQUE; break; case SHARED : is_blocked = (aureader->blockemm & EMM_SHARED ) == EMM_SHARED; break; case GLOBAL : is_blocked = (aureader->blockemm & EMM_GLOBAL ) == EMM_GLOBAL; break; } // if not already blocked we check for block by len if (!is_blocked) is_blocked = cs_emmlen_is_blocked( aureader, ep->emm[2] ) ; if (is_blocked != 0) { #ifdef WEBIF aureader->emmblocked[ep->type]++; is_blocked = aureader->emmblocked[ep->type]; #endif /* we have to write the log for blocked EMM here because this EMM never reach the reader module where the rest of EMM log is done. */ if (aureader->logemm & 0x08) { rdr_log(aureader, "%s emmtype=%s, len=%d, idx=0, cnt=%d: blocked (0 ms)", client->account->usr, typtext[ep->type], ep->emm[2], is_blocked); } continue; } client->lastemm = time((time_t*)0); client->emmok++; if (client->account) client->account->emmok++; first_client->emmok++; //Check emmcache early: int32_t i; unsigned char md5tmp[CS_EMMSTORESIZE]; struct s_client *au_cl = aureader->client; MD5(ep->emm, ep->emm[2], md5tmp); ep->client = client; for (i=0; i<CS_EMMCACHESIZE; i++) { if (!memcmp(au_cl->emmcache[i].emmd5, md5tmp, CS_EMMSTORESIZE)) { rdr_debug_mask(aureader, D_EMM, "emm found in cache: count %d rewrite %d", au_cl->emmcache[i].count, aureader->rewritemm); if (aureader->cachemm && (au_cl->emmcache[i].count > aureader->rewritemm)) { reader_log_emm(aureader, ep, i, 2, NULL); return; } break; } } EMM_PACKET *emm_pack; if (cs_malloc(&emm_pack, sizeof(EMM_PACKET))) { rdr_debug_mask(aureader, D_EMM, "emm is being sent to reader"); memcpy(emm_pack, ep, sizeof(EMM_PACKET)); add_job(aureader->client, ACTION_READER_EMM, emm_pack, sizeof(EMM_PACKET)); } } if (emmnok > 0 && emmnok == ll_count(client->aureader_list)) { client->emmnok++; if (client->account) client->account->emmnok++; first_client->emmnok++; } }
/* 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; }
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; }
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); }
static int32_t conax_card_info(struct s_reader * reader) { def_resp; int32_t type, i, j, k=0, n=0, l; uint16_t provid = 0; char provname[32], pdate[32], chid[32]; static const uchar insC6[] = {0xDD, 0xC6, 0x00, 0x00, 0x03, 0x1C, 0x01, 0x00}; static const uchar ins26[] = {0xDD, 0x26, 0x00, 0x00, 0x03, 0x1C, 0x01, 0x01}; uchar insCA[] = {0xDD, 0xCA, 0x00, 0x00, 0x00}; char *txt[] = { "Package", "PPV-Event" }; static const uchar *cmd[] = { insC6, ins26 }; time_t start_t = 0, end_t = 0; uint32_t cxclass = 0; cs_clear_entitlement(reader); // reset the entitlements for (type=0; type<2; type++) { n=0; write_cmd(cmd[type], cmd[type]+5); while (cta_res[cta_lr-2]==0x98) { insCA[4]=cta_res[cta_lr-1]; // get len write_cmd(insCA, NULL); // read if ((cta_res[cta_lr-2]==0x90) || (cta_res[cta_lr-2]==0x98)) { for (j=0; j<cta_lr-2; j+=cta_res[j+1]+2) { provid=(cta_res[j+2+type]<<8) | cta_res[j+3+type]; chid[0] = '\0'; for (k=0, i=j+4+type; (i<j+cta_res[j+1]); i+=cta_res[i+1]+2) { switch(cta_res[i]) { case 0x01: l=(cta_res[i+1]<(sizeof(provname)-1)) ? cta_res[i+1] : sizeof(provname)-1; memcpy(provname, cta_res+i+2, l); provname[l]='\0'; break; case 0x30: if (k > 1) { rdr_log(reader, "%s: %d, id: %04X%s, date: %s - %s, name: %s", txt[type], ++n, provid, chid, pdate, pdate+16, trim(provname)); // add entitlements to list cs_add_entitlement(reader, reader->caid, b2ll(4, reader->prid[0]), provid, cxclass, start_t, end_t, type + 1); k = 0; chid[0] = '\0'; } if(k == 0) start_t = chid_date(cta_res+i+2, pdate, 15); else end_t = chid_date(cta_res+i+2, pdate+16, 15) /* add 23:59:59 here: */ + 0x1517F; ++k; break; case 0x20: // Provider classes case 0x90: // (?) not sure what this is, saw it once in log snprintf(chid, sizeof(chid), ", classes: %02X%02X%02X%02X", cta_res[i+2], cta_res[i+3], cta_res[i+4] ,cta_res[i+5]); cxclass = b2ll(4, &cta_res[i+2]); break; } } rdr_log(reader, "%s: %d, id: %04X%s, date: %s - %s, name: %s", txt[type], ++n, provid, chid, pdate, pdate+16, trim(provname)); // add entitlements to list cs_add_entitlement(reader, reader->caid, b2ll(4, reader->prid[0]), provid, cxclass, start_t, end_t, type + 1); } } } } rdr_log(reader, "ready for requests"); return OK; }
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; }
bool IO_Serial_Read (struct s_reader * reader, uint32_t delay, uint32_t timeout, uint32_t size, unsigned char * data) { uint32_t count = 0; if (timeout == 0){ // General fix for readers not communicating timeout and delay if (reader->read_timeout != 0) timeout = reader->read_timeout; else timeout = 9990000; // hope 99990000 is long enough! rdr_debug_mask(reader, D_DEVICE,"Warning: read timeout 0 changed to %d us", timeout); } rdr_debug_mask(reader, D_DEVICE,"Read timeout %d us, read delay %d us, to read %d char(s), chunksize %d char(s)", timeout, delay, size, size); if (reader->crdr.read_written && reader->written > 0) { // these readers need to read all transmitted chars before they can receive! unsigned char buf[256]; rdr_debug_mask(reader, D_DEVICE,"Reading %d echoed transmitted chars...", reader->written); int32_t n = reader->written; reader->written=0; if(IO_Serial_Read (reader, 0, 9990000, n, buf)) // use 9990000 = aprox 10 seconds (since written chars could be hughe!) return ERROR; rdr_debug_mask(reader, D_DEVICE,"Reading of echoed transmitted chars done!"); } #if defined(WITH_STAPI) || defined(__SH4__) //internal stapi and sh4 readers need special treatment as they don't respond correctly to poll and some sh4 boxes only can read 1 byte at once if(reader->typ == R_INTERNAL){ int32_t readed; #if defined(WITH_STAPI) const int32_t chunksize = INT_MAX; #elif defined(__SH4__) const int32_t chunksize = 1; #endif struct timeval tv, tv_spent; gettimeofday(&tv,0); memcpy(&tv_spent,&tv,sizeof(struct timeval)); readed=0; while((((tv_spent.tv_sec-tv.tv_sec)*1000000) + ((tv_spent.tv_usec-tv.tv_usec)/1000000L)) < (time_t)(timeout)) { readed = read(reader->handle, &data[count], size-count>=chunksize?chunksize:size-count); gettimeofday(&tv_spent,0); if(readed > 0) count +=readed; if(count < size){ if(readed < chunksize) cs_sleepus(1); continue; } else break; } if(count < size) { rdr_ddump_mask(reader, D_DEVICE, data, count, "Receiving:"); return ERROR; } } else #endif // read all chars at once for all other boxes { while(count < size){ int32_t readed = -1, errorcount=0; AGAIN: if(IO_Serial_WaitToRead (reader, delay, timeout)) { rdr_debug_mask(reader, D_DEVICE, "Timeout in IO_Serial_WaitToRead, timeout=%d us", timeout); return ERROR; } while (readed <0 && errorcount < 10) { readed = read (reader->handle, &data[count], size-count); if (readed < 0) { if (errno == EINTR) continue; // try again in case of interrupt if (errno == EAGAIN) goto AGAIN; //EAGAIN needs select procedure again rdr_log(reader, "ERROR: %s (errno=%d %s)", __func__, errno, strerror(errno)); errorcount++; } } if (readed == 0) { rdr_ddump_mask(reader, D_DEVICE, data, count, "Receiving:"); rdr_debug_mask(reader, D_DEVICE, "Received End of transmission"); return ERROR; } count +=readed; } } rdr_ddump_mask(reader, D_DEVICE, data, count, "Receiving:"); return OK; }
int32_t MP35_Init(struct s_reader * reader) { MP35_info reader_info; BYTE rec_buf[32]; BYTE parameter; int32_t original_mhz; rdr_debug_mask(reader, D_IFD, "Initializing MP35 reader"); current_product = 0; original_mhz = reader->mhz; // MP3.5 commands should be always be written using 9600 baud at 3.58MHz reader->mhz = 357; call(IO_Serial_SetParams(reader, 9600, 8, PARITY_NONE, 1, IO_SERIAL_HIGH, IO_SERIAL_HIGH)); IO_Serial_Sendbreak(reader, MP35_BREAK_LENGTH); IO_Serial_DTR_Clr(reader); IO_Serial_DTR_Set(reader); cs_sleepms(200); IO_Serial_Flush(reader); memset(rec_buf, 0x00, sizeof(rec_buf)); call(IO_Serial_Write(reader, MP35_WRITE_DELAY, 2, fw_version)); call(IO_Serial_Read(reader, MP35_READ_DELAY, 4, rec_buf)); if(rec_buf[3] != ACK) { rdr_debug_mask(reader, D_IFD, "Failed MP35 command: fw_version"); return ERROR; } if (MP35_product_info(reader, rec_buf[1], rec_buf[0], rec_buf[2], &reader_info) != OK) { rdr_log(reader, "MP35_Init: unknown product code"); return ERROR; } if(reader_info.current_product == 0x10) // USB Phoenix { if(original_mhz == 357) { rdr_log(reader, "MP35_Init: Using oscillator 1 (3.57MHz)"); parameter = 0x01; } else if(original_mhz == 368) { rdr_log(reader, "MP35_Init: Using oscillator 2 (3.68MHz)"); parameter = 0x02; } else if(original_mhz == 600) { rdr_log(reader, "MP35_Init: Using oscillator 3 (6.00MHz)"); parameter = 0x03; } else { rdr_log(reader, "MP35_Init: MP35 support only mhz=357, mhz=368 or mhz=600"); rdr_log(reader, "MP35_Init: Forced oscillator 1 (3.57MHz)"); parameter = 0x01; original_mhz = 357; } memset(rec_buf, 0x00, sizeof(rec_buf)); call(IO_Serial_Write(reader, MP35_WRITE_DELAY, 2, set_mode_osc)); call(IO_Serial_Write(reader, MP35_WRITE_DELAY, 1, ¶meter)); call(IO_Serial_Read(reader, MP35_READ_DELAY, 1, rec_buf)); // Read ACK from previous command if(rec_buf[0] != ACK) { rdr_debug_mask(reader, D_IFD, "Failed MP35 command: set_mode_osc"); return ERROR; } rdr_log(reader, "MP35_Init: Leaving programming mode"); memset(rec_buf, 0x00, sizeof(rec_buf)); call(IO_Serial_Write(reader, MP35_WRITE_DELAY, 2, exit_program_mode)); call(IO_Serial_Read(reader, MP35_READ_DELAY, 1, rec_buf)); if(rec_buf[0] != ACK) { rdr_debug_mask(reader, D_IFD, "Failed MP35 command: exit_program_mode"); return ERROR; } } else //MP3.5 or MP3.6 { if(reader_info.product_fw_version >= 0x0500) { int32_t info_len; char info[sizeof(rec_buf) - 2]; memset(rec_buf, 0x00, sizeof(rec_buf)); call(IO_Serial_Write(reader, MP35_WRITE_DELAY, 2, fw_info)); call(IO_Serial_Read(reader, MP35_READ_DELAY, 1, rec_buf)); info_len = rec_buf[0]; call(IO_Serial_Read(reader, MP35_READ_DELAY, info_len + 1, rec_buf)); if(rec_buf[info_len] != ACK) { rdr_debug_mask(reader, D_IFD, "Failed MP35 command: fw_info"); return ERROR; } memcpy(info, rec_buf, info_len); info[info_len] = '\0'; rdr_log(reader, "MP35_Init: FW Info - %s", info); } memset(rec_buf, 0x00, sizeof(rec_buf)); if(original_mhz == 357) { rdr_log(reader, "MP35_Init: Using oscillator 1 (3.57MHz)"); call(IO_Serial_Write(reader, MP35_WRITE_DELAY, 2, phoenix_mode)); } else if(original_mhz == 600) { rdr_log(reader, "MP35_Init: Using oscillator 2 (6.00MHz)"); call(IO_Serial_Write(reader, MP35_WRITE_DELAY, 2, phoenix_6mhz_mode)); } else { rdr_log(reader, "MP35_Init: MP35 support only mhz=357 or mhz=600"); rdr_log(reader, "MP35_Init: Forced oscillator 1 (3.57MHz)"); call(IO_Serial_Write(reader, MP35_WRITE_DELAY, 2, phoenix_mode)); original_mhz = 357; } } reader->mhz = original_mhz; // We might have switched oscillator here current_product = reader_info.current_product; IO_Serial_Flush(reader); return OK; }
bool IO_Serial_Write (struct s_reader * reader, uint32_t delay, uint32_t timeout, uint32_t size, const unsigned char * data) { if (timeout == 0){ // General fix for readers not communicating timeout and delay if (reader->char_delay != 0) timeout = reader->char_delay; else timeout = 1000000; rdr_debug_mask(reader, D_DEVICE,"Warning: write timeout 0 changed to %d us", timeout); } uint32_t count, to_send, i_w; unsigned char data_w[512]; to_send = (delay? 1: size); // calculate chars to send at one rdr_debug_mask(reader, D_DEVICE,"Write timeout %d us, write delay %d us, to send %d char(s), chunksize %d char(s)", timeout, delay, size, to_send); for (count = 0; count < size; count += to_send) { if (count + to_send > size){ to_send = size - count; } uint16_t errorcount=0, to_do=to_send; for (i_w=0; i_w < to_send; i_w++) data_w [i_w] = data [count + i_w]; rdr_ddump_mask(reader, D_DEVICE, data_w+(to_send-to_do), to_do, "Sending:"); AGAIN: if (!IO_Serial_WaitToWrite (reader, delay, timeout)) { while (to_do !=0){ int32_t u = write (reader->handle, data_w+(to_send-to_do), to_do); if (u < 1) { if (errno==EINTR) continue; //try again in case of Interrupted system call if (errno==EAGAIN) goto AGAIN; //EAGAIN needs a select procedure again errorcount++; int16_t written = count + to_send - to_do; if (u != 0) { rdr_log(reader, "ERROR: %s: Written=%d of %d (errno=%d %s)", __func__, written , size, errno, strerror(errno)); } if (errorcount > 10){ //exit if more than 10 errors return ERROR; } } else { to_do -= u; errorcount = 0; if (reader->crdr.read_written) reader->written += u; // these readers echo transmitted chars } } } else { rdr_log(reader, "Timeout in IO_Serial_WaitToWrite, delay=%d us, timeout=%d us", delay, timeout); if (reader->crdr.read_written && reader->written > 0) { // these readers need to read all transmitted chars before they can receive! unsigned char buf[256]; rdr_debug_mask(reader, D_DEVICE,"Reading %d echoed transmitted chars...", reader->written); int32_t n = reader->written; if(IO_Serial_Read (reader, 0, 9990000, n, buf)) // use 9990000 = aprox 10 seconds (since written chars could be hughe!) return ERROR; reader->written=0; rdr_debug_mask(reader, D_DEVICE,"Reading of echoed transmitted chars done!"); } return ERROR; } } if (reader->crdr.read_written && reader->written > 0) { // these readers need to read all transmitted chars before they can receive! unsigned char buf[256]; rdr_debug_mask(reader, D_DEVICE,"Reading %d echoed transmitted chars...", reader->written); int32_t n = reader->written; if(IO_Serial_Read (reader, 0, 9990000, n, buf)) // use 9990000 = aprox 10 seconds (since written chars could be hughe!) return ERROR; reader->written=0; rdr_debug_mask(reader, D_DEVICE,"Reading of echoed transmitted chars done!"); } return OK; }
bool cardreader_init(struct s_reader *reader) { struct s_client *client = reader->client; client->typ = 'r'; int8_t i = 0; set_localhost_ip(&client->ip); while((cardreader_device_init(reader) == 2) && i < 10) { cs_sleepms(2000); if(!ll_contains(configured_readers, reader) || !is_valid_client(client) || reader->enable != 1) { return false; } i++; } if (i >= 10) { reader->card_status = READER_DEVICE_ERROR; cardreader_close(reader); reader->enable = 0; return false; } else { if(reader->typ == R_INTERNAL) { if(boxtype_is("dm8000") || boxtype_is("dm800") || boxtype_is("dm800se")) {reader->cardmhz = 2700;} if(boxtype_is("dm500") || boxtype_is("dm600pvr")) {reader->cardmhz = 3150;} if(boxtype_is("dm7025")) {reader->cardmhz = 8300;} if((!strncmp(boxtype_get(), "vu", 2 ))||(boxtype_is("ini-8000am"))) {reader->cardmhz = 2700; reader->mhz = 450;} // only one speed for vu+ and Atemio Nemesis due to usage of TDA8024 } if((reader->cardmhz > 2000) && (reader->typ != R_SMART)) { rdr_log(reader, "Reader initialized (device=%s, detect=%s%s, pll max=%.2f MHz, wanted mhz=%.2f MHz)", reader->device, reader->detect & 0x80 ? "!" : "", RDR_CD_TXT[reader->detect & 0x7f], (float)reader->cardmhz / 100, (float)reader->mhz / 100); rdr_log(reader,"Reader sci internal, detected box type: %s", boxtype_get()); } else { if (reader->typ == R_SMART || is_smargo_reader(reader)) { rdr_log_dbg(reader, D_IFD, "clocking for smartreader with smartreader or smargo protocol"); if (reader->cardmhz >= 2000) reader->cardmhz = 369; else if (reader->cardmhz >= 1600) reader->cardmhz = 1600; else if (reader->cardmhz >= 1200) reader->cardmhz = 1200; else if (reader->cardmhz >= 961) reader->cardmhz = 961; else if (reader->cardmhz >= 800) reader->cardmhz = 800; else if (reader->cardmhz >= 686) reader->cardmhz = 686; else if (reader->cardmhz >= 600) reader->cardmhz = 600; else if (reader->cardmhz >= 534) reader->cardmhz = 534; else if (reader->cardmhz >= 480) reader->cardmhz = 480; else if (reader->cardmhz >= 436) reader->cardmhz = 436; else if (reader->cardmhz >= 400) reader->cardmhz = 400; else if (reader->cardmhz >= 369) reader->cardmhz = 369; else if (reader->cardmhz == 357) reader->cardmhz = 369; else // 357 not a default smartreader setting if (reader->cardmhz >= 343) reader->cardmhz = 343; else reader->cardmhz = 320; if (reader->mhz >= 1600) reader->mhz = 1600; else if (reader->mhz >= 1200) reader->mhz = 1200; else if (reader->mhz >= 961) reader->mhz = 961; else if (reader->mhz >= 900) reader->mhz = 900; else if (reader->mhz >= 800) reader->mhz = 800; else if (reader->mhz >= 686) reader->mhz = 686; else if (reader->mhz >= 600) reader->mhz = 600; else if (reader->mhz >= 534) reader->mhz = 534; else if (reader->mhz >= 480) reader->mhz = 480; else if (reader->mhz >= 436) reader->mhz = 436; else if (reader->mhz >= 400) reader->mhz = 369; else if (reader->mhz >= 369) reader->mhz = 369; else if (reader->mhz == 357) reader->mhz = 369; else // 357 not a default smartreader setting if (reader->mhz >= 343) reader->mhz = 343; else reader->mhz = 320; } if ((reader->typ == R_SMART || is_smargo_reader(reader)) && reader->autospeed == 1) { rdr_log(reader, "Reader initialized (device=%s, detect=%s%s, mhz= AUTO, cardmhz=%d)", reader->device, reader->detect & 0x80 ? "!" : "", RDR_CD_TXT[reader->detect & 0x7f], reader->cardmhz); } else { rdr_log(reader, "Reader initialized (device=%s, detect=%s%s, mhz=%d, cardmhz=%d)", reader->device, reader->detect & 0x80 ? "!" : "", RDR_CD_TXT[reader->detect & 0x7f], reader->mhz, reader->cardmhz); if (reader->typ == R_INTERNAL && !(reader->cardmhz > 2000)) rdr_log(reader,"Reader sci internal, detected box type: %s", boxtype_get()); } } return true; } }
static int32_t pcsc_init(struct s_reader *pcsc_reader) { ULONG rv; DWORD dwReaders = 0; LPSTR mszReaders = NULL; char *ptr, **readers = NULL; char *device = pcsc_reader->device; int32_t nbReaders; int32_t reader_nb; rdr_log_dbg(pcsc_reader, D_DEVICE, "PCSC establish context for PCSC pcsc_reader %s", device); SCARDCONTEXT hContext; memset(&hContext, 0, sizeof(hContext)); rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext); if(rv == SCARD_S_SUCCESS) { if(!cs_malloc(&pcsc_reader->crdr_data, sizeof(struct pcsc_data))) { return ERROR; } struct pcsc_data *crdr_data = pcsc_reader->crdr_data; crdr_data->hContext = hContext; // here we need to list the pcsc readers and get the name from there, // the pcsc_reader->device should contain the pcsc_reader number // and after the actual device name is copied in crdr_data->pcsc_name . rv = SCardListReaders(crdr_data->hContext, NULL, NULL, &dwReaders); if(rv != SCARD_S_SUCCESS) { rdr_log_dbg(pcsc_reader, D_DEVICE, "PCSC failed listing readers [1] : (%lx)", (unsigned long)rv); return ERROR; } if(!cs_malloc(&mszReaders, dwReaders)) { return ERROR; } rv = SCardListReaders(crdr_data->hContext, NULL, mszReaders, &dwReaders); if(rv != SCARD_S_SUCCESS) { rdr_log_dbg(pcsc_reader, D_DEVICE, "PCSC failed listing readers [2]: (%lx)", (unsigned long)rv); NULLFREE(mszReaders); return ERROR; } /* Extract readers from the null separated string and get the total * number of readers */ nbReaders = 0; ptr = mszReaders; while(*ptr != '\0') { ptr += strlen(ptr) + 1; nbReaders++; } if(nbReaders == 0) { rdr_log(pcsc_reader, "PCSC : no pcsc_reader found"); NULLFREE(mszReaders); return ERROR; } if(!cs_malloc(&readers, nbReaders * sizeof(char *))) { NULLFREE(mszReaders); return ERROR; } char* device_line; char* device_first; char* device_second; device_line = strdup((const char *)&pcsc_reader->device); device_first = strsep(&device_line, ":"); device_second = strsep(&device_line, ":"); reader_nb = atoi(device_first); /* fill the readers table */ nbReaders = 0; ptr = mszReaders; while(*ptr != '\0') { rdr_log_dbg(pcsc_reader, D_DEVICE, "PCSC pcsc_reader %d: %s", nbReaders, ptr); readers[nbReaders] = ptr; if ((reader_nb == -1) && (device_second != NULL) && strstr(ptr,device_second)){ reader_nb = nbReaders; } ptr += strlen(ptr) + 1; nbReaders++; } if(reader_nb < 0 || reader_nb >= nbReaders) { rdr_log(pcsc_reader, "Wrong pcsc_reader index: %d", reader_nb); NULLFREE(mszReaders); NULLFREE(readers); NULLFREE(device_line); return ERROR; } if (readers) { snprintf(crdr_data->pcsc_name, sizeof(crdr_data->pcsc_name), "%s", readers[reader_nb]); NULLFREE(readers); } NULLFREE(mszReaders); NULLFREE(device_line); } else { rdr_log(pcsc_reader, "PCSC failed establish context (%lx)", (unsigned long)rv); return ERROR; } return OK; }
static int32_t pcsc_check_card_inserted(struct s_reader *pcsc_reader) { struct pcsc_data *crdr_data = pcsc_reader->crdr_data; DWORD dwState, dwAtrLen, dwReaderLen; unsigned char pbAtr[64]; SCARDHANDLE rv; dwAtrLen = sizeof(pbAtr); rv = 0; dwState = 0; dwReaderLen = 0; // Do we have a card ? if(!crdr_data->pcsc_has_card && !crdr_data->hCard) { // try connecting to the card rv = SCardConnect(crdr_data->hContext, crdr_data->pcsc_name, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &crdr_data->hCard, &crdr_data->dwActiveProtocol); if(rv == (SCARDHANDLE)SCARD_E_NO_SMARTCARD) { // no card in pcsc_reader crdr_data->pcsc_has_card = 0; if(crdr_data->hCard) { SCardDisconnect(crdr_data->hCard, SCARD_RESET_CARD); crdr_data->hCard = 0; } // rdr_log_dbg(pcsc_reader, D_DEVICE, "PCSC card in %s removed / absent [dwstate=%lx rv=(%lx)]", crdr_data->pcsc_name, dwState, (unsigned long)rv ); return OK; } else if(rv == (SCARDHANDLE)SCARD_W_UNRESPONSIVE_CARD) { // there is a problem with the card in the pcsc_reader crdr_data->pcsc_has_card = 0; crdr_data->hCard = 0; rdr_log(pcsc_reader, "PCSC card in %s is unresponsive. Eject and re-insert please.", crdr_data->pcsc_name); return ERROR; } else if(rv == SCARD_S_SUCCESS) { // we have a card crdr_data->pcsc_has_card = 1; rdr_log(pcsc_reader, "PCSC was opened with handle: %ld", (long)crdr_data->hCard); } else { // if we get here we have a bigger problem -> display status and debug // rdr_log_dbg(pcsc_reader, D_DEVICE, "PCSC pcsc_reader %s status [dwstate=%lx rv=(%lx)]", crdr_data->pcsc_name, dwState, (unsigned long)rv ); return ERROR; } } // if we get there the card is ready, check its status rv = SCardStatus(crdr_data->hCard, NULL, &dwReaderLen, &dwState, &crdr_data->dwActiveProtocol, pbAtr, &dwAtrLen); if(rv == SCARD_S_SUCCESS && (dwState & (SCARD_PRESENT | SCARD_NEGOTIABLE | SCARD_POWERED))) { return OK; } else { SCardDisconnect(crdr_data->hCard, SCARD_RESET_CARD); crdr_data->hCard = 0; crdr_data->pcsc_has_card = 0; } return ERROR; }
void do_emm_from_file(struct s_reader * reader) { if (!reader->emmfile) return; char token[256]; FILE *fp; if (reader->emmfile[0] == '/') snprintf(token, sizeof(token), "%s", reader->emmfile); //pathname included else get_config_filename(token, sizeof(token), reader->emmfile); //only file specified, look in confdir for this file if (!(fp = fopen (token, "rb"))) { rdr_log(reader, "ERROR: Cannot open EMM file '%s' (errno=%d %s)\n", token, errno, strerror(errno)); return; } EMM_PACKET *eptmp; if (!cs_malloc(&eptmp, sizeof(EMM_PACKET))) { fclose (fp); return; } size_t ret = fread(eptmp, sizeof(EMM_PACKET), 1, fp); if (ret < 1 && ferror(fp)) { rdr_log(reader, "ERROR: Can't read EMM from file '%s' (errno=%d %s)", token, errno, strerror(errno)); free(eptmp); fclose(fp); return; } fclose (fp); eptmp->caid[0] = (reader->caid >> 8) & 0xFF; eptmp->caid[1] = reader->caid & 0xFF; if (reader->nprov > 0) memcpy(eptmp->provid, reader->prid[0], sizeof(eptmp->provid)); eptmp->emmlen = eptmp->emm[2] + 3; struct s_cardsystem *cs = get_cardsystem_by_caid(reader->caid); if (cs && cs->get_emm_type && !cs->get_emm_type(eptmp, reader)) { rdr_debug_mask(reader, D_EMM, "emm skipped, get_emm_type() returns error"); free(eptmp); return; } //save old b_nano value //clear lsb and lsb+1, so no blocking, and no saving for this nano uint16_t save_s_nano = reader->s_nano; uint16_t save_b_nano = reader->b_nano; uint32_t save_saveemm = reader->saveemm; reader->s_nano = reader->b_nano = 0; reader->saveemm = 0; int32_t rc = cardreader_do_emm(reader, eptmp); if (rc == OK) rdr_log(reader, "EMM from file %s was successful written.", token); else rdr_log(reader, "ERROR: EMM read from file %s NOT processed correctly! (rc=%d)", token, rc); //restore old block/save settings reader->s_nano = save_s_nano; reader->b_nano = save_b_nano; reader->saveemm = save_saveemm; free(eptmp); }
static void Azbox_SetMode(struct s_reader *reader, int32_t mode) { sc_mode = mode; rdr_log(reader, "openxcas sc: set mode %d", sc_mode); }
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; }
/* Bulcrypt ECM structure: 80 70 - ECM header (80 | 81) 4c - ECM length after this field (0x4c == 76 bytes) 4f 8d 87 0b - unixts == 1334675211 == Tue Apr 17 18:06:51 EEST 2012 00 66 - *FIXME* Program number? 00 7d - *FIXME* ce 70 - ECM counter 0b 88 - ECM type xx yy zz .. - Encrypted ECM payload (64 bytes) */ static int32_t bulcrypt_do_ecm(struct s_reader * reader, const ECM_REQUEST *er, struct s_ecm_answer *ea) { char tmp[512]; uchar ecm_cmd[256]; def_resp int32_t ecm_len = check_sct_len(er->ecm, 3); if (ecm_len < 64 || ecm_len > 188) { rdr_log(reader, "Wrong ECM length: %d", ecm_len); return ERROR; } // CMD: DE 20 00 00 4C memcpy(ecm_cmd, cmd_ecm, sizeof(cmd_ecm)); ecm_cmd[4] = er->ecm[2]; // Set ECM length memcpy(ecm_cmd + sizeof(cmd_ecm), er->ecm + 3, ecm_cmd[4]); // Send ECM write_cmd(ecm_cmd, ecm_cmd + 5); if (cta_lr != 2) { rdr_log(reader, "(ecm_cmd) Unexpected card answer: %s", cs_hexdump(1, cta_res, cta_lr, tmp, sizeof(tmp))); return ERROR; } if (cta_res[0] == 0x90 && cta_res[1] == 0x03) { rdr_log(reader, "No active subscription."); return ERROR; } if ( !(cta_res[0] == 0x90 && cta_res[1] == 0x13) ) { rdr_log(reader, "(ecm_cmd) Unexpected card answer: %s", cs_hexdump(1, cta_res, cta_lr, tmp, sizeof(tmp))); return ERROR; } // Call get_cw write_cmd(cmd_ecm_get_cw, NULL); // rdr_log(reader, "CW_LOG: %s", cs_hexdump(1, cta_res, cta_lr, tmp, sizeof(tmp))); if (cta_lr < 20 || (cta_res[0] != 0x0a && cta_res[1] != 0x11)) { rdr_log(reader, "(get_cw) Unexpected card answer: %s", cs_hexdump(1, cta_res, cta_lr, tmp, sizeof(tmp))); return ERROR; } // *FIXME* is the bellow info true? // 0x80 (ver 1) is supported // 0xc0 (ver 2) is *NOT* supported currently if (cta_res[2] == 0xc0) { rdr_log(reader, "Possibly unsupported codeword (bulcrypt v2): %s", cs_hexdump(1, cta_res, cta_lr, tmp, sizeof(tmp))); // *FIXME* commented for testing, this really should be an error //return ERROR; } // Remove code word obfuscation uchar *cw = cta_res + 3; if (reader->bulcrypt_version == 1) { int i; for (i = 0 ; i < 16; i++) { cw[i] = cw[i] ^ sess_key[i]; } } if (er->ecm[0] == 0x81) { // Even/Odd CWs should be exchanged memcpy(ea->cw, cw + 8, 8); memcpy(ea->cw + 8, cw, 8); } else { memcpy(ea->cw, cw, 8); memcpy(ea->cw + 8, cw + 8, 8); } // Check if DCW is valid if (!cw_is_valid(reader, ea->cw) || !cw_is_valid(reader, ea->cw + 8)) return ERROR; return OK; }
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; }
static int32_t conax_do_ecm(struct s_reader * reader, const ECM_REQUEST *er, struct s_ecm_answer *ea) { def_resp; int32_t i,j,n,num_dw=0, rc=0; unsigned char insA2[] = { 0xDD,0xA2,0x00,0x00,0x00 }; unsigned char insCA[] = { 0xDD,0xCA,0x00,0x00,0x00 }; unsigned char exp[] = {0x01, 0x00, 0x01}; unsigned char buf[256]; if ((n=check_sct_len(er->ecm, 3))<0) return ERROR; buf[0]=0x14; buf[1]=n+1; if(0x0 != PairingECMRotation(reader, er, n)) buf[2]=2; // card will answer with encrypted dw else buf[2]=0; memcpy(buf+3, er->ecm, n); insA2[4]=n+3; write_cmd(insA2, buf); // write Header + ECM while ((cta_res[cta_lr-2]==0x98) && // Antwort ((insCA[4]=cta_res[cta_lr-1])>0) && (insCA[4]!=0xFF)) { write_cmd(insCA, NULL); //Codeword auslesen if ((cta_res[cta_lr-2]==0x98) || ((cta_res[cta_lr-2]==0x90) )) { /*checks if answer is encrypted with RSA algo and decrypts it if needed*/ if(0x81 == cta_res[0] && 2 == cta_res[2] >> 5) /*81 XX 5X*/ { if(0x00 == cta_res[cta_lr-1]) rc = RSA_CNX(reader, cta_res, reader->rsa_mod, exp, cta_lr, 64u, 3u); else rc = -4; /*card has no right to decode this channel*/ } if(0 == rc) for(i = 0; i < cta_lr-2 && num_dw < 2; i+=cta_res[i+1]+2) { switch (cta_res[i]) { case 0x25: if ( (cta_res[i+1]>=0xD) && !((n=cta_res[i+4])&0xFE) ) { rc|=(1<<n); memcpy(ea->cw+(n<<3), cta_res+i+7, 8); ++num_dw; } break; case 0x31: if ( (cta_res[i+1]==0x02 && cta_res[i+2]==0x00 && cta_res[i+3]==0x00) || \ (cta_res[i+1]==0x02 && cta_res[i+2]==0x40 && cta_res[i+3]==0x00) ) break; else if (strcmp(reader->pincode, "none")) { conax_send_pin(reader); write_cmd(insA2, buf); // write Header + ECM while ((cta_res[cta_lr-2]==0x98) && // Antwort ((insCA[4]=cta_res[cta_lr-1])>0) && (insCA[4]!=0xFF)) { write_cmd(insCA, NULL); //Codeword auslesen if ((cta_res[cta_lr-2]==0x98) || ((cta_res[cta_lr-2]==0x90) && (!cta_res[cta_lr-1]))) { for(j=0;j<cta_lr-2; j+=cta_res[j+1]+2) if ((cta_res[j]==0x25) && // access: is cw (cta_res[j+1]>=0xD) && // 0xD: 5 header + 8 cw !((n=cta_res[j+4])&0xFE)) // cw idx must be 0 or 1 { rc|=(1<<n); memcpy(ea->cw+(n<<3), cta_res+j+7, 8); ++num_dw; } } } } break; } } } } switch(rc) { case -1: rdr_log(reader, "conax decode ECM problem - RSA key is probably faulty"); break; case -2: rdr_log(reader, "conax RSA pairing - wrong size of data"); break; case -3: rdr_log(reader, "conax RSA pairing- wrong size of data for second round"); case -4: rdr_log(reader, "card has no right to decode this channel"); break; } /* answer 9011 - conax smart card need reset */ if(2<=cta_lr && 0x90==cta_res[cta_lr-2] && 0x11==cta_res[cta_lr-1]) { rdr_log(reader, "conax card hangs - reset is required"); reader->card_status = UNKNOWN; } if (rc==3) return OK; else return ERROR; }
bool cardreader_init(struct s_reader *reader) { struct s_client *client = reader->client; client->typ = 'r'; int8_t i = 0; set_localhost_ip(&client->ip); while((cardreader_device_init(reader) == 2) && i < 10) { cs_sleepms(2000); if(!ll_contains(configured_readers, reader) || !is_valid_client(client) || reader->enable != 1) { return false; } i++; } if (i >= 10) { reader->card_status = READER_DEVICE_ERROR; cardreader_close(reader); reader->enable = 0; return false; } else { if((reader->cardmhz > 2000) && (reader->typ != R_SMART)) { rdr_log(reader, "Reader initialized (device=%s, detect=%s%s, pll max=%.2f MHz, wanted mhz=%.2f MHz)", reader->device, reader->detect & 0x80 ? "!" : "", RDR_CD_TXT[reader->detect & 0x7f], (float)reader->cardmhz / 100, (float)reader->mhz / 100); rdr_log(reader,"Reader sci internal, detected box type: %s", stb_boxtype ? stb_boxtype : "generic"); } else { if ((reader->typ == R_SMART) || (!strcasecmp(reader->crdr.desc, "smargo")) ){ rdr_debug_mask(reader, D_IFD, "clocking for smartreader with smartreader or smargo protocol"); if (reader->cardmhz >= 2000) reader->cardmhz = 369; else if (reader->cardmhz >= 1600) reader->cardmhz = 1600; else if (reader->cardmhz >= 1200) reader->cardmhz = 1200; else if (reader->cardmhz >= 961) reader->cardmhz = 961; else if (reader->cardmhz >= 800) reader->cardmhz = 800; else if (reader->cardmhz >= 686) reader->cardmhz = 686; else if (reader->cardmhz >= 600) reader->cardmhz = 600; else if (reader->cardmhz >= 534) reader->cardmhz = 534; else if (reader->cardmhz >= 480) reader->cardmhz = 480; else if (reader->cardmhz >= 436) reader->cardmhz = 436; else if (reader->cardmhz >= 400) reader->cardmhz = 400; else if (reader->cardmhz >= 369) reader->cardmhz = 369; else if (reader->cardmhz == 357) reader->cardmhz = 369; else // 357 not a default smartreader setting if (reader->cardmhz >= 343) reader->cardmhz = 343; else reader->cardmhz = 320; if (reader->mhz >= 1600) reader->mhz = 1600; else if (reader->mhz >= 1200) reader->mhz = 1200; else if (reader->mhz >= 961) reader->mhz = 961; else if (reader->mhz >= 900) reader->mhz = 900; else if (reader->mhz >= 800) reader->mhz = 800; else if (reader->mhz >= 686) reader->mhz = 686; else if (reader->mhz >= 600) reader->mhz = 600; else if (reader->mhz >= 534) reader->mhz = 534; else if (reader->mhz >= 480) reader->mhz = 480; else if (reader->mhz >= 436) reader->mhz = 436; else if (reader->mhz >= 400) reader->mhz = 369; else if (reader->mhz >= 369) reader->mhz = 369; else if (reader->mhz == 357) reader->mhz = 369; else // 357 not a default smartreader setting if (reader->mhz >= 343) reader->mhz = 343; else reader->mhz = 320; } if (((reader->typ == R_SMART) && (reader->autospeed == 1)) || ((!strcasecmp(reader->crdr.desc, "smargo")) && (reader->autospeed == 1))) { rdr_log(reader, "Reader initialized (device=%s, detect=%s%s, mhz= AUTO, cardmhz=%d)", reader->device, reader->detect & 0x80 ? "!" : "", RDR_CD_TXT[reader->detect & 0x7f], reader->cardmhz); } else { rdr_log(reader, "Reader initialized (device=%s, detect=%s%s, mhz=%d, cardmhz=%d)", reader->device, reader->detect & 0x80 ? "!" : "", RDR_CD_TXT[reader->detect & 0x7f], reader->mhz, reader->cardmhz); } } return true; } }
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; }
static int32_t pcsc_init(struct s_reader *pcsc_reader) { ULONG rv; DWORD dwReaders; LPSTR mszReaders = NULL; char *ptr, **readers = NULL; char *device = pcsc_reader->device; int32_t nbReaders; int32_t reader_nb; pcsc_reader->pcsc_has_card=0; pcsc_reader->hCard=0; pcsc_reader->hContext=0; rdr_debug_mask(pcsc_reader, D_DEVICE, "PCSC establish context for PCSC pcsc_reader %s", device); rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &pcsc_reader->hContext); if ( rv == SCARD_S_SUCCESS ) { // here we need to list the pcsc readers and get the name from there, // the pcsc_reader->device should contain the pcsc_reader number // and after the actual device name is copied in pcsc_reader->pcsc_name . rv = SCardListReaders(pcsc_reader->hContext, NULL, NULL, &dwReaders); if( rv != SCARD_S_SUCCESS ) { rdr_debug_mask(pcsc_reader, D_DEVICE, "PCSC failed listing readers [1] : (%lx)", (unsigned long)rv); return ERROR; } if (!cs_malloc(&mszReaders, dwReaders)) return ERROR; rv = SCardListReaders(pcsc_reader->hContext, NULL, mszReaders, &dwReaders); if( rv != SCARD_S_SUCCESS ) { rdr_debug_mask(pcsc_reader, D_DEVICE, "PCSC failed listing readers [2]: (%lx)", (unsigned long)rv); free(mszReaders); return ERROR; } /* Extract readers from the null separated string and get the total * number of readers */ nbReaders = 0; ptr = mszReaders; while (*ptr != '\0') { ptr += strlen(ptr)+1; nbReaders++; } if (nbReaders == 0) { rdr_log(pcsc_reader, "PCSC : no pcsc_reader found"); free(mszReaders); return ERROR; } if (!cs_malloc(&readers, nbReaders * sizeof(char *))) return ERROR; /* fill the readers table */ nbReaders = 0; ptr = mszReaders; while (*ptr != '\0') { rdr_debug_mask(pcsc_reader, D_DEVICE, "PCSC pcsc_reader %d: %s", nbReaders, ptr); readers[nbReaders] = ptr; ptr += strlen(ptr)+1; nbReaders++; } reader_nb=atoi((const char *)&pcsc_reader->device); if (reader_nb < 0 || reader_nb >= nbReaders) { rdr_log(pcsc_reader, "Wrong pcsc_reader index: %d", reader_nb); free(mszReaders); free(readers); return ERROR; } snprintf(pcsc_reader->pcsc_name,sizeof(pcsc_reader->pcsc_name),"%s",readers[reader_nb]); free(mszReaders); free(readers); } else { rdr_log(pcsc_reader, "PCSC failed establish context (%lx)", (unsigned long)rv); return ERROR; } return OK; }
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; }
int32_t ICC_Async_Activate(struct s_reader *reader, ATR *atr, uint16_t deprecated) { rdr_debug_mask(reader, D_IFD, "Activating card"); reader->current_baudrate = DEFAULT_BAUDRATE; if(reader->atr[0] != 0 && !reader->ins7e11_fast_reset) { rdr_log(reader, "Using ATR from reader config"); ATR_InitFromArray(atr, reader->atr, ATR_MAX_SIZE); } else { call(reader->crdr.activate(reader, atr)); if(reader->crdr.skip_extra_atr_parsing) { return OK; } } unsigned char atrarr[ATR_MAX_SIZE]; uint32_t atr_size; ATR_GetRaw(atr, atrarr, &atr_size); char tmp[atr_size * 3 + 1]; // dirty hack for seca cards on Golden Interstar Xspeed internal reader char *hack_golden_interstar = cs_hexdump(1, atrarr, atr_size, tmp, sizeof(tmp)); int result = strncmp(hack_golden_interstar, "18 40 D8 ", sizeof(tmp)); if (!result) { rdr_log(reader, "Disabling rom rev detection. Golden Star internal reader dirty hack"); reader->ins7e11_fast_reset = 2; } // end dirty hack If a solution to the stb's sci driver is found remove this hack rdr_log(reader, "ATR: %s", cs_hexdump(1, atrarr, atr_size, tmp, sizeof(tmp))); memcpy(reader->card_atr, atrarr, atr_size); reader->card_atr_length = atr_size; /* Get ICC reader->convention */ if(ATR_GetConvention(atr, &(reader->convention)) != ATR_OK) { rdr_log(reader, "ERROR: Could not read reader->convention"); reader->convention = 0; reader->protocol_type = 0; return ERROR; } reader->protocol_type = ATR_PROTOCOL_TYPE_T0; // Parse_ATR and InitCard need to be included in lock because they change parity of serial port if(reader->crdr.lock) { reader->crdr.lock(reader); } int32_t ret = Parse_ATR(reader, atr, deprecated); if(reader->crdr.unlock) { reader->crdr.unlock(reader); } if(ret) { rdr_log(reader, "ERROR: Parse_ATR returned error"); } if(ret) { return ERROR; } rdr_debug_mask(reader, D_IFD, "Card succesfully activated"); return OK; }
static int32_t dre_set_provider_info(struct s_reader *reader) { def_resp; int32_t i; int subscr_cmd_len = 4; uchar subscr[4];// = { 0x59, 0x14 }; // subscriptions uchar dates[] = { 0x5b, 0x00, 0x14 }; //validity dates uchar subscr_len = 0, n = 0; struct dre_data *csystem_data = reader->csystem_data; cs_clear_entitlement(reader); switch(csystem_data->provider) { case 0x02: case 0x03: subscr[0] = 0x84; subscr[1] = 0; subscr[2] = 0x5F; subscr[3] = csystem_data->provider; dates[0] = 0x85; subscr_len = 0x5F; break; case 0x18: case 0x19: case 0x1A: subscr[0] = 0x94; subscr[1] = 0; subscr[2] = 0x5F; subscr[3] = csystem_data->provider; dates[0] = 0x95; subscr_len = 0x5F; break; default: subscr[0] = 0x59; subscr[1] = csystem_data->provider; subscr_len = 0x20; subscr_cmd_len = 2; } chk_subscr: if((dre_script(subscr, subscr_cmd_len, 0, 0, 0))) //ask subscription packages, returns error on 0x11 card { uchar pbm[subscr_len]; char tmp_dbg[subscr_len*2+1]; memcpy(pbm, cta_res + 3, cta_lr - 6); rdr_log_dbg(reader, D_READER, "pbm: %s", cs_hexdump(0, pbm, subscr_len, tmp_dbg, sizeof(tmp_dbg))); for(i = 0; i < subscr_len; i++) if(pbm[i] != 0xff) { dates[1] = i; dates[2] = csystem_data->provider; dre_cmd(dates); //ask for validity dates time_t start; time_t end; start = (cta_res[3] << 24) | (cta_res[4] << 16) | (cta_res[5] << 8) | cta_res[6]; end = (cta_res[7] << 24) | (cta_res[8] << 16) | (cta_res[9] << 8) | cta_res[10]; struct tm temp; localtime_r(&start, &temp); int32_t startyear = temp.tm_year + 1900; int32_t startmonth = temp.tm_mon + 1; int32_t startday = temp.tm_mday; localtime_r(&end, &temp); int32_t endyear = temp.tm_year + 1900; int32_t endmonth = temp.tm_mon + 1; int32_t endday = temp.tm_mday; rdr_log(reader, "active package %i valid from %04i/%02i/%02i to %04i/%02i/%02i", i+n, startyear, startmonth, startday, endyear, endmonth, endday); cs_add_entitlement(reader, reader->caid, b2ll(4, reader->prid[0]), 0, i+n, start, end, 5, 1); } } if(subscr_len == 0x5F) // read second part subscription packages, for DRE3 and DRE4 { subscr[1] = 0x5F; subscr[2] = 0x21; subscr_len = 0x21; n = 0x5F; goto chk_subscr; } return OK; }
int32_t ICC_Async_CardWrite(struct s_reader *reader, unsigned char *command, uint16_t command_len, unsigned char *rsp, uint16_t *lr) { int32_t ret; *lr = 0; //will be returned in case of error if(reader->crdr.card_write) { call(reader->crdr.card_write(reader, command, rsp, lr, command_len)); return OK; } if(reader->crdr.lock) { reader->crdr.lock(reader); } int32_t try = 1; uint16_t type = 0; do { switch(reader->protocol_type) { if(try > 1) rdr_log(reader, "Warning: needed try nr %i, next ECM has some delay", try); case ATR_PROTOCOL_TYPE_T0: ret = Protocol_T0_Command(reader, command, command_len, rsp, lr); type = 0; break; case ATR_PROTOCOL_TYPE_T1: ret = Protocol_T1_Command(reader, command, command_len, rsp, lr); type = 1; if(ret != OK && !reader->crdr.skip_t1_command_retries) { //try to resync rdr_log(reader, "Resync error: readtimeouts %d/%d (max/min) us, writetimeouts %d/%d (max/min) us", reader->maxreadtimeout, reader->minreadtimeout, reader->maxwritetimeout, reader->minwritetimeout); unsigned char resync[] = { 0x21, 0xC0, 0x00, 0xE1 }; ret = Protocol_T1_Command(reader, resync, sizeof(resync), rsp, lr); if(ret == OK) { //reader->ifsc = DEFAULT_IFSC; //tryfix cardtimeouts: ifsc is setup at card init, on resync it should not return to default_ifsc rdr_log(reader, "T1 Resync command succesfull ifsc = %i", reader->ifsc); ret = ERROR; } else { rdr_log(reader, "T1 Resync command error, trying to reactivate!"); ATR atr; ICC_Async_Activate(reader, &atr, reader->deprecated); if(reader->crdr.unlock) { reader->crdr.unlock(reader); } return ERROR; } } break; case ATR_PROTOCOL_TYPE_T14: ret = Protocol_T14_ExchangeTPDU(reader, command, command_len, rsp, lr); type = 14; break; default: rdr_log(reader, "ERROR: Unknown protocol type %i", reader->protocol_type); type = 99; // use 99 for unknown. ret = ERROR; } try++; } while((try < 3) && (ret != OK)); //always do one retry when failing if(reader->crdr.unlock) { reader->crdr.unlock(reader); } if(ret) { rdr_debug_mask(reader, D_TRACE, "ERROR: Protocol_T%d_Command returns error", type); return ERROR; } rdr_ddump_mask(reader, D_READER, rsp, *lr, "Answer from cardreader:"); return OK; } int32_t ICC_Async_GetTimings(struct s_reader *reader, uint32_t wait_etu) { int32_t timeout = ETU_to_us(reader, wait_etu); rdr_debug_mask(reader, D_IFD, "Setting timeout to %i ETU (%d us)", wait_etu, timeout); return timeout; }
static int32_t dre_command(struct s_reader *reader, const uchar *cmd, int32_t cmdlen, unsigned char *cta_res, uint16_t *p_cta_lr, uint8_t crypted, uint8_t keynum, uint8_t dre_v, uint8_t cmd_type) //attention: inputcommand will be changed!!!! answer will be in cta_res, length cta_lr ; returning 1 = no error, return ERROR = err { uchar startcmd[] = { 0x80, 0xFF, 0x10, 0x01, 0x05 }; //any command starts with this, //last byte is nr of bytes of the command that will be sent //after the startcmd //response on startcmd+cmd: = { 0x61, 0x05 } //0x61 = "OK", last byte is nr. of bytes card will send uchar reqans[] = { 0x00, 0xC0, 0x00, 0x00, 0x08 }; //after command answer has to be requested, //last byte must be nr. of bytes that card has reported to send uchar command[256]; uchar checksum; char tmp[256]; int32_t headerlen = sizeof(startcmd); if(dre_v > 0) { startcmd[1] = 0; startcmd[2] = crypted; startcmd[3] = keynum; } startcmd[4] = cmdlen + 3 - cmd_type; //commandlength + type + len + checksum bytes memcpy(command, startcmd, headerlen); command[headerlen++] = cmd_type ? 0x86 : CMD_BYTE; //type command[headerlen++] = cmdlen + (cmd_type == 1 ? 0 : 1); //len = command + 1 checksum byte memcpy(command + headerlen, cmd, cmdlen); if(!cmd_type) { checksum = ~xor(cmd, cmdlen); //rdr_log_dbg(reader, D_READER, "Checksum: %02x", checksum); cmdlen += headerlen; command[cmdlen++] = checksum; } else cmdlen += headerlen; reader_cmd2icc(reader, command, cmdlen, cta_res, p_cta_lr); if((*p_cta_lr != 2) || (cta_res[0] != OK_RESPONSE)) { rdr_log(reader, "command sent to card: %s", cs_hexdump(0, command, cmdlen, tmp, sizeof(tmp))); rdr_log(reader, "unexpected answer from card: %s", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp))); return ERROR; //error } rdr_log_dbg(reader, D_READER, "command sent to card: %s", cs_hexdump(0, command, cmdlen, tmp, sizeof(tmp))); rdr_log_dbg(reader, D_READER, "answer from card: %s", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp))); reqans[4] = cta_res[1]; //adapt length byte reader_cmd2icc(reader, reqans, 5, cta_res, p_cta_lr); if(cta_res[0] != CMD_BYTE) { rdr_log(reader, "unknown response: cta_res[0] expected to be %02x, is %02x", CMD_BYTE, cta_res[0]); return ERROR; } if((cta_res[1] == 0x03) && (cta_res[2] == 0xe2)) { switch(cta_res[3+dre_v]) { case 0xe1: rdr_log(reader, "checksum error: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp))); break; case 0xe2: rdr_log(reader, "wrong cmd len: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp))); break; case 0xe3: rdr_log(reader, "illegal command: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp))); break; case 0xe4: rdr_log(reader, "wrong adress type: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp))); break; case 0xe5: rdr_log(reader, "wrong CMD param: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp))); break; case 0xe6: rdr_log(reader, "wrong UA: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp))); break; case 0xe7: rdr_log(reader, "wrong group: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp))); break; case 0xe8: rdr_log(reader, "wrong key num: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp))); break; case 0xeb: rdr_log(reader, "No key or subscribe : %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp))); break; case 0xec: rdr_log(reader, "wrong signature: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp))); break; case 0xed: rdr_log(reader, "wrong provider: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp))); break; case 0xef: rdr_log(reader, "wrong GEO code: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp))); break; default: rdr_log_dbg(reader, D_READER, "unknown error: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp))); break; } return ERROR; //error } int32_t length_excl_leader = *p_cta_lr; if((cta_res[*p_cta_lr - 2] == 0x90) && (cta_res[*p_cta_lr - 1] == 0x00)) { length_excl_leader -= 2; } checksum = ~xor(cta_res + 2, length_excl_leader - 3); if(cta_res[length_excl_leader - 1] != checksum) { rdr_log(reader, "checksum does not match, expected %02x received %02x:%s", checksum, cta_res[length_excl_leader - 1], cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp))); return ERROR; //error } return OK; }
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; }