Browse Source

Split tsdecrypt to data.{c,h}, camd.{c,h} and tables.{c,h}

Georgi Chorbadzhiyski 13 years ago
parent
commit
427cec7bb2
8 changed files with 501 additions and 420 deletions
  1. 1
    1
      Makefile
  2. 206
    0
      camd.c
  3. 12
    0
      camd.h
  4. 87
    0
      data.c
  5. 28
    0
      data.h
  6. 150
    0
      tables.c
  7. 12
    0
      tables.h
  8. 5
    419
      tsdecrypt.c

+ 1
- 1
Makefile View File

@@ -10,7 +10,7 @@ FUNCS_LIB = $(FUNCS_DIR)/libfuncs.a
10 10
 TS_DIR = libts
11 11
 TS_LIB = $(TS_DIR)/libts.a
12 12
 
13
-tsdecrypt_OBJS = util.o tsdecrypt.o $(FUNCS_LIB) $(TS_LIB)
13
+tsdecrypt_OBJS = data.o util.o camd.o tables.o tsdecrypt.o $(FUNCS_LIB) $(TS_LIB)
14 14
 tsdecrypt_LIBS = -lcrypto -ldvbcsa -lpthread
15 15
 
16 16
 CLEAN_OBJS = tsdecrypt $(tsdecrypt_OBJS) *~

+ 206
- 0
camd.c View File

@@ -0,0 +1,206 @@
1
+#include <string.h>
2
+#include <sys/errno.h>
3
+
4
+#include <sys/socket.h>
5
+#include <netinet/in.h>
6
+#include <arpa/inet.h>
7
+
8
+#include <openssl/aes.h>
9
+#include <openssl/md5.h>
10
+
11
+#include <dvbcsa/dvbcsa.h>
12
+
13
+#include "libfuncs/libfuncs.h"
14
+#include "libts/tsfuncs.h"
15
+
16
+#include "util.h"
17
+#include "camd.h"
18
+
19
+
20
+extern uint8_t cur_cw[16];
21
+extern int is_valid_cw;
22
+extern struct dvbcsa_key_s *csakey[2];
23
+
24
+static int camd35_server_fd;
25
+extern struct in_addr camd35_server_addr;
26
+extern unsigned int camd35_server_port;
27
+extern char *camd35_user;
28
+extern char *camd35_pass;
29
+
30
+static uint32_t camd35_auth = 0;
31
+static AES_KEY camd35_aes_encrypt_key;
32
+static AES_KEY camd35_aes_decrypt_key;
33
+
34
+static uint8_t invalid_cw[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
35
+
36
+static inline int valid_cw(uint8_t *cw) {
37
+	return memcmp(cw, invalid_cw, 16) != 0;
38
+}
39
+
40
+static int connect_to(struct in_addr ip, int port) {
41
+	ts_LOGf("Connecting to %s:%d\n", inet_ntoa(ip), port);
42
+
43
+	int fd = socket(PF_INET, SOCK_STREAM, 0);
44
+	if (fd < 0)	{
45
+		ts_LOGf("Could not create socket | %s\n", strerror(errno));
46
+		return -1;
47
+	}
48
+
49
+	struct sockaddr_in sock;
50
+	sock.sin_family = AF_INET;
51
+	sock.sin_port = htons(port);
52
+	sock.sin_addr = ip;
53
+	if (do_connect(fd, (struct sockaddr *)&sock, sizeof(sock), 1000) < 0) {
54
+		ts_LOGf("Could not connect to %s:%d | %s\n", inet_ntoa(ip), port, strerror(errno));
55
+		return -1;
56
+	}
57
+
58
+	ts_LOGf("Connected with fd:%d\n", fd);
59
+	return fd;
60
+}
61
+
62
+// 4 auth header, 20 header size, 256 max data size, 16 potential padding
63
+#define HDR_LEN     (20)
64
+#define BUF_SIZE	(4 + HDR_LEN + 256 + 16)
65
+
66
+static void camd35_init_auth(char *user, char *pass) {
67
+	unsigned char dump[16];
68
+	camd35_auth = crc32(0L, MD5((unsigned char *)user, strlen(user), dump), 16);
69
+
70
+	MD5((unsigned char *)pass, strlen(pass), dump);
71
+
72
+	AES_set_encrypt_key(dump, 128, &camd35_aes_encrypt_key);
73
+	AES_set_decrypt_key(dump, 128, &camd35_aes_decrypt_key);
74
+}
75
+
76
+int camd35_connect() {
77
+	if (camd35_server_fd < 0)
78
+		camd35_server_fd = connect_to(camd35_server_addr, camd35_server_port);
79
+	return camd35_server_fd;
80
+}
81
+
82
+void camd35_disconnect() {
83
+	shutdown_fd(&camd35_server_fd);
84
+}
85
+
86
+static int camd35_recv(uint8_t *data, int *data_len) {
87
+	int i;
88
+
89
+	// Read AUTH token
90
+	ssize_t r = fdread(camd35_server_fd, (char *)data, 4);
91
+	if (r < 4)
92
+		return -1;
93
+	uint32_t auth_token = (((data[0] << 24) | (data[1] << 16) | (data[2]<<8) | data[3]) & 0xffffffffL);
94
+	if (auth_token != camd35_auth)
95
+		ts_LOGf("WARN: recv auth 0x%08x != camd35_auth 0x%08x\n", auth_token, camd35_auth);
96
+
97
+	*data_len = 256;
98
+	for (i = 0; i < *data_len; i += 16) { // Read and decrypt payload
99
+		fdread(camd35_server_fd, (char *)data + i, 16);
100
+		AES_decrypt(data + i, data + i, &camd35_aes_decrypt_key);
101
+		if (i == 0)
102
+			*data_len = boundary(4, data[1] + 20); // Initialize real data length
103
+	}
104
+	return *data_len;
105
+}
106
+
107
+#define ERR(x) do { ts_LOGf("%s", x); return NULL; } while (0)
108
+
109
+static uint8_t *camd35_recv_cw() {
110
+	uint8_t data[BUF_SIZE];
111
+	int data_len = 0;
112
+
113
+NEXT:
114
+	if (camd35_recv(data, &data_len) < 0)
115
+		ERR("No data!");
116
+
117
+	if (data[0] < 0x01) {
118
+		ts_LOGf("Not valid CW response, skipping it. data[0] = 0x%02x\n", data[0]);
119
+		goto NEXT;
120
+	}
121
+
122
+	if (data_len < 48)
123
+		ERR("len mismatch != 48");
124
+
125
+	if (data[1] < 0x10)
126
+		ERR("CW len mismatch != 0x10");
127
+
128
+	uint16_t ca_id = (data[10] << 8) | data[11];
129
+	uint16_t idx   = (data[16] << 8) | data[17];
130
+	uint8_t *cw = data + 20;
131
+	memcpy(cur_cw, cw, 16);
132
+
133
+	char cw_dump[16 * 6];
134
+	ts_hex_dump_buf(cw_dump, 16 * 6, cw, 16, 0);
135
+	ts_LOGf("CW  | CAID: 0x%04x ---------------------------------- IDX: 0x%04x Data: %s\n", ca_id, idx, cw_dump);
136
+
137
+	is_valid_cw = valid_cw(cur_cw);
138
+	dvbcsa_key_set(cur_cw    , csakey[0]);
139
+	dvbcsa_key_set(cur_cw + 8, csakey[1]);
140
+
141
+	return NULL;
142
+}
143
+
144
+#undef ERR
145
+
146
+
147
+static int camd35_send(uint8_t *data, uint8_t data_len) {
148
+	unsigned int i;
149
+	uint8_t buf[BUF_SIZE];
150
+	uint8_t *bdata = buf + 4;
151
+
152
+	camd35_connect();
153
+
154
+	if (!camd35_auth)
155
+		camd35_init_auth(camd35_user, camd35_pass);
156
+
157
+	init_4b(camd35_auth, buf); // Put authentication token
158
+	memcpy(bdata, data, data_len); // Put data
159
+
160
+	for (i = 0; i < data_len; i += 16) // Encrypt payload
161
+		AES_encrypt(data + i, bdata + i, &camd35_aes_encrypt_key);
162
+
163
+	return fdwrite(camd35_server_fd, (char *)buf, data_len + 4);
164
+}
165
+
166
+static void camd35_buf_init(uint8_t *buf, uint8_t *data, uint8_t data_len) {
167
+	memset(buf, 0, HDR_LEN); // Reset header
168
+	memset(buf + HDR_LEN, 0xff, BUF_SIZE - HDR_LEN); // Reset data
169
+	buf[1] = data_len; // Data length
170
+	init_4b(crc32(0L, data, data_len), buf + 4); // Data CRC is at buf[4]
171
+	memcpy(buf + HDR_LEN, data, data_len); // Copy data to buf
172
+}
173
+
174
+int camd35_send_ecm(uint16_t service_id, uint16_t ca_id, uint16_t idx, uint8_t *data, uint8_t data_len) {
175
+	uint8_t buf[BUF_SIZE];
176
+	uint32_t provider_id = 0;
177
+	int to_send = boundary(4, HDR_LEN + data_len);
178
+
179
+	camd35_buf_init(buf, data, data_len);
180
+
181
+	buf[0] = 0x00; // CMD ECM request
182
+	init_2b(service_id , buf + 8);
183
+	init_2b(ca_id      , buf + 10);
184
+	init_4b(provider_id, buf + 12);
185
+	init_2b(idx        , buf + 16);
186
+	buf[18] = 0xff;
187
+	buf[19] = 0xff;
188
+
189
+	camd35_send(buf, to_send);
190
+	camd35_recv_cw();
191
+	return 0;
192
+}
193
+
194
+int camd35_send_emm(uint16_t ca_id, uint8_t *data, uint8_t data_len) {
195
+	uint8_t buf[BUF_SIZE];
196
+	uint32_t prov_id = 0;
197
+	int to_send = boundary(4, data_len + HDR_LEN);
198
+
199
+	camd35_buf_init(buf, data, data_len);
200
+
201
+	buf[0] = 0x06; // CMD incomming EMM
202
+	init_2b(ca_id  , buf + 10);
203
+	init_4b(prov_id, buf + 12);
204
+
205
+	return camd35_send(buf, to_send);
206
+}

+ 12
- 0
camd.h View File

@@ -0,0 +1,12 @@
1
+#ifndef CAMD_H
2
+#define CAMD_H
3
+
4
+#include <inttypes.h>
5
+
6
+int camd35_connect();
7
+void camd35_disconnect();
8
+
9
+int camd35_send_ecm(uint16_t service_id, uint16_t ca_id, uint16_t idx, uint8_t *data, uint8_t data_len);
10
+int camd35_send_emm(uint16_t ca_id, uint8_t *data, uint8_t data_len);
11
+
12
+#endif

+ 87
- 0
data.c View File

@@ -0,0 +1,87 @@
1
+#include <stdio.h>
2
+#include <stdlib.h>
3
+#include <time.h>
4
+#include <string.h>
5
+
6
+#include "data.h"
7
+
8
+struct ts *ts_alloc() {
9
+	struct ts *ts = calloc(1, sizeof(struct ts));
10
+	ts->pat	     = ts_pat_alloc();
11
+	ts->curpat   = ts_pat_alloc();
12
+
13
+	ts->cat      = ts_cat_alloc();
14
+	ts->curcat   = ts_cat_alloc();
15
+
16
+	ts->pmt      = ts_pmt_alloc();
17
+	ts->curpmt   = ts_pmt_alloc();
18
+
19
+	ts->emm      = ts_privsec_alloc();
20
+	ts->last_emm = ts_privsec_alloc();
21
+
22
+	ts->ecm      = ts_privsec_alloc();
23
+	ts->last_ecm = ts_privsec_alloc();
24
+
25
+	pidmap_clear(&ts->pidmap);
26
+
27
+	return ts;
28
+}
29
+
30
+void ts_free(struct ts **pts) {
31
+	struct ts *ts = *pts;
32
+	if (ts) {
33
+		ts_pat_free(&ts->pat);
34
+		ts_pat_free(&ts->curpat);
35
+		ts_cat_free(&ts->cat);
36
+		ts_cat_free(&ts->curcat);
37
+		ts_pmt_free(&ts->pmt);
38
+		ts_pmt_free(&ts->curpmt);
39
+		ts_privsec_free(&ts->emm);
40
+		ts_privsec_free(&ts->last_emm);
41
+		ts_privsec_free(&ts->ecm);
42
+		ts_privsec_free(&ts->last_ecm);
43
+		FREE(*pts);
44
+	}
45
+}
46
+
47
+void LOG_func(const char *msg) {
48
+	char date[64];
49
+	struct tm tm;
50
+	time_t now;
51
+	now = time(NULL);
52
+	localtime_r(&now, &tm);
53
+	strftime(date, sizeof(date), "%F %H:%M:%S", localtime(&now));
54
+	fprintf(stderr, "%s | %s", date, msg);
55
+}
56
+
57
+extern int debug_level;
58
+extern unsigned long ts_pack;
59
+extern int ts_pack_shown;
60
+extern uint8_t cur_cw[16];
61
+
62
+void show_ts_pack(uint16_t pid, char *wtf, char *extra, uint8_t *ts_packet) {
63
+	char cw1_dump[8 * 6];
64
+	char cw2_dump[8 * 6];
65
+	if (debug_level >= 4) {
66
+		if (ts_pack_shown)
67
+			return;
68
+		int stype = ts_packet_get_scrambled(ts_packet);
69
+		ts_hex_dump_buf(cw1_dump, 8 * 6, cur_cw    , 8, 0);
70
+		ts_hex_dump_buf(cw2_dump, 8 * 6, cur_cw + 8, 8, 0);
71
+		fprintf(stderr, "@ %s %s %03x %5ld %7ld | %s   %s | %s\n",
72
+			stype == 0 ? "------" :
73
+			stype == 2 ? "even 0" :
74
+			stype == 3 ? "odd  1" : "??????",
75
+			wtf,
76
+			pid,
77
+			ts_pack, ts_pack * 188,
78
+			cw1_dump, cw2_dump, extra ? extra : wtf);
79
+	}
80
+}
81
+
82
+void dump_ts_pack(uint16_t pid, uint8_t *ts_packet) {
83
+	if (pid == 0x010)		show_ts_pack(pid, "nit", NULL, ts_packet);
84
+	else if (pid == 0x11)	show_ts_pack(pid, "sdt", NULL, ts_packet);
85
+	else if (pid == 0x12)	show_ts_pack(pid, "epg", NULL, ts_packet);
86
+	else					show_ts_pack(pid, "---", NULL, ts_packet);
87
+}

+ 28
- 0
data.h View File

@@ -0,0 +1,28 @@
1
+#ifndef DATA_H
2
+#define DATA_H
3
+
4
+#include "libts/tsfuncs.h"
5
+
6
+struct ts {
7
+	struct ts_pat		*pat, *curpat;
8
+	struct ts_cat		*cat, *curcat;
9
+	struct ts_pmt		*pmt, *curpmt;
10
+	struct ts_privsec	*emm, *last_emm;
11
+	struct ts_privsec	*ecm, *last_ecm;
12
+	uint16_t			pmt_pid;
13
+	uint16_t			service_id;
14
+	uint16_t			emm_caid, emm_pid;
15
+	uint16_t			ecm_caid, ecm_pid;
16
+	uint16_t			ecm_counter;
17
+	pidmap_t			pidmap;
18
+};
19
+
20
+struct ts *ts_alloc();
21
+void ts_free(struct ts **pts);
22
+
23
+void LOG_func(const char *msg);
24
+
25
+void show_ts_pack(uint16_t pid, char *wtf, char *extra, uint8_t *ts_packet);
26
+void dump_ts_pack(uint16_t pid, uint8_t *ts_packet);
27
+
28
+#endif

+ 150
- 0
tables.c View File

@@ -0,0 +1,150 @@
1
+#include "data.h"
2
+#include "tables.h"
3
+#include "camd.h"
4
+
5
+#include "libts/tsfuncs.h"
6
+#include "libfuncs/libfuncs.h"
7
+
8
+extern enum CA_system req_CA_sys;
9
+extern int debug_level;
10
+extern int emm_send;
11
+
12
+#define handle_table_changes(TABLE) \
13
+	do { \
14
+		show_ts_pack(pid, #TABLE, NULL, ts_packet); \
15
+		ts->cur##TABLE = ts_##TABLE##_push_packet(ts->cur##TABLE, ts_packet); \
16
+		if (!ts->cur##TABLE->initialized) \
17
+			return;  \
18
+		if (ts_##TABLE##_is_same(ts->TABLE, ts->cur##TABLE)) { \
19
+			ts_##TABLE##_clear(ts->cur##TABLE); \
20
+			return; \
21
+		} \
22
+		ts_##TABLE##_free(&ts->TABLE); \
23
+		ts->TABLE = ts_##TABLE##_copy(ts->cur##TABLE); \
24
+		ts_##TABLE##_clear(ts->cur##TABLE); \
25
+		if (debug_level >= 1) \
26
+			ts_##TABLE##_dump(ts->TABLE); \
27
+	} while(0)
28
+
29
+void process_pat(struct ts *ts, uint16_t pid, uint8_t *ts_packet) {
30
+	int i;
31
+	if (pid != 0x00)
32
+		return;
33
+
34
+	handle_table_changes(pat);
35
+
36
+	for (i=0;i<ts->pat->programs_num;i++) {
37
+		struct ts_pat_program *prg = ts->pat->programs[i];
38
+		if (prg->pid) {
39
+			if (prg->program != 0) {
40
+				ts->pmt_pid    = prg->pid;
41
+				ts->service_id = prg->program;
42
+			}
43
+		}
44
+	}
45
+}
46
+
47
+void process_cat(struct ts *ts, uint16_t pid, uint8_t *ts_packet) {
48
+	if (pid != 0x01)
49
+		return;
50
+
51
+	handle_table_changes(cat);
52
+
53
+	ts_get_emm_info(ts->cat, req_CA_sys, &ts->emm_caid, &ts->emm_pid);
54
+}
55
+
56
+void process_pmt(struct ts *ts, uint16_t pid, uint8_t *ts_packet) {
57
+	int i;
58
+	if (!pid || pid != ts->pmt_pid)
59
+		return;
60
+
61
+	handle_table_changes(pmt);
62
+
63
+	pidmap_clear(&ts->pidmap);
64
+	pidmap_set(&ts->pidmap, 0x0000); // PAT
65
+	pidmap_set(&ts->pidmap, 0x0011); // SDT
66
+	pidmap_set(&ts->pidmap, ts->pmt->ts_header.pid); // PMT PID
67
+	pidmap_set(&ts->pidmap, ts->pmt->PCR_pid); // PCR
68
+	for (i=0;i<ts->pmt->streams_num;i++) {
69
+		struct ts_pmt_stream *stream = ts->pmt->streams[i];
70
+		pidmap_set(&ts->pidmap, stream->pid); // Data
71
+	}
72
+
73
+	if (!ts->ecm_caid) {
74
+		ts_get_ecm_info(ts->pmt, req_CA_sys, &ts->ecm_caid, &ts->ecm_pid);
75
+		char *CA_sys = ts_get_CA_sys_txt(ts_get_CA_sys(ts->ecm_caid));
76
+		ts_LOGf("%s Service : 0x%04x\n", CA_sys, ts->service_id);
77
+		ts_LOGf("%s CA_id   : 0x%04x\n", CA_sys, ts->emm_caid);
78
+		ts_LOGf("%s EMM pid : 0x%04x\n", CA_sys, ts->emm_pid);
79
+		ts_LOGf("%s ECM pid : 0x%04x\n", CA_sys, ts->ecm_pid);
80
+	}
81
+}
82
+
83
+#define dump_sz      (16)
84
+#define dump_buf_sz  (dump_sz * 6)
85
+
86
+void process_emm(struct ts *ts, uint16_t pid, uint8_t *ts_packet) {
87
+	char dump[dump_buf_sz];
88
+	if (!ts->emm_pid || ts->emm_pid != pid)
89
+		return;
90
+
91
+	show_ts_pack(pid, "emm", NULL, ts_packet);
92
+
93
+	if (!emm_send)
94
+		return;
95
+
96
+	ts->emm = ts_privsec_push_packet(ts->emm, ts_packet);
97
+	if (!ts->emm->initialized)
98
+		return;
99
+
100
+	struct ts_header *th = &ts->emm->ts_header;
101
+	struct ts_section_header *sec = ts->emm->section_header;
102
+	if (debug_level >= 2) {
103
+		ts_hex_dump_buf(dump, dump_buf_sz, sec->section_data, min(dump_sz, sec->section_data_len), 0);
104
+		ts_LOGf("EMM | CAID: 0x%04x PID 0x%04x Table: 0x%02x Length: %3d ----------- Data: %s..\n",
105
+			ts->emm_caid,
106
+			th->pid,
107
+			sec->table_id,
108
+			sec->section_data_len,
109
+			dump);
110
+	}
111
+	camd35_send_emm(ts->emm_caid, sec->section_data, sec->section_data_len);
112
+	ts_privsec_copy(ts->emm, ts->last_emm);
113
+	ts_privsec_clear(ts->emm);
114
+}
115
+
116
+void process_ecm(struct ts *ts, uint16_t pid, uint8_t *ts_packet) {
117
+	char dump[dump_buf_sz];
118
+	if (!ts->ecm_pid || ts->ecm_pid != pid)
119
+		return;
120
+
121
+	ts->ecm = ts_privsec_push_packet(ts->ecm, ts_packet);
122
+	if (!ts->ecm->initialized)
123
+		return;
124
+
125
+	struct ts_header *th = &ts->ecm->ts_header;
126
+	struct ts_section_header *sec = ts->ecm->section_header;
127
+	int duplicate = ts_privsec_is_same(ts->ecm, ts->last_ecm);
128
+	if (!duplicate) {
129
+		ts_hex_dump_buf(dump, dump_buf_sz, sec->section_data, min(dump_sz, sec->section_data_len), 0);
130
+		ts_LOGf("ECM | CAID: 0x%04x PID 0x%04x Table: 0x%02x Length: %3d IDX: 0x%04x Data: %s..\n",
131
+			ts->ecm_caid,
132
+			th->pid,
133
+			sec->table_id,
134
+			sec->section_data_len,
135
+			ts->ecm_counter,
136
+			dump);
137
+		camd35_send_ecm(ts->service_id, ts->ecm_caid, ts->ecm_counter++, sec->section_data, sec->section_data_len);
138
+	} else if (debug_level >= 3) {
139
+		ts_LOGf("ECM | CAID: 0x%04x PID 0x%04x Table: 0x%02x Length: %3d IDX: 0x%04x Data: -dup-\n",
140
+			ts->ecm_caid,
141
+			th->pid,
142
+			sec->table_id,
143
+			sec->section_data_len,
144
+			ts->ecm_counter - 1);
145
+	}
146
+	ts_privsec_copy(ts->ecm, ts->last_ecm);
147
+	ts_privsec_clear(ts->ecm);
148
+
149
+	show_ts_pack(pid, !duplicate ? "ecm" : "ec+", NULL, ts_packet);
150
+}

+ 12
- 0
tables.h View File

@@ -0,0 +1,12 @@
1
+#ifndef TABLE_H
2
+#define TABLES_H
3
+
4
+#include "data.h"
5
+
6
+void process_pat(struct ts *ts, uint16_t pid, uint8_t *ts_packet);
7
+void process_cat(struct ts *ts, uint16_t pid, uint8_t *ts_packet);
8
+void process_pmt(struct ts *ts, uint16_t pid, uint8_t *ts_packet);
9
+void process_emm(struct ts *ts, uint16_t pid, uint8_t *ts_packet);
10
+void process_ecm(struct ts *ts, uint16_t pid, uint8_t *ts_packet);
11
+
12
+#endif

+ 5
- 419
tsdecrypt.c View File

@@ -1,143 +1,32 @@
1 1
 #include <stdio.h>
2 2
 #include <stdlib.h>
3 3
 #include <unistd.h>
4
-#include <netdb.h>
5
-#include <sched.h>
6 4
 #include <string.h>
7
-#include <time.h>
8
-#include <fcntl.h>
9
-#include <sys/types.h>
10
-#include <sys/stat.h>
11
-#include <sys/time.h>
12
-#include <sys/errno.h>
13
-
14
-#include <sys/socket.h>
15
-#include <netinet/in.h>
16
-#include <arpa/inet.h>
17
-
18
-#include <openssl/aes.h>
19
-#include <openssl/md5.h>
20 5
 
21 6
 #include <dvbcsa/dvbcsa.h>
22 7
 
23 8
 #include "libfuncs/libfuncs.h"
24 9
 #include "libts/tsfuncs.h"
25 10
 
11
+#include "data.h"
26 12
 #include "util.h"
13
+#include "camd.h"
14
+#include "tables.h"
27 15
 
28 16
 uint8_t cur_cw[16];
29 17
 int is_valid_cw = 0;
30
-uint8_t invalid_cw[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
31 18
 struct dvbcsa_key_s *csakey[2];
32 19
 
33
-static inline int valid_cw(uint8_t *cw) {
34
-	return memcmp(cw, invalid_cw, 16) != 0;
35
-}
36
-
37
-
38
-struct ts {
39
-	struct ts_pat		*pat, *curpat;
40
-	struct ts_cat		*cat, *curcat;
41
-	struct ts_pmt		*pmt, *curpmt;
42
-	struct ts_privsec	*emm, *last_emm;
43
-	struct ts_privsec	*ecm, *last_ecm;
44
-	uint16_t			pmt_pid;
45
-	uint16_t			service_id;
46
-	uint16_t			emm_caid, emm_pid;
47
-	uint16_t			ecm_caid, ecm_pid;
48
-	uint16_t			ecm_counter;
49
-	pidmap_t			pidmap;
50
-};
51
-
52
-struct ts *ts_alloc() {
53
-	struct ts *ts = calloc(1, sizeof(struct ts));
54
-	ts->pat	     = ts_pat_alloc();
55
-	ts->curpat   = ts_pat_alloc();
56
-
57
-	ts->cat      = ts_cat_alloc();
58
-	ts->curcat   = ts_cat_alloc();
59
-
60
-	ts->pmt      = ts_pmt_alloc();
61
-	ts->curpmt   = ts_pmt_alloc();
62
-
63
-	ts->emm      = ts_privsec_alloc();
64
-	ts->last_emm = ts_privsec_alloc();
65
-
66
-	ts->ecm      = ts_privsec_alloc();
67
-	ts->last_ecm = ts_privsec_alloc();
68
-
69
-	pidmap_clear(&ts->pidmap);
70
-
71
-	return ts;
72
-}
73
-
74
-void ts_free(struct ts **pts) {
75
-	struct ts *ts = *pts;
76
-	if (ts) {
77
-		ts_pat_free(&ts->pat);
78
-		ts_pat_free(&ts->curpat);
79
-		ts_cat_free(&ts->cat);
80
-		ts_cat_free(&ts->curcat);
81
-		ts_pmt_free(&ts->pmt);
82
-		ts_pmt_free(&ts->curpmt);
83
-		ts_privsec_free(&ts->emm);
84
-		ts_privsec_free(&ts->last_emm);
85
-		ts_privsec_free(&ts->ecm);
86
-		ts_privsec_free(&ts->last_ecm);
87
-		FREE(*pts);
88
-	}
89
-}
90
-
91
-void LOG_func(const char *msg) {
92
-	char date[64];
93
-	struct tm tm;
94
-	time_t now;
95
-	now = time(NULL);
96
-	localtime_r(&now, &tm);
97
-	strftime(date, sizeof(date), "%F %H:%M:%S", localtime(&now));
98
-	fprintf(stderr, "%s | %s", date, msg);
99
-}
100
-
20
+int debug_level = 0;
101 21
 unsigned long ts_pack = 0;
102 22
 int ts_pack_shown = 0;
103
-int debug_level = 0;
104
-
105
-static void show_ts_pack(uint16_t pid, char *wtf, char *extra, uint8_t *ts_packet) {
106
-	char cw1_dump[8 * 6];
107
-	char cw2_dump[8 * 6];
108
-	if (debug_level >= 4) {
109
-		if (ts_pack_shown)
110
-			return;
111
-		int stype = ts_packet_get_scrambled(ts_packet);
112
-		ts_hex_dump_buf(cw1_dump, 8 * 6, cur_cw    , 8, 0);
113
-		ts_hex_dump_buf(cw2_dump, 8 * 6, cur_cw + 8, 8, 0);
114
-		fprintf(stderr, "@ %s %s %03x %5ld %7ld | %s   %s | %s\n",
115
-			stype == 0 ? "------" :
116
-			stype == 2 ? "even 0" :
117
-			stype == 3 ? "odd  1" : "??????",
118
-			wtf,
119
-			pid,
120
-			ts_pack, ts_pack * 188,
121
-			cw1_dump, cw2_dump, extra ? extra : wtf);
122
-	}
123
-}
124
-
125
-static void dump_ts_pack(uint16_t pid, uint8_t *ts_packet) {
126
-	if (pid == 0x010)		show_ts_pack(pid, "nit", NULL, ts_packet);
127
-	else if (pid == 0x11)	show_ts_pack(pid, "sdt", NULL, ts_packet);
128
-	else if (pid == 0x12)	show_ts_pack(pid, "epg", NULL, ts_packet);
129
-	else					show_ts_pack(pid, "---", NULL, ts_packet);
130
-}
131 23
 
132 24
 enum CA_system req_CA_sys = CA_CONNAX;
133
-int server_fd = -1;
134 25
 struct in_addr camd35_server_addr;
135 26
 unsigned int camd35_server_port = 2233;
136 27
 char *camd35_user = "user";
137 28
 char *camd35_pass = "pass";
138 29
 uint32_t camd35_auth = 0;
139
-AES_KEY camd35_aes_encrypt_key;
140
-AES_KEY camd35_aes_decrypt_key;
141 30
 
142 31
 int emm_send = 1;
143 32
 int pid_filter = 0;
@@ -276,309 +165,6 @@ void parse_options(int argc, char **argv) {
276 165
 	ts_LOGf("PID filter : %s\n", pid_filter ? "enabled" : "disabled");
277 166
 }
278 167
 
279
-static int connect_to(struct in_addr ip, int port) {
280
-	ts_LOGf("Connecting to %s:%d\n", inet_ntoa(ip), port);
281
-
282
-	int fd = socket(PF_INET, SOCK_STREAM, 0);
283
-	if (fd < 0)	{
284
-		ts_LOGf("Could not create socket | %s\n", strerror(errno));
285
-		return -1;
286
-	}
287
-
288
-	struct sockaddr_in sock;
289
-	sock.sin_family = AF_INET;
290
-	sock.sin_port = htons(port);
291
-	sock.sin_addr = ip;
292
-	if (do_connect(fd, (struct sockaddr *)&sock, sizeof(sock), 1000) < 0) {
293
-		ts_LOGf("Could not connect to %s:%d | %s\n", inet_ntoa(ip), port, strerror(errno));
294
-		return -1;
295
-	}
296
-
297
-	ts_LOGf("Connected with fd:%d\n", fd);
298
-	return fd;
299
-}
300
-
301
-// 4 auth header, 20 header size, 256 max data size, 16 potential padding
302
-#define HDR_LEN     (20)
303
-#define BUF_SIZE	(4 + HDR_LEN + 256 + 16)
304
-
305
-static void camd35_init_auth(char *user, char *pass) {
306
-	unsigned char dump[16];
307
-	camd35_auth = crc32(0L, MD5((unsigned char *)user, strlen(user), dump), 16);
308
-
309
-	MD5((unsigned char *)pass, strlen(pass), dump);
310
-
311
-	AES_set_encrypt_key(dump, 128, &camd35_aes_encrypt_key);
312
-	AES_set_decrypt_key(dump, 128, &camd35_aes_decrypt_key);
313
-}
314
-
315
-static void camd35_connect() {
316
-	if (server_fd < 0)
317
-		server_fd = connect_to(camd35_server_addr, camd35_server_port);
318
-}
319
-
320
-static int camd35_recv(uint8_t *data, int *data_len) {
321
-	int i;
322
-
323
-	// Read AUTH token
324
-	ssize_t r = fdread(server_fd, (char *)data, 4);
325
-	if (r < 4)
326
-		return -1;
327
-	uint32_t auth_token = (((data[0] << 24) | (data[1] << 16) | (data[2]<<8) | data[3]) & 0xffffffffL);
328
-	if (auth_token != camd35_auth)
329
-		ts_LOGf("WARN: recv auth 0x%08x != camd35_auth 0x%08x\n", auth_token, camd35_auth);
330
-
331
-	*data_len = 256;
332
-	for (i = 0; i < *data_len; i += 16) { // Read and decrypt payload
333
-		fdread(server_fd, (char *)data + i, 16);
334
-		AES_decrypt(data + i, data + i, &camd35_aes_decrypt_key);
335
-		if (i == 0)
336
-			*data_len = boundary(4, data[1] + 20); // Initialize real data length
337
-	}
338
-	return *data_len;
339
-}
340
-
341
-#define ERR(x) do { ts_LOGf("%s", x); return NULL; } while (0)
342
-
343
-static uint8_t *camd35_recv_cw() {
344
-	uint8_t data[BUF_SIZE];
345
-	int data_len = 0;
346
-
347
-NEXT:
348
-	if (camd35_recv(data, &data_len) < 0)
349
-		ERR("No data!");
350
-
351
-	if (data[0] < 0x01) {
352
-		ts_LOGf("Not valid CW response, skipping it. data[0] = 0x%02x\n", data[0]);
353
-		goto NEXT;
354
-	}
355
-
356
-	if (data_len < 48)
357
-		ERR("len mismatch != 48");
358
-
359
-	if (data[1] < 0x10)
360
-		ERR("CW len mismatch != 0x10");
361
-
362
-	uint16_t ca_id = (data[10] << 8) | data[11];
363
-	uint16_t idx   = (data[16] << 8) | data[17];
364
-	uint8_t *cw = data + 20;
365
-	memcpy(cur_cw, cw, 16);
366
-
367
-	char cw_dump[16 * 6];
368
-	ts_hex_dump_buf(cw_dump, 16 * 6, cw, 16, 0);
369
-	ts_LOGf("CW  | CAID: 0x%04x ---------------------------------- IDX: 0x%04x Data: %s\n", ca_id, idx, cw_dump);
370
-
371
-	is_valid_cw = valid_cw(cur_cw);
372
-	dvbcsa_key_set(cur_cw    , csakey[0]);
373
-	dvbcsa_key_set(cur_cw + 8, csakey[1]);
374
-
375
-	return NULL;
376
-}
377
-
378
-#undef ERR
379
-
380
-
381
-static int camd35_send(uint8_t *data, uint8_t data_len) {
382
-	unsigned int i;
383
-	uint8_t buf[BUF_SIZE];
384
-	uint8_t *bdata = buf + 4;
385
-
386
-	camd35_connect();
387
-
388
-	if (!camd35_auth)
389
-		camd35_init_auth(camd35_user, camd35_pass);
390
-
391
-	init_4b(camd35_auth, buf); // Put authentication token
392
-	memcpy(bdata, data, data_len); // Put data
393
-
394
-	for (i = 0; i < data_len; i += 16) // Encrypt payload
395
-		AES_encrypt(data + i, bdata + i, &camd35_aes_encrypt_key);
396
-
397
-	return fdwrite(server_fd, (char *)buf, data_len + 4);
398
-}
399
-
400
-static void camd35_buf_init(uint8_t *buf, uint8_t *data, uint8_t data_len) {
401
-	memset(buf, 0, HDR_LEN); // Reset header
402
-	memset(buf + HDR_LEN, 0xff, BUF_SIZE - HDR_LEN); // Reset data
403
-	buf[1] = data_len; // Data length
404
-	init_4b(crc32(0L, data, data_len), buf + 4); // Data CRC is at buf[4]
405
-	memcpy(buf + HDR_LEN, data, data_len); // Copy data to buf
406
-}
407
-
408
-static int camd35_send_ecm(uint16_t service_id, uint16_t ca_id, uint16_t idx, uint8_t *data, uint8_t data_len) {
409
-	uint8_t buf[BUF_SIZE];
410
-	uint32_t provider_id = 0;
411
-	int to_send = boundary(4, HDR_LEN + data_len);
412
-
413
-	camd35_buf_init(buf, data, data_len);
414
-
415
-	buf[0] = 0x00; // CMD ECM request
416
-	init_2b(service_id , buf + 8);
417
-	init_2b(ca_id      , buf + 10);
418
-	init_4b(provider_id, buf + 12);
419
-	init_2b(idx        , buf + 16);
420
-	buf[18] = 0xff;
421
-	buf[19] = 0xff;
422
-
423
-	camd35_send(buf, to_send);
424
-	camd35_recv_cw();
425
-	return 0;
426
-}
427
-
428
-static int camd35_send_emm(uint16_t ca_id, uint8_t *data, uint8_t data_len) {
429
-	uint8_t buf[BUF_SIZE];
430
-	uint32_t prov_id = 0;
431
-	int to_send = boundary(4, data_len + HDR_LEN);
432
-
433
-	camd35_buf_init(buf, data, data_len);
434
-
435
-	buf[0] = 0x06; // CMD incomming EMM
436
-	init_2b(ca_id  , buf + 10);
437
-	init_4b(prov_id, buf + 12);
438
-
439
-	return camd35_send(buf, to_send);
440
-}
441
-
442
-#define handle_table_changes(TABLE) \
443
-	do { \
444
-		show_ts_pack(pid, #TABLE, NULL, ts_packet); \
445
-		ts->cur##TABLE = ts_##TABLE##_push_packet(ts->cur##TABLE, ts_packet); \
446
-		if (!ts->cur##TABLE->initialized) \
447
-			return;  \
448
-		if (ts_##TABLE##_is_same(ts->TABLE, ts->cur##TABLE)) { \
449
-			ts_##TABLE##_clear(ts->cur##TABLE); \
450
-			return; \
451
-		} \
452
-		ts_##TABLE##_free(&ts->TABLE); \
453
-		ts->TABLE = ts_##TABLE##_copy(ts->cur##TABLE); \
454
-		ts_##TABLE##_clear(ts->cur##TABLE); \
455
-		if (debug_level >= 1) \
456
-			ts_##TABLE##_dump(ts->TABLE); \
457
-	} while(0)
458
-
459
-void process_pat(struct ts *ts, uint16_t pid, uint8_t *ts_packet) {
460
-	int i;
461
-	if (pid != 0x00)
462
-		return;
463
-
464
-	handle_table_changes(pat);
465
-
466
-	for (i=0;i<ts->pat->programs_num;i++) {
467
-		struct ts_pat_program *prg = ts->pat->programs[i];
468
-		if (prg->pid) {
469
-			if (prg->program != 0) {
470
-				ts->pmt_pid    = prg->pid;
471
-				ts->service_id = prg->program;
472
-			}
473
-		}
474
-	}
475
-}
476
-
477
-void process_cat(struct ts *ts, uint16_t pid, uint8_t *ts_packet) {
478
-	if (pid != 0x01)
479
-		return;
480
-
481
-	handle_table_changes(cat);
482
-
483
-	ts_get_emm_info(ts->cat, req_CA_sys, &ts->emm_caid, &ts->emm_pid);
484
-}
485
-
486
-void process_pmt(struct ts *ts, uint16_t pid, uint8_t *ts_packet) {
487
-	int i;
488
-	if (!pid || pid != ts->pmt_pid)
489
-		return;
490
-
491
-	handle_table_changes(pmt);
492
-
493
-	pidmap_clear(&ts->pidmap);
494
-	pidmap_set(&ts->pidmap, 0x0000); // PAT
495
-	pidmap_set(&ts->pidmap, 0x0011); // SDT
496
-	pidmap_set(&ts->pidmap, ts->pmt->ts_header.pid); // PMT PID
497
-	pidmap_set(&ts->pidmap, ts->pmt->PCR_pid); // PCR
498
-	for (i=0;i<ts->pmt->streams_num;i++) {
499
-		struct ts_pmt_stream *stream = ts->pmt->streams[i];
500
-		pidmap_set(&ts->pidmap, stream->pid); // Data
501
-	}
502
-
503
-	if (!ts->ecm_caid) {
504
-		ts_get_ecm_info(ts->pmt, req_CA_sys, &ts->ecm_caid, &ts->ecm_pid);
505
-		char *CA_sys = ts_get_CA_sys_txt(ts_get_CA_sys(ts->ecm_caid));
506
-		ts_LOGf("%s Service : 0x%04x\n", CA_sys, ts->service_id);
507
-		ts_LOGf("%s CA_id   : 0x%04x\n", CA_sys, ts->emm_caid);
508
-		ts_LOGf("%s EMM pid : 0x%04x\n", CA_sys, ts->emm_pid);
509
-		ts_LOGf("%s ECM pid : 0x%04x\n", CA_sys, ts->ecm_pid);
510
-	}
511
-}
512
-
513
-#define dump_sz      (16)
514
-#define dump_buf_sz  (dump_sz * 6)
515
-
516
-void process_emm(struct ts *ts, uint16_t pid, uint8_t *ts_packet) {
517
-	char dump[dump_buf_sz];
518
-	if (!ts->emm_pid || ts->emm_pid != pid)
519
-		return;
520
-
521
-	show_ts_pack(pid, "emm", NULL, ts_packet);
522
-
523
-	if (!emm_send)
524
-		return;
525
-
526
-	ts->emm = ts_privsec_push_packet(ts->emm, ts_packet);
527
-	if (!ts->emm->initialized)
528
-		return;
529
-
530
-	struct ts_header *th = &ts->emm->ts_header;
531
-	struct ts_section_header *sec = ts->emm->section_header;
532
-	if (debug_level >= 2) {
533
-		ts_hex_dump_buf(dump, dump_buf_sz, sec->section_data, min(dump_sz, sec->section_data_len), 0);
534
-		ts_LOGf("EMM | CAID: 0x%04x PID 0x%04x Table: 0x%02x Length: %3d ----------- Data: %s..\n",
535
-			ts->emm_caid,
536
-			th->pid,
537
-			sec->table_id,
538
-			sec->section_data_len,
539
-			dump);
540
-	}
541
-	camd35_send_emm(ts->emm_caid, sec->section_data, sec->section_data_len);
542
-	ts_privsec_copy(ts->emm, ts->last_emm);
543
-	ts_privsec_clear(ts->emm);
544
-}
545
-
546
-void process_ecm(struct ts *ts, uint16_t pid, uint8_t *ts_packet) {
547
-	char dump[dump_buf_sz];
548
-	if (!ts->ecm_pid || ts->ecm_pid != pid)
549
-		return;
550
-
551
-	ts->ecm = ts_privsec_push_packet(ts->ecm, ts_packet);
552
-	if (!ts->ecm->initialized)
553
-		return;
554
-
555
-	struct ts_header *th = &ts->ecm->ts_header;
556
-	struct ts_section_header *sec = ts->ecm->section_header;
557
-	int duplicate = ts_privsec_is_same(ts->ecm, ts->last_ecm);
558
-	if (!duplicate) {
559
-		ts_hex_dump_buf(dump, dump_buf_sz, sec->section_data, min(dump_sz, sec->section_data_len), 0);
560
-		ts_LOGf("ECM | CAID: 0x%04x PID 0x%04x Table: 0x%02x Length: %3d IDX: 0x%04x Data: %s..\n",
561
-			ts->ecm_caid,
562
-			th->pid,
563
-			sec->table_id,
564
-			sec->section_data_len,
565
-			ts->ecm_counter,
566
-			dump);
567
-		camd35_send_ecm(ts->service_id, ts->ecm_caid, ts->ecm_counter++, sec->section_data, sec->section_data_len);
568
-	} else if (debug_level >= 3) {
569
-		ts_LOGf("ECM | CAID: 0x%04x PID 0x%04x Table: 0x%02x Length: %3d IDX: 0x%04x Data: -dup-\n",
570
-			ts->ecm_caid,
571
-			th->pid,
572
-			sec->table_id,
573
-			sec->section_data_len,
574
-			ts->ecm_counter - 1);
575
-	}
576
-	ts_privsec_copy(ts->ecm, ts->last_ecm);
577
-	ts_privsec_clear(ts->ecm);
578
-
579
-	show_ts_pack(pid, !duplicate ? "ecm" : "ec+", NULL, ts_packet);
580
-}
581
-
582 168
 void ts_process_packets(struct ts *ts, uint8_t *data, ssize_t data_len) {
583 169
 	ssize_t i;
584 170
 	for (i=0; i<data_len; i += 188) {
@@ -657,6 +243,6 @@ int main(int argc, char **argv) {
657 243
 	dvbcsa_key_free(csakey[0]);
658 244
 	dvbcsa_key_free(csakey[1]);
659 245
 
660
-	shutdown_fd(&server_fd);
246
+	camd35_disconnect();
661 247
 	exit(0);
662 248
 }

Loading…
Cancel
Save