Browse Source

Add support for multiple IRDETO types.

With this patch Bulsatcom irdeto ECM stream can be used
for decoding.
Georgi Chorbadzhiyski 12 years ago
parent
commit
f8480e6772
4 changed files with 91 additions and 11 deletions
  1. 4
    0
      data.c
  2. 4
    0
      data.h
  3. 72
    10
      tables.c
  4. 11
    1
      tsdecrypt.c

+ 4
- 0
data.c View File

@@ -18,9 +18,11 @@ void data_init(struct ts *ts) {
18 18
 
19 19
 	ts->emm      = ts_privsec_alloc();
20 20
 	ts->last_emm = ts_privsec_alloc();
21
+	ts->tmp_emm  = ts_privsec_alloc();
21 22
 
22 23
 	ts->ecm      = ts_privsec_alloc();
23 24
 	ts->last_ecm = ts_privsec_alloc();
25
+	ts->tmp_ecm  = ts_privsec_alloc();
24 26
 
25 27
 	pidmap_clear(&ts->pidmap);
26 28
 	pidmap_clear(&ts->cc);
@@ -76,8 +78,10 @@ void data_free(struct ts *ts) {
76 78
 	ts_pmt_free(&ts->curpmt);
77 79
 	ts_privsec_free(&ts->emm);
78 80
 	ts_privsec_free(&ts->last_emm);
81
+	ts_privsec_free(&ts->tmp_emm);
79 82
 	ts_privsec_free(&ts->ecm);
80 83
 	ts_privsec_free(&ts->last_ecm);
84
+	ts_privsec_free(&ts->tmp_ecm);
81 85
 
82 86
 	dvbcsa_key_free(ts->key.csakey[0]);
83 87
 	dvbcsa_key_free(ts->key.csakey[1]);

+ 4
- 0
data.h View File

@@ -79,6 +79,8 @@ struct ts {
79 79
 	struct ts_pmt		*pmt, *curpmt;
80 80
 	struct ts_privsec	*emm, *last_emm;
81 81
 	struct ts_privsec	*ecm, *last_ecm;
82
+	struct ts_privsec	*tmp_emm;
83
+	struct ts_privsec	*tmp_ecm;
82 84
 	uint16_t			pmt_pid;
83 85
 	uint16_t			service_id;
84 86
 	uint16_t			emm_caid, emm_pid;
@@ -107,6 +109,8 @@ struct ts {
107 109
 	int					emm_only;
108 110
 	int					pid_filter;
109 111
 
112
+	uint8_t				irdeto_ecm;
113
+
110 114
 	int					rtp_input;
111 115
 
112 116
 	struct io			input;

+ 72
- 10
tables.c View File

@@ -81,10 +81,8 @@ void process_pmt(struct ts *ts, uint16_t pid, uint8_t *ts_packet) {
81 81
 #define dump_sz      (16)
82 82
 #define dump_buf_sz  (dump_sz * 6)
83 83
 
84
-void process_emm(struct ts *ts, uint16_t pid, uint8_t *ts_packet) {
84
+static void __process_emm(struct ts *ts, uint16_t pid, uint8_t *ts_packet) {
85 85
 	char dump[dump_buf_sz];
86
-	if (!ts->emm_pid || ts->emm_pid != pid)
87
-		return;
88 86
 
89 87
 	show_ts_pack(ts, pid, "emm", NULL, ts_packet);
90 88
 
@@ -111,19 +109,21 @@ void process_emm(struct ts *ts, uint16_t pid, uint8_t *ts_packet) {
111 109
 	ts_privsec_clear(ts->emm);
112 110
 }
113 111
 
114
-void process_ecm(struct ts *ts, uint16_t pid, uint8_t *ts_packet) {
112
+static void __process_ecm(struct ts *ts, uint16_t pid, uint8_t *ts_packet) {
115 113
 	char dump[dump_buf_sz];
116 114
 
117
-	if (ts->emm_only)
118
-		return;
119
-
120
-	if (!ts->ecm_pid || ts->ecm_pid != pid)
121
-		return;
122
-
123 115
 	ts->ecm = ts_privsec_push_packet(ts->ecm, ts_packet);
124 116
 	if (!ts->ecm->initialized)
125 117
 		return;
126 118
 
119
+	if (ts->req_CA_sys == CA_IRDETO) {
120
+		int type = ts->ecm->section_header->section_data[4];
121
+		if (type != ts->irdeto_ecm) {
122
+			ts_privsec_clear(ts->ecm);
123
+			return;
124
+		}
125
+	}
126
+
127 127
 	struct ts_header *th = &ts->ecm->ts_header;
128 128
 	struct ts_section_header *sec = ts->ecm->section_header;
129 129
 	int duplicate = ts_privsec_is_same(ts->ecm, ts->last_ecm);
@@ -153,3 +153,65 @@ void process_ecm(struct ts *ts, uint16_t pid, uint8_t *ts_packet) {
153 153
 
154 154
 	show_ts_pack(ts, pid, !duplicate ? "ecm" : "ec+", NULL, ts_packet);
155 155
 }
156
+
157
+// There are cryptosystems that are puting more than one PSI table
158
+// in TS packet. IRDETO is such example. Because libtsfuncs assumes
159
+// that one ts packet can produce maximum 1 PSI table, the following
160
+// workaround is used for EMM/ECM private sections. Basically we detect
161
+// if after the section there is something else than 0xff (filler) and
162
+// if there is something change ts_packet pointer field to point to
163
+// start of the potential section and reparse section.
164
+void process_ecm(struct ts *ts, uint16_t pid, uint8_t *ts_packet) {
165
+	int section_end;
166
+
167
+	if (ts->emm_only)
168
+		return;
169
+
170
+	if (!ts->ecm_pid || ts->ecm_pid != pid)
171
+		return;
172
+
173
+process_psi:
174
+	ts->tmp_ecm = ts_privsec_push_packet(ts->tmp_ecm, ts_packet);
175
+	if (!ts->tmp_ecm->initialized) {
176
+		__process_ecm(ts, pid, ts_packet);
177
+		return;
178
+	}
179
+
180
+	section_end = ts->tmp_ecm->section_header->pointer_field + ts->tmp_ecm->section_header->section_length + 3 + 4 + 1;
181
+	if (section_end < 188 && ts_packet[section_end] != 0xff) {
182
+		__process_ecm(ts, pid, ts_packet);
183
+		ts_packet[4] = ts_packet[4] + ts->tmp_ecm->section_header->section_length + 3;
184
+		ts_privsec_clear(ts->tmp_ecm);
185
+		goto process_psi;
186
+	} else {
187
+		__process_ecm(ts, pid, ts_packet);
188
+	}
189
+
190
+	ts_privsec_clear(ts->tmp_ecm);
191
+}
192
+
193
+void process_emm(struct ts *ts, uint16_t pid, uint8_t *ts_packet) {
194
+	int section_end;
195
+
196
+	if (!ts->emm_pid || ts->emm_pid != pid)
197
+		return;
198
+
199
+process_psi:
200
+	ts->tmp_emm = ts_privsec_push_packet(ts->tmp_emm, ts_packet);
201
+	if (!ts->tmp_emm->initialized) {
202
+		__process_emm(ts, pid, ts_packet);
203
+		return;
204
+	}
205
+
206
+	section_end = ts->tmp_emm->section_header->pointer_field + ts->tmp_emm->section_header->section_length + 3 + 4 + 1;
207
+	if (section_end < 188 && ts_packet[section_end] != 0xff) {
208
+		__process_emm(ts, pid, ts_packet);
209
+		ts_packet[4] = ts_packet[4] + ts->tmp_emm->section_header->section_length + 3;
210
+		ts_privsec_clear(ts->tmp_emm);
211
+		goto process_psi;
212
+	} else {
213
+		__process_emm(ts, pid, ts_packet);
214
+	}
215
+
216
+	ts_privsec_clear(ts->tmp_emm);
217
+}

+ 11
- 1
tsdecrypt.c View File

@@ -65,6 +65,9 @@ static void show_help(struct ts *ts) {
65 65
 	printf("    -P server_pass | default: %s\n", ts->camd35.pass);
66 66
 	printf("    -y usec_delay  | Sleep X usec between sending ECM/EMM packets to OSCAM. Default: %d\n", ts->packet_delay);
67 67
 	printf("\n");
68
+	printf("  ECM options:\n");
69
+	printf("    -G ecm_type    | IRDETO: Process only ECMs with selected type (0,1,2,3). Default: %d\n", ts->irdeto_ecm);
70
+	printf("\n");
68 71
 	printf("  EMM options:\n");
69 72
 	printf("    -E             | Process only EMMs without decoding input stream. Default: %s\n", ts->emm_only ? "true" : "false");
70 73
 	printf("    -f <seconds>   | Report how much EMMs has been send for processing each X seconds.\n");
@@ -112,7 +115,7 @@ static int parse_io_param(struct io *io, char *opt, int open_flags, mode_t open_
112 115
 
113 116
 static void parse_options(struct ts *ts, int argc, char **argv) {
114 117
 	int j, i, ca_err = 0, server_err = 1, input_addr_err = 0, output_addr_err = 0, output_intf_err = 0, ident_err = 0;
115
-	while ((j = getopt(argc, argv, "i:d:l:L:c:s:I:O:o:t:U:P:y:f:eEzpD:hR")) != -1) {
118
+	while ((j = getopt(argc, argv, "i:d:l:L:c:s:I:O:o:t:U:P:y:f:eEzpD:hRG:")) != -1) {
116 119
 		char *p = NULL;
117 120
 		switch (j) {
118 121
 			case 'i':
@@ -176,6 +179,10 @@ static void parse_options(struct ts *ts, int argc, char **argv) {
176 179
 				ts->output.ttl = atoi(optarg);
177 180
 				break;
178 181
 
182
+			case 'G':
183
+				ts->irdeto_ecm = atoi(optarg);
184
+				break;
185
+
179 186
 			case 'U':
180 187
 				strncpy(ts->camd35.user, optarg, sizeof(ts->camd35.user) - 1);
181 188
 				ts->camd35.user[sizeof(ts->camd35.user) - 1] = 0;
@@ -258,6 +265,9 @@ static void parse_options(struct ts *ts, int argc, char **argv) {
258 265
 	} else if (ts->input.type == FILE_IO) {
259 266
 		ts_LOGf("Input file : %s\n", ts->input.fd == 0 ? "STDIN" : ts->input.fname);
260 267
 	}
268
+	if (ts->req_CA_sys == CA_IRDETO)
269
+		ts_LOGf("Irdeto ECM : %d\n", ts->irdeto_ecm);
270
+
261 271
 	if (!ts->emm_only)
262 272
 	{
263 273
 		if (ts->output.type == NET_IO) {

Loading…
Cancel
Save