source: trunk/reader-dre.c @ 834

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

Fix Unique EMM DreCrypt? cmd42

  • Property svn:eol-style set to native
File size: 12.3 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 0xec:
117      cs_log ("DRECRYPT wrong signature: %s.", cs_hexdump (0, cta_res, cta_lr));
118      break;
119    default:
120      cs_debug ("DRECRYPT unknown error: %s.", cs_hexdump (0, cta_res, cta_lr));
121      break;
122    }
123    return 0;           //error
124  }
125  int length_excl_leader = cta_lr;
126  if ((cta_res[cta_lr - 2] == 0x90) && (cta_res[cta_lr - 1] == 0x00))
127    length_excl_leader -= 2;
128
129  checksum = ~xor (cta_res + 2, length_excl_leader - 3);
130
131  if (cta_res[length_excl_leader - 1] != checksum) {
132    cs_log ("DRECRYPT checksum does not match, expected %02x received %02x:%s", checksum,
133        cta_res[length_excl_leader - 1], cs_hexdump (0, cta_res, cta_lr));
134    return 0;           //error
135  }
136  return 1;
137}
138
139int dre_card_init (uchar * atr, int atrsize)
140{
141  static uchar ua[] = { 0x43, 0x15 };   // get serial number (UA)
142  static uchar providers[] = { 0x49, 0x15 };    // get providers
143  int i;
144
145  if ((atr[0] != 0x3b) || (atr[1] != 0x15) || (atr[2] != 0x11) || (atr[3] != 0x12 || atr[4] != 0xca || atr[5] != 0x07))
146    return (0);
147
148  provider = atr[6];
149  uchar checksum = xor (atr + 1, 6);
150
151  if (checksum != atr[7])
152    cs_log ("DRECRYPT Warning: expected ATR checksum %02x, smartcard reports %02x", checksum, atr[7]);
153
154  switch (atr[6]) {
155  case 0x11:
156    card = "Tricolor Centr";
157    reader[ridx].caid[0] = 0x4ae0;
158    mode = 41;
159    break;          //59 type card = MSP (74 type = ATMEL)
160  case 0x12:
161    card = "Cable TV";
162    reader[ridx].caid[0] = 0x4ae0;  //TODO not sure about this one
163    mode = 41;          //TODO not sure
164    break;
165  case 0x14:
166    card = "Tricolor Syberia / Platforma HD new";
167    reader[ridx].caid[0] = 0x4ae1;
168    mode = 51;
169    break;          //59 type card
170  case 0x15:
171    card = "Platforma HD / DW old";
172    reader[ridx].caid[0] = 0x4ae1;
173    mode = 51;
174    break;          //59 type card
175  default:
176    card = "Unknown";
177    reader[ridx].caid[0] = 0x4ae1;
178    mode = 51;
179    break;
180  }
181
182  memset (reader[ridx].prid, 0x00, 8);
183
184  static uchar cmd30[] =
185    { 0x30, 0x81, 0x00, 0x81, 0x82, 0x03, 0x84, 0x05, 0x06, 0x87, 0x08, 0x09, 0x00, 0x81, 0x82, 0x03, 0x84, 0x05,
186    0x00
187  };
188  dre_cmd (cmd30);      //unknown command, generates error on card 0x11 and 0x14
189/*
190response:
19159 03 E2 E3
192FE 48 */
193
194  static uchar cmd54[] = { 0x54, 0x14 };    // geocode
195  cmd54[1] = provider;
196  uchar geocode = 0;
197  if ((dre_cmd (cmd54)))    //error would not be fatal, like on 0x11 cards
198    geocode = cta_res[3];
199
200  providers[1] = provider;
201  if (!(dre_cmd (providers)))
202    return 0;           //fatal error
203  if ((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
204    return 0;
205  uchar provname[128];
206  for (i = 0; ((i < cta_res[2] - 6) && (i < 128)); i++) {
207    provname[i] = cta_res[6 + i];
208    if (provname[i] == 0x00)
209      break;
210  }
211  int major_version = cta_res[3];
212  int minor_version = cta_res[4];
213
214  ua[1] = provider;
215  dre_cmd (ua);         //error would not be fatal
216
217  int hexlength = cta_res[1] - 2;   //discard first and last byte, last byte is always checksum, first is answer code
218
219  reader[ridx].hexserial[0] = 0;
220  reader[ridx].hexserial[1] = 0;
221  memcpy (reader[ridx].hexserial + 2, cta_res + 3, hexlength);
222
223  int low_dre_id = ((cta_res[4] << 16) | (cta_res[5] << 8) | cta_res[6]) - 48608;
224  int dre_chksum = 0;
225  uchar buf[32];
226  sprintf ((char *)buf, "%i%i%08i", provider - 16, major_version + 1, low_dre_id);
227  for (i = 0; i < 32; i++) {
228    if (buf[i] == 0x00)
229      break;
230    dre_chksum += buf[i] - 48;
231  }
232
233  //cs_ri_log("type: DRECrypt, caid: %04X, serial: %llu, card: v%x",
234  cs_log ("type: DRECrypt, caid: %04X, serial: %s, dre id: %i%i%i%08i, geocode %i, card: %s v%i.%i",
235      reader[ridx].caid[0], cs_hexdump (0, reader[ridx].hexserial + 2, 4), dre_chksum, provider - 16,
236      major_version + 1, low_dre_id, geocode, card, major_version, minor_version);
237  cs_log ("Provider name:%s.", provname);
238
239
240  memset (reader[ridx].sa, 0, sizeof (reader[ridx].sa));
241  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...
242
243  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],
244      reader[ridx].sa[0][3], cs_hexdump (0, reader[ridx].hexserial + 2, 4));
245
246  //reader[ridx].nprov = 1; TODO doesnt seem necessary
247
248  if (!dre_set_provider_info ())
249    return 0;           //fatal error
250
251  cs_log ("ready for requests");
252  return (1);
253}
254
255int dre_do_ecm (ECM_REQUEST * er)
256{
257  if (mode == 41) {
258    static uchar ecmcmd41[] = { 0x41,
259      0x58, 0x1f, 0x00,     //fixed part, dont change
260      0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,   //0x01 - 0x08: next key
261      0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,   //0x11 - 0x18: current key
262      0x3b, 0x59, 0x11      //0x3b = keynumber, can be a value 56 ;; 0x59 number of package = 58+1 - Pay Package ;; 0x11 = provider
263    };
264    ecmcmd41[22] = provider;
265    memcpy (ecmcmd41 + 4, er->ecm + 8, 16);
266    ecmcmd41[20] = er->ecm[6];  //keynumber
267    ecmcmd41[21] = 0x58 + er->ecm[25];  //package number
268    cs_debug ("DEBUG: unused ECM info front:%s", cs_hexdump (0, er->ecm, 8));
269    cs_debug ("DEBUG: unused ECM info back:%s", cs_hexdump (0, er->ecm + 24, er->ecm[2] + 2 - 24));
270    if ((dre_cmd (ecmcmd41))) { //ecm request
271      if ((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
272                return 0;       //exit if response is not 90 00
273      memcpy (er->cw, cta_res + 11, 8);
274      memcpy (er->cw + 8, cta_res + 3, 8);
275
276      return 1;
277    }
278  }
279  else {
280
281    static uchar ecmcmd51[] = { 0x51, 0x02, 0x56, 0x05, 0x00, 0x4A, 0xE3,   //fixed header?
282      0x9C, 0xDA,       //first three nibbles count up, fourth nibble counts down; all ECMs sent twice
283      0xC1, 0x71, 0x21, 0x06, 0xF0, 0x14, 0xA7, 0x0E,   //next key?
284      0x89, 0xDA, 0xC9, 0xD7, 0xFD, 0xB9, 0x06, 0xFD,   //current key?
285      0xD5, 0x1E, 0x2A, 0xA3, 0xB5, 0xA0, 0x82, 0x11,   //key or signature?
286      0x14          //provider
287    };
288    memcpy (ecmcmd51 + 1, er->ecm + 5, 0x21);
289    cs_debug ("DEBUG: unused ECM info front:%s", cs_hexdump (0, er->ecm, 5));
290    cs_debug ("DEBUG: unused ECM info back:%s", cs_hexdump (0, er->ecm + 37, 4));
291    ecmcmd51[33] = provider;    //no part of sig
292    if ((dre_cmd (ecmcmd51))) { //ecm request
293      if ((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
294                return 0;       //exit if response is not 90 00
295      memcpy (er->cw, cta_res + 11, 8);
296      memcpy (er->cw + 8, cta_res + 3, 8);
297      return 1;
298    }
299  }
300  return 0;
301}
302
303int dre_do_emm (EMM_PACKET * ep)
304{
305
306  int emm_length = ((ep->emm[1] & 0x0f) << 8) + ep->emm[2];
307
308  cs_ddump (ep->emm, emm_length + 3, "EMM:");
309  ep->type = ep->emm[0];
310
311  if (mode == 51) {
312    static uchar emmcmd52[0x3a];
313    emmcmd52[0] = 0x52;
314    int i;
315    for (i = 0; i < 2; i++) {
316      memcpy (emmcmd52 + 1, ep->emm + 5 + 32 + i * 56, 56);
317      emmcmd52[0x39] = provider;
318      if ((dre_cmd (emmcmd52)))
319                if ((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
320                return 0;       //exit if response is not 90 00
321        }
322  }
323  else {
324    static uchar emmcmd42[] =
325      { 0x42, 0x85, 0x58, 0x01, 0xC8, 0x00, 0x00, 0x00, 0x05, 0xB8, 0x0C, 0xBD, 0x7B, 0x07, 0x04, 0xC8,
326      0x77, 0x31, 0x95, 0xF2, 0x30, 0xB7, 0xE9, 0xEE, 0x0F, 0x81, 0x39, 0x1C, 0x1F, 0xA9, 0x11, 0x3E,
327      0xE5, 0x0E, 0x8E, 0x50, 0xA4, 0x31, 0xBB, 0x01, 0x00, 0xD6, 0xAF, 0x69, 0x60, 0x04, 0x70, 0x3A,
328      0x91,
329      0x56, 0x58, 0x11
330    };
331        int i;
332        switch (ep->emm[0]) {
333            case 0x87: //unique EMM
334            for (i = 0; i < 2; i++) {
335                    memcpy (emmcmd42 + 1, ep->emm + 42 + i*49, 48);
336                    emmcmd42[49] = ep->emm[i*49 + 41]; //keynr
337                    emmcmd42[50] = 0x58 + ep->emm[40]; //package nr
338                emmcmd42[51] = provider;
339                if ((dre_cmd (emmcmd42))) {
340                  if ((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
341                            return 0;       //exit if response is not 90 00
342                    }
343                }
344                break;
345            case 0x89: //shared EMM
346            default:
347            memcpy (emmcmd42 + 1, ep->emm + 6, 48);
348            emmcmd42[51] = provider;
349            //emmcmd42[50] = ecmcmd42[2]; //TODO package nr could also be fixed 0x58
350            emmcmd42[50] = 0x58;
351            emmcmd42[49] = ep->emm[5];  //keynr
352            /* response:
353               59 05 A2 02 05 01 5B
354               90 00 */
355            if ((dre_cmd (emmcmd42))) { //first emm request
356              if ((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
357                        return 0;       //exit if response is not 90 00
358       
359              memcpy (emmcmd42 + 1, ep->emm + 55, 7);   //TODO OR next two lines?
360              /*memcpy (emmcmd42 + 1, ep->emm + 55, 7);  //FIXME either I cant count or my EMM log contains errors
361                 memcpy (emmcmd42 + 8, ep->emm + 67, 41); */
362              emmcmd42[51] = provider;
363              //emmcmd42[50] = ecmcmd42[2]; //TODO package nr could also be fixed 0x58
364              emmcmd42[50] = 0x58;
365              emmcmd42[49] = ep->emm[54];   //keynr
366              if ((dre_cmd (emmcmd42))) {   //second emm request
367                        if ((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
368                            return 0;       //exit if response is not 90 00
369              }
370            }
371        }
372  }
373  return 1;         //success
374}
375
376int dre_card_info (void)
377{
378  return (1);
379}
Note: See TracBrowser for help on using the repository browser.