source: trunk/reader-dre.c @ 3181

Last change on this file since 3181 was 3181, checked in by dingo35, 9 years ago

Adding threadsafety FIXMEs, feel free to join checking..

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