source: trunk/reader-dre.c @ 1948

Last change on this file since 1948 was 1948, checked in by merek, 10 years ago

Revert last UMP changes as this causes signal 11 and is not realy stable

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