source: trunk/reader-dre.c @ 492

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

Fix ECM Tricolor

  • Property svn:eol-style set to native
File size: 12.7 KB
Line 
1#include "globals.h"
2#include "reader-common.h"
3//#include <stdlib.h>
4
5extern uchar cta_cmd[], cta_res[];
6extern ushort cta_lr;
7static unsigned short pmap = 0; // provider-maptable
8unsigned long long serial;
9char *card;
10static uchar provider;
11static short int mode;
12
13#define OK_RESPONSE 0x61
14#define CMD_BYTE 0x59
15
16#define dre_cmd(cmd) \
17{ \
18    dre_command(cmd, sizeof(cmd)); \
19}
20
21int dre_set_provider_info (void)
22{
23  int i;
24  static uchar cmd59[] = { 0x59, 0x14 };    // subscriptions
25  static uchar cmd5b[] = { 0x5b, 0x00, 0x14 };  //validity dates
26
27  cmd59[1] = provider;
28  if ((dre_cmd (cmd59))) {  //ask subscription packages, returns error on 0x11 card
29    uchar pbm[32];
30    memcpy (pbm, cta_res + 3, cta_lr - 6);
31    cs_debug ("DRECRYPT pbm: %s", cs_hexdump (0, pbm, 32));
32
33    if (pbm[0] == 0xff)
34      cs_log ("No active packages!");
35    else
36      for (i = 0; i < 32; i++)
37    if (pbm[i] != 0xff) {
38      cmd5b[1] = i;
39      cmd5b[2] = provider;
40      dre_cmd (cmd5b);  //ask for validity dates
41
42      time_t start;
43      time_t end;
44      start = (cta_res[3] << 24) | (cta_res[4] << 16) | (cta_res[5] << 8) | cta_res[6];
45      end = (cta_res[7] << 24) | (cta_res[8] << 16) | (cta_res[9] << 8) | cta_res[10];
46
47      struct tm *temp;
48
49      temp = localtime (&start);
50      int startyear = temp->tm_year + 1900;
51      int startmonth = temp->tm_mon + 1;
52      int startday = temp->tm_mday;
53      temp = localtime (&end);
54      int endyear = temp->tm_year + 1900;
55      int endmonth = temp->tm_mon + 1;
56      int endday = temp->tm_mday;
57      cs_log ("Active package %i valid from %04i/%02i/%02i to %04i/%02i/%02i", i, startyear, startmonth, startday,
58          endyear, endmonth, endday);
59    }
60  }
61  return 1;
62}
63
64uchar xor (uchar * cmd, int cmdlen)
65{
66  int i;
67  uchar checksum = 0x00;
68  for (i = 0; i < cmdlen; i++)
69    checksum ^= cmd[i];
70  return checksum;
71}
72
73
74int dre_command (uchar * cmd, int cmdlen)   //attention: inputcommand will be changed!!!! answer will be in cta_res, length cta_lr ; returning 1 = no error, return 0 = err
75{
76  static uchar startcmd[] = { 0x80, 0xFF, 0x10, 0x01, 0x05 };   //any command starts with this,
77  //last byte is nr of bytes of the command that will be sent
78  //after the startcmd
79//response on startcmd+cmd:     = { 0x61, 0x05 }  //0x61 = "OK", last byte is nr. of bytes card will send
80  static uchar reqans[] = { 0x00, 0xC0, 0x00, 0x00, 0x08 }; //after command answer has to be requested,
81  //last byte must be nr. of bytes that card has reported to send
82  uchar command[256];
83  int headerlen = sizeof (startcmd);
84  startcmd[4] = cmdlen + 3; //commandlength + type + len + checksum bytes
85  memcpy (command, startcmd, headerlen);
86  command[headerlen++] = CMD_BYTE;  //type
87  command[headerlen++] = cmdlen + 1;    //len = command + 1 checksum byte
88  memcpy (command + headerlen, cmd, cmdlen);
89
90  uchar checksum = ~xor (cmd, cmdlen);
91  //cs_debug ("Checksum: %02x", checksum);
92  cmdlen += headerlen;
93  command[cmdlen++] = checksum;
94
95  reader_cmd2icc (command, cmdlen);
96
97  if ((cta_lr != 2) || (cta_res[0] != OK_RESPONSE)) {
98    cs_log ("DRECRYPT ERROR: unexpected answer from card: %s", cs_hexdump (0, cta_res, cta_lr));
99    return 0;           //error
100  }
101
102  reqans[4] = cta_res[1];   //adapt length byte
103  reader_cmd2icc (reqans, 5);
104
105  if (cta_res[0] != CMD_BYTE) {
106    cs_log ("DRECRYPT Unknown response: cta_res[0] expected to be %02x, is %02x", CMD_BYTE, cta_res[0]);
107    return 0;
108  }
109  if ((cta_res[1] == 0x03) && (cta_res[2] == 0xe2)) {
110    switch (cta_res[3]) {
111    case 0xe1:
112      cs_log ("DRECRYPT checksum error: %s.", cs_hexdump (0, cta_res, cta_lr));
113      break;
114    case 0xe2:
115      cs_log ("DRECRYPT wrong provider: %s.", cs_hexdump (0, cta_res, cta_lr));
116      break;
117    case 0xec:
118      cs_log ("DRECRYPT wrong signature: %s.", cs_hexdump (0, cta_res, cta_lr));
119      break;
120    default:
121      cs_debug ("DRECRYPT unknown error: %s.", cs_hexdump (0, cta_res, cta_lr));
122      break;
123    }
124    return 0;           //error
125  }
126  int length_excl_leader = cta_lr;
127  if ((cta_res[cta_lr - 2] == 0x90) && (cta_res[cta_lr - 1] == 0x00))
128    length_excl_leader -= 2;
129
130  checksum = ~xor (cta_res + 2, length_excl_leader - 3);
131
132  if (cta_res[length_excl_leader - 1] != checksum) {
133    cs_log ("DRECRYPT checksum does not match, expected %02x received %02x:%s", checksum,
134        cta_res[length_excl_leader - 1], cs_hexdump (0, cta_res, cta_lr));
135    return 0;           //error
136  }
137  return 1;
138}
139
140int dre_card_init (uchar * atr, int atrsize)
141{
142  static uchar ua[] = { 0x43, 0x15 };   // get serial number (UA)
143  static uchar providers[] = { 0x49, 0x15 };    // get providers
144  int i;
145
146  if ((atr[0] != 0x3b) || (atr[1] != 0x15) || (atr[2] != 0x11) || (atr[3] != 0x12 || atr[4] != 0xca || atr[5] != 0x07))
147    return (0);
148
149  provider = atr[6];
150  uchar checksum = xor (atr + 1, 6);
151
152  if (checksum != atr[7])
153    cs_log ("DRECRYPT Warning: expected ATR checksum %02x, smartcard reports %02x", checksum, atr[7]);
154
155  switch (atr[6]) {
156  case 0x11:
157    card = "Tricolor Centr";
158    reader[ridx].caid[0] = 0x4ae0;
159    mode = 41;
160    break;          //59 type card = MSP (74 type = ATMEL)
161  case 0x12:
162    card = "Cable TV";
163    reader[ridx].caid[0] = 0x4ae0;  //TODO not sure about this one
164    mode = 41;          //TODO not sure
165    break;
166  case 0x14:
167    card = "Tricolor Syberia / Platforma HD new";
168    reader[ridx].caid[0] = 0x4ae1;
169    mode = 51;
170    break;          //59 type card
171  case 0x15:
172    card = "Platforma HD / DW old";
173    reader[ridx].caid[0] = 0x4ae1;  //TODO not sure
174    mode = 41;          //TODO not sure
175    break;          //59 type card
176  default:
177    card = "Unknown";
178    reader[ridx].caid[0] = 0x4ae1;  //TODO: what is sensible value here?
179    mode = 51;
180    break;
181  }
182
183  memset (reader[ridx].prid, 0xff, sizeof (reader[ridx].prid));
184  memset (reader[ridx].prid, 0x00, 8);
185
186  static uchar cmd30[] =
187    { 0x30, 0x81, 0x00, 0x81, 0x82, 0x03, 0x84, 0x05, 0x06, 0x87, 0x08, 0x09, 0x00, 0x81, 0x82, 0x03, 0x84, 0x05,
188    0x00
189  };
190  dre_cmd (cmd30);      //unknown command, generates error on card 0x11 and 0x14
191/*
192response:
19359 03 E2 E3
194FE 48 */
195
196  static uchar cmd54[] = { 0x54, 0x14 };    // geocode
197  cmd54[1] = provider;
198  uchar geocode = 0;
199  if ((dre_cmd (cmd54)))    //error would not be fatal, like on 0x11 cards
200    geocode = cta_res[3];
201
202  providers[1] = provider;
203  if (!(dre_cmd (providers)))
204    return 0;           //fatal error
205  if ((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
206    return 0;
207  uchar provname[128];
208  for (i = 0; ((i < cta_res[2] - 6) && (i < 128)); i++) {
209    provname[i] = cta_res[6 + i];
210    if (provname[i] == 0x00)
211      break;
212  }
213  int major_version = cta_res[3];
214  int minor_version = cta_res[4];
215
216  ua[1] = provider;
217  dre_cmd (ua);         //error would not be fatal
218
219  for (i = 0; i < 8; i++)
220    reader[ridx].hexserial[i] = 0;
221  int hexlength = cta_res[1] - 2;   //discard first and last byte, last byte is always checksum, first is always rubbish?
222
223  memcpy (reader[ridx].hexserial + 8 - hexlength, cta_res + 3, hexlength);
224
225  int low_dre_id = ((cta_res[4] << 16) | (cta_res[5] << 8) | cta_res[6]) - 48608;
226  int dre_chksum = 0;
227  uchar buf[32];
228  sprintf (buf, "%i%i%08i", provider - 16, major_version + 1, low_dre_id);
229  for (i = 0; i < 32; i++) {
230    if (buf[i] == 0x00)
231      break;
232    dre_chksum += buf[i] - 48;
233  }
234
235  //cs_ri_log("type: DRECrypt, caid: %04X, serial: %llu, card: v%x",
236  cs_log ("type: DRECrypt, caid: %04X, serial: %s, dre id: %i%i%i%08i, geocode %i, card: %s v%i.%i",
237      reader[ridx].caid[0], cs_hexdump (0, reader[ridx].hexserial, 8), dre_chksum, provider - 16, major_version + 1,
238      low_dre_id, geocode, card, major_version, minor_version);
239  cs_log ("Provider name:%s.", provname);
240
241
242  memcpy (&reader[ridx].sa[0][0], &reader[ridx].hexserial + 4, 4);  //copy unique address also in shared address, because we dont know what it is...
243
244  if (!dre_set_provider_info ())
245    return 0;           //fatal error
246
247
248  /* Unknown function 51
249     59
250     23 51 82 3B 05 00 4A D4 CA
251     A3 1D A2
252     DF 95 29 90 65 E1 95 B8 1C 91 87 C8 B5 CB 62 2F
253     09
254     F7 BC 18 BA 14  some byte seems to be missing !?!
255
256     ANOTHER INS is the same except last line:
257     EF C7 1D 4C E3 14 last byte stays the same = provider byte???
258
259     response: DW info retour
260     59 12 D2 8E 7A FE BA 6C DF 31 49
261     1A 8F 34
262     98 48 42 CE 0D DE
263     90 00 */
264
265
266  //memcpy(&reader[ridx].prid[i][2], cta_res, 2);
267
268//############### PLAYGROUND ////
269
270//from bbs, provider = 15???
271//static uchar ecmtest[] = { 0x51, 0x01, 0x56, 0x00, 0x00, 0x48, 0xC6, 0xF0, 0x19, 0x01, 0xD4, 0xDF, 0x4F, 0xD7, 0x91, 0x55, 0x68, 0x02, 0x72, 0xF7, 0x98, 0x28, 0xBD, 0x78, 0x8E, 0x4E, 0xE8, 0xED, 0x0B, 0x51, 0xBF, 0xA4, 0x4E, 0x15 };
272//from log, works:
273//static uchar ecmtest[] = { 0x51, 0x02, 0x56, 0x05, 0x00, 0x4A, 0xE3, 0x9C, 0xDA, 0xC1, 0x71, 0x21, 0x06, 0xF0, 0x14, 0xA7, 0x0E, 0x89, 0xDA, 0xC9, 0xD7, 0xFD, 0xB9, 0x06, 0xFD, 0xD5, 0x1E, 0x2A, 0xA3, 0xB5, 0xA0, 0x82, 0x11, 0x14 };
274/*  static uchar ecmtest[] =
275    { 0x51, 0x03, 0x56, 0x05, 0x00, 0x4A, 0xE4, 0x58, 0x02, 0x8B, 0xAE, 0x42, 0xEE, 0xE2, 0x6A, 0x7F, 0x51, 0xE0, 0x7D,
2760xCE, 0x20, 0x8A, 0x24, 0xE8, 0xBA, 0xA6, 0xC3, 0xCB, 0x35, 0x45, 0x35, 0x52, 0x94, 0x14 };
277*/
278//from platforma itself through dvbviewer
279/*
280  static uchar ecmtest[] =
281    { 0x51, 0x02, 0x56, 0x00, 0x00, 0x4A, 0xEC, 0x00, 0xAA, 0x31, 0x39, 0x06, 0x57, 0x94, 0x55, 0x1D, 0x23, 0x52, 0x88,
2820x3D, 0xA8, 0x62, 0xDC, 0xA2, 0x98, 0xD7, 0xAB, 0x0D, 0x80, 0x60, 0x15, 0xF5, 0x07, 0x14 };
283*/
284  //from redirected dvbviewer
285  static uchar ecmtest[] =
286    { 0x51, 0x02, 0x56, 0x00, 0x00, 0x4A, 0xEC, 0x3B, 0xF6, 0x56, 0x5A, 0x43, 0x95, 0x43, 0x05, 0x02, 0xBB, 0x46, 0x22,
287    0x27, 0xEF, 0x33, 0xF4, 0xA9, 0xD0, 0x65, 0xDB, 0x57, 0x8F, 0x8F, 0x7C, 0x19, 0x36, 0x14
288  };
289
290//rest: 0x93, 0x36, 0x58, 0xC9
291
292
293  //ecmcmd51[33]=provider; //FIXME part of signatur
294
295//int hans, index, save;
296//for (index=1; index<3; index++) {
297//  save = ecmtest[index];
298//  for (hans=0; hans<256; hans++) {
299//   ecmtest[index] = hans;
300//    if ((dre_cmd(ecmtest)))
301//      cs_log("HANS SUCCESS");
302//  }
303//  ecmtest[index] = save;
304//}
305
306//############### PLAYGROUND ////
307  cs_log ("ready for requests");
308  return (1);
309}
310
311static int get_prov_index (char *provid)    //returns provider id or -1 if not found
312{
313  int prov;
314  for (prov = 0; prov < reader[ridx].nprov; prov++) //search for provider index
315    if (!memcmp (provid, &reader[ridx].prid[prov][2], 2))
316      return (prov);
317  return (-1);
318}
319
320
321int dre_do_ecm (ECM_REQUEST * er)
322{
323  //
324  //cmd41 is not known for card provider 0x14 ???
325  if (mode == 41) {
326    static uchar ecmcmd41[] = { 0x41,
327      0x58, 0x1f, 0x00,     //fixed part, dont change
328      0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,   //0x01 - 0x08: next key
329      0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,   //0x11 - 0x18: current key
330      0x3b, 0x59, 0x11      //0x3b = keynumber, can be a value 56 ;; 0x59 number of package = 58+1 - Pay Package ;; 0x11 = provider
331    };
332    ecmcmd41[22] = provider;
333    memcpy (ecmcmd41 + 4, er->ecm + 8, 16);
334    ecmcmd41[20] = er->ecm[6];  //keynumber
335    ecmcmd41[21] = 0x58 + er->ecm[25];
336    cs_debug ("DEBUG: unused ECM info front:%s", cs_hexdump (0, er->ecm, 8));
337    cs_debug ("DEBUG: unused ECM info back:%s", cs_hexdump (0, er->ecm + 24, er->ecm[2]+2-24));
338    if ((dre_cmd (ecmcmd41))) { //ecm request
339      if ((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
340    return (0);     //exit if response is not 90 00 //TODO: if response is 9027 ppv mode is possible!
341      //memcpy(er->cw,cta_res+3,16);
342      //or swap bytes:
343      memcpy (er->cw, cta_res + 11, 8);
344      memcpy (er->cw + 8, cta_res + 3, 8);
345
346      //  return 0; //FIXME only used for testing CWs
347      return 1;
348    }
349  }
350  else {
351
352    //cmd51 is used for provider 0x14
353    static uchar ecmcmd51[] = { 0x51, 0x02, 0x56, 0x05, 0x00, 0x4A, 0xE3,   //fixed header?
354      0x9C, 0xDA,       //first three nibbles count up, fourth nibble counts down; all ECMs sent twice
355      0xC1, 0x71, 0x21, 0x06, 0xF0, 0x14, 0xA7, 0x0E,   //next key?
356      0x89, 0xDA, 0xC9, 0xD7, 0xFD, 0xB9, 0x06, 0xFD,   //current key?
357      0xD5, 0x1E, 0x2A, 0xA3, 0xB5, 0xA0, 0x82, 0x11,   //key or signature?
358      0x14          //provider
359    };
360    memcpy (ecmcmd51 + 1, er->ecm + 5, 0x21);
361    //cs_log ("DEBUG: ECM: %s", cs_hexdump (0, er->ecm, er->ecm[2] + 3));
362    cs_debug ("DEBUG: unused ECM info front:%s", cs_hexdump (0, er->ecm, 5));
363    cs_debug ("DEBUG: unused ECM info back:%s", cs_hexdump (0, er->ecm + 37, 4));
364    ecmcmd51[33] = provider;    //no part of sig
365    if ((dre_cmd (ecmcmd51))) { //ecm request
366      if ((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
367    return (0);     //exit if response is not 90 00 //TODO: if response is 9027 ppv mode is possible!
368      //memcpy(er->cw,cta_res+3,16);
369      //or swap bytes:
370      memcpy (er->cw, cta_res + 11, 8);
371      memcpy (er->cw + 8, cta_res + 3, 8);
372
373      //  return 0; //FIXME only used for testing CWs
374      return 1;
375    }
376  }
377  return 0;
378}
379
380int dre_do_emm (EMM_PACKET * ep)
381{
382  return 0;         //FIXME STUB
383}
384
385int dre_card_info (void)
386{
387  return (1);
388}
Note: See TracBrowser for help on using the repository browser.