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 conax_do_ecm(struct s_reader * reader, const ECM_REQUEST *er, struct s_ecm_answer *ea) { def_resp; int32_t i,j,n,num_dw=0, rc=0; unsigned char insA2[] = { 0xDD,0xA2,0x00,0x00,0x00 }; unsigned char insCA[] = { 0xDD,0xCA,0x00,0x00,0x00 }; unsigned char exp[] = {0x01, 0x00, 0x01}; unsigned char buf[256]; if ((n=check_sct_len(er->ecm, 3))<0) return ERROR; buf[0]=0x14; buf[1]=n+1; if(0x0 != PairingECMRotation(reader, er, n)) buf[2]=2; // card will answer with encrypted dw else buf[2]=0; memcpy(buf+3, er->ecm, n); insA2[4]=n+3; write_cmd(insA2, buf); // write Header + ECM while ((cta_res[cta_lr-2]==0x98) && // Antwort ((insCA[4]=cta_res[cta_lr-1])>0) && (insCA[4]!=0xFF)) { write_cmd(insCA, NULL); //Codeword auslesen if ((cta_res[cta_lr-2]==0x98) || ((cta_res[cta_lr-2]==0x90) )) { /*checks if answer is encrypted with RSA algo and decrypts it if needed*/ if(0x81 == cta_res[0] && 2 == cta_res[2] >> 5) /*81 XX 5X*/ { if(0x00 == cta_res[cta_lr-1]) rc = RSA_CNX(reader, cta_res, reader->rsa_mod, exp, cta_lr, 64u, 3u); else rc = -4; /*card has no right to decode this channel*/ } if(0 == rc) for(i = 0; i < cta_lr-2 && num_dw < 2; i+=cta_res[i+1]+2) { switch (cta_res[i]) { case 0x25: if ( (cta_res[i+1]>=0xD) && !((n=cta_res[i+4])&0xFE) ) { rc|=(1<<n); memcpy(ea->cw+(n<<3), cta_res+i+7, 8); ++num_dw; } break; case 0x31: if ( (cta_res[i+1]==0x02 && cta_res[i+2]==0x00 && cta_res[i+3]==0x00) || \ (cta_res[i+1]==0x02 && cta_res[i+2]==0x40 && cta_res[i+3]==0x00) ) break; else if (strcmp(reader->pincode, "none")) { conax_send_pin(reader); write_cmd(insA2, buf); // write Header + ECM while ((cta_res[cta_lr-2]==0x98) && // Antwort ((insCA[4]=cta_res[cta_lr-1])>0) && (insCA[4]!=0xFF)) { write_cmd(insCA, NULL); //Codeword auslesen if ((cta_res[cta_lr-2]==0x98) || ((cta_res[cta_lr-2]==0x90) && (!cta_res[cta_lr-1]))) { for(j=0;j<cta_lr-2; j+=cta_res[j+1]+2) if ((cta_res[j]==0x25) && // access: is cw (cta_res[j+1]>=0xD) && // 0xD: 5 header + 8 cw !((n=cta_res[j+4])&0xFE)) // cw idx must be 0 or 1 { rc|=(1<<n); memcpy(ea->cw+(n<<3), cta_res+j+7, 8); ++num_dw; } } } } break; } } } } switch(rc) { case -1: rdr_log(reader, "conax decode ECM problem - RSA key is probably faulty"); break; case -2: rdr_log(reader, "conax RSA pairing - wrong size of data"); break; case -3: rdr_log(reader, "conax RSA pairing- wrong size of data for second round"); case -4: rdr_log(reader, "card has no right to decode this channel"); break; } /* answer 9011 - conax smart card need reset */ if(2<=cta_lr && 0x90==cta_res[cta_lr-2] && 0x11==cta_res[cta_lr-1]) { rdr_log(reader, "conax card hangs - reset is required"); reader->card_status = UNKNOWN; } if (rc==3) return OK; else return ERROR; }
/* Bulcrypt ECM structure: 80 70 - ECM header (80 | 81) 4c - ECM length after this field (0x4c == 76 bytes) 4f 8d 87 0b - unixts == 1334675211 == Tue Apr 17 18:06:51 EEST 2012 00 66 - *FIXME* Program number? 00 7d - *FIXME* ce 70 - ECM counter 0b 88 - ECM type xx yy zz .. - Encrypted ECM payload (64 bytes) */ static int32_t bulcrypt_do_ecm(struct s_reader * reader, const ECM_REQUEST *er, struct s_ecm_answer *ea) { char tmp[512]; uchar ecm_cmd[256]; def_resp int32_t ecm_len = check_sct_len(er->ecm, 3); if (ecm_len < 64 || ecm_len > 188) { rdr_log(reader, "Wrong ECM length: %d", ecm_len); return ERROR; } // CMD: DE 20 00 00 4C memcpy(ecm_cmd, cmd_ecm, sizeof(cmd_ecm)); ecm_cmd[4] = er->ecm[2]; // Set ECM length memcpy(ecm_cmd + sizeof(cmd_ecm), er->ecm + 3, ecm_cmd[4]); // Send ECM write_cmd(ecm_cmd, ecm_cmd + 5); if (cta_lr != 2) { rdr_log(reader, "(ecm_cmd) Unexpected card answer: %s", cs_hexdump(1, cta_res, cta_lr, tmp, sizeof(tmp))); return ERROR; } if (cta_res[0] == 0x90 && cta_res[1] == 0x03) { rdr_log(reader, "No active subscription."); return ERROR; } if ( !(cta_res[0] == 0x90 && cta_res[1] == 0x13) ) { rdr_log(reader, "(ecm_cmd) Unexpected card answer: %s", cs_hexdump(1, cta_res, cta_lr, tmp, sizeof(tmp))); return ERROR; } // Call get_cw write_cmd(cmd_ecm_get_cw, NULL); // rdr_log(reader, "CW_LOG: %s", cs_hexdump(1, cta_res, cta_lr, tmp, sizeof(tmp))); if (cta_lr < 20 || (cta_res[0] != 0x0a && cta_res[1] != 0x11)) { rdr_log(reader, "(get_cw) Unexpected card answer: %s", cs_hexdump(1, cta_res, cta_lr, tmp, sizeof(tmp))); return ERROR; } // *FIXME* is the bellow info true? // 0x80 (ver 1) is supported // 0xc0 (ver 2) is *NOT* supported currently if (cta_res[2] == 0xc0) { rdr_log(reader, "Possibly unsupported codeword (bulcrypt v2): %s", cs_hexdump(1, cta_res, cta_lr, tmp, sizeof(tmp))); // *FIXME* commented for testing, this really should be an error //return ERROR; } // Remove code word obfuscation uchar *cw = cta_res + 3; if (reader->bulcrypt_version == 1) { int i; for (i = 0 ; i < 16; i++) { cw[i] = cw[i] ^ sess_key[i]; } } if (er->ecm[0] == 0x81) { // Even/Odd CWs should be exchanged memcpy(ea->cw, cw + 8, 8); memcpy(ea->cw + 8, cw, 8); } else { memcpy(ea->cw, cw, 8); memcpy(ea->cw + 8, cw + 8, 8); } // Check if DCW is valid if (!cw_is_valid(reader, ea->cw) || !cw_is_valid(reader, ea->cw + 8)) return ERROR; return OK; }
static int32_t bulcrypt_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; }