source: trunk/reader-dre.c @ 2050

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

DRE SA filter only for caid 0x4ae1 - part 2

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