static void tvhcsa_csa_cbc_flush ( tvhcsa_t *csa, struct mpegts_service *s ) { #if ENABLE_DVBCSA tvhtrace(LS_CSA, "%p: CSA flush - descramble packets for service \"%s\" MAX=%d even=%d odd=%d fill=%d", csa,((mpegts_service_t *)s)->s_dvb_svcname, csa->csa_cluster_size,csa->csa_fill_even,csa->csa_fill_odd,csa->csa_fill); if(csa->csa_fill_even) { csa->csa_tsbbatch_even[csa->csa_fill_even].data = NULL; dvbcsa_bs_decrypt(csa->csa_key_even, csa->csa_tsbbatch_even, 184); csa->csa_fill_even = 0; } if(csa->csa_fill_odd) { csa->csa_tsbbatch_odd[csa->csa_fill_odd].data = NULL; dvbcsa_bs_decrypt(csa->csa_key_odd, csa->csa_tsbbatch_odd, 184); csa->csa_fill_odd = 0; } ts_recv_packet2(s, csa->csa_tsbcluster, csa->csa_fill * 188); csa->csa_fill = 0; #else #error "Unknown CSA descrambler" #endif }
static void tvhcsa_csa_cbc_flush ( tvhcsa_t *csa, struct mpegts_service *s ) { #if ENABLE_DVBCSA if(csa->csa_fill_even) { csa->csa_tsbbatch_even[csa->csa_fill_even].data = NULL; dvbcsa_bs_decrypt(csa->csa_key_even, csa->csa_tsbbatch_even, 184); csa->csa_fill_even = 0; } if(csa->csa_fill_odd) { csa->csa_tsbbatch_odd[csa->csa_fill_odd].data = NULL; dvbcsa_bs_decrypt(csa->csa_key_odd, csa->csa_tsbbatch_odd, 184); csa->csa_fill_odd = 0; } ts_recv_packet2(s, csa->csa_tsbcluster, csa->csa_fill * 188); csa->csa_fill = 0; #else int r, l; unsigned char *vec[3]; vec[0] = csa->csa_tsbcluster; vec[1] = csa->csa_tsbcluster + csa->csa_fill * 188; vec[2] = NULL; r = decrypt_packets(csa->csa_keys, vec); if(r > 0) { ts_recv_packet2(s, csa->csa_tsbcluster, r * 188); l = csa->csa_fill - r; assert(l >= 0); if(l > 0) memmove(csa->csa_tsbcluster, csa->csa_tsbcluster + r * 188, l * 188); csa->csa_fill = l; } else { csa->csa_fill = 0; } #endif }
/* The following routine is taken from benchbitslice in libdvbcsa */ void dvbcsa_benchmark(void) { struct timeval t0, t1; struct dvbcsa_bs_key_s *key = dvbcsa_bs_key_alloc(); unsigned int n, i, npackets = 0; unsigned int batch_size = dvbcsa_bs_batch_size(); uint8_t data[batch_size + 1][188]; struct dvbcsa_bs_batch_s pcks[batch_size + 1]; uint8_t cw[8] = { 0x12, 0x34, 0x56, 0x78, 0x89, 0xab, 0xcd, 0xef, }; dvbcsa_bs_key_set (cw, key); printf("Batch size %d packets.\n\n", batch_size); for (i = 0; i < batch_size; i++) { pcks[i].data = data[i]; pcks[i].len = 184; memset(data[i], rand(), pcks[i].len); } pcks[i].data = NULL; gettimeofday(&t0, NULL); for (n = (1 << 12) / batch_size; n < (1 << 19) / batch_size; n *= 2) { printf(" Decrypting %6u mpegts packets\r", n * batch_size); fflush(stdout); for (i = 0; i < n; i++) { dvbcsa_bs_decrypt(key, pcks, 184); } npackets += n * batch_size; } gettimeofday(&t1, NULL); unsigned long long usec = timeval_diff_usec(&t0, &t1); printf("DONE: %u packets (%u bytes) decrypted in %llu ms = %.1f Mbits/s\n\n", npackets, npackets * 188, usec / 1000, (double)(npackets * 188 * 8) / (double)usec ); dvbcsa_bs_key_free(key); }
static void tvhcsa_des_flush ( tvhcsa_t *csa, struct mpegts_service *s ) { #if ENABLE_DVBCSA int i; const uint8_t *t0; if(csa->csa_fill_even) { csa->csa_tsbbatch_even[csa->csa_fill_even].data = NULL; dvbcsa_bs_decrypt(csa->csa_key_even, csa->csa_tsbbatch_even, 184); csa->csa_fill_even = 0; } if(csa->csa_fill_odd) { csa->csa_tsbbatch_odd[csa->csa_fill_odd].data = NULL; dvbcsa_bs_decrypt(csa->csa_key_odd, csa->csa_tsbbatch_odd, 184); csa->csa_fill_odd = 0; } t0 = csa->csa_tsbcluster; for(i = 0; i < csa->csa_fill; i++) { ts_recv_packet2(s, t0); t0 += 188; } csa->csa_fill = 0; #else int r; unsigned char *vec[3]; while(1) { vec[0] = csa->csa_tsbcluster; vec[1] = csa->csa_tsbcluster + csa->csa_fill * 188; vec[2] = NULL; r = decrypt_packets(csa->csa_keys, vec); if(r > 0) { int i; const uint8_t *t0 = csa->csa_tsbcluster; for(i = 0; i < r; i++) { ts_recv_packet2(s, t0); t0 += 188; } r = csa->csa_fill - r; assert(r >= 0); if(r > 0) memmove(csa->csa_tsbcluster, t0, r * 188); csa->csa_fill = r; } else { csa->csa_fill = 0; } break; } #endif }
inline void csa_decrypt_multiple_odd(csakey_t *csakey, struct csa_batch *batch) { struct csakey *key = (struct csakey *)csakey; dvbcsa_bs_decrypt(key->bs_csakey[1], (struct dvbcsa_bs_batch_s *)batch, 184); }
bool cDeCSA::Decrypt(unsigned char *data, int len, int& packetsCount) { cMutexLock lock(&mutex); // printf("Begin Decrypting %d\n", len); int currIdx=-1; len-=(TS_SIZE-1); int l; int packets=0, cryptedPackets=0; for(l=0; l<len && cryptedPackets<cs; l+=TS_SIZE) { unsigned int ev_od=data[l+3]&0xC0; int adaptation_field_exist = (data[l+3]&0x30)>>4; if((ev_od==0x80 || ev_od==0xC0) && adaptation_field_exist!=2) { // encrypted int idx=pidmap[((data[l+1]<<8)+data[l+2])&(MAX_CSA_PIDS-1)]; if(currIdx<0 || idx==currIdx) { // same or no index currIdx=idx; if(ev_od!=even_odd[idx]) { if (cryptedPackets==0) { even_odd[idx]=ev_od; wait.Broadcast(); printf("adapter%d/demux%d idx %d: change to %s key\n", adapter, demux, idx, (ev_od&0x40)?"odd":"even"); bool doWait=false; if(ev_od&0x40) { flags[idx]&=~FL_EVEN_GOOD; if(!(flags[idx]&FL_ODD_GOOD)) doWait=true; } else { flags[idx]&=~FL_ODD_GOOD; if(!(flags[idx]&FL_EVEN_GOOD)) doWait=true; } if(doWait) { printf("adapter%d/demux%d idx %d: %s key not ready (%d ms)\n", adapter, demux, idx, (ev_od&0x40)?"odd":"even", MAX_KEY_WAIT); if(flags[idx]&FL_ACTIVITY) { flags[idx]&=~FL_ACTIVITY; if(wait.TimedWait(mutex,MAX_KEY_WAIT)) printf("adapter%d/demux%d idx %d: successfully waited for key\n", adapter, demux, idx); else printf("adapter%d/demux%d idx %d: timed out. proceeding anyways\n", adapter, demux, idx); } else printf("adapter%d/demux%d idx %d: not active. wait skipped\n", adapter, demux, idx); } } else { break; } } } else break; if (adaptation_field_exist==1) { pcks[cryptedPackets].data = data+l+4; pcks[cryptedPackets].len = 184; } else if (adaptation_field_exist==3) { pcks[cryptedPackets].data = data+l+5+data[l+4]; pcks[cryptedPackets].len = 183-data[l+4]; } cryptedPackets++; } data[l+3] &= 0x3F; packets++; } if (cryptedPackets>0) { // printf("Begin Decrypting cryptedPackets %d\n",cryptedPackets); for (int i=cryptedPackets;i<=cs;i++) { pcks[i].data = NULL; } if (GetKeyStruct(currIdx)) { // printf("Begin Decrypting GetKeyStruct %d\n",currIdx); if (even_odd[currIdx]&0x40) { dvbcsa_bs_decrypt(csa_bs_key_odd[currIdx], pcks, 184); } else { dvbcsa_bs_decrypt(csa_bs_key_even[currIdx], pcks, 184); } } } packetsCount = packets; return true; }