source: trunk/reader-dre.c @ 1125

Last change on this file since 1125 was 1125, checked in by C.H.A.D.o, 10 years ago

Remove unused parameters

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