source: trunk/reader-videoguard1.c@ 3182

Last change on this file since 3182 was 3182, checked in by dingo35, 10 years ago

Readers checked on threadsafety except videoguard-common

File size: 15.0 KB
Line 
1#include "globals.h"
2#include "reader-common.h"
3#include "reader-videoguard-common.h"
4
5
6static int vg1_do_cmd(struct s_reader *reader, const unsigned char *ins, const unsigned char *txbuff, unsigned char *rxbuff, unsigned char *cta_res)
7{
8 ushort cta_lr;
9 unsigned char ins2[5];
10 memcpy(ins2, ins, 5);
11 unsigned char len = 0;
12 len = ins2[4];
13
14 unsigned char tmp[264];
15 if (!rxbuff) {
16 rxbuff = tmp;
17 }
18
19 if (txbuff == NULL) {
20 if (!write_cmd_vg(ins2, NULL) || !status_ok(cta_res + len)) {
21 return -1;
22 }
23 memcpy(rxbuff, ins2, 5);
24 memcpy(rxbuff + 5, cta_res, len);
25 memcpy(rxbuff + 5 + len, cta_res + len, 2);
26 } else {
27 if (!write_cmd_vg(ins2, (uchar *) txbuff) || !status_ok(cta_res)) {
28 return -2;
29 }
30 memcpy(rxbuff, ins2, 5);
31 memcpy(rxbuff + 5, txbuff, len);
32 memcpy(rxbuff + 5 + len, cta_res, 2);
33 }
34
35 return len;
36}
37
38static void read_tiers(struct s_reader *reader)
39{
40 def_resp;
41// static const unsigned char ins2a[5] = { 0x48, 0x2a, 0x00, 0x00, 0x00 };
42 int l;
43
44// return; // Not working at present so just do nothing
45
46// l = vg1_do_cmd(reader, ins2a, NULL, NULL, cta_res);
47// if (l < 0 || !status_ok(cta_res + l))
48// {
49// return;
50// }
51 unsigned char ins76[5] = { 0x48, 0x76, 0x00, 0x00, 0x00 };
52 ins76[3] = 0x7f;
53 ins76[4] = 2;
54 if (!write_cmd_vg(ins76, NULL) || !status_ok(cta_res + 2)) {
55 return;
56 }
57 ins76[3] = 0;
58 ins76[4] = 0x0a;
59 int num = cta_res[1];
60 int i;
61#ifdef CS_RDR_INIT_HIST
62 reader->init_history_pos = 0; //reset for re-read
63 memset(reader->init_history, 0, sizeof(reader->init_history));
64#endif
65 for (i = 0; i < num; i++) {
66 ins76[2] = i;
67 l = vg1_do_cmd(reader, ins76, NULL, NULL, cta_res);
68 if (l < 0 || !status_ok(cta_res + l)) {
69 return;
70 }
71 if (cta_res[2] == 0 && cta_res[3] == 0) {
72 break;
73 }
74 int y, m, d, H, M, S;
75 rev_date_calc(&cta_res[4], &y, &m, &d, &H, &M, &S, reader->card_baseyear);
76 unsigned short tier_id = (cta_res[2] << 8) | cta_res[3];
77 char *tier_name = get_tiername(tier_id, reader->caid[0]);
78 cs_ri_log(reader, "[videoguard1-reader] tier: %04x, expiry date: %04d/%02d/%02d-%02d:%02d:%02d %s", tier_id, y, m, d, H, M, S, tier_name);
79 }
80}
81
82int videoguard1_card_init(struct s_reader *reader, ATR newatr)
83{
84
85 get_hist;
86 /* 40 B0 09 4A 50 01 4E 5A */
87 if ((hist_size < 7) || (hist[1] != 0xB0) || (hist[3] != 0x4A) || (hist[4] != 0x50)) {
88 return ERROR;
89 }
90
91 get_atr;
92 def_resp;
93
94 // Copy the atr info into the reader, can we not do this in reader-common.c?
95 reader->atrlen = atr_size;
96 memcpy(reader->atr,atr,atr_size);
97
98 /* set information on the card stored in reader-videoguard-common.c */
99 set_known_card_info(reader);
100
101 if((reader->ndsversion != NDS1) && ((reader->card_system_version != NDS1) || (reader->ndsversion != NDSAUTO))) {
102 /* known ATR and not NDS1
103 or unknown ATR and not forced to NDS1
104 or known NDS1 ATR and forced to another NDS version
105 ... probably not NDS1 */
106 return ERROR;
107 }
108
109 cs_ri_log(reader, "[videoguard1-reader] type: %s, baseyear: %i", reader->card_desc, reader->card_baseyear);
110 if(reader->ndsversion == NDS1){
111 cs_log("[videoguard1-reader] forced to NDS1+");
112 }
113
114 /* NDS1 Class 48 only cards only need a very basic initialisation
115 NDS1 Class 48 only cards do not respond to vg1_do_cmd(ins7416)
116 nor do they return list of valid command therefore do not even try
117 NDS1 Class 48 only cards need to be told the length as (48, ins, 00, 80, 01)
118 does not return the length */
119
120 int l = 0;
121 unsigned char buff[256];
122
123 /* Try to get the boxid from the card, even if BoxID specified in the config file
124 also used to check if it is an NDS1 card as the returned information will
125 not be encrypted if it is an NDS1 card */
126
127 unsigned char ins36[5] = { 0x48, 0x36, 0x00, 0x00, 0x90 };
128 unsigned char boxID[4];
129 int boxidOK = 0;
130 l = vg1_do_cmd(reader, ins36, NULL, buff, cta_res);
131 if (buff[7] > 0x0F) {
132 cs_log("[videoguard1-reader] class48 ins36: encrypted - therefore not an NDS1 card");
133 return ERROR;
134 } else {
135 /* skipping the initial fixed fields: cmdecho (4) + length (1) + encr/rev++ (4) */
136 int i = 9;
137 int gotUA = 0;
138 while (i < l) {
139 if (!gotUA && buff[i] < 0xF0) { /* then we guess that the next 4 bytes is the UA */
140 gotUA = 1;
141 i += 4;
142 } else {
143 switch (buff[i]) { /* object length vary depending on type */
144 case 0x00: /* padding */
145 {
146 i += 1;
147 break;
148 }
149 case 0xEF: /* card status */
150 {
151 i += 3;
152 break;
153 }
154 case 0xD1:
155 {
156 i += 4;
157 break;
158 }
159 case 0xDF: /* next server contact */
160 {
161 i += 5;
162 break;
163 }
164 case 0xF3: /* boxID */
165 {
166 memcpy(&boxID, &buff[i + 1], sizeof(boxID));
167 boxidOK = 1;
168 i += 5;
169 break;
170 }
171 case 0xF6:
172 {
173 i += 6;
174 break;
175 }
176 case 0xFC: /* No idea seems to with with NDS1 */
177 {
178 i += 14;
179 break;
180 }
181 case 0x01: /* date & time */
182 {
183 i += 7;
184 break;
185 }
186 case 0xFA:
187 {
188 i += 9;
189 break;
190 }
191 case 0x5E:
192 case 0x67: /* signature */
193 case 0xDE:
194 case 0xE2:
195 case 0xE9: /* tier dates */
196 case 0xF8: /* Old PPV Event Record */
197 case 0xFD:
198 {
199 i += buff[i + 1] + 2; /* skip length + 2 bytes (type and length) */
200 break;
201 }
202 default: /* default to assume a length byte */
203 {
204 cs_log("[videoguard1-reader] class48 ins36: returned unknown type=0x%02X - parsing may fail", buff[i]);
205 i += buff[i + 1] + 2;
206 }
207 }
208 }
209 }
210 }
211
212 // cs_log("[videguard1nz-reader] calculated BoxID: %02X%02X%02X%02X", boxID[0], boxID[1], boxID[2], boxID[3]);
213
214 /* the boxid is specified in the config */
215 if (reader->boxid > 0) {
216 int i;
217 for (i = 0; i < 4; i++) {
218 boxID[i] = (reader->boxid >> (8 * (3 - i))) % 0x100;
219 }
220 // cs_log("[videguard1nz-reader] config BoxID: %02X%02X%02X%02X", boxID[0], boxID[1], boxID[2], boxID[3]);
221 }
222
223 if (!boxidOK) {
224 cs_log("[videoguard1-reader] no boxID available");
225 return ERROR;
226 }
227
228 // Send BoxID
229 unsigned char ins4C[5] = { 0x48, 0x4C, 0x00, 0x00, 0x09 };
230 unsigned char payload4C[9] = { 0, 0, 0, 0, 3, 0, 0, 0, 4 };
231 memcpy(payload4C, boxID, 4);
232 if (!write_cmd_vg(ins4C, payload4C) || !status_ok(cta_res + l)) {
233 cs_log("[videoguard1-reader] class48 ins4C: sending boxid failed");
234 return ERROR;
235 }
236
237 unsigned char ins58[5] = { 0x48, 0x58, 0x00, 0x00, 0x17 };
238 l = vg1_do_cmd(reader, ins58, NULL, buff, cta_res);
239 if (l < 0) {
240 cs_log("[videoguard1-reader] class48 ins58: failed");
241 return ERROR;
242 }
243
244 memset(reader->hexserial, 0, 8);
245 memcpy(reader->hexserial + 2, cta_res + 1, 4);
246 memcpy(reader->sa, cta_res + 1, 3);
247 // reader->caid[0] = cta_res[24] * 0x100 + cta_res[25];
248 /* Force caid until can figure out how to get it */
249 reader->caid[0] = 0x9 * 0x100 + 0x69;
250
251 /* we have one provider, 0x0000 */
252 reader->nprov = 1;
253 memset(reader->prid, 0x00, sizeof(reader->prid));
254
255 cs_ri_log(reader,
256 "[videoguard1-reader] type: VideoGuard, caid: %04X, serial: %02X%02X%02X%02X, BoxID: %02X%02X%02X%02X",
257 reader->caid[0], reader->hexserial[2], reader->hexserial[3], reader->hexserial[4], reader->hexserial[5], boxID[0], boxID[1], boxID[2], boxID[3]);
258 cs_log("[videoguard1-reader] ready for requests - this is in testing please send -d 255 logs");
259
260 return OK;
261}
262
263int videoguard1_do_ecm(struct s_reader *reader, ECM_REQUEST * er)
264{
265 unsigned char cta_res[CTA_RES_LEN];
266 unsigned char ins40[5] = { 0x48, 0x40, 0x00, 0x80, 0xFF };
267 static const unsigned char ins54[5] = { 0x48, 0x54, 0x00, 0x00, 0x0D };
268 int posECMpart2 = er->ecm[6] + 7;
269 int lenECMpart2 = er->ecm[posECMpart2];
270 unsigned char tbuff[264];
271 unsigned char rbuff[264];
272 memcpy(&tbuff[0], &(er->ecm[posECMpart2 + 1]), lenECMpart2 - 1);
273 ins40[4] = lenECMpart2;
274 int l;
275 l = vg1_do_cmd(reader, ins40, tbuff, NULL, cta_res);
276 if (l > 0 && status_ok(cta_res)) {
277 l = vg1_do_cmd(reader, ins54, NULL, rbuff, cta_res);
278 if (l > 0 && status_ok(cta_res + l)) {
279 if (!cw_is_valid(rbuff+5,0)) //sky cards report 90 00 = ok but send cw = 00 when channel not subscribed
280 {
281 cs_log("[videoguard1-reader] class48 ins54 status 90 00 but cw=00 -> channel not subscribed");
282 return ERROR;
283 }
284
285 if(er->ecm[0]&1) {
286 memset(er->cw+0, 0, 8);
287 memcpy(er->cw+8, rbuff + 5, 8);
288 } else {
289 memcpy(er->cw+0, rbuff + 5, 8);
290 memset(er->cw+8, 0, 8);
291 }
292 return OK;
293 }
294 }
295 cs_log("[videoguard1-reader] class48 ins54 (%d) status not ok %02x %02x", l, cta_res[0], cta_res[1]);
296 return ERROR;
297}
298
299static int num_addr(const unsigned char *data)
300{
301 return ((data[3] & 0x30) >> 4) + 1;
302}
303
304/*
305Example of GLOBAL EMM's
306This one has IRD-EMM + Card-EMM
30782 70 20 00 02 06 02 7D 0E 89 53 71 16 90 14 40
30801 ED 17 7D 9E 1F 28 CF 09 97 54 F1 8E 72 06 E7
30951 AF F5
310This one has only IRD-EMM
31182 70 6D 00 07 69 01 30 07 14 5E 0F FF FF 00 06
31200 0D 01 00 03 01 00 00 00 0F 00 00 00 5E 01 00
31301 0C 2E 70 E4 55 B6 D2 34 F7 44 86 9E 5C 91 14
31481 FC DF CB D0 86 65 77 DF A9 E1 6B A8 9F 9B DE
31590 92 B9 AA 6C B3 4E 87 D2 EC 92 DA FC 71 EF 27
316B3 C3 D0 17 CF 0B D6 5E 8C DB EB B3 37 55 6E 09
3177F 27 3C F1 85 29 C9 4E 0B EE DF 68 BE 00 C9 00
318*/
319static const unsigned char *payload_addr(uchar emmtype, const unsigned char *data, const unsigned char *a)
320{
321 int s;
322 int l;
323 const unsigned char *ptr = NULL;
324 int position = -1;
325 int numAddrs = 0;
326 switch (emmtype) {
327 case SHARED:
328 {
329 s = 3;
330 break;
331 }
332 case UNIQUE:
333 {
334 s = 4;
335 break;
336 }
337 default:
338 {
339 s = 0;
340 }
341 }
342
343 numAddrs = num_addr(data);
344 if (s > 0) {
345 for (l = 0; l < numAddrs; l++) {
346 if (!memcmp(&data[l * 4 + 4], a + 2, s)) {
347 position = l;
348 break;
349 }
350 }
351 }
352
353 int num_filter = (position == -1) ? 0 : numAddrs;
354 /* skip header and the filter list */
355 ptr = data + 4 + 4 * num_filter;
356 if (*ptr != 0x02 && *ptr != 0x07) // some clients omit 00 00 separator */
357 {
358 ptr += 2; // skip 00 00 separator
359 if (*ptr == 0x00)
360 ptr++; // skip optional 00
361 ptr++; // skip the 1st bitmap len
362 }
363
364 /* check for IRD-EMM */
365 if (*ptr != 0x02 && *ptr != 0x07) {
366 return NULL;
367 }
368
369 /* skip IRD-EMM part, 02 00 or 02 06 xx aabbccdd yy */
370 ptr += 2 + ptr[1];
371 /* check for EMM boundaries - ptr should not exceed EMM length */
372 if ((int) (ptr - (data + 3)) >= data[2]) {
373 return NULL;
374 }
375
376 for (l = 0; l < position; l++) {
377 /* skip the payload of the previous sub-EMM */
378 ptr += 1 + ptr[0];
379 /* check for EMM boundaries - ptr should not exceed EMM length */
380 if ((int) (ptr - (data + 3)) >= data[2]) {
381 return NULL;
382 }
383
384 /* skip optional 00 */
385 if (*ptr == 0x00) {
386 ptr++;
387 }
388
389 /* skip the bitmap len */
390 ptr++;
391 /* check for IRD-EMM */
392 if (*ptr != 0x02 && *ptr != 0x07) {
393 return NULL;
394 }
395
396 /* skip IRD-EMM part, 02 00 or 02 06 xx aabbccdd yy */
397 ptr += 2 + ptr[1];
398 }
399
400 return ptr;
401}
402
403int videoguard1_get_emm_type(EMM_PACKET * ep, struct s_reader *rdr)
404{
405
406/*
40782 30 ad 70 00 XX XX XX 00 XX XX XX 00 XX XX XX 00 XX XX XX 00 00
408d3 02 00 22 90 20 44 02 4a 50 1d 88 ab 02 ac 79 16 6c df a1 b1 b7 77 00 ba eb 63 b5 c9 a9 30 2b 43 e9 16 a9 d5 14 00
409d3 02 00 22 90 20 44 02 13 e3 40 bd 29 e4 90 97 c3 aa 93 db 8d f5 6b e4 92 dd 00 9b 51 03 c9 3d d0 e2 37 44 d3 bf 00
410d3 02 00 22 90 20 44 02 97 79 5d 18 96 5f 3a 67 70 55 bb b9 d2 49 31 bd 18 17 2a e9 6f eb d8 76 ec c3 c9 cc 53 39 00
411d2 02 00 21 90 1f 44 02 99 6d df 36 54 9c 7c 78 1b 21 54 d9 d4 9f c1 80 3c 46 10 76 aa 75 ef d6 82 27 2e 44 7b 00
412*/
413
414 int i, pos;
415 int serial_count = ((ep->emm[3] >> 4) & 3) + 1;
416 int serial_len = (ep->emm[3] & 0x80) ? 3 : 4;
417 uchar emmtype = (ep->emm[3] & VG_EMMTYPE_MASK) >> 6;
418 pos = 4 + (serial_len * serial_count) + 2;
419 switch (emmtype) {
420 case VG_EMMTYPE_G:
421 {
422 ep->type = GLOBAL;
423 cs_debug_mask(D_EMM, "VIDEOGUARD1 EMM: GLOBAL");
424 return TRUE;
425 }
426 case VG_EMMTYPE_U:
427 {
428 cs_debug_mask(D_EMM, "VIDEOGUARD1 EMM: UNIQUE");
429 ep->type = UNIQUE;
430 if (ep->emm[1] == 0) // detected UNIQUE EMM from cccam (there is no serial)
431 {
432 return TRUE;
433 }
434
435 for (i = 1; i <= serial_count; i++) {
436 if (!memcmp(rdr->hexserial + 2, ep->emm + (serial_len * i), serial_len)) {
437 memcpy(ep->hexserial, ep->emm + (serial_len * i), serial_len);
438 return TRUE;
439 }
440
441 pos = pos + ep->emm[pos + 5] + 5;
442 }
443 return FALSE; // if UNIQUE but no serial match return FALSE
444 }
445 case VG_EMMTYPE_S:
446 {
447 ep->type = SHARED;
448 cs_debug_mask(D_EMM, "VIDEOGUARD1 EMM: SHARED");
449 return TRUE; // FIXME: no check for SA
450 }
451 default:
452 {
453 if (ep->emm[pos - 2] != 0x00 && ep->emm[pos - 1] != 0x00 && ep->emm[pos - 1] != 0x01) {
454 //remote emm without serial
455 ep->type = UNKNOWN;
456 return TRUE;
457 }
458 return FALSE;
459 }
460 }
461}
462
463void videoguard1_get_emm_filter(struct s_reader *rdr, uchar * filter)
464{
465 filter[0] = 0xFF;
466 filter[1] = 3;
467 //ToDo videoguard1_get_emm_filter basic construction
468 filter[2] = UNIQUE;
469 filter[3] = 0;
470 filter[4 + 0] = 0x82;
471 filter[4 + 0 + 16] = 0xFF;
472 memcpy(filter + 4 + 2, rdr->hexserial + 2, 4);
473 memset(filter + 4 + 2 + 16, 0xFF, 4);
474 filter[36] = UNIQUE;
475 filter[37] = 0;
476 filter[38 + 0] = 0x82;
477 filter[38 + 0 + 16] = 0xFF;
478 memcpy(filter + 38 + 6, rdr->hexserial + 2, 4);
479 memset(filter + 38 + 6 + 16, 0xFF, 4);
480 filter[70] = UNIQUE;
481 filter[71] = 0;
482 filter[72 + 0] = 0x82;
483 filter[72 + 0 + 16] = 0xFF;
484 memcpy(filter + 72 + 10, rdr->hexserial + 2, 4);
485 memset(filter + 72 + 10 + 16, 0xFF, 4);
486 /* filter[104]=UNIQUE;
487 filter[105]=0;
488
489 filter[106+0] = 0x82;
490 filter[106+0+16] = 0xFF;
491
492 memcpy(filter+106+14, rdr->hexserial+2, 2);
493 memset(filter+106+14+16, 0xFF, 2); */
494 return;
495}
496
497int videoguard1_do_emm(struct s_reader *reader, EMM_PACKET * ep)
498{
499 unsigned char cta_res[CTA_RES_LEN];
500 unsigned char ins42[5] = {
501 0x48, 0x42, 0x00, 0x00, 0xFF
502 };
503 int rc = ERROR;
504 const unsigned char *payload = payload_addr(ep->type, ep->emm, reader->hexserial);
505 while (payload) {
506 ins42[4] = *payload;
507 int l = vg1_do_cmd(reader, ins42, payload + 1, NULL, cta_res);
508 if (l > 0 && status_ok(cta_res)) {
509 rc = OK;
510 }
511
512 cs_debug_mask(D_EMM, "[videoguard1-reader] EMM request return code : %02X%02X", cta_res[0], cta_res[1]);
513 //cs_dump(ep->emm, 64, "EMM:");
514 if (status_ok(cta_res) && (cta_res[1] & 0x01)) {
515 read_tiers(reader);
516 }
517
518 if (num_addr(ep->emm) == 1 && (int) (&payload[1] - &ep->emm[0]) + *payload + 1 < ep->l) {
519 payload += *payload + 1;
520 if (*payload == 0x00) {
521 ++payload;
522 }
523 ++payload;
524 if (*payload != 0x02) {
525 break;
526 }
527 payload += 2 + payload[1];
528 } else {
529 payload = 0;
530 }
531
532 }
533
534 return (rc);
535}
536
537int videoguard1_card_info(struct s_reader *reader)
538{
539 /* info is displayed in init, or when processing info */
540 cs_log("[videoguard1-reader] card detected");
541 cs_log("[videoguard1-reader] type: %s", reader->card_desc);
542 read_tiers(reader);
543 return OK;
544}
545
546void reader_videoguard1(struct s_cardsystem *ph)
547{
548 ph->do_emm=videoguard1_do_emm;
549 ph->do_ecm=videoguard1_do_ecm;
550 ph->card_info=videoguard1_card_info;
551 ph->card_init=videoguard1_card_init;
552 ph->get_emm_type=videoguard1_get_emm_type;
553 ph->caids[0]=0x09;
554}
Note: See TracBrowser for help on using the repository browser.