source: trunk/reader-dre.c @ 936

Last change on this file since 936 was 936, checked in by landlord, 10 years ago

Update for DRECAM EMM 0xe3 illegal command, thanks to satfox

  • Property svn:eol-style set to native
File size: 12.5 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;
7unsigned long long serial;
8char *card;
9static uchar provider;
10static short int mode;
11
12#define OK_RESPONSE 0x61
13#define CMD_BYTE 0x59
14
15#define dre_cmd(cmd) \
16{ \
17    dre_command(cmd, sizeof(cmd)); \
18}
19
20int dre_set_provider_info (void)
21{
22  int i;
23  static uchar cmd59[] = { 0x59, 0x14 };    // subscriptions
24  static uchar cmd5b[] = { 0x5b, 0x00, 0x14 };  //validity dates
25
26  cmd59[1] = provider;
27  if ((dre_cmd (cmd59))) {  //ask subscription packages, returns error on 0x11 card
28    uchar pbm[32];
29    memcpy (pbm, cta_res + 3, cta_lr - 6);
30    cs_debug ("DRECRYPT pbm: %s", cs_hexdump (0, pbm, 32));
31
32    if (pbm[0] == 0xff)
33      cs_log ("No active packages!");
34    else
35      for (i = 0; i < 32; i++)
36    if (pbm[i] != 0xff) {
37      cmd5b[1] = i;
38      cmd5b[2] = provider;
39      dre_cmd (cmd5b);  //ask for validity dates
40
41      time_t start;
42      time_t end;
43      start = (cta_res[3] << 24) | (cta_res[4] << 16) | (cta_res[5] << 8) | cta_res[6];
44      end = (cta_res[7] << 24) | (cta_res[8] << 16) | (cta_res[9] << 8) | cta_res[10];
45
46      struct tm *temp;
47
48      temp = localtime (&start);
49      int startyear = temp->tm_year + 1900;
50      int startmonth = temp->tm_mon + 1;
51      int startday = temp->tm_mday;
52      temp = localtime (&end);
53      int endyear = temp->tm_year + 1900;
54      int endmonth = temp->tm_mon + 1;
55      int endday = temp->tm_mday;
56      cs_log ("Active package %i valid from %04i/%02i/%02i to %04i/%02i/%02i", i, startyear, startmonth, startday,
57          endyear, endmonth, endday);
58    }
59  }
60  return 1;
61}
62
63uchar xor (uchar * cmd, int cmdlen)
64{
65  int i;
66  uchar checksum = 0x00;
67  for (i = 0; i < cmdlen; i++)
68    checksum ^= cmd[i];
69  return checksum;
70}
71
72
73int 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
74{
75  static uchar startcmd[] = { 0x80, 0xFF, 0x10, 0x01, 0x05 };   //any command starts with this,
76  //last byte is nr of bytes of the command that will be sent
77  //after the startcmd
78//response on startcmd+cmd:     = { 0x61, 0x05 }  //0x61 = "OK", last byte is nr. of bytes card will send
79  static uchar reqans[] = { 0x00, 0xC0, 0x00, 0x00, 0x08 }; //after command answer has to be requested,
80  //last byte must be nr. of bytes that card has reported to send
81  uchar command[256];
82  int headerlen = sizeof (startcmd);
83  startcmd[4] = cmdlen + 3; //commandlength + type + len + checksum bytes
84  memcpy (command, startcmd, headerlen);
85  command[headerlen++] = CMD_BYTE;  //type
86  command[headerlen++] = cmdlen + 1;    //len = command + 1 checksum byte
87  memcpy (command + headerlen, cmd, cmdlen);
88
89  uchar checksum = ~xor (cmd, cmdlen);
90  //cs_debug ("Checksum: %02x", checksum);
91  cmdlen += headerlen;
92  command[cmdlen++] = checksum;
93
94  reader_cmd2icc (command, cmdlen);
95
96  if ((cta_lr != 2) || (cta_res[0] != OK_RESPONSE)) {
97    cs_log ("DRECRYPT ERROR: unexpected answer from card: %s", cs_hexdump (0, cta_res, cta_lr));
98    return 0;           //error
99  }
100
101  reqans[4] = cta_res[1];   //adapt length byte
102  reader_cmd2icc (reqans, 5);
103
104  if (cta_res[0] != CMD_BYTE) {
105    cs_log ("DRECRYPT Unknown response: cta_res[0] expected to be %02x, is %02x", CMD_BYTE, cta_res[0]);
106    return 0;
107  }
108  if ((cta_res[1] == 0x03) && (cta_res[2] == 0xe2)) {
109    switch (cta_res[3]) {
110    case 0xe1:
111      cs_log ("DRECRYPT checksum error: %s.", cs_hexdump (0, cta_res, cta_lr));
112      break;
113    case 0xe2:
114      cs_log ("DRECRYPT wrong provider: %s.", cs_hexdump (0, cta_res, cta_lr));
115      break;
116    case 0xe3:
117      cs_log ("DRECRYPT illegal command: %s.", cs_hexdump (0, cta_res, cta_lr)); 
118      break;
119    case 0xec:
120      cs_log ("DRECRYPT wrong signature: %s.", cs_hexdump (0, cta_res, cta_lr));
121      break;
122    default:
123      cs_debug ("DRECRYPT unknown error: %s.", cs_hexdump (0, cta_res, cta_lr));
124      break;
125    }
126    return 0;           //error
127  }
128  int length_excl_leader = cta_lr;
129  if ((cta_res[cta_lr - 2] == 0x90) && (cta_res[cta_lr - 1] == 0x00))
130    length_excl_leader -= 2;
131
132  checksum = ~xor (cta_res + 2, length_excl_leader - 3);
133
134  if (cta_res[length_excl_leader - 1] != checksum) {
135    cs_log ("DRECRYPT checksum does not match, expected %02x received %02x:%s", checksum,
136        cta_res[length_excl_leader - 1], cs_hexdump (0, cta_res, cta_lr));
137    return 0;           //error
138  }
139  return 1;
140}
141
142int dre_card_init (uchar * atr, int atrsize)
143{
144  static uchar ua[] = { 0x43, 0x15 };   // get serial number (UA)
145  static uchar providers[] = { 0x49, 0x15 };    // get providers
146  int i;
147
148  if ((atr[0] != 0x3b) || (atr[1] != 0x15) || (atr[2] != 0x11) || (atr[3] != 0x12 || atr[4] != 0xca || atr[5] != 0x07))
149    return (0);
150
151  provider = atr[6];
152  uchar checksum = xor (atr + 1, 6);
153
154  if (checksum != atr[7])
155    cs_log ("DRECRYPT Warning: expected ATR checksum %02x, smartcard reports %02x", checksum, atr[7]);
156
157  switch (atr[6]) {
158  case 0x11:
159    card = "Tricolor Centr";
160    reader[ridx].caid[0] = 0x4ae0;
161    mode = 41;
162    break;          //59 type card = MSP (74 type = ATMEL)
163  case 0x12:
164    card = "Cable TV";
165    reader[ridx].caid[0] = 0x4ae0;  //TODO not sure about this one
166    mode = 41;          //TODO not sure
167    break;
168  case 0x14:
169    card = "Tricolor Syberia / Platforma HD new";
170    reader[ridx].caid[0] = 0x4ae1;
171    mode = 51;
172    break;          //59 type card
173  case 0x15:
174    card = "Platforma HD / DW old";
175    reader[ridx].caid[0] = 0x4ae1;
176    mode = 51;
177    break;          //59 type card
178  default:
179    card = "Unknown";
180    reader[ridx].caid[0] = 0x4ae1;
181    mode = 51;
182    break;
183  }
184
185  memset (reader[ridx].prid, 0x00, 8);
186
187  static uchar cmd30[] =
188    { 0x30, 0x81, 0x00, 0x81, 0x82, 0x03, 0x84, 0x05, 0x06, 0x87, 0x08, 0x09, 0x00, 0x81, 0x82, 0x03, 0x84, 0x05,
189    0x00
190  };
191  dre_cmd (cmd30);      //unknown command, generates error on card 0x11 and 0x14
192/*
193response:
19459 03 E2 E3
195FE 48 */
196
197  static uchar cmd54[] = { 0x54, 0x14 };    // geocode
198  cmd54[1] = provider;
199  uchar geocode = 0;
200  if ((dre_cmd (cmd54)))    //error would not be fatal, like on 0x11 cards
201    geocode = cta_res[3];
202
203  providers[1] = provider;
204  if (!(dre_cmd (providers)))
205    return 0;           //fatal error
206  if ((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
207    return 0;
208  uchar provname[128];
209  for (i = 0; ((i < cta_res[2] - 6) && (i < 128)); i++) {
210    provname[i] = cta_res[6 + i];
211    if (provname[i] == 0x00)
212      break;
213  }
214  int major_version = cta_res[3];
215  int minor_version = cta_res[4];
216
217  ua[1] = provider;
218  dre_cmd (ua);         //error would not be fatal
219
220  int hexlength = cta_res[1] - 2;   //discard first and last byte, last byte is always checksum, first is answer code
221
222  reader[ridx].hexserial[0] = 0;
223  reader[ridx].hexserial[1] = 0;
224  memcpy (reader[ridx].hexserial + 2, cta_res + 3, hexlength);
225
226  int low_dre_id = ((cta_res[4] << 16) | (cta_res[5] << 8) | cta_res[6]) - 48608;
227  int dre_chksum = 0;
228  uchar buf[32];
229  sprintf ((char *)buf, "%i%i%08i", provider - 16, major_version + 1, low_dre_id);
230  for (i = 0; i < 32; i++) {
231    if (buf[i] == 0x00)
232      break;
233    dre_chksum += buf[i] - 48;
234  }
235
236  //cs_ri_log("type: DRECrypt, caid: %04X, serial: %llu, card: v%x",
237  cs_log ("type: DRECrypt, caid: %04X, serial: %s, dre id: %i%i%i%08i, geocode %i, card: %s v%i.%i",
238      reader[ridx].caid[0], cs_hexdump (0, reader[ridx].hexserial + 2, 4), dre_chksum, provider - 16,
239      major_version + 1, low_dre_id, geocode, card, major_version, minor_version);
240  cs_log ("Provider name:%s.", provname);
241
242
243  memset (reader[ridx].sa, 0, sizeof (reader[ridx].sa));
244  memcpy (reader[ridx].sa[0], reader[ridx].hexserial + 2, 1);   //copy first byte of unique address also in shared address, because we dont know what it is...
245
246  cs_log ("DEBUG: SA = %02X%02X%02X%02X, UA = %s", reader[ridx].sa[0][0], reader[ridx].sa[0][1], reader[ridx].sa[0][2],
247      reader[ridx].sa[0][3], cs_hexdump (0, reader[ridx].hexserial + 2, 4));
248
249  //reader[ridx].nprov = 1; TODO doesnt seem necessary
250
251  if (!dre_set_provider_info ())
252    return 0;           //fatal error
253
254  cs_log ("ready for requests");
255  return (1);
256}
257
258int dre_do_ecm (ECM_REQUEST * er)
259{
260  if (mode == 41) {
261    static uchar ecmcmd41[] = { 0x41,
262      0x58, 0x1f, 0x00,     //fixed part, dont change
263      0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,   //0x01 - 0x08: next key
264      0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,   //0x11 - 0x18: current key
265      0x3b, 0x59, 0x11      //0x3b = keynumber, can be a value 56 ;; 0x59 number of package = 58+1 - Pay Package ;; 0x11 = provider
266    };
267    ecmcmd41[22] = provider;
268    memcpy (ecmcmd41 + 4, er->ecm + 8, 16);
269    ecmcmd41[20] = er->ecm[6];  //keynumber
270    ecmcmd41[21] = 0x58 + er->ecm[25];  //package number
271    cs_debug ("DEBUG: unused ECM info front:%s", cs_hexdump (0, er->ecm, 8));
272    cs_debug ("DEBUG: unused ECM info back:%s", cs_hexdump (0, er->ecm + 24, er->ecm[2] + 2 - 24));
273    if ((dre_cmd (ecmcmd41))) { //ecm request
274      if ((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
275                return 0;       //exit if response is not 90 00
276      memcpy (er->cw, cta_res + 11, 8);
277      memcpy (er->cw + 8, cta_res + 3, 8);
278
279      return 1;
280    }
281  }
282  else {
283
284    static uchar ecmcmd51[] = { 0x51, 0x02, 0x56, 0x05, 0x00, 0x4A, 0xE3,   //fixed header?
285      0x9C, 0xDA,       //first three nibbles count up, fourth nibble counts down; all ECMs sent twice
286      0xC1, 0x71, 0x21, 0x06, 0xF0, 0x14, 0xA7, 0x0E,   //next key?
287      0x89, 0xDA, 0xC9, 0xD7, 0xFD, 0xB9, 0x06, 0xFD,   //current key?
288      0xD5, 0x1E, 0x2A, 0xA3, 0xB5, 0xA0, 0x82, 0x11,   //key or signature?
289      0x14          //provider
290    };
291    memcpy (ecmcmd51 + 1, er->ecm + 5, 0x21);
292    cs_debug ("DEBUG: unused ECM info front:%s", cs_hexdump (0, er->ecm, 5));
293    cs_debug ("DEBUG: unused ECM info back:%s", cs_hexdump (0, er->ecm + 37, 4));
294    ecmcmd51[33] = provider;    //no part of sig
295    if ((dre_cmd (ecmcmd51))) { //ecm request
296      if ((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
297                return 0;       //exit if response is not 90 00
298      memcpy (er->cw, cta_res + 11, 8);
299      memcpy (er->cw + 8, cta_res + 3, 8);
300      return 1;
301    }
302  }
303  return 0;
304}
305
306int dre_do_emm (EMM_PACKET * ep)
307{
308
309  int emm_length = ((ep->emm[1] & 0x0f) << 8) + ep->emm[2];
310
311  cs_ddump (ep->emm, emm_length + 3, "EMM:");
312  ep->type = ep->emm[0];
313
314  if (mode == 51) {
315    static uchar emmcmd52[0x3a];
316    emmcmd52[0] = 0x52;
317    int i;
318    for (i = 0; i < 2; i++) {
319      memcpy (emmcmd52 + 1, ep->emm + 5 + 32 + i * 56, 56);
320      emmcmd52[0x39] = provider;
321      if ((dre_cmd (emmcmd52)))
322                if ((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
323                return 0;       //exit if response is not 90 00
324        }
325  }
326  else {
327    static uchar emmcmd42[] =
328      { 0x42, 0x85, 0x58, 0x01, 0xC8, 0x00, 0x00, 0x00, 0x05, 0xB8, 0x0C, 0xBD, 0x7B, 0x07, 0x04, 0xC8,
329      0x77, 0x31, 0x95, 0xF2, 0x30, 0xB7, 0xE9, 0xEE, 0x0F, 0x81, 0x39, 0x1C, 0x1F, 0xA9, 0x11, 0x3E,
330      0xE5, 0x0E, 0x8E, 0x50, 0xA4, 0x31, 0xBB, 0x01, 0x00, 0xD6, 0xAF, 0x69, 0x60, 0x04, 0x70, 0x3A,
331      0x91,
332      0x56, 0x58, 0x11
333    };
334        int i;
335        switch (ep->emm[0]) {
336            case 0x87: //unique EMM
337            for (i = 0; i < 2; i++) {
338                    memcpy (emmcmd42 + 1, ep->emm + 42 + i*49, 48);
339                    emmcmd42[49] = ep->emm[i*49 + 41]; //keynr
340                    emmcmd42[50] = 0x58 + ep->emm[40]; //package nr
341                emmcmd42[51] = provider;
342                if ((dre_cmd (emmcmd42))) {
343                  if ((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
344                            return 0;       //exit if response is not 90 00
345                    }
346                }
347                break;
348            case 0x89: //shared EMM
349            default:
350            memcpy (emmcmd42 + 1, ep->emm + 6, 48);
351            emmcmd42[51] = provider;
352            //emmcmd42[50] = ecmcmd42[2]; //TODO package nr could also be fixed 0x58
353            emmcmd42[50] = 0x58;
354            emmcmd42[49] = ep->emm[5];  //keynr
355            /* response:
356               59 05 A2 02 05 01 5B
357               90 00 */
358            if ((dre_cmd (emmcmd42))) { //first emm request
359              if ((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
360                        return 0;       //exit if response is not 90 00
361       
362              memcpy (emmcmd42 + 1, ep->emm + 55, 7);   //TODO OR next two lines?
363              /*memcpy (emmcmd42 + 1, ep->emm + 55, 7);  //FIXME either I cant count or my EMM log contains errors
364                 memcpy (emmcmd42 + 8, ep->emm + 67, 41); */
365              emmcmd42[51] = provider;
366              //emmcmd42[50] = ecmcmd42[2]; //TODO package nr could also be fixed 0x58
367              emmcmd42[50] = 0x58;
368              emmcmd42[49] = ep->emm[54];   //keynr
369              if ((dre_cmd (emmcmd42))) {   //second emm request
370                        if ((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
371                            return 0;       //exit if response is not 90 00
372              }
373            }
374        }
375  }
376  return 1;         //success
377}
378
379int dre_card_info (void)
380{
381  return (1);
382}
Note: See TracBrowser for help on using the repository browser.