static int32_t dgcrypt_cmd(struct s_reader *rdr, const uint8_t *buf, const int32_t buflen, uint8_t *response, uint16_t *response_length, uint16_t min_response_len) { rdr->ifsc = 195; rdr->ns = 1; if (DEBUG) { char tmp[512]; rdr_log(rdr, "SEND -> %s(%d)", cs_hexdump(1, buf, buflen, tmp, sizeof(tmp)), buflen); } int32_t ret = reader_cmd2icc(rdr, buf, buflen, response, response_length); if (DEBUG) { char tmp[512]; rdr_log(rdr, "RECV <- %s(%d) ret=%d", cs_hexdump(1, response, *response_length, tmp, sizeof(tmp)), *response_length, ret); } // reader_cmd2icc retuns ERROR=1, OK=0 - the opposite of OK and ERROR defines in reader-common.h if (ret) { rdr_log(rdr, "ERROR: reader_cmd2icc() ret=%d", ret); return ERROR; } if (*response_length < 2 || *response_length < min_response_len) { rdr_log(rdr, "ERROR: response_length=%d < min_response_length=%d", *response_length, min_response_len); return ERROR; // Response is two short } if (response[*response_length - 2] != 0x90 || response[*response_length - 1] != 0x00) { rdr_log(rdr, "ERROR: response[-2] != 0x90 its 0x%02X", response[*response_length - 2]); rdr_log(rdr, "ERROR: response[-1] != 0x00 its 0x%02X", response[*response_length - 1]); return ERROR; // The reader responded with "command not OK" } return OK; }
static int32_t griffin_exec_cmd(struct s_reader *rdr, uint8_t cmd_op, const uint8_t *data, uint8_t data_len, uint8_t *response, uint16_t *response_length) { struct griffin_data *csystem_data = rdr->csystem_data; uint8_t buf[cmd_buf_len]; int32_t ret = reader_cmd2icc(rdr, buf, griffin_init_cmd(rdr, buf, csystem_data->cmd_base + cmd_op, data, data_len), response, response_length); if (DEBUG) { char tmp[1024]; rdr_log(rdr, "RECV[1] <- %s (ret=%d resp_len=%d)", cs_hexdump(1, response, *response_length, tmp, sizeof(tmp)), ret, *response_length); } if (ret || *response_length < 2) return ERROR; // Response is two short if (response[0] != 0x90) return ERROR; // Invalid response if (response[1] == 0) return OK; // Nothing to retrieve, command OK // Retrieve response uint8_t cmd_read_response = 0x02; if (csystem_data->cmd_base > 0x10) cmd_read_response += csystem_data->cmd_base - 0x10; ret = reader_cmd2icc(rdr, buf, griffin_init_cmd(rdr, buf, cmd_read_response, NULL, response[1]), response, response_length); if (DEBUG) { char tmp[1024]; rdr_log(rdr, "RECV[2] <- %s (ret=%d resp_len=%d)", cs_hexdump(1, response, *response_length, tmp, sizeof(tmp)), ret, *response_length); } if (ret || *response_length < 2) return ERROR; // Response is two short if (response[*response_length - 2] != 0x90) return ERROR; // Invalid response if (response[*response_length - 1] != 0x00) return ERROR; // We don't expect command_op 0x12 to return more data return OK; }
static int32_t conax_get_emm_type(EMM_PACKET *ep, struct s_reader * rdr) { int32_t i, ok = 0; char tmp_dbg[17]; rdr_debug_mask(rdr, D_EMM, "Entered conax_get_emm_type ep->emm[2]=%02x", ep->emm[2]); for (i = 0; i < rdr->nprov; i++) { ok = (!memcmp(&ep->emm[6], rdr->sa[i], 4)); if (ok) break; } if (ok) { ep->type = SHARED; memset(ep->hexserial, 0, 8); memcpy(ep->hexserial, &ep->emm[6], 4); rdr_debug_mask_sensitive(rdr, D_EMM, "SHARED, ep->hexserial = {%s}", cs_hexdump(1, ep->hexserial, 8, tmp_dbg, sizeof(tmp_dbg))); return 1; } else { if (!memcmp(&ep->emm[6], rdr->hexserial + 2, 4)) { ep->type = UNIQUE; memset(ep->hexserial, 0, 8); memcpy(ep->hexserial+2, &ep->emm[6], 4); rdr_debug_mask_sensitive(rdr, D_EMM, "UNIQUE, ep->hexserial = {%s}", cs_hexdump(1, ep->hexserial, 8, tmp_dbg, sizeof(tmp_dbg))); return 1; } else { ep->type = GLOBAL; rdr_debug_mask(rdr, D_EMM, "GLOBAL"); memset(ep->hexserial, 0, 8); return 1; } } }
static int32_t bulcrypt_get_emm_type(EMM_PACKET *ep, struct s_reader *reader) { char dump_emm_sn[64]; int32_t emm_len = check_sct_len(ep->emm, 3); memset(ep->hexserial, 0, 8); if (emm_len < 176) { rdr_debug_mask(reader, D_TRACE | D_EMM, "emm_len < 176 (%u): %s", emm_len, cs_hexdump(1, ep->emm, 12, dump_emm_sn, sizeof(dump_emm_sn))); ep->type = UNKNOWN; return 0; } uint8_t mask_last = 0x00; ep->type = UNKNOWN; switch (ep->emm[0]) { case BULCRYPT_EMM_UNIQUE_82: ep->type = UNIQUE; mask_last = 0xF0; break; // Bulsatcom case BULCRYPT_EMM_UNIQUE_8a: ep->type = UNIQUE; mask_last = 0xF0; break; // Polaris case BULCRYPT_EMM_UNIQUE_85: ep->type = UNIQUE; mask_last = 0x00; break; // Bulsatcom case BULCRYPT_EMM_UNIQUE_8b: ep->type = UNIQUE; mask_last = 0x00; break; // Polaris case BULCRYPT_EMM_SHARED_84: ep->type = SHARED; break; } bool ret = false; if (ep->type == UNIQUE) { // The serial numbers looks like this: // aa bb cc dd // To match EMM_82 and EMM_8a serial we compare (mask_last == 0xf0): // aa bb cc d- // To match EMM_85 and EMM_8b serial we compare (mask_last == 0x00): // aa bb cc -- memcpy(ep->hexserial, ep->emm + 3, 4); ret = reader->hexserial[0] == ep->hexserial[0] && reader->hexserial[1] == ep->hexserial[1] && reader->hexserial[2] == ep->hexserial[2] && ((reader->hexserial[3] & mask_last) == (ep->hexserial[3] & mask_last)); } else if (ep->type == SHARED) { // To match EMM_84 // aa bb -- -- memcpy(ep->hexserial, ep->emm + 3, 2); ret = reader->hexserial[0] == ep->hexserial[0] && reader->hexserial[1] == ep->hexserial[1]; } if (ret) { char dump_card_sn[64]; cs_hexdump(1, reader->hexserial, 4, dump_card_sn, sizeof(dump_card_sn)); cs_hexdump(1, ep->hexserial, 4, dump_emm_sn, sizeof(dump_emm_sn)); rdr_log_sensitive(reader, "EMM_%s-%02x, emm_sn = {%s}, card_sn = {%s}", ep->type == UNIQUE ? "UNIQUE" : ep->type == SHARED ? "SHARED" : "??????", ep->emm[0], dump_emm_sn, dump_card_sn); } return ret; }
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; }
static void rsakey_fn(const char *token, char *value, void *setting, FILE *f) { struct s_reader *rdr = setting; if(value) { int32_t len = strlen(value); if(len != 128 && len != 240) { rdr->rsa_mod_length = 0; memset(rdr->rsa_mod, 0, 120); } else { if(key_atob_l(value, rdr->rsa_mod, len)) { fprintf(stderr, "reader rsakey parse error, %s=%s\n", token, value); rdr->rsa_mod_length = 0; memset(rdr->rsa_mod, 0, sizeof(rdr->rsa_mod)); } else { rdr->rsa_mod_length = len/2; } } return; } int32_t len = rdr->rsa_mod_length; if(len > 0) { char tmp[len * 2 + 1]; fprintf_conf(f, "rsakey", "%s\n", cs_hexdump(0, rdr->rsa_mod, len, tmp, sizeof(tmp))); } else if(cfg.http_full_cfg) { fprintf_conf(f, "rsakey", "\n"); } }
static void boxkey_fn(const char *token, char *value, void *setting, FILE *f) { struct s_reader *rdr = setting; if(value) { int32_t len = strlen(value); if(len != 16 && len != 32) { memset(rdr->boxkey, 0, sizeof(rdr->boxkey)); } else { if(key_atob_l(value, rdr->boxkey, len)) { fprintf(stderr, "reader boxkey parse error, %s=%s\n", token, value); memset(rdr->boxkey, 0, sizeof(rdr->boxkey)); } } return; } int32_t len = check_filled(rdr->boxkey, sizeof(rdr->boxkey)); if(len > 0) { if(len > 8) { len = 16; } else { len = 8; } char tmp[len * 2 + 1]; fprintf_conf(f, "boxkey", "%s\n", cs_hexdump(0, rdr->boxkey, len, tmp, sizeof(tmp))); } else if(cfg.http_full_cfg) { fprintf_conf(f, "boxkey", "\n"); } }
static void boxkey_fn(const char *token, char *value, void *setting, FILE *f) { struct s_reader *rdr = setting; if(value) { int32_t len = strlen(value); if(((len % 8) != 0) || len == 0 || len > 32) { rdr->boxkey_length = 0; memset(rdr->boxkey, 0, sizeof(rdr->boxkey)); } else { if(key_atob_l(value, rdr->boxkey, len)) { fprintf(stderr, "reader boxkey parse error, %s=%s\n", token, value); rdr->boxkey_length = 0; memset(rdr->boxkey, 0, sizeof(rdr->boxkey)); } else { rdr->boxkey_length = len/2; } } return; } int32_t len = rdr->boxkey_length; if(len > 0) { char tmp[len * 2 + 1]; fprintf_conf(f, "boxkey", "%s\n", cs_hexdump(0, rdr->boxkey, len, tmp, sizeof(tmp))); } else if(cfg.http_full_cfg) { fprintf_conf(f, "boxkey", "\n"); } }
static void ins7E_fn(const char *token, char *value, void *setting, long var_size, FILE *f) { uint8_t *var = setting; var_size -= 1; // var_size contains sizeof(var) which is [X + 1] if(value) { int32_t len = strlen(value); if(len != var_size * 2 || key_atob_l(value, var, len)) { if(len > 0) { fprintf(stderr, "reader %s parse error, %s=%s\n", token, token, value); } memset(var, 0, var_size + 1); } else { var[var_size] = 1; // found and correct } return; } if(var[var_size]) { char tmp[var_size * 2 + 1]; fprintf_conf(f, token, "%s\n", cs_hexdump(0, var, var_size, tmp, sizeof(tmp))); } else if(cfg.http_full_cfg) { fprintf_conf(f, token, "\n"); } }
int32_t constcw_analyse_file(uint16_t c_caid, uint32_t UNUSED(c_prid), uint16_t c_sid, uchar *dcw) { //CAID:PROVIDER:SID:PMT:PID::XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX FILE *fp; char token[512]; uint32_t caid, provid, sid, pmt, pid; int32_t cw[16]; fp=fopen(cur_client()->reader->device, "r"); if (!fp) return (0); while (fgets(token, sizeof(token), fp)){ if (token[0]=='#') continue; sscanf(token, "%4x:%6x:%4x:%4x:%4x::%2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x", &caid, &provid, &sid, &pmt, &pid, &cw[0], &cw[1], &cw[2], &cw[3], &cw[4], &cw[5], &cw[6], &cw[7], &cw[8], &cw[9], &cw[10], &cw[11], &cw[12], &cw[13], &cw[14], &cw[15]); //cs_log("Line found: %s", token); if (c_caid == caid && c_sid == sid){ fclose(fp); int8_t i; for(i = 0; i < 16; ++i) dcw[i] = (uchar) cw[i]; cs_log("Entry found: %04X:%06X:%04X:%04X:%04X::%s", caid, provid, sid, pmt, pid, cs_hexdump(1, dcw, 16, token, sizeof(token))); return 1; } } fclose(fp); return 0; }
static void saveemm(struct s_reader *aureader, EMM_PACKET *ep) { FILE *fp; char tmp[17]; char buf[80]; char token[256]; char *tmp2; time_t rawtime; uint32_t emmtype; struct tm timeinfo; if (ep->type == UNKNOWN) emmtype = EMM_UNKNOWN; else emmtype = 1 << (ep->type - 1); // should this nano be saved? if (((1 << (ep->emm[0] % 0x80)) & aureader->s_nano) || (aureader->saveemm & emmtype)) { time(&rawtime); localtime_r(&rawtime, &timeinfo); // to access LOCAL date/time info int32_t emm_length = ((ep->emm[1] & 0x0f) << 8) | ep->emm[2]; strftime(buf, sizeof(buf), "%Y/%m/%d %H:%M:%S", &timeinfo); fp = fopen(get_emmlog_filename(token, sizeof(token), aureader->label, "log"), "a"); if (!fp) { rdr_log(aureader, "ERROR: Cannot open file '%s' (errno=%d: %s)\n", token, errno, strerror(errno)); } else { if (cs_malloc(&tmp2, (emm_length + 3) * 2 + 1)) { fprintf(fp, "%s %s ", buf, cs_hexdump(0, ep->hexserial, 8, tmp, sizeof(tmp))); fprintf(fp, "%s\n", cs_hexdump(0, ep->emm, emm_length + 3, tmp2, (emm_length + 3) * 2 + 1)); free(tmp2); rdr_log(aureader, "Successfully added EMM to %s", token); } fclose(fp); } fp = fopen(get_emmlog_filename(token, sizeof(token), aureader->label, "bin"), "ab"); if (!fp) { rdr_log(aureader, "ERROR: Cannot open file '%s' (errno=%d: %s)\n", token, errno, strerror(errno)); } else { if ((int)fwrite(ep->emm, 1, emm_length + 3, fp) == emm_length + 3) { rdr_log(aureader, "Successfully added binary EMM to %s", token); } else { rdr_log(aureader, "ERROR: Cannot write binary EMM to %s (errno=%d: %s)\n", token, errno, strerror(errno)); } fclose(fp); } } }
static int32_t oscam_ser_send_ecm(struct s_client *client, ECM_REQUEST *er, uchar *buf) { char *tmp; switch(client->serialdata->oscam_ser_proto) { case P_HSIC: memset(buf, 0, 12); buf[0] = 2; i2b_buf(2, er->caid, buf + 1); i2b_buf(3, er->prid, buf + 3); i2b_buf(2, er->pid, buf + 6); i2b_buf(2, er->srvid, buf + 10); memcpy(buf + 12, er->ecm, er->ecmlen); oscam_ser_send(client, buf, 12 + er->ecmlen); break; case P_BOMBA: oscam_ser_send(client, er->ecm, er->ecmlen); break; case P_DSR95: if(cs_malloc(&tmp, er->ecmlen * 2 + 1)) { if(client->serialdata->dsr9500type == P_DSR_WITHSID) { snprintf((char *)buf, 512, "%c%08X%04X%s%04X\n\r", 3, er->prid, er->caid, cs_hexdump(0, er->ecm, er->ecmlen, tmp, er->ecmlen * 2 + 1), er->srvid); oscam_ser_send(client, buf, (er->ecmlen << 1) + 19); // 1 + 8 + 4 + l*2 + 4 + 2 } else { snprintf((char *)buf, 512, "%c%08X%04X%s\n\r", 3, er->prid, er->caid, cs_hexdump(0, er->ecm, er->ecmlen, tmp, er->ecmlen * 2 + 1)); oscam_ser_send(client, buf, (er->ecmlen << 1) + 15); // 1 + 8 + 4 + l*2 + 2 } free(tmp); } break; case P_ALPHA: buf[0] = 0x80; i2b_buf(2, 2 + er->ecmlen, buf + 1); i2b_buf(2, er->caid, buf + 3); memcpy(buf + 5, er->ecm, er->ecmlen); oscam_ser_send(client, buf, oscam_ser_alpha_convert(buf, 5 + er->ecmlen)); break; } return (0); }
static int32_t radegast_recv_chk(struct s_client *client, uchar *dcw, int32_t *rc, uchar *buf, int32_t UNUSED(n)) { if ((buf[0] == 2) && (buf[1] == 0x12)) { char tmp_dbg[33]; memcpy(dcw, buf+4, 16); cs_debug_mask(D_CLIENT, "radegast: recv chk - %s", cs_hexdump(0, dcw, 16, tmp_dbg, sizeof(tmp_dbg))); *rc = 1; return(client->reader->msg_idx); } return (-1); }
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]; 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 bulcrypt_do_emm(struct s_reader *reader, EMM_PACKET *ep) { char tmp[512]; uchar emm_cmd[1024]; def_resp // DE 04 xx yy B0 // xx == EMM type (emm[0]) // yy == EMM type2 (emm[5]) // B0 == EMM len (176) memcpy(emm_cmd, cmd_emm1, sizeof(cmd_emm1)); memcpy(emm_cmd + sizeof(cmd_emm1), ep->emm + 7, 176); switch (ep->emm[0]) { case BULCRYPT_EMM_UNIQUE_82: emm_cmd[2] = ep->emm[0]; // 0x82 break; case BULCRYPT_EMM_UNIQUE_8a: // Polaris equivallent of 0x82 emm_cmd[2] = 0x82; emm_cmd[3] = 0x0b; break; case BULCRYPT_EMM_SHARED_84: emm_cmd[2] = ep->emm[0]; // 0x84 emm_cmd[3] = ep->emm[5]; // 0x0b break; case BULCRYPT_EMM_UNIQUE_85: case BULCRYPT_EMM_UNIQUE_8b: // Polaris 0x85 equivallent of 0x85 memcpy(emm_cmd, cmd_emm2, sizeof(cmd_emm2)); emm_cmd[2] = ep->emm[5]; // 0xXX (Last bytes of the serial) emm_cmd[3] = ep->emm[6]; // 0x0b break; } // Write emm write_cmd(emm_cmd, emm_cmd + 5); if (cta_lr != 2 || cta_res[0] != 0x90 || (cta_res[1] != 0x00 && cta_res[1] != 0x0a)) { rdr_log(reader, "(emm_cmd) Unexpected card answer: %s", cs_hexdump(1, cta_res, cta_lr, tmp, sizeof(tmp))); return ERROR; } if (ep->emm[0] == BULCRYPT_EMM_UNIQUE_82 && cta_res[0] == 0x90 && cta_res[1] == 0x0a) { rdr_log(reader, "Your subscription data was updated."); add_job(reader->client, ACTION_READER_CARDINFO, NULL, 0); } 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; }
void cardreader_process_ecm(struct s_reader *reader, struct s_client *cl, ECM_REQUEST *er) { if (ecm_ratelimit_check(reader, er, 1) != OK) { rdr_debug_mask(reader, D_READER, "%s: ratelimit check failed.", __func__); return; // reader_mode = 1: checkout ratelimiter in reader mode so srvid can be replaced } cs_ddump_mask(D_ATR, er->ecm, er->ecmlen, "ecm:"); struct timeb tps, tpe; cs_ftime(&tps); struct s_ecm_answer ea; memset(&ea, 0, sizeof(struct s_ecm_answer)); int32_t rc = cardreader_do_ecm(reader, er, &ea); rdr_debug_mask(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[32]; rdr_debug_mask(reader, D_READER, "Error processing ecm for caid %04X, srvid %04X, servicename: %s", er->caid, er->srvid, get_servicename(cl, er->srvid, er->caid, buf)); ea.rc = E_NOTFOUND; ea.rcEx = 0; ICC_Async_DisplayMsg(reader, "Eer"); } if (rc == E_CORRUPT) { char buf[32]; rdr_debug_mask(reader, D_READER, "Error processing ecm for caid %04X, srvid %04X, servicename: %s", er->caid, er->srvid, get_servicename(cl, er->srvid, er->caid, buf)); ea.rc = E_NOTFOUND; ea.rcEx = E2_WRONG_CHKSUM; //flag it as wrong checksum memcpy (ea.msglog,"Invalid ecm type for card",25); } cs_ftime(&tpe); cl->lastecm=time((time_t*)0); char ecmd5[17*3]; cs_hexdump(0, er->ecmd5, 16, ecmd5, sizeof(ecmd5)); rdr_debug_mask(reader, D_READER, "ecm hash: %s real time: %ld ms", ecmd5, 1000 * (tpe.time - tps.time) + tpe.millitm - tps.millitm); write_ecm_answer(reader, er, ea.rc, ea.rcEx, ea.cw, ea.msglog); reader_post_process(reader); }
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); }
void cs_log_int(uint16_t mask, int8_t lock __attribute__((unused)), const uchar *buf, int32_t n, const char *fmt, ...) { va_list params; char log_txt[LOG_BUF_SIZE]; int32_t i, len = 0; pthread_mutex_lock(&log_mutex); if (((mask & cs_dblevel) || !mask) && (fmt)) { va_start(params, fmt); len = get_log_header(1, log_txt); vsnprintf(log_txt + len, sizeof(log_txt) - len, fmt, params); va_end(params); int repeated_line = strcmp(last_log_txt, log_txt + len) == 0; if (last_log_duplicates > 0) { if (!last_log_ts) // Must be initialized once last_log_ts = log_ts; // Report duplicated lines when the new log line is different // than the old or 60 seconds have passed. if (!repeated_line || log_ts - last_log_ts >= 60) { char dupl[len + 32]; len = get_log_header(2, dupl); snprintf(dupl + len - 1, len + 32, "--- Skipped %d duplicated log lines ---", last_log_duplicates); write_to_log_int(dupl, 0); last_log_duplicates = 0; last_log_ts = log_ts; } } if (!repeated_line) { memcpy(last_log_txt, log_txt + len, LOG_BUF_SIZE); write_to_log_int(log_txt, len); } else { last_log_duplicates++; } } if (buf && ((mask & cs_dblevel) || !mask)) { for (i=0; i<n; i+=16) { len = get_log_header(0, log_txt); cs_hexdump(1, buf+i, (n-i>16) ? 16 : n-i, log_txt + len, sizeof(log_txt) - len); write_to_log_int(log_txt, len); } } pthread_mutex_unlock(&log_mutex); }
// Sets cmd_buf and returns buf_len static uint32_t griffin_init_cmd(struct s_reader *rdr, uint8_t *cmd_buf, uint8_t cmd_op, const uint8_t *data, uint8_t data_len) { #define cmd_len 5 memset(cmd_buf, 0, cmd_buf_len); cmd_buf[0] = 0xDC; // Command start cmd_buf[1] = cmd_op; cmd_buf[2] = 0x00; cmd_buf[3] = 0x00; cmd_buf[4] = data_len; // Set payload length if (data && data_len) memcpy(cmd_buf + cmd_len, data, data_len); uint32_t len = cmd_len + (data ? data_len : 0); if (DEBUG) { char tmp[1024]; rdr_log(rdr, "SEND[-] -> %s", cs_hexdump(1, cmd_buf, len, tmp, sizeof(tmp))); } return len; }
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; }
void cs_log_hex(const char *log_prefix, const uint8_t *buf, int32_t n, const char *fmt, ...) { if(logStarted == 0) { return; } SAFE_MUTEX_LOCK_NOLOG(&log_mutex); __do_log(); if(buf) { int32_t i; __init_log_prefix("%10s "); for(i = 0; i < n; i += 16) { cs_hexdump(1, buf + i, (n - i > 16) ? 16 : n - i, log_txt + hdr_len + log_prefix_len, sizeof(log_txt) - (hdr_len + log_prefix_len)); write_to_log_int(log_txt, hdr_len, hdr_logcount_offset, hdr_date_offset, hdr_time_offset, hdr_info_offset); } } SAFE_MUTEX_UNLOCK_NOLOG(&log_mutex); }
static int32_t bulcrypt_do_emm(struct s_reader *reader, EMM_PACKET *ep) { char tmp[512]; uchar emm_cmd[1024]; def_resp switch (ep->emm[0]) { case BULCRYPT_EMM_UNIQUE_82: // DE 02 82 00 B0 memcpy(emm_cmd, cmd_emm_uniq, sizeof(cmd_emm)); memcpy(emm_cmd + sizeof(cmd_emm), ep->emm + 7, 176); break; case BULCRYPT_EMM_UNIQUE_85: case BULCRYPT_EMM_SHARED_84: case BULCRYPT_EMM_8b: case BULCRYPT_EMM_8a: // DE 04 00 00 B0 memcpy(emm_cmd, cmd_emm, sizeof(cmd_emm)); memcpy(emm_cmd + sizeof(cmd_emm), ep->emm + 7, 176); emm_cmd[2] = ep->emm[5]; // Emm cmd 1 emm_cmd[3] = ep->emm[6]; // Emm cmd 2 break; } // Write emm write_cmd(emm_cmd, emm_cmd + 5); if (cta_lr != 2 || cta_res[0] != 0x90 || (cta_res[1] != 0x00 && cta_res[1] != 0x0a)) { rdr_log(reader, "(emm_cmd) Unexpected card answer: %s", cs_hexdump(1, cta_res, cta_lr, tmp, sizeof(tmp))); return ERROR; } if (ep->emm[0] == BULCRYPT_EMM_UNIQUE_82 && cta_res[0] == 0x90 && cta_res[1] == 0x0a) rdr_log(reader, "Your subscription data was updated."); return OK; }
void cs_log_int(uint16_t mask, int8_t lock __attribute__((unused)), const uchar *buf, int32_t n, const char *fmt, ...) { va_list params; char log_txt[LOG_BUF_SIZE]; int32_t i, len = 0; if (((mask & cs_dblevel) || !mask) && (fmt)) { va_start(params, fmt); len = get_log_header(1, log_txt); vsnprintf(log_txt + len, sizeof(log_txt) - len, fmt, params); write_to_log_int(log_txt, len); va_end(params); } if (buf && (mask & cs_dblevel || !mask)) { for (i=0; i<n; i+=16) { len = get_log_header(0, log_txt); cs_hexdump(1, buf+i, (n-i>16) ? 16 : n-i, log_txt + len, sizeof(log_txt) - len); write_to_log_int(log_txt, len); } } }
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 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 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 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 constcw_analyse_file(uint16_t c_caid, uint32_t c_prid, uint16_t c_sid, uint16_t c_pmtpid, uint32_t c_vpid, uint16_t c_ecmpid, uchar *dcw) { //CAID:PROVIDER:SID:PMTPID:ECMPID:VPID:XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX FILE *fp; char token[512]; uint32_t caid, provid, sid, vpid, pmtpid, ecmpid; int32_t cw[16]; fp = fopen(cur_client()->reader->device, "r"); if(!fp) { cs_log("ERROR: Can't open %s (errno=%d %s)", cur_client()->reader->device, errno, strerror(errno)); return (0); } cs_log("Searching CW for CAID %04X PROVID %06X SRVID %04X ECMPID %04X PMTPID %04X VPID %04X", c_caid, c_prid, c_sid, c_ecmpid, c_pmtpid, c_vpid); while(fgets(token, sizeof(token), fp)) { if(token[0] == '#') { continue; } vpid = 0; int ret = sscanf(token, "%4x:%6x:%4x:%4x:%4x::%2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x", &caid, &provid, &sid, &pmtpid, &ecmpid, &cw[0], &cw[1], &cw[2], &cw[3], &cw[4], &cw[5], &cw[6], &cw[7], &cw[8], &cw[9], &cw[10], &cw[11], &cw[12], &cw[13], &cw[14], &cw[15]); if(ret != 21){ ret = sscanf(token, "%4x:%6x:%4x:%4x:%4x:%4x:%2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x", &caid, &provid, &sid, &pmtpid, &ecmpid, &vpid, &cw[0], &cw[1], &cw[2], &cw[3], &cw[4], &cw[5], &cw[6], &cw[7], &cw[8], &cw[9], &cw[10], &cw[11], &cw[12], &cw[13], &cw[14], &cw[15]); if(ret != 22) continue; } //cs_log("Line found: %s", token); if(c_caid == caid && c_sid == sid && (!provid || provid == c_prid) && (!pmtpid || !c_pmtpid || pmtpid == c_pmtpid) && (!vpid || !c_vpid || vpid == c_vpid) && (!ecmpid || !c_ecmpid || ecmpid == c_ecmpid)) { fclose(fp); int8_t i; for(i = 0; i < 16; ++i) { dcw[i] = (uchar) cw[i]; } cs_log("Entry found: %04X@%06X:%04X:%04X:%04X:%04X:%s", caid, provid, sid, pmtpid, ecmpid, vpid, cs_hexdump(1, dcw, 16, token, sizeof(token))); return 1; } } fclose(fp); return 0; }
void cs_log_int(uint16_t mask, int8_t lock __attribute__((unused)), const uchar *buf, int32_t n, const char *fmt, ...) { if((mask & cs_dblevel) || !mask) { va_list params; int32_t dupl_header_len, repeated_line, i, len = 0; pthread_mutex_lock(&log_mutex); if(fmt) { va_start(params, fmt); len = get_log_header(1, log_txt); vsnprintf(log_txt + len, sizeof(log_txt) - len, fmt, params); va_end(params); if(cfg.logduplicatelines) { memcpy(last_log_txt, log_txt + len, LOG_BUF_SIZE); write_to_log_int(log_txt, len); } else { repeated_line = strcmp(last_log_txt, log_txt + len) == 0; if(last_log_duplicates > 0) { if(!cs_valid_time(&last_log_ts)) // Must be initialized once { last_log_ts = log_ts; } // Report duplicated lines when the new log line is different // than the old or 60 seconds have passed. int32_t gone = comp_timeb(&log_ts, &last_log_ts); if(!repeated_line || gone >= 60*1000) { dupl_header_len = get_log_header(2, dupl); snprintf(dupl + dupl_header_len - 1, sizeof(dupl) - dupl_header_len, "--- Skipped %u duplicated log lines ---", last_log_duplicates); write_to_log_int(dupl, 0); last_log_duplicates = 0; last_log_ts = log_ts; } } if(!repeated_line) { memcpy(last_log_txt, log_txt + len, LOG_BUF_SIZE); write_to_log_int(log_txt, len); } else { last_log_duplicates++; } } } if(buf) { for(i = 0; i < n; i += 16) { len = get_log_header(0, log_txt); cs_hexdump(1, buf + i, (n - i > 16) ? 16 : n - i, log_txt + len, sizeof(log_txt) - len); write_to_log_int(log_txt, len); } } pthread_mutex_unlock(&log_mutex); } }