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 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 void cmd_test(struct s_reader *reader) { def_resp; int i; uchar drecmd[] = { 0x00, 0x02 }; char tmp[64]; for(i = 0; i <= 0xFF; i++) { if(i == 0x45) continue; drecmd[0] = i; dre_cmd(drecmd); if(cta_res[2] == 0xE2) { if(cta_res[3] != 0xE3) rdr_log(reader, "cmd %02X error %02X",i ,cta_res[3]); } else { rdr_log(reader, "cmd %02X answer %s",i ,cs_hexdump(0, cta_res, cta_res[1]+2, tmp, sizeof(tmp))); } } uchar drecmd[64]; //memset(drecmd, 0, 64); //drecmd[0] = 0x71; for(i = 2; i <= 64; i++) { memset(drecmd, 0, 64); drecmd[i-1] = 0x02; drecmd[0] = 0x71; dre_script(drecmd, i, 0, 0, 0); if(cta_res[2] == 0xE2) { if((cta_res[3] != 0xE2) & (cta_res[3] != 0xED)) rdr_log(reader, "Len %02X error %02X",i ,cta_res[3]); if((cta_res[3] & 0xF0) != 0xE0) rdr_log(reader, "Len %02X answer %s",i ,cs_hexdump(0, cta_res, cta_res[1]+2, tmp, sizeof(tmp))); } else { rdr_log(reader, "Len %02X answer %s",i ,cs_hexdump(0, cta_res, cta_res[1]+2, tmp, sizeof(tmp))); } } } */ static int32_t dre_card_init(struct s_reader *reader, ATR *newatr) { get_atr; def_resp; uchar ua[] = { 0x43, 0x15 }; // get serial number (UA) uchar providers[] = { 0x49, 0x15 }; // get providers uchar cmd56[] = { 0x56, 0x00 }; int32_t i; char *card; char tmp[9]; if((atr[0] != 0x3b) || (atr[1] != 0x15) || (atr[2] != 0x11) || (atr[3] != 0x12) || ( ((atr[4] != 0x01) || (atr[5] != 0x01)) && ((atr[4] != 0xca) || (atr[5] != 0x07)) && ((atr[4] != 0xcb) || (atr[5] != 0x07)) && ((atr[4] != 0xcc) || (atr[5] != 0x07)) && ((atr[4] != 0xcd) || (atr[5] != 0x07)) )) { return ERROR; } if(!cs_malloc(&reader->csystem_data, sizeof(struct dre_data))) { return ERROR; } struct dre_data *csystem_data = reader->csystem_data; csystem_data->provider = atr[6]; uchar checksum = xor(atr + 1, 6); if(checksum != atr[7]) { rdr_log(reader, "warning: expected ATR checksum %02x, smartcard reports %02x", checksum, atr[7]); } switch(atr[6]) { case 0: if(!(dre_cmd(cmd56))) { return ERROR; } if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00)) { return ERROR; } switch(cta_res[4]) { case 0x02: card = "Tricolor Centr DRE3"; reader->caid = 0x4ae1; break; case 0x03: card = "Tricolor Syberia DRE3"; reader->caid = 0x4ae1; break; case 0x18: case 0x19: card = "Tricolor Centr DRE4"; reader->caid = 0x2710; break; case 0x1A: card = "Tricolor Syberia DRE4"; reader->caid = 0x2710; break; default: return ERROR; } csystem_data->provider = cta_res[4]; providers[0] = 0x83; break; case 0x11: card = "Tricolor Centr DRE2"; reader->caid = 0x4ae1; break; //59 type card = MSP (74 type = ATMEL) case 0x12: card = "Cable TV"; reader->caid = 0x4ae1; //TODO not sure about this one break; case 0x14: card = "Tricolor Syberia DRE2"; reader->caid = 0x4ae1; break; //59 type card case 0x15: card = "Platforma HD / DW old"; reader->caid = 0x4ae1; break; //59 type card default: return ERROR; } memset(reader->prid, 0x00, 8); if(atr[6] > 0) { reader->prid[0][3] = atr[6]; } else { reader->prid[0][3] = csystem_data->provider; } uchar cmd54[] = { 0x54, 0x14 }; // geocode cmd54[1] = csystem_data->provider; uchar geocode = 0; if((dre_cmd(cmd54))) //error would not be fatal, like on 0x11 cards { geocode = cta_res[3]; } providers[1] = csystem_data->provider; if(!(dre_cmd(providers))) { return ERROR; } //fatal error if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00)) { return ERROR; } uchar provname[128]; for(i = 0; ((i < cta_res[2] - 6) && (i < 128)); i++) { provname[i] = cta_res[6 + i]; if(provname[i] == 0x00) { break; } } int32_t major_version = cta_res[3]; int32_t minor_version = cta_res[4]; ua[1] = csystem_data->provider; dre_cmd(ua); //error would not be fatal int32_t hexlength = cta_res[1] - 2; //discard first and last byte, last byte is always checksum, first is answer code if(reader->force_ua) { rdr_log(reader, "WARNING!!!! used UA from force_ua %08X", reader->force_ua); memcpy(cta_res + 3, &reader->force_ua, 4); } reader->hexserial[0] = 0; reader->hexserial[1] = 0; memcpy(reader->hexserial + 2, cta_res + 3, hexlength); int32_t low_dre_id, dre_chksum; uchar buf[32]; if(major_version < 0x3) { low_dre_id = ((cta_res[4] << 16) | (cta_res[5] << 8) | cta_res[6]) - 48608; dre_chksum = 0; snprintf((char *)buf, sizeof(buf), "%i%i%08i", csystem_data->provider - 16, major_version + 1, low_dre_id); for(i = 0; i < 32; i++) { if(buf[i] == 0x00) { break; } dre_chksum += buf[i] - 48; } if(major_version < 2) { reader->caid = 0x4ae0; card = csystem_data->provider == 0x11 ? "Tricolor Centr DRE1" : "Tricolor Syberia DRE1"; } rdr_log(reader, "type: DRE Crypt, caid: %04X, serial: {%s}, dre id: %i%i%i%08i, geocode %i, card: %s v%i.%i", reader->caid, cs_hexdump(0, reader->hexserial + 2, 4, tmp, sizeof(tmp)), dre_chksum, csystem_data->provider - 16, major_version + 1, low_dre_id, geocode, card, major_version, minor_version); } else { low_dre_id = ((cta_res[4] << 16) | (cta_res[5] << 8) | cta_res[6]); dre_chksum = 0; snprintf((char *)buf, sizeof(buf), "%i%i%08i", csystem_data->provider, major_version, low_dre_id); for(i = 0; i < 32; i++) { if(buf[i] == 0x00) { break; } dre_chksum += buf[i] - 48; } rdr_log(reader, "type: DRE Crypt, caid: %04X, serial: {%s}, dre id: %i%03i%i%08i, geocode %i, card: %s v%i.%i", reader->caid, cs_hexdump(0, reader->hexserial + 2, 4, tmp, sizeof(tmp)), dre_chksum, csystem_data->provider, major_version, low_dre_id, geocode, card, major_version, minor_version); } rdr_log(reader, "Provider name:%s.", provname); memset(reader->sa, 0, sizeof(reader->sa)); memcpy(reader->sa[0], reader->hexserial + 2, 1); //copy first byte of unique address also in shared address, because we dont know what it is... rdr_log_sensitive(reader, "SA = %02X%02X%02X%02X, UA = {%s}", reader->sa[0][0], reader->sa[0][1], reader->sa[0][2], reader->sa[0][3], cs_hexdump(0, reader->hexserial + 2, 4, tmp, sizeof(tmp))); reader->nprov = 1; // cmd_test(reader); // exec user script, wicardd format if(reader->userscript != NULL) { uint8_t *usercmd = NULL; int cmd_len; int n; char *tempbuf = malloc(2048); trim2(reader->userscript); FILE *pFile = fopen(reader->userscript, "rt"); if(pFile != NULL) { uchar ignoreProvid = 0; uchar crypted = 0; uchar cryptkey = 0; do { tempbuf[0] = '\0'; if(usercmd != NULL) free(usercmd); if(fgets(tempbuf, 2048, pFile) == NULL) continue; if(strlen(tempbuf) < 10) continue; trim2(tempbuf); ignoreProvid = 0; crypted = 0; cryptkey = 0; if(tempbuf[0] == '8' && tempbuf[1] == '6' && csystem_data->provider == 0x11) ignoreProvid = 1; else if(strncmp(tempbuf ,"REG2" ,4) == 0) { dre_read_ee(reader, &tempbuf[4] ,csystem_data->provider); continue; } else if(strncmp(tempbuf ,"CR" ,2) == 0) { crypted = 1; cryptkey = ((tempbuf[2] - (tempbuf[2] > 0x39 ? 0x37:0x30)) << 4) + ((tempbuf[3] - (tempbuf[3] > 0x39 ? 0x37:0x30)) & 0xF); } else if(tempbuf[0] != '5' && tempbuf[1] != '9') continue; strtoupper(tempbuf); cmd_len = strlen(tempbuf) / 2 - 3 + ignoreProvid - (crypted * 2); usercmd = malloc(cmd_len); for(i=0,n= 4+(crypted * 4);i<cmd_len;i++,n+=2) { usercmd[i] = ((tempbuf[n] - (tempbuf[n] > 0x39 ? 0x37:0x30)) << 4) + ((tempbuf[n+1] - (tempbuf[n+1] > 0x39 ? 0x37:0x30)) & 0xF); } /*if(usercmd[cmd_len-1] != csystem_data->provider && !ignoreProvid) { rdr_log(reader, "Skip script: current provid %02X , script provid %02X", csystem_data->provider, usercmd[cmd_len-1]); continue; } */ rdr_log(reader, "User script: %s", tempbuf); /*ret =*/ rdr_log(reader, "Script %s", (dre_script(usercmd, cmd_len, ignoreProvid, crypted, cryptkey)) ? "done" : "error"); } while(!feof(pFile)); } else { rdr_log(reader, "Can't open script file (%s)", reader->userscript); } //if(usercmd != NULL) free(usercmd); if(tempbuf != NULL) free(tempbuf); } if(csystem_data->provider == 0x11) { memset(reader->prid[1], 0x00, 8); reader->prid[1][3] = 0xFE; reader->nprov = 2; } if(!dre_set_provider_info(reader)) { return ERROR; } //fatal error rdr_log(reader, "ready for requests"); return OK; }
static int32_t viaccess_card_info(struct s_reader * reader) { def_resp; int32_t i, l; uchar insac[] = { 0xca, 0xac, 0x00, 0x00, 0x00 }; // select data uchar insb8[] = { 0xca, 0xb8, 0x00, 0x00, 0x00 }; // read selected data uchar insa4[] = { 0xca, 0xa4, 0x00, 0x00, 0x00 }; // select issuer uchar insc0[] = { 0xca, 0xc0, 0x00, 0x00, 0x00 }; // read data item static const uchar ins24[] = { 0xca, 0x24, 0x00, 0x00, 0x09 }; // set pin static const uchar cls[] = { 0x00, 0x21, 0xff, 0x9f}; static const uchar pin[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04}; reader->last_geo.provid = 0; reader->last_geo.geo_len = 0; reader->last_geo.geo[0] = 0; rdr_log(reader, "card detected"); cs_clear_entitlement(reader); //reset the entitlements // set pin write_cmd(ins24, pin); insac[2]=0xa4; write_cmd(insac, NULL); // request unique id insb8[4]=0x07; write_cmd(insb8, NULL); // read unique id rdr_log_sensitive(reader, "serial: {%llu}", (unsigned long long) b2ll(5, cta_res+2)); insa4[2]=0x00; write_cmd(insa4, NULL); // select issuer 0 for (i=1; (cta_res[cta_lr-2]==0x90) && (cta_res[cta_lr-1]==0); i++) { uint32_t l_provid, l_sa; uchar l_name[64]; insc0[4]=0x1a; write_cmd(insc0, NULL); // show provider properties cta_res[2]&=0xF0; l_provid=b2i(3, cta_res); insac[2]=0xa5; write_cmd(insac, NULL); // request sa insb8[4]=0x06; write_cmd(insb8, NULL); // read sa l_sa=b2i(4, cta_res+2); insac[2]=0xa7; write_cmd(insac, NULL); // request name insb8[4]=0x02; write_cmd(insb8, NULL); // read name nano + len l=cta_res[1]; insb8[4]=l; write_cmd(insb8, NULL); // read name cta_res[l]=0; trim((char *)cta_res); if (cta_res[0]) snprintf((char *)l_name, sizeof(l_name), ", name: %s", cta_res); else l_name[0]=0; // read GEO insac[2]=0xa6; write_cmd(insac, NULL); // request GEO insb8[4]=0x02; write_cmd(insb8, NULL); // read GEO nano + len l=cta_res[1]; char tmp[l*3+1]; insb8[4]=l; write_cmd(insb8, NULL); // read geo rdr_log_sensitive(reader, "provider: %d, id: {%06X%s}, sa: {%08X}, geo: %s", i, l_provid, l_name, l_sa, (l<4) ? "empty" : cs_hexdump(1, cta_res, l, tmp, sizeof(tmp))); // read classes subscription insac[2]=0xa9; insac[4]=4; write_cmd(insac, cls); // request class subs while( (cta_res[cta_lr-2]==0x90) && (cta_res[cta_lr-1]==0) ) { insb8[4]=0x02; write_cmd(insb8, NULL); // read class subs nano + len if( (cta_res[cta_lr-2]==0x90) && (cta_res[cta_lr-1]==0) ) { l=cta_res[1]; insb8[4]=l; write_cmd(insb8, NULL); // read class subs if( (cta_res[cta_lr-2]==0x90) && (cta_res[cta_lr-1]==0x00 || cta_res[cta_lr-1]==0x08) ) { show_class(reader, NULL, l_provid, cta_res, cta_lr-2); } } } insac[4]=0; insa4[2]=0x02; write_cmd(insa4, NULL); // select next provider } //return ERROR; return OK; }
static int32_t viaccess_card_init(struct s_reader * reader, ATR *newatr) { get_atr; def_resp; int32_t i; uchar buf[256]; uchar insac[] = { 0xca, 0xac, 0x00, 0x00, 0x00 }; // select data uchar insb8[] = { 0xca, 0xb8, 0x00, 0x00, 0x00 }; // read selected data uchar insa4[] = { 0xca, 0xa4, 0x00, 0x00, 0x00 }; // select issuer uchar insc0[] = { 0xca, 0xc0, 0x00, 0x00, 0x00 }; // read data item static const uchar insFAC[] = { 0x87, 0x02, 0x00, 0x00, 0x03 }; // init FAC static const uchar FacDat[] = { 0x00, 0x00, 0x28 }; static unsigned char ins8702_data[] = { 0x00, 0x00, 0x11}; static unsigned char ins8704[] = { 0x87, 0x04, 0x00, 0x00, 0x07 }; static unsigned char ins8706[] = { 0x87, 0x06, 0x00, 0x00, 0x04 }; if ((atr[1]!=0x77) || ((atr[2]!=0x18) && (atr[2]!=0x11) && (atr[2]!=0x19)) || ((atr[9]!=0x68) && (atr[9]!=0x6C))) return ERROR; write_cmd(insFAC, FacDat); if( !(cta_res[cta_lr-2]==0x90 && cta_res[cta_lr-1]==0) ) return ERROR; memset(&reader->last_geo, 0, sizeof(reader->last_geo)); write_cmd(insFAC, ins8702_data); if ((cta_res[cta_lr-2]==0x90) && (cta_res[cta_lr-1]==0x00)) { write_cmd(ins8704, NULL); if ((cta_res[cta_lr-2]==0x90) && (cta_res[cta_lr-1]==0x00)) { write_cmd(ins8706, NULL); if ((cta_res[cta_lr-2]==0x90) && (cta_res[cta_lr-1]==0x00)) { reader->last_geo.number_ecm =(cta_res[2]<<8) | (cta_res[3]); rdr_log(reader, "using ecm #%x for long viaccess ecm",reader->last_geo.number_ecm); } } } // switch((atr[atrsize-4]<<8)|atr[atrsize-3]) // { // case 0x6268: ver="2.3"; break; // case 0x6668: ver="2.4(?)"; break; // case 0xa268: // default: ver="unknown"; break; // } reader->caid=0x500; memset(reader->prid, 0xff, sizeof(reader->prid)); insac[2]=0xa4; write_cmd(insac, NULL); // request unique id insb8[4]=0x07; write_cmd(insb8, NULL); // read unique id memcpy(reader->hexserial, cta_res+2, 5); // rdr_log(reader, "[viaccess-reader] type: Viaccess, ver: %s serial: %llu", ver, b2ll(5, cta_res+2)); rdr_log_sensitive(reader, "type: Viaccess (%sstandard atr), caid: %04X, serial: {%llu}", atr[9]==0x68?"":"non-",reader->caid, (unsigned long long) b2ll(5, cta_res+2)); i=0; insa4[2]=0x00; write_cmd(insa4, NULL); // select issuer 0 buf[0]=0; while((cta_res[cta_lr-2]==0x90) && (cta_res[cta_lr-1]==0)) { insc0[4]=0x1a; write_cmd(insc0, NULL); // show provider properties cta_res[2]&=0xF0; reader->prid[i][0]=0; memcpy(&reader->prid[i][1], cta_res, 3); memcpy(&reader->availkeys[i][0], cta_res+10, 16); snprintf((char *)buf+strlen((char *)buf), sizeof(buf)-strlen((char *)buf), ",%06X", b2i(3, &reader->prid[i][1])); //rdr_log(reader, "[viaccess-reader] buf: %s", buf); insac[2]=0xa5; write_cmd(insac, NULL); // request sa insb8[4]=0x06; write_cmd(insb8, NULL); // read sa memcpy(&reader->sa[i][0], cta_res+2, 4); /* insac[2]=0xa7; write_cmd(insac, NULL); // request name insb8[4]=0x02; write_cmd(insb8, NULL); // read name nano + len l=cta_res[1]; insb8[4]=l; write_cmd(insb8, NULL); // read name cta_res[l]=0; rdr_log(reader, "[viaccess-reader] name: %s", cta_res); */ insa4[2]=0x02; write_cmd(insa4, NULL); // select next issuer i++; } reader->nprov=i; rdr_log(reader, "providers: %d (%s)", reader->nprov, buf+1); if (cfg.ulparent) unlock_parental(reader); rdr_log(reader, "ready for requests"); return OK; }
static int32_t conax_card_init(struct s_reader * reader, ATR *newatr) { unsigned char cta_res[CTA_RES_LEN]; int32_t i, j, n; static const uchar ins26[] = {0xDD, 0x26, 0x00, 0x00, 0x03, 0x10, 0x01, 0x40}; uchar ins82[] = {0xDD, 0x82, 0x00, 0x00, 0x11, 0x11, 0x0f, 0x01, 0xb0, 0x0f, 0xff, \ 0xff, 0xfb, 0x00, 0x00, 0x09, 0x04, 0x0b, 0x00, 0xe0, 0x30, 0x2b }; uchar cardver=0; get_hist; if ((hist_size < 4) || (memcmp(hist,"0B00",4))) return ERROR; reader->caid=0xB00; if ((n=read_record(reader, ins26, ins26+5, cta_res))<=0) return ERROR; // read caid, card-version for (i=0; i<n; i+=cta_res[i+1]+2) switch(cta_res[i]) { case 0x20: cardver=cta_res[i+2]; break; case 0x28: reader->caid=(cta_res[i+2]<<8)|cta_res[i+3]; } // Ins82 command needs to use the correct CAID reported in nano 0x28 ins82[17]=(reader->caid>>8)&0xFF; ins82[18]=(reader->caid)&0xFF; if ((n=read_record(reader, ins82, ins82+5, cta_res))<=0) return ERROR; // read serial reader->nprov = 0; for (j=0, i=2; i<n; i+=cta_res[i+1]+2) switch(cta_res[i]) { case 0x23: if (cta_res[i+5] != 0x00) { memcpy(reader->hexserial, &cta_res[i+3], 6); } else { memcpy(reader->sa[j], &cta_res[i+5], 4); j++; reader->nprov++; } break; } memset(reader->prid, 0x00, sizeof(reader->prid)); rdr_log_sensitive(reader, "type: Conax, caid: %04X, serial: {%llu}, hex serial: {%02x%02x%02x%02x}, card: v%d", reader->caid, (unsigned long long) b2ll(6, reader->hexserial), reader->hexserial[2], reader->hexserial[3], reader->hexserial[4], reader->hexserial[5], cardver); rdr_log(reader, "Providers: %d", reader->nprov); for (j=0; j<reader->nprov; j++) { rdr_log(reader, "Provider: %d Provider-Id: %06X", j+1, b2i(4, reader->prid[j])); rdr_log_sensitive(reader, "Provider: %d SharedAddress: {%08X}", j+1, b2i(4, reader->sa[j])); } return OK; }
static int32_t bulcrypt_card_init(struct s_reader *reader, ATR *newatr) { int i; char tmp[1024]; char card_serial[16]; const uchar *set_key_command; uchar card_type; get_atr def_resp reader->bulcrypt_version = 0; if (memcmp(atr, atr_carpet, MIN(sizeof(atr_carpet), atr_size)) != 0) { if (atr_size == 3) { rdr_log(reader, "ATR_len=3 but ATR is unknown: %s", cs_hexdump(1, atr, atr_size, tmp, sizeof(tmp))); } return ERROR; } reader->nprov = 1; memset(reader->prid, 0, sizeof(reader->prid)); memset(reader->hexserial, 0, sizeof(reader->hexserial)); memset(card_serial, 0, sizeof(card_serial)); rdr_log(reader, "Bulcrypt card detected, checking card version."); // Do we have Bulcrypt V2 card? write_cmd(cmd_card_v2_key1, NULL); write_cmd(cmd_card_v2_key2, NULL); if (cta_lr < 18 || (cta_res[0] != 0x11 && cta_res[1] != 0x10)) { // The card is v1 reader->bulcrypt_version = 1; set_key_command = cmd_set_key; } else { // The card is v2 reader->bulcrypt_version = 2; set_key_command = cmd_set_key_v2; } // Set CW obfuscation key write_cmd(set_key_command, set_key_command + 5); if (cta_lr < 2 || (cta_res[0] != 0x90 && cta_res[1] != 0x00)) { rdr_log(reader, "(cmd_set_key) Unexpected card answer: %s", cs_hexdump(1, cta_res, cta_lr, tmp, sizeof(tmp))); return ERROR; } rdr_log(reader, "Bulcrypt v%d card detected.%s", reader->bulcrypt_version, reader->bulcrypt_version != 1 ? " *UNSUPPORTED CARD VERSION*" : ""); // Read card type write_cmd(cmd_cardtype1, NULL); write_cmd(cmd_cardtype2, NULL); if (cta_lr < 5 || (cta_res[0] != 0x01 && cta_res[1] != 0x01)) { rdr_log(reader, "(cmd_cardtype) Unexpected card answer: %s", cs_hexdump(1, cta_res, cta_lr, tmp, sizeof(tmp))); return ERROR; } card_type = cta_res[2]; // We have seen 0x4c and 0x75 // *FIXME* Unknown command write_cmd(cmd_unkn_0a1, NULL); write_cmd(cmd_unkn_0a2, NULL); // Read card HEX serial write_cmd(cmd_cardsn1, NULL); write_cmd(cmd_cardsn2, NULL); if (cta_lr < 6 || (cta_res[0] != 0x02 && cta_res[1] != 0x04)) { rdr_log(reader, "(card_sn) Unexpected card answer: %s", cs_hexdump(1, cta_res, cta_lr, tmp, sizeof(tmp))); return ERROR; } memcpy(reader->hexserial, cta_res + 2, 4); // Skip bottom four bits (they are 0x0b on our cards) reader->hexserial[3] = reader->hexserial[3] & 0xF0; // Read card ASCII serial write_cmd(cmd_ascsn1, NULL); write_cmd(cmd_ascsn2, NULL); if (cta_lr < 15 || (cta_res[0] != 0x05 && cta_res[1] != 0x0d)) { rdr_log(reader, "(asc_sn) Unexpected card answer: %s", cs_hexdump(1, cta_res, cta_lr, tmp, sizeof(tmp))); return ERROR; } memcpy(card_serial, cta_res + 2, 13); cta_lr = strlen(card_serial); for (i = 0; i < cta_lr; i++) { if (card_serial[i] == ' ') continue; // Sanity check if (!isdigit(card_serial[i])) card_serial[i] = '*'; } // Write empty ECM, *FIXME* why are we doing this? To prepare the card somehow? write_cmd(cmd_ecm_empty, NULL); // The HEX serial have nothing to do with Serial (they do not match) rdr_log_sensitive(reader, "CAID: 0x4AEE|0x5581, CardType: 0x%02x, Serial: {%s}, HexSerial: {%02X %02X %02X %02X}", card_type, card_serial, reader->hexserial[0], reader->hexserial[1], reader->hexserial[2], reader->hexserial[3]); rdr_log(reader, "Ready for requests."); return OK; }
static int32_t griffin_card_init(struct s_reader *rdr, ATR *newatr) { int32_t i; get_atr def_resp if(atr_size < 10) { return ERROR; } // 0 1 2 3 4 5 6 7 8 9 // ATR: 3B 08 yy 01 xx xx xx xx 10 00 if(atr[0] != 0x3b || atr[1] != 0x08 || atr[3] != 0x01 || atr[9] != 0x00) { return ERROR; } if(!cs_malloc(&rdr->csystem_data, sizeof(struct griffin_data))) { return ERROR; } struct griffin_data *csystem_data = rdr->csystem_data; rdr->nprov = 1; memset(rdr->sa, 0, sizeof(rdr->sa)); memset(rdr->prid, 0, sizeof(rdr->prid)); memset(rdr->hexserial, 0, sizeof(rdr->hexserial)); rdr->caid = (0x55 << 8) | atr[2]; memcpy(rdr->hexserial, atr + 4, 4); csystem_data->cmd_base = atr[8]; rdr_log_sensitive(rdr, "[griffin-reader] card detected, cmd_base: %02X caid: %04X hexserial: {%02X %02X %02X %02X}", csystem_data->cmd_base, rdr->caid, rdr->hexserial[0], rdr->hexserial[1], rdr->hexserial[2], rdr->hexserial[3]); griffin_cmd(GRIFFIN_CMD_INIT, NULL, 0, 2); csystem_data->cmd_base = cta_res[2]; // already set from ATR griffin_cmd(GRIFFIN_CMD_GET_HEX_SERIAL, NULL, 0, 6); memcpy(rdr->hexserial, cta_res + 2, 4); char serial[16]; memset(serial, 0, sizeof(serial)); griffin_cmd(GRIFFIN_CMD_GET_ASCII_SERIAL, NULL, 0, 14); memcpy(serial, cta_res + 2, 12); griffin_cmd(GRIFFIN_CMD_GET_CAID, NULL, 0, 4); rdr->caid = (cta_res[2] << 8) | cta_res[3]; griffin_cmd(GRIFFIN_CMD_GET_CARD_ADDRESS, NULL, 0, 48); for(i = 1 ; i < CS_MAXPROV; i++) { if(3 + (i * 16) + 4 > cta_lr) { break; } memcpy(rdr->sa[i - 1], cta_res + 3 + (i * 16), 4); } // Unknown commands griffin_cmd(0x22, NULL, 0, 2); griffin_cmd(0x10, NULL, 0, 2); griffin_cmd(0x14, NULL, 0, 2); //griffin_cmd(0x2a, NULL, 0, 2); //griffin_cmd(0x30, NULL, 0, 2); for(i = 0 ; i < CS_MAXPROV; i++) { if(array_has_nonzero_byte(rdr->sa[i], 4)) { rdr_log_sensitive(rdr, "CAID: 0x%04X, Serial: {%s}, HexSerial: {%02X %02X %02X %02X} Addr: {%02X %02X %02X %02X}", rdr->caid, serial, rdr->hexserial[0], rdr->hexserial[1], rdr->hexserial[2], rdr->hexserial[3], rdr->sa[i][0], rdr->sa[i][1], rdr->sa[i][2], rdr->sa[i][3]); } } rdr_log(rdr, "Ready for requests."); return OK; }
static int32_t dre_card_init (struct s_reader * reader, ATR *newatr) { get_atr; def_resp; uchar ua[] = { 0x43, 0x15 }; // get serial number (UA) uchar providers[] = { 0x49, 0x15 }; // get providers int32_t i; char *card; char tmp[9]; if ((atr[0] != 0x3b) || (atr[1] != 0x15) || (atr[2] != 0x11) || (atr[3] != 0x12) || ( ((atr[4] != 0xca) || (atr[5] != 0x07)) && ((atr[4] != 0x01) || (atr[5] != 0x01)) )) return ERROR; reader->provider = atr[6]; uchar checksum = xor (atr + 1, 6); if (checksum != atr[7]) rdr_log(reader, "warning: expected ATR checksum %02x, smartcard reports %02x", checksum, atr[7]); switch (atr[6]) { case 0x11: card = "Tricolor Centr"; reader->caid = 0x4ae1; break; //59 type card = MSP (74 type = ATMEL) case 0x12: card = "Cable TV"; reader->caid = 0x4ae1; //TODO not sure about this one break; case 0x14: card = "Tricolor Syberia / Platforma HD new"; reader->caid = 0x4ae1; break; //59 type card case 0x15: card = "Platforma HD / DW old"; reader->caid = 0x4ae1; break; //59 type card default: card = "Unknown"; reader->caid = 0x4ae1; break; } memset (reader->prid, 0x00, 8); static const uchar cmd30[] = { 0x30, 0x81, 0x00, 0x81, 0x82, 0x03, 0x84, 0x05, 0x06, 0x87, 0x08, 0x09, 0x00, 0x81, 0x82, 0x03, 0x84, 0x05, 0x00 }; dre_cmd (cmd30); //unknown command, generates error on card 0x11 and 0x14 /* response: 59 03 E2 E3 FE 48 */ uchar cmd54[] = { 0x54, 0x14 }; // geocode cmd54[1] = reader->provider; uchar geocode = 0; if ((dre_cmd (cmd54))) //error would not be fatal, like on 0x11 cards geocode = cta_res[3]; providers[1] = reader->provider; if (!(dre_cmd (providers))) return ERROR; //fatal error if ((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00)) return ERROR; uchar provname[128]; for (i = 0; ((i < cta_res[2] - 6) && (i < 128)); i++) { provname[i] = cta_res[6 + i]; if (provname[i] == 0x00) break; } int32_t major_version = cta_res[3]; int32_t minor_version = cta_res[4]; ua[1] = reader->provider; dre_cmd (ua); //error would not be fatal int32_t hexlength = cta_res[1] - 2; //discard first and last byte, last byte is always checksum, first is answer code reader->hexserial[0] = 0; reader->hexserial[1] = 0; memcpy (reader->hexserial + 2, cta_res + 3, hexlength); int32_t low_dre_id = ((cta_res[4] << 16) | (cta_res[5] << 8) | cta_res[6]) - 48608; int32_t dre_chksum = 0; uchar buf[32]; snprintf ((char *)buf, sizeof(buf), "%i%i%08i", reader->provider - 16, major_version + 1, low_dre_id); for (i = 0; i < 32; i++) { if (buf[i] == 0x00) break; dre_chksum += buf[i] - 48; } rdr_log (reader, "type: DRE Crypt, caid: %04X, serial: {%s}, dre id: %i%i%i%08i, geocode %i, card: %s v%i.%i", reader->caid, cs_hexdump(0, reader->hexserial + 2, 4, tmp, sizeof(tmp)), dre_chksum, reader->provider - 16, major_version + 1, low_dre_id, geocode, card, major_version, minor_version); rdr_log (reader, "Provider name:%s.", provname); memset (reader->sa, 0, sizeof (reader->sa)); memcpy (reader->sa[0], reader->hexserial + 2, 1); //copy first byte of unique address also in shared address, because we dont know what it is... rdr_log_sensitive(reader, "SA = %02X%02X%02X%02X, UA = {%s}", reader->sa[0][0], reader->sa[0][1], reader->sa[0][2], reader->sa[0][3], cs_hexdump(0, reader->hexserial + 2, 4, tmp, sizeof(tmp))); reader->nprov = 1; if (!dre_set_provider_info (reader)) return ERROR; //fatal error rdr_log(reader, "ready for requests"); return OK; }
static int32_t bulcrypt_get_emm_type(EMM_PACKET *ep, struct s_reader *reader) { char dump_emm_sn[64], dump_card_sn[64]; unsigned int emm_len = check_sct_len(ep->emm, 3); int32_t ret = FALSE; memset(ep->hexserial, 0, 8); if (emm_len < 176) { rdr_debug_mask(reader, D_EMM, "emm_len < 176 (%u): %s", emm_len, cs_hexdump(1, ep->emm, 12, dump_emm_sn, sizeof(dump_emm_sn))); ep->type = UNKNOWN; return FALSE; } cs_hexdump(1, reader->hexserial, 3, dump_card_sn, sizeof(dump_card_sn)); #define compare_hex_serial(serial_len) \ do { \ cs_hexdump(1, ep->hexserial, serial_len, dump_emm_sn, sizeof(dump_emm_sn)); \ ret = memcmp(ep->hexserial, reader->hexserial, serial_len) == 0; \ } while(0) #define check_serial(serial_len) \ do { \ memcpy(ep->hexserial, ep->emm + 3, serial_len); \ compare_hex_serial(serial_len); \ } while(0) #define check_serial_skip_first(serial_len) \ do { \ memcpy(ep->hexserial, ep->emm + 4, serial_len); \ compare_hex_serial(serial_len); \ } while(0) switch (ep->emm[0]) { case BULCRYPT_EMM_UNIQUE_82: case BULCRYPT_EMM_UNIQUE_85: ep->type = UNIQUE; check_serial(3); if (ret) rdr_log_sensitive(reader, "EMM_UNIQUE-%02x-{%02x}, emm_sn = {%s}, card_sn = {%s}", ep->emm[0], ep->emm[6], dump_emm_sn, dump_card_sn); break; case BULCRYPT_EMM_SHARED_84: ep->type = SHARED; check_serial(2); if (ret) rdr_log_sensitive(reader, "EMM_SHARED-%02x-{%02x-%02x}, emm_sn = {%s}, card_sn = {%s}", ep->emm[0], ep->emm[5], ep->emm[6], dump_emm_sn, dump_card_sn); break; case BULCRYPT_EMM_8a: ep->type = UNKNOWN; check_serial_skip_first(2); if (ret) rdr_log_sensitive(reader, "EMM_UNKNOWN-%02x-{%02x-%02x}, emm_sn = {%s}, card_sn = {%s}", ep->emm[0], ep->emm[5], ep->emm[6], dump_emm_sn, dump_card_sn); break; case BULCRYPT_EMM_8b: ep->type = GLOBAL; check_serial_skip_first(1); if (ret) rdr_log_sensitive(reader, "EMM_GLOBAL-%02x-{%02x-%02x}, emm_sn = {%s}, card_sn = {%s}", ep->emm[0], ep->emm[5], ep->emm[6], dump_emm_sn, dump_card_sn); break; case BULCRYPT_EMM_FILLER: ep->type = UNKNOWN; break; default: ep->type = UNKNOWN; rdr_log(reader, "UNKNOWN_EMM len: %u, %s..", emm_len, cs_hexdump(1, ep->emm, 12, dump_emm_sn, sizeof(dump_emm_sn))); break; } return ret; }