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