int32_t cardreader_do_ecm(struct s_reader *reader, ECM_REQUEST *er, struct s_ecm_answer *ea) { int32_t rc = -1; if((rc = cardreader_do_checkhealth(reader))) { rdr_log_dbg(reader, D_READER, "%s: cardreader_do_checkhealth returned rc=%d", __func__, rc); struct s_client *cl = reader->client; if(cl) { cl->last_srvid = er->srvid; cl->last_caid = er->caid; cl->last_provid = er->prid; cl->last = time((time_t *)0); } if(reader->csystem_active && reader->csystem && reader->csystem->do_ecm) { rc = reader->csystem->do_ecm(reader, er, ea); rdr_log_dbg(reader, D_READER, "%s: after csystem->do_ecm rc=%d", __func__, rc); } else { rc = 0; } } rdr_log_dbg(reader, D_READER, "%s: ret rc=%d", __func__, rc); return (rc); }
static int32_t pcsc_do_api(struct s_reader *pcsc_reader, const uchar *buf, uchar *cta_res, uint16_t *cta_lr, int32_t l) { LONG rv; DWORD dwSendLength, dwRecvLength; *cta_lr = 0; if(!l) { rdr_log(pcsc_reader, "ERROR: Data length to be send to the pcsc_reader is %d", l); return ERROR; } char tmp[l * 3]; dwRecvLength = CTA_RES_LEN; struct pcsc_data *crdr_data = pcsc_reader->crdr_data; if(crdr_data->dwActiveProtocol == SCARD_PROTOCOL_T0) { // explanantion as to why we do the test on buf[4] : // Issuing a command without exchanging data : //To issue a command to the card that does not involve the exchange of data (either sent or received), the send and receive buffers must be formatted as follows. //The pbSendBuffer buffer must contain the CLA, INS, P1, and P2 values for the T=0 operation. The P3 value is not sent. (This is to differentiate the header from the case where 256 bytes are expected to be returned.) //The cbSendLength parameter must be set to four, the size of the T=0 header information (CLA, INS, P1, and P2). //The pbRecvBuffer will receive the SW1 and SW2 status codes from the operation. //The pcbRecvLength should be at least two and will be set to two upon return. if(buf[4]) { dwSendLength = l; } else { dwSendLength = l - 1; } rdr_log_dbg(pcsc_reader, D_DEVICE, "sending %lu bytes to PCSC : %s", (unsigned long)dwSendLength, cs_hexdump(1, buf, l, tmp, sizeof(tmp))); rv = SCardTransmit(crdr_data->hCard, SCARD_PCI_T0, (LPCBYTE) buf, dwSendLength, NULL, (LPBYTE) cta_res, (LPDWORD) &dwRecvLength); *cta_lr = dwRecvLength; } else if(crdr_data->dwActiveProtocol == SCARD_PROTOCOL_T1) { dwSendLength = l; rdr_log_dbg(pcsc_reader, D_DEVICE, "sending %lu bytes to PCSC : %s", (unsigned long)dwSendLength, cs_hexdump(1, buf, l, tmp, sizeof(tmp))); rv = SCardTransmit(crdr_data->hCard, SCARD_PCI_T1, (LPCBYTE) buf, dwSendLength, NULL, (LPBYTE) cta_res, (LPDWORD) &dwRecvLength); *cta_lr = dwRecvLength; } else { rdr_log_dbg(pcsc_reader, D_DEVICE, "PCSC invalid protocol (T=%lu)", (unsigned long)crdr_data->dwActiveProtocol); return ERROR; } rdr_log_dbg(pcsc_reader, D_DEVICE, "received %d bytes from PCSC with rv=%lx : %s", *cta_lr, (unsigned long)rv, cs_hexdump(1, cta_res, *cta_lr, tmp, sizeof(tmp))); rdr_log_dbg(pcsc_reader, D_DEVICE, "PCSC doapi (%lx ) (T=%d), %d", (unsigned long)rv, (crdr_data->dwActiveProtocol == SCARD_PROTOCOL_T0 ? 0 : 1), *cta_lr); if(rv == SCARD_S_SUCCESS) { return OK; } else { return ERROR; } }
static int32_t dre_do_ecm(struct s_reader *reader, const ECM_REQUEST *er, struct s_ecm_answer *ea) { def_resp; char tmp_dbg[256]; struct dre_data *csystem_data = reader->csystem_data; if(reader->caid == 0x4ae0) { uchar ecmcmd41[] = { 0x41, 0x58, 0x1f, 0x00, //fixed part, dont change 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, //0x01 - 0x08: next key 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, //0x11 - 0x18: current key 0x3b, 0x59, 0x11 //0x3b = keynumber, can be a value 56 ;; 0x59 number of package = 58+1 - Pay Package ;; 0x11 = provider }; ecmcmd41[22] = csystem_data->provider; memcpy(ecmcmd41 + 4, er->ecm + 8, 16); ecmcmd41[20] = er->ecm[6]; //keynumber ecmcmd41[21] = 0x58 + er->ecm[25]; //package number rdr_log_dbg(reader, D_READER, "unused ECM info front:%s", cs_hexdump(0, er->ecm, 8, tmp_dbg, sizeof(tmp_dbg))); rdr_log_dbg(reader, D_READER, "unused ECM info back:%s", cs_hexdump(0, er->ecm + 24, er->ecm[2] + 2 - 24, tmp_dbg, sizeof(tmp_dbg))); if((dre_cmd(ecmcmd41))) //ecm request { if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00)) { return ERROR; } //exit if response is not 90 00 memcpy(ea->cw, cta_res + 11, 8); memcpy(ea->cw + 8, cta_res + 3, 8); return OK; } } else { uchar ecmcmd51[] = { 0x51, 0x02, 0x56, 0x05, 0x00, 0x4A, 0xE3, //fixed header? 0x9C, 0xDA, //first three nibbles count up, fourth nibble counts down; all ECMs sent twice 0xC1, 0x71, 0x21, 0x06, 0xF0, 0x14, 0xA7, 0x0E, //next key? 0x89, 0xDA, 0xC9, 0xD7, 0xFD, 0xB9, 0x06, 0xFD, //current key? 0xD5, 0x1E, 0x2A, 0xA3, 0xB5, 0xA0, 0x82, 0x11, //key or signature? 0x14 //provider }; memcpy(ecmcmd51 + 1, er->ecm + 5, 0x21); rdr_log_dbg(reader, D_READER, "unused ECM info front:%s", cs_hexdump(0, er->ecm, 5, tmp_dbg, sizeof(tmp_dbg))); rdr_log_dbg(reader, D_READER, "unused ECM info back:%s", cs_hexdump(0, er->ecm + 37, 4, tmp_dbg, sizeof(tmp_dbg))); ecmcmd51[33] = csystem_data->provider; //no part of sig if((dre_cmd(ecmcmd51))) //ecm request { if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00)) { return ERROR; } //exit if response is not 90 00 DREover(er->ecm, cta_res + 3); memcpy(ea->cw, cta_res + 11, 8); memcpy(ea->cw + 8, cta_res + 3, 8); return OK; } } return ERROR; }
void cardreader_process_ecm(struct s_reader *reader, struct s_client *cl, ECM_REQUEST *er) { cs_log_dump_dbg(D_ATR, er->ecm, er->ecmlen, "ecm:"); struct timeb tps, tpe; struct s_ecm_answer ea; memset(&ea, 0, sizeof(struct s_ecm_answer)); cs_ftime(&tps); int32_t rc = cardreader_do_ecm(reader, er, &ea); cs_ftime(&tpe); rdr_log_dbg(reader, D_READER, "%s: cardreader_do_ecm returned rc=%d (ERROR=%d)", __func__, rc, ERROR); ea.rc = E_FOUND; //default assume found ea.rcEx = 0; //no special flag if(rc == ERROR) { char buf[CS_SERVICENAME_SIZE]; rdr_log_dbg(reader, D_READER, "Error processing ecm for caid %04X, provid %06X, srvid %04X, servicename: %s", er->caid, er->prid, er->srvid, get_servicename(cl, er->srvid, er->prid, er->caid, buf, sizeof(buf))); ea.rc = E_NOTFOUND; ea.rcEx = 0; ICC_Async_DisplayMsg(reader, "Eer"); } if(rc == E_CORRUPT) { char buf[CS_SERVICENAME_SIZE]; rdr_log_dbg(reader, D_READER, "Error processing ecm for caid %04X, provid %06X, srvid %04X, servicename: %s", er->caid, er->prid, er->srvid, get_servicename(cl, er->srvid, er->prid, er->caid, buf, sizeof(buf))); ea.rc = E_NOTFOUND; ea.rcEx = E2_WRONG_CHKSUM; //flag it as wrong checksum memcpy(ea.msglog, "Invalid ecm type for card", 25); } write_ecm_answer(reader, er, ea.rc, ea.rcEx, ea.cw, ea.msglog, ea.tier, &ea.cw_ex); cl->lastecm = time((time_t *)0); char ecmd5[17 * 3]; cs_hexdump(0, er->ecmd5, 16, ecmd5, sizeof(ecmd5)); rdr_log_dbg(reader, D_READER, "ecm hash: %s real time: %"PRId64" ms", ecmd5, comp_timeb(&tpe, &tps)); reader_post_process(reader); }
bool detect_db2com_reader(struct s_reader *reader) { struct stat sb; if(stat(DEV_MULTICAM, &sb) == -1) { return false; } if(stat(reader->device, &sb) == 0) { if(S_ISCHR(sb.st_mode)) { int32_t dev_major = major(sb.st_rdev); int32_t dev_minor = minor(sb.st_rdev); if(dev_major == 4 || dev_major == 5) { int32_t rc; switch(dev_minor & 0x3F) { case 0: rc = R_DB2COM1; break; case 1: rc = R_DB2COM2; break; default: return false; } reader->typ = rc; } rdr_log_dbg(reader, D_READER, "device is major: %d, minor: %d, typ=%d", dev_major, dev_minor, reader->typ); } } return true; }
static int32_t griffin_get_emm_type(EMM_PACKET *ep, struct s_reader *rdr) { memcpy(ep->hexserial, ep->emm + 3, 4); switch(ep->emm[0]) { case 0x82: case 0x83: if(memcmp(ep->hexserial, rdr->sa[0], 4) == 0) { if(DEBUG) { rdr_log_sensitive(rdr, "SHARED EMM TYPE:%02X SA:{%02X %02X %02X %02X}", ep->emm[0], ep->emm[3], ep->emm[4], ep->emm[5], ep->emm[6]); } ep->type = SHARED; } if(memcmp(ep->hexserial, rdr->sa[1], 4) == 0) { if(DEBUG) { rdr_log_sensitive(rdr, "UNIQUE EMM TYPE:%02X SA:{%02X %02X %02X %02X}", ep->emm[0], ep->emm[3], ep->emm[4], ep->emm[5], ep->emm[6]); } ep->type = UNIQUE; } break; default: ep->type = UNKNOWN; rdr_log_dbg(rdr, D_EMM, "UNKNOWN EMM TYPE:%02X SA:%02X %02X %02X %02X", ep->emm[0], ep->emm[3], ep->emm[4], ep->emm[5], ep->emm[6]); } return OK; }
static int32_t pcsc_close(struct s_reader *pcsc_reader) { struct pcsc_data *crdr_data = pcsc_reader->crdr_data; rdr_log_dbg(pcsc_reader, D_IFD, "PCSC : Closing device %s", pcsc_reader->device); SCardDisconnect(crdr_data->hCard, SCARD_LEAVE_CARD); SCardReleaseContext(crdr_data->hContext); return OK; }
static int32_t Sc8in1_DebugSignals(struct s_reader *reader, uint16_t slot, const char *extra) { uint32_t msr; if(ioctl(reader->handle, TIOCMGET, &msr) < 0) { return ERROR; } rdr_log_dbg(reader, D_DEVICE, "SC8in1: Signals(%s): Slot: %i, DTR: %u, RTS: %u", extra, slot, msr & TIOCM_DTR ? 1 : 0, msr & TIOCM_RTS ? 1 : 0); return OK; }
static bool db2com_DTR_RTS(struct s_reader *reader, int32_t *dtr, int32_t *rts) { int32_t rc; uint16_t msr; uint16_t rts_bits[2] = { 0x10, 0x800 }; uint16_t dtr_bits[2] = {0x100, 0 }; int32_t mcport = reader->typ == R_DB2COM2; rc = ioctl(reader->fdmc, MULTICAM_GET_PCDAT, &msr); if(rc < 0) { return ERROR; } if(dtr) { rdr_log_dbg(reader, D_DEVICE, "%s DTR:%s", __func__, *dtr ? "set" : "clear"); if(dtr_bits[mcport]) { if(*dtr) { msr &= (uint16_t)(~dtr_bits[mcport]); } else { msr |= dtr_bits[mcport]; } rc = ioctl(reader->fdmc, MULTICAM_SET_PCDAT, &msr); } else { rc = 0; // Dummy, can't handle using multicam.o } } if(rts) { rdr_log_dbg(reader, D_DEVICE, "%s RTS:%s", __func__, *rts ? "set" : "clear"); if(*rts) { msr &= (uint16_t)(~rts_bits[mcport]); } else { msr |= rts_bits[mcport]; } rc = ioctl(reader->fdmc, MULTICAM_SET_PCDAT, &msr); } if(rc < 0) { return ERROR; } return OK; }
static int32_t Cool_SetClockrate(struct s_reader *reader, int32_t mhz) { struct cool_data *crdr_data = reader->crdr_data; uint32_t clk; clk = mhz * 10000; int32_t ret = cnxt_smc_set_clock_freq(crdr_data->handle, clk); coolapi_check_error("cnxt_smc_set_clock_freq", ret); call(Cool_FastReset(reader)); rdr_log_dbg(reader, D_DEVICE, "COOL: clock succesfully set to %i", clk); return OK; }
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 struct dre_data *csystem_data = reader->csystem_data; cs_clear_entitlement(reader); cmd59[1] = csystem_data->provider; if((dre_cmd(cmd59))) //ask subscription packages, returns error on 0x11 card { uchar pbm[32]; char tmp_dbg[65]; memcpy(pbm, cta_res + 3, cta_lr - 6); rdr_log_dbg(reader, D_READER, "pbm: %s", cs_hexdump(0, pbm, 32, tmp_dbg, sizeof(tmp_dbg))); if(pbm[0] == 0xff) { rdr_log(reader, "no active packages"); } else for(i = 0; i < 32; i++) if(pbm[i] != 0xff) { cmd5b[1] = i; cmd5b[2] = csystem_data->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; rdr_log(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, 1); } } return OK; }
int32_t cardreader_do_checkhealth(struct s_reader *reader) { struct s_client *cl = reader->client; if(reader_card_inserted(reader)) { if(reader->card_status == NO_CARD || reader->card_status == UNKNOWN) { rdr_log(reader, "card detected"); led_status_card_detected(); reader->card_status = CARD_NEED_INIT; add_job(cl, ACTION_READER_RESET, NULL, 0); } } else { rdr_log_dbg(reader, D_READER, "%s: !reader_card_inserted", __func__); if(reader->card_status == CARD_INSERTED || reader->card_status == CARD_NEED_INIT) { rdr_log(reader, "card ejected"); reader_nullcard(reader); if(reader->csystem && reader->csystem->card_done) reader->csystem->card_done(reader); NULLFREE(reader->csystem_data); if(cl) { cl->lastemm = 0; cl->lastecm = 0; } led_status_card_ejected(); } reader->card_status = NO_CARD; } rdr_log_dbg(reader, D_READER, "%s: reader->card_status = %d, ret = %d", __func__, reader->card_status, reader->card_status == CARD_INSERTED); return reader->card_status == CARD_INSERTED; }
static int32_t pcsc_activate_card(struct s_reader *pcsc_reader, uchar *atr, uint16_t *atr_size) { struct pcsc_data *crdr_data = pcsc_reader->crdr_data; LONG rv; DWORD dwState, dwAtrLen, dwReaderLen; unsigned char pbAtr[ATR_MAX_SIZE]; char tmp[sizeof(pbAtr) * 3 + 1]; rdr_log_dbg(pcsc_reader, D_DEVICE, "PCSC initializing card in (%s)", crdr_data->pcsc_name); dwAtrLen = sizeof(pbAtr); dwReaderLen = 0; rdr_log_dbg(pcsc_reader, D_DEVICE, "PCSC resetting card in (%s) with handle %ld", crdr_data->pcsc_name, (long)(crdr_data->hCard)); rv = SCardReconnect(crdr_data->hCard, SCARD_SHARE_EXCLUSIVE, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, SCARD_RESET_CARD, &crdr_data->dwActiveProtocol); if(rv != SCARD_S_SUCCESS) { rdr_log_dbg(pcsc_reader, D_DEVICE, "ERROR: PCSC failed to reset card (%lx)", (unsigned long)rv); return ERROR; } rdr_log_dbg(pcsc_reader, D_DEVICE, "PCSC resetting done on card in (%s)", crdr_data->pcsc_name); rdr_log_dbg(pcsc_reader, D_DEVICE, "PCSC Protocol (T=%d)", (crdr_data->dwActiveProtocol == SCARD_PROTOCOL_T0 ? 0 : 1)); rdr_log_dbg(pcsc_reader, D_DEVICE, "PCSC getting ATR for card in (%s)", crdr_data->pcsc_name); rv = SCardStatus(crdr_data->hCard, NULL, &dwReaderLen, &dwState, &crdr_data->dwActiveProtocol, pbAtr, &dwAtrLen); if(rv == SCARD_S_SUCCESS) { rdr_log_dbg(pcsc_reader, D_DEVICE, "PCSC Protocol (T=%d)", (crdr_data->dwActiveProtocol == SCARD_PROTOCOL_T0 ? 0 : 1)); memcpy(atr, pbAtr, dwAtrLen); *atr_size = dwAtrLen; rdr_log(pcsc_reader, "ATR: %s", cs_hexdump(1, (uchar *)pbAtr, dwAtrLen, tmp, sizeof(tmp))); memcpy(pcsc_reader->card_atr, pbAtr, dwAtrLen); pcsc_reader->card_atr_length = dwAtrLen; return OK; } else { rdr_log_dbg(pcsc_reader, D_DEVICE, "ERROR: PCSC failed to get ATR for card (%lx)", (unsigned long)rv); } return ERROR; }
static int32_t Cool_Reset(struct s_reader *reader, ATR *atr) { struct cool_data *crdr_data = reader->crdr_data; int32_t ret; if(!reader->ins7e11_fast_reset) { //set freq to reader->cardmhz if necessary uint32_t clk; ret = cnxt_smc_get_clock_freq(crdr_data->handle, &clk); coolapi_check_error("cnxt_smc_get_clock_freq", ret); if(clk / 10000 != (uint32_t)reader->cardmhz) { rdr_log_dbg(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_log(reader, "Doing fast reset"); } //reset card ret = cnxt_smc_reset_card(crdr_data->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(crdr_data->handle, buf, &n); coolapi_check_error("cnxt_smc_get_atr", ret); call(!ATR_InitFromArray(atr, buf, n) != ERROR); { cs_sleepms(50); 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; }
static int32_t Cool_WriteSettings(struct s_reader *reader, struct s_cardreader_settings *s) { struct cool_data *crdr_data = reader->crdr_data; //first set freq back to reader->mhz if necessary uint32_t clk; int32_t ret = cnxt_smc_get_clock_freq(crdr_data->handle, &clk); coolapi_check_error("cnxt_smc_get_clock_freq", ret); if(clk / 10000 != (uint32_t)reader->mhz) { rdr_log_dbg(reader, D_DEVICE, "COOL: clock freq: %i, scheduling change to %i", clk, reader->mhz * 10000); call(Cool_SetClockrate(reader, reader->mhz)); } uint32_t BLKTime = 0, CHTime = 0; uint8_t BKGuardTime = 0; switch(reader->protocol_type) { case ATR_PROTOCOL_TYPE_T1: if(reader->BWT > 11) { BLKTime = (reader->BWT - 11); } if(reader->CWT > 11) { CHTime = (reader->CWT - 11); } if(s->BGT > 11) { BKGuardTime = (s->BGT - 11); } else { BKGuardTime = 11; } //For T1, the BGT minimum time shall be 22 work etus. BGT is effectively offset by 11 etus internally. if(!crdr_data->pps) { ret = cnxt_smc_set_F_D_factors(crdr_data->handle, s->F, s->D); coolapi_check_error("cnxt_smc_set_F_D_factors", ret); } break; case ATR_PROTOCOL_TYPE_T0: case ATR_PROTOCOL_TYPE_T14: default: BLKTime = 0; if(s->WWT > 12) { CHTime = (s->WWT - 12); } if(s->BGT > 12) { BKGuardTime = (s->BGT - 12); } if(BKGuardTime < 4) { BKGuardTime = 4; } //For T0, the BGT minimum time shall be 16 work etus. BGT is effectively offset by 12 etus internally. if(!crdr_data->pps) { if(reader->protocol_type == ATR_PROTOCOL_TYPE_T14) { ret = cnxt_smc_set_F_D_factors(crdr_data->handle, 620, 1); } else { ret = cnxt_smc_set_F_D_factors(crdr_data->handle, s->F, s->D); } coolapi_check_error("cnxt_smc_set_F_D_factors", ret); } break; } ret = cnxt_smc_set_convention(crdr_data->handle, reader->convention); coolapi_check_error("cnxt_smc_set_convention", ret); CNXT_SMC_TIMEOUT timeout; ret = cnxt_smc_get_config_timeout(crdr_data->handle, &timeout); coolapi_check_error("cnxt_smc_get_config_timeout", ret); timeout.BLKTime = BLKTime; timeout.CHTime = CHTime; timeout.CHGuardTime = s->EGT; timeout.BKGuardTime = BKGuardTime; ret = cnxt_smc_set_config_timeout(crdr_data->handle, timeout); coolapi_check_error("cnxt_smc_set_config_timeout", ret); Cool_Print_Comm_Parameters(reader); 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 void process_clients(void) { int32_t i, k, j, rc, pfdcount = 0; struct s_client *cl; struct s_reader *rdr; struct pollfd *pfd; struct s_client **cl_list; struct timeb start, end; // start time poll, end time poll uint32_t cl_size = 0; uchar buf[10]; if(pipe(thread_pipe) == -1) { printf("cannot create pipe, errno=%d\n", errno); exit(1); } cl_size = chk_resize_cllist(&pfd, &cl_list, 0, 100); pfd[pfdcount].fd = thread_pipe[0]; pfd[pfdcount].events = POLLIN | POLLPRI; cl_list[pfdcount] = NULL; while(!exit_oscam) { pfdcount = 1; //connected tcp clients for(cl = first_client->next; cl; cl = cl->next) { if(cl->init_done && !cl->kill && cl->pfd && cl->typ == 'c' && !cl->is_udp) { if(cl->pfd && !cl->thread_active) { cl_size = chk_resize_cllist(&pfd, &cl_list, cl_size, pfdcount); cl_list[pfdcount] = cl; pfd[pfdcount].fd = cl->pfd; pfd[pfdcount++].events = POLLIN | POLLPRI; } } //reader: //TCP: // - TCP socket must be connected // - no active init thread //UDP: // - connection status ignored // - no active init thread rdr = cl->reader; if(rdr && cl->typ == 'p' && cl->init_done) { if(cl->pfd && !cl->thread_active && ((rdr->tcp_connected && rdr->ph.type == MOD_CONN_TCP) || (rdr->ph.type == MOD_CONN_UDP))) { cl_size = chk_resize_cllist(&pfd, &cl_list, cl_size, pfdcount); cl_list[pfdcount] = cl; pfd[pfdcount].fd = cl->pfd; pfd[pfdcount++].events = (POLLIN | POLLPRI); } } } //server (new tcp connections or udp messages) for(k = 0; k < CS_MAX_MOD; k++) { struct s_module *module = &modules[k]; if((module->type & MOD_CONN_NET)) { for(j = 0; j < module->ptab.nports; j++) { if(module->ptab.ports[j].fd) { cl_size = chk_resize_cllist(&pfd, &cl_list, cl_size, pfdcount); cl_list[pfdcount] = NULL; pfd[pfdcount].fd = module->ptab.ports[j].fd; pfd[pfdcount++].events = (POLLIN | POLLPRI); } } } } if(pfdcount >= 1024) { cs_log("WARNING: too many users!"); } cs_ftime(&start); // register start time rc = poll(pfd, pfdcount, 5000); if(rc < 1) { continue; } cs_ftime(&end); // register end time for(i = 0; i < pfdcount && rc > 0; i++) { if(pfd[i].revents == 0) { continue; } // skip sockets with no changes rc--; //event handled! cs_log_dbg(D_TRACE, "[OSCAM] new event %d occurred on fd %d after %"PRId64" ms inactivity", pfd[i].revents, pfd[i].fd, comp_timeb(&end, &start)); //clients cl = cl_list[i]; if(cl && !is_valid_client(cl)) { continue; } if(pfd[i].fd == thread_pipe[0] && (pfd[i].revents & (POLLIN | POLLPRI))) { // a thread ended and cl->pfd should be added to pollfd list again (thread_active==0) int32_t len = read(thread_pipe[0], buf, sizeof(buf)); if(len == -1) { cs_log_dbg(D_TRACE, "[OSCAM] Reading from pipe failed (errno=%d %s)", errno, strerror(errno)); } cs_log_dump_dbg(D_TRACE, buf, len, "[OSCAM] Readed:"); continue; } //clients // message on an open tcp connection if(cl && cl->init_done && cl->pfd && (cl->typ == 'c' || cl->typ == 'm')) { if(pfd[i].fd == cl->pfd && (pfd[i].revents & (POLLHUP | POLLNVAL | POLLERR))) { //client disconnects kill_thread(cl); continue; } if(pfd[i].fd == cl->pfd && (pfd[i].revents & (POLLIN | POLLPRI))) { add_job(cl, ACTION_CLIENT_TCP, NULL, 0); } } //reader // either an ecm answer, a keepalive or connection closed from a proxy // physical reader ('r') should never send data without request rdr = NULL; struct s_client *cl2 = NULL; if(cl && cl->typ == 'p') { rdr = cl->reader; if(rdr) { cl2 = rdr->client; } } if(rdr && cl2 && cl2->init_done) { if(cl2->pfd && pfd[i].fd == cl2->pfd && (pfd[i].revents & (POLLHUP | POLLNVAL | POLLERR))) { //connection to remote proxy was closed //oscam should check for rdr->tcp_connected and reconnect on next ecm request sent to the proxy network_tcp_connection_close(rdr, "closed"); rdr_log_dbg(rdr, D_READER, "connection closed"); } if(cl2->pfd && pfd[i].fd == cl2->pfd && (pfd[i].revents & (POLLIN | POLLPRI))) { add_job(cl2, ACTION_READER_REMOTE, NULL, 0); } } //server sockets // new connection on a tcp listen socket or new message on udp listen socket if(!cl && (pfd[i].revents & (POLLIN | POLLPRI))) { for(k = 0; k < CS_MAX_MOD; k++) { struct s_module *module = &modules[k]; if((module->type & MOD_CONN_NET)) { for(j = 0; j < module->ptab.nports; j++) { if(module->ptab.ports[j].fd && module->ptab.ports[j].fd == pfd[i].fd) { accept_connection(module, k, j); } } } } } } cs_ftime(&start); // register start time for new poll next run first_client->last = time((time_t *)0); } NULLFREE(pfd); NULLFREE(cl_list); return; }
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; }
int32_t Protocol_T1_Command(struct s_reader *reader, unsigned char *command, uint16_t command_len, unsigned char *rsp, uint16_t *lr) { uint8_t block_data[T1_BLOCK_MAX_SIZE]; uint8_t rsp_type, bytes, nr, wtx; uint16_t counter; int32_t ret, timeout; bool more; uint32_t block_length = 0; if(command[1] == T1_BLOCK_S_IFS_REQ) { uint8_t inf = command[3]; /* Create an IFS request S-Block */ timeout = ICC_Async_GetTimings(reader, reader->CWT); // we are going to send: CWT timeout //cs_sleepus(reader->block_delay); // we were receiving, now sending so wait BGT time ret = T1_Block_SendSBlock(reader, block_data, T1_BLOCK_S_IFS_REQ, 1, &inf, timeout); rdr_log_dbg(reader, D_IFD, "Protocol: Sending block S(IFS request, %d)", inf); /* Receive a block */ timeout = ICC_Async_GetTimings(reader, reader->BWT); // we are going to receive so set Block Waiting Timeout! //cs_sleepus(reader->block_delay); // we were sending, now receiving so wait BGT time ret = Protocol_T1_ReceiveBlock(reader, block_data, &block_length, &rsp_type, timeout); if(ret == OK) { /* Positive IFS Response S-Block received */ if(rsp_type == T1_BLOCK_S_IFS_RES) { rdr_log_dbg(reader, D_IFD, "Protocol: Received block S(IFS response, %d)", block_data[3]); } } return ret; } else if(command[1] == T1_BLOCK_S_RESYNCH_REQ) { /* Create an Resynch request S-Block */ timeout = ICC_Async_GetTimings(reader, reader->CWT); // we are going to send: CWT timeout //cs_sleepus(reader->block_delay); // we were receiving, now sending so wait BGT time ret = T1_Block_SendSBlock(reader, block_data, T1_BLOCK_S_RESYNCH_REQ, 0, NULL, timeout); rdr_log_dbg(reader, D_IFD, "Protocol: Sending block S(RESYNCH request)"); /* Receive a block */ timeout = ICC_Async_GetTimings(reader, reader->BWT); // we are going to receive so set Block Waiting Timeout! //cs_sleepus(reader->block_delay); // we were sending, now receiving so wait BGT time ret = Protocol_T1_ReceiveBlock(reader, block_data, &block_length, &rsp_type, timeout); if(ret == OK) { /* Positive IFS Response S-Block received */ if(rsp_type == T1_BLOCK_S_RESYNCH_RES) { rdr_log_dbg(reader, D_IFD, "Protocol: Received block S(RESYNCH response)"); reader->ns = 0; } } return ret; } /* Calculate the number of bytes to send */ counter = 0; bytes = MIN(command_len, reader->ifsc); /* See if chaining is needed */ more = (command_len > reader->ifsc); /* Increment ns */ reader->ns = (reader->ns == 1) ? 0 : 1; //toggle from 0 to 1 and back /* Create an I-Block */ timeout = ICC_Async_GetTimings(reader, reader->CWT); // we are going to send: CWT timeout //cs_sleepus(reader->block_delay); // we were receiving, now sending so wait BGT time ret = T1_Block_SendIBlock(reader, block_data, bytes, command, reader->ns, more, timeout); rdr_log_dbg(reader, D_IFD, "Sending block I(%d,%d)", reader->ns, more); while((ret == OK) && more) { /* Receive a block */ timeout = ICC_Async_GetTimings(reader, reader->BWT); // we are going to receive so set Block Waiting Timeout! //cs_sleepus(reader->block_delay); // we were sending, now receiving so wait BGT time ret = Protocol_T1_ReceiveBlock(reader, block_data, &block_length, &rsp_type, timeout); if(ret == OK) { /* Positive ACK R-Block received */ if(rsp_type == T1_BLOCK_R_OK) { rdr_log_dbg(reader, D_IFD, "Protocol: Received block R(%d)", T1_Block_GetNR(block_data)); /* Increment ns */ reader->ns = (reader->ns == 1) ? 0 : 1; //toggle from 0 to 1 and back /* Calculate the number of bytes to send */ counter += bytes; bytes = MIN(command_len - counter, reader->ifsc); /* See if chaining is needed */ more = (command_len - counter > reader->ifsc); /* Send an I-Block */ timeout = ICC_Async_GetTimings(reader, reader->CWT); // we are going to send: CWT timeout //cs_sleepus(reader->block_delay); // we were receiving, now sending so wait BGT time ret = T1_Block_SendIBlock(reader, block_data, bytes, command + counter, reader->ns, more, timeout); rdr_log_dbg(reader, D_IFD, "Protocol: Sending block I(%d,%d)", reader->ns, more); } else { rdr_log_dbg(reader, D_TRACE, "ERROR: T1 Command %02X not implemented", rsp_type); return ERROR; } } else { rdr_log_dbg(reader, D_TRACE, "ERROR: T1 Command returned error"); return ERROR; } } /* Reset counter */ counter = 0; more = 1; wtx = 1; while((ret == OK) && more) { /* Receive a block */ timeout = ICC_Async_GetTimings(reader, wtx * reader->BWT); // we are going to receive so set Block Waiting Timeout! //cs_sleepus(reader->block_delay); // we were sending, now receiving so wait BGT time ret = Protocol_T1_ReceiveBlock(reader, block_data, &block_length, &rsp_type, timeout); wtx = 1; // reset WTX value since its only valid for first received I block if(ret == OK) { if(rsp_type == T1_BLOCK_I) { rdr_log_dbg(reader, D_IFD, "Protocol: Received block I(%d,%d)", T1_Block_GetNS(block_data), T1_Block_GetMore(block_data)); bytes = T1_Block_GetLen(block_data); /* Calculate nr */ nr = (T1_Block_GetNS(block_data) + 1) % 2; if(counter + bytes > T1_BLOCK_MAX_SIZE) { return ERROR; } memcpy(rsp + counter, block_data + 3, bytes); counter += bytes; /* See if chaining is requested */ more = T1_Block_GetMore(block_data); if(more) { /* Send R-Block */ timeout = ICC_Async_GetTimings(reader, reader->CWT); // we are going to send: CWT timeout //cs_sleepus(reader->block_delay); // we were receiving, now sending so wait BGT time ret = T1_Block_SendRBlock(reader, block_data, T1_BLOCK_R_OK, nr, timeout); rdr_log_dbg(reader, D_IFD, "Protocol: Sending block R(%d)", nr); } } else if(rsp_type == T1_BLOCK_S_WTX_REQ) /* WTX Request S-Block received */ { /* Get wtx multiplier */ wtx = block_data[3]; rdr_log_dbg(reader, D_IFD, "Protocol: Received block S(WTX request, %d)", wtx); /* Send an WTX response S-Block */ timeout = ICC_Async_GetTimings(reader, reader->CWT); // we are going to send: CWT timeout //cs_sleepus(reader->block_delay); // we were receiving, now sending so wait BGT time ret = T1_Block_SendSBlock(reader, block_data, T1_BLOCK_S_WTX_RES, 1, &wtx, timeout); rdr_log_dbg(reader, D_IFD, "Protocol: Sending block S(WTX response, %d)", wtx); } else { rdr_log_dbg(reader, D_TRACE, "ERROR: T1 Command %02X not implemented in Receive Block", rsp_type); ret = ERROR; //not implemented } } } if(ret == OK) { *lr = counter; } return ret; }
static int32_t dre_do_ecm(struct s_reader *reader, const ECM_REQUEST *er, struct s_ecm_answer *ea) { def_resp; uint16_t overcryptId; uint8_t tmp[16]; char tmp_dbg[256]; struct dre_data *csystem_data = reader->csystem_data; if(reader->caid == 0x4ae0) { uchar ecmcmd41[] = { 0x41, 0x58, 0x1f, 0x00, //fixed part, dont change 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, //0x01 - 0x08: next key 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, //0x11 - 0x18: current key 0x3b, 0x59, 0x11 //0x3b = keynumber, can be a value 56 ;; 0x59 number of package = 58+1 - Pay Package ;; 0x11 = provider }; ecmcmd41[22] = csystem_data->provider; memcpy(ecmcmd41 + 4, er->ecm + 8, 16); ecmcmd41[20] = er->ecm[6]; //keynumber ecmcmd41[21] = 0x58 + er->ecm[25]; //package number rdr_log_dbg(reader, D_READER, "unused ECM info front:%s", cs_hexdump(0, er->ecm, 8, tmp_dbg, sizeof(tmp_dbg))); rdr_log_dbg(reader, D_READER, "unused ECM info back:%s", cs_hexdump(0, er->ecm + 24, er->ecm[2] + 2 - 24, tmp_dbg, sizeof(tmp_dbg))); if((dre_cmd(ecmcmd41))) //ecm request { if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00)) { return ERROR; } //exit if response is not 90 00 memcpy(ea->cw, cta_res + 11, 8); memcpy(ea->cw + 8, cta_res + 3, 8); return OK; } } else if(reader->caid == 0x4ae1) { if(csystem_data->provider == 0x11 || csystem_data->provider == 0x14) { uchar ecmcmd51[] = { 0x51, 0x02, 0x56, 0x05, 0x00, 0x4A, 0xE3, //fixed header? 0x9C, 0xDA, //first three nibbles count up, fourth nibble counts down; all ECMs sent twice 0xC1, 0x71, 0x21, 0x06, 0xF0, 0x14, 0xA7, 0x0E, //next key? 0x89, 0xDA, 0xC9, 0xD7, 0xFD, 0xB9, 0x06, 0xFD, //current key? 0xD5, 0x1E, 0x2A, 0xA3, 0xB5, 0xA0, 0x82, 0x11, //key or signature? 0x14 //provider }; memcpy(ecmcmd51 + 1, er->ecm + 5, 0x21); rdr_log_dbg(reader, D_READER, "unused ECM info front:%s", cs_hexdump(0, er->ecm, 5, tmp_dbg, sizeof(tmp_dbg))); rdr_log_dbg(reader, D_READER, "unused ECM info back:%s", cs_hexdump(0, er->ecm + 37, 4, tmp_dbg, sizeof(tmp_dbg))); ecmcmd51[33] = csystem_data->provider; //no part of sig if((dre_cmd(ecmcmd51))) //ecm request { if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00)) { return ERROR; } //exit if response is not 90 00 if(er->ecm[2] >= 46 && er->ecm[43] == 1 && csystem_data->provider == 0x11) { memcpy(tmp, cta_res + 11, 8); memcpy(tmp + 8, cta_res + 3, 8); overcryptId = b2i(2, &er->ecm[44]); rdr_log_dbg(reader, D_READER, "ICG ID: %04X", overcryptId); Drecrypt2OverCW(overcryptId,tmp); if(isValidDCW(tmp)) { memcpy(ea->cw, tmp, 16); return OK; } return ERROR; } DREover(reader, er->ecm, cta_res + 3); if(isValidDCW(cta_res + 3)) { memcpy(ea->cw, cta_res + 11, 8); memcpy(ea->cw + 8, cta_res + 3, 8); return OK; } } } else if((csystem_data->provider == 0x02 || csystem_data->provider == 0x03) && er->ecm[3] == 3) { // DRE 3 if (er->ecm[4] == 2) { memcpy( ea->cw , &er->ecm[42], 8); memcpy(&ea->cw[8], &er->ecm[34], 8); return OK; } uchar cmdlen; uchar crypted = er->ecm[8] & 1; uchar cryptkey = (er->ecm[8] & 6) >> 1; if (crypted == 0) { cmdlen = 50; } else { cmdlen = 57; } uchar ecmcmd[cmdlen]; memcpy(ecmcmd, &er->ecm[17], cmdlen-1); ecmcmd[cmdlen-1] = csystem_data->provider; dre_cmd_c(ecmcmd, crypted, cryptkey); if(cta_res[2] == 0xD2 && isValidDCW(cta_res + 3)) { memcpy(ea->cw, cta_res+11, 8); memcpy(ea->cw+8, cta_res+3, 8); return OK; } } } else if(reader->caid == 0x2710 && er->ecm[3] == 4)
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; }