#include "tcp.h"
#include "psi.h"
#include "tsdemux.h"
-#include "ffdecsa/FFdecsa.h"
+#include <dvbcsa/dvbcsa.h>
#include "capmt.h"
#include "notify.h"
#include "subscriptions.h"
CT_FORBIDDEN
} ct_keystate;
- /* buffer for keystruct */
- void *ct_keys;
+ /* buffers for keystructs */
+ struct dvbcsa_bs_key_s *ct_key_even;
+ struct dvbcsa_bs_key_s *ct_key_odd;
/* CSA */
int ct_cluster_size;
uint8_t *ct_tsbcluster;
+ struct dvbcsa_bs_batch_s *ct_tsbbatch_even;
+ struct dvbcsa_bs_batch_s *ct_tsbbatch_odd;
int ct_fill;
+ int ct_fill_even;
+ int ct_fill_odd;
/* current sequence number */
uint16_t ct_seq;
LIST_REMOVE(ct, ct_link);
- free_key_struct(ct->ct_keys);
+ dvbcsa_bs_key_free(ct->ct_key_odd);
+ dvbcsa_bs_key_free(ct->ct_key_even);
+ free(ct->ct_tsbbatch_odd);
+ free(ct->ct_tsbbatch_even);
free(ct->ct_tsbcluster);
free(ct);
}
continue;
if (memcmp(even, invalid, 8))
- set_even_control_word(ct->ct_keys, even);
+ dvbcsa_bs_key_set(even, ct->ct_key_even);
if (memcmp(odd, invalid, 8))
- set_odd_control_word(ct->ct_keys, odd);
+ dvbcsa_bs_key_set(odd, ct->ct_key_odd);
if(ct->ct_keystate != CT_RESOLVED)
tvhlog(LOG_INFO, "capmt", "Obtained key for service \"%s\"",t->s_svcname);
const uint8_t *tsb)
{
capmt_service_t *ct = (capmt_service_t *)td;
- int r, i;
- unsigned char *vec[3];
+ uint8_t *pkt;
+ int xc0;
+ int ev_od;
+ int len;
+ int offset;
+ int n;
+ // FIXME: //int residue;
+ int i;
uint8_t *t0;
if(ct->ct_keystate == CT_FORBIDDEN)
if(ct->ct_keystate != CT_RESOLVED)
return -1;
- memcpy(ct->ct_tsbcluster + ct->ct_fill * 188, tsb, 188);
+ pkt = ct->ct_tsbcluster + ct->ct_fill * 188;
+ memcpy(pkt, tsb, 188);
ct->ct_fill++;
+ do { // handle this packet
+ xc0 = pkt[3] & 0xc0;
+ if(xc0 == 0x00) { // clear
+ break;
+ }
+ if(xc0 == 0x40) { // reserved
+ break;
+ }
+ if(xc0 == 0x80 || xc0 == 0xc0) { // encrypted
+ ev_od = (xc0 & 0x40) >> 6; // 0 even, 1 odd
+ pkt[3] &= 0x3f; // consider it decrypted now
+ if(pkt[3] & 0x20) { // incomplete packet
+ offset = 4 + pkt[4] + 1;
+ len = 188 - offset;
+ n = len >> 3;
+ // FIXME: //residue = len - (n << 3);
+ if(n == 0) { // decrypted==encrypted!
+ break; // this doesn't need more processing
+ }
+ } else {
+ len = 184;
+ offset = 4;
+ // FIXME: //n = 23;
+ // FIXME: //residue = 0;
+ }
+ if(ev_od == 0) {
+ ct->ct_tsbbatch_even[ct->ct_fill_even].data = pkt + offset;
+ ct->ct_tsbbatch_even[ct->ct_fill_even].len = len;
+ ct->ct_fill_even++;
+ } else {
+ ct->ct_tsbbatch_odd[ct->ct_fill_odd].data = pkt + offset;
+ ct->ct_tsbbatch_odd[ct->ct_fill_odd].len = len;
+ ct->ct_fill_odd++;
+ }
+ }
+ } while(0);
+
if(ct->ct_fill != ct->ct_cluster_size)
return 0;
- ct->ct_fill = 0;
-
- vec[0] = ct->ct_tsbcluster;
- vec[1] = ct->ct_tsbcluster + ct->ct_cluster_size * 188;
- vec[2] = NULL;
+ if(ct->ct_fill_even) {
+ ct->ct_tsbbatch_even[ct->ct_fill_even].data = NULL;
+ dvbcsa_bs_decrypt(ct->ct_key_even, ct->ct_tsbbatch_even, 184);
+ ct->ct_fill_even = 0;
+ }
+ if(ct->ct_fill_odd) {
+ ct->ct_tsbbatch_odd[ct->ct_fill_odd].data = NULL;
+ dvbcsa_bs_decrypt(ct->ct_key_odd, ct->ct_tsbbatch_odd, 184);
+ ct->ct_fill_odd = 0;
+ }
- while(1) {
- t0 = vec[0];
- r = decrypt_packets(ct->ct_keys, vec);
- if(r == 0)
- break;
- for(i = 0; i < r; i++) {
+ t0 = ct->ct_tsbcluster;
+ for(i = 0; i < ct->ct_fill; i++) {
ts_recv_packet2(t, t0);
t0 += 188;
}
- }
+ ct->ct_fill = 0;
return 0;
}
elementary_stream_t *st;
/* create new capmt service */
- ct = calloc(1, sizeof(capmt_service_t));
- ct->ct_cluster_size = get_suggested_cluster_size();
- ct->ct_tsbcluster = malloc(ct->ct_cluster_size * 188);
- ct->ct_seq = capmt->capmt_seq++;
+ ct = calloc(1, sizeof(capmt_service_t));
+ ct->ct_cluster_size = dvbcsa_bs_batch_size();
+ ct->ct_tsbcluster = malloc(ct->ct_cluster_size * 188);
+ ct->ct_tsbbatch_even = malloc((ct->ct_cluster_size + 1) *
+ sizeof(struct dvbcsa_bs_batch_s));
+ ct->ct_tsbbatch_odd = malloc((ct->ct_cluster_size + 1) *
+ sizeof(struct dvbcsa_bs_batch_s));
+ ct->ct_seq = capmt->capmt_seq++;
TAILQ_FOREACH(st, &t->s_components, es_link) {
caid_t *c;
}
}
- ct->ct_keys = get_key_struct();
+ ct->ct_key_even = dvbcsa_bs_key_alloc();
+ ct->ct_key_odd = dvbcsa_bs_key_alloc();
ct->ct_capmt = capmt;
ct->ct_service = t;
#include "tcp.h"
#include "psi.h"
#include "tsdemux.h"
-#include "ffdecsa/FFdecsa.h"
+#include <dvbcsa/dvbcsa.h>
#include "cwc.h"
#include "notify.h"
#include "atomic.h"
CS_IDLE
} cs_keystate;
- void *cs_keys;
+ struct dvbcsa_bs_key_s *cs_key_even;
+ struct dvbcsa_bs_key_s *cs_key_odd;
uint8_t cs_cw[16];
*/
int cs_cluster_size;
uint8_t *cs_tsbcluster;
+ struct dvbcsa_bs_batch_s *cs_tsbbatch_even;
+ struct dvbcsa_bs_batch_s *cs_tsbbatch_odd;
int cs_fill;
+ int cs_fill_even;
+ int cs_fill_odd;
LIST_HEAD(, ecm_pid) cs_pids;
ct->cs_pending_cw_update = 0;
for(i = 0; i < 8; i++)
if(ct->cs_cw[i]) {
- set_even_control_word(ct->cs_keys, ct->cs_cw);
+ dvbcsa_bs_key_set(ct->cs_cw, ct->cs_key_even);
break;
}
for(i = 0; i < 8; i++)
if(ct->cs_cw[8 + i]) {
- set_odd_control_word(ct->cs_keys, ct->cs_cw + 8);
+ dvbcsa_bs_key_set(ct->cs_cw + 8, ct->cs_key_odd);
break;
}
}
const uint8_t *tsb)
{
cwc_service_t *ct = (cwc_service_t *)td;
- int r;
- unsigned char *vec[3];
+ uint8_t *pkt;
+ int xc0;
+ int ev_od;
+ int len;
+ int offset;
+ int n;
+ // FIXME: //int residue;
if(ct->cs_keystate == CS_FORBIDDEN)
return 1;
if(ct->cs_fill == 0 && ct->cs_pending_cw_update)
update_keys(ct);
- memcpy(ct->cs_tsbcluster + ct->cs_fill * 188, tsb, 188);
+ pkt = ct->cs_tsbcluster + ct->cs_fill * 188;
+ memcpy(pkt, tsb, 188);
ct->cs_fill++;
+ do { // handle this packet
+ xc0 = pkt[3] & 0xc0;
+ if(xc0 == 0x00) { // clear
+ break;
+ }
+ if(xc0 == 0x40) { // reserved
+ break;
+ }
+ if(xc0 == 0x80 || xc0 == 0xc0) { // encrypted
+ ev_od = (xc0 & 0x40) >> 6; // 0 even, 1 odd
+ pkt[3] &= 0x3f; // consider it decrypted now
+ if(pkt[3] & 0x20) { // incomplete packet
+ offset = 4 + pkt[4] + 1;
+ len = 188 - offset;
+ n = len >> 3;
+ // FIXME: //residue = len - (n << 3);
+ if(n == 0) { // decrypted==encrypted!
+ break; // this doesn't need more processing
+ }
+ } else {
+ len = 184;
+ offset = 4;
+ // FIXME: //n = 23;
+ // FIXME: //residue = 0;
+ }
+ if(ev_od == 0) {
+ ct->cs_tsbbatch_even[ct->cs_fill_even].data = pkt + offset;
+ ct->cs_tsbbatch_even[ct->cs_fill_even].len = len;
+ ct->cs_fill_even++;
+ } else {
+ ct->cs_tsbbatch_odd[ct->cs_fill_odd].data = pkt + offset;
+ ct->cs_tsbbatch_odd[ct->cs_fill_odd].len = len;
+ ct->cs_fill_odd++;
+ }
+ }
+ } while(0);
+
if(ct->cs_fill != ct->cs_cluster_size)
return 0;
- while(1) {
+ if(ct->cs_fill_even) {
+ ct->cs_tsbbatch_even[ct->cs_fill_even].data = NULL;
+ dvbcsa_bs_decrypt(ct->cs_key_even, ct->cs_tsbbatch_even, 184);
+ ct->cs_fill_even = 0;
+ }
+ if(ct->cs_fill_odd) {
+ ct->cs_tsbbatch_odd[ct->cs_fill_odd].data = NULL;
+ dvbcsa_bs_decrypt(ct->cs_key_odd, ct->cs_tsbbatch_odd, 184);
+ ct->cs_fill_odd = 0;
+ }
- vec[0] = ct->cs_tsbcluster;
- vec[1] = ct->cs_tsbcluster + ct->cs_fill * 188;
- vec[2] = NULL;
-
- r = decrypt_packets(ct->cs_keys, vec);
- if(r > 0) {
+ {
int i;
const uint8_t *t0 = ct->cs_tsbcluster;
- for(i = 0; i < r; i++) {
+ for(i = 0; i < ct->cs_fill; i++) {
ts_recv_packet2(t, t0);
t0 += 188;
}
-
- r = ct->cs_fill - r;
- assert(r >= 0);
-
- if(r > 0)
- memmove(ct->cs_tsbcluster, t0, r * 188);
- ct->cs_fill = r;
-
- if(ct->cs_pending_cw_update && r > 0)
- continue;
- } else {
- ct->cs_fill = 0;
- }
- break;
}
+ ct->cs_fill = 0;
+
if(ct->cs_pending_cw_update)
update_keys(ct);
LIST_REMOVE(ct, cs_link);
- free_key_struct(ct->cs_keys);
+ dvbcsa_bs_key_free(ct->cs_key_odd);
+ dvbcsa_bs_key_free(ct->cs_key_even);
+ free(ct->cs_tsbbatch_odd);
+ free(ct->cs_tsbbatch_even);
free(ct->cs_tsbcluster);
free(ct);
}
continue;
ct = calloc(1, sizeof(cwc_service_t));
- ct->cs_cluster_size = get_suggested_cluster_size();
+ ct->cs_cluster_size = dvbcsa_bs_batch_size();
ct->cs_tsbcluster = malloc(ct->cs_cluster_size * 188);
+ ct->cs_tsbbatch_even = malloc((ct->cs_cluster_size + 1) *
+ sizeof(struct dvbcsa_bs_batch_s));
+ ct->cs_tsbbatch_odd = malloc((ct->cs_cluster_size + 1) *
+ sizeof(struct dvbcsa_bs_batch_s));
- ct->cs_keys = get_key_struct();
+ ct->cs_key_even = dvbcsa_bs_key_alloc();
+ ct->cs_key_odd = dvbcsa_bs_key_alloc();
ct->cs_cwc = cwc;
ct->cs_service = t;
ct->cs_okchannel = -3;