source: trunk/reader-dre.c @ 1946

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

Merge from UMP r1973-1979

  • Property svn:eol-style set to native
File size: 13.2 KB
Line 
1#include "globals.h"
2#include "reader-common.h"
3
4static uchar provider;
5static short int mode;
6
7#define OK_RESPONSE 0x61
8#define CMD_BYTE 0x59
9
10static uchar xor (uchar * cmd, int cmdlen)
11{
12  int i;
13  uchar checksum = 0x00;
14  for (i = 0; i < cmdlen; i++)
15    checksum ^= cmd[i];
16  return checksum;
17}
18
19static int dre_command (struct s_reader * reader, uchar * cmd, int cmdlen, unsigned char * cta_res, unsigned short * cta_length)    //attention: inputcommand will be changed!!!! answer will be in cta_res, length cta_lr ; returning 1 = no error, return ERROR = err
20{
21  def_resp2;
22  static uchar startcmd[] = { 0x80, 0xFF, 0x10, 0x01, 0x05 };   //any command starts with this,
23  //last byte is nr of bytes of the command that will be sent
24  //after the startcmd
25//response on startcmd+cmd:     = { 0x61, 0x05 }  //0x61 = "OK", last byte is nr. of bytes card will send
26  static uchar reqans[] = { 0x00, 0xC0, 0x00, 0x00, 0x08 }; //after command answer has to be requested,
27  //last byte must be nr. of bytes that card has reported to send
28  uchar command[256];
29  int headerlen = sizeof (startcmd);
30  startcmd[4] = cmdlen + 3; //commandlength + type + len + checksum bytes
31  memcpy (command, startcmd, headerlen);
32  command[headerlen++] = CMD_BYTE;  //type
33  command[headerlen++] = cmdlen + 1;    //len = command + 1 checksum byte
34  memcpy (command + headerlen, cmd, cmdlen);
35
36  uchar checksum = ~xor (cmd, cmdlen);
37  //cs_debug ("[dre-reader] Checksum: %02x", checksum);
38  cmdlen += headerlen;
39  command[cmdlen++] = checksum;
40
41  reader_cmd2icc (reader, command, cmdlen, cta_res, &cta_lr);
42
43  if ((cta_lr != 2) || (cta_res[0] != OK_RESPONSE)) {
44    cs_log ("[dre-reader] unexpected answer from card: %s", cs_hexdump (0, cta_res, cta_lr));
45    return ERROR;           //error
46  }
47
48  reqans[4] = cta_res[1];   //adapt length byte
49  reader_cmd2icc (reader, reqans, 5, cta_res, &cta_lr);
50
51  if (cta_res[0] != CMD_BYTE) {
52    cs_log ("[dre-reader] unknown response: cta_res[0] expected to be %02x, is %02x", CMD_BYTE, cta_res[0]);
53    return ERROR;
54  }
55  if ((cta_res[1] == 0x03) && (cta_res[2] == 0xe2)) {
56    switch (cta_res[3]) {
57    case 0xe1:
58      cs_log ("[dre-reader] checksum error: %s.", cs_hexdump (0, cta_res, cta_lr));
59      break;
60    case 0xe2:
61      cs_log ("[dre-reader] wrong provider: %s.", cs_hexdump (0, cta_res, cta_lr));
62      break;
63    case 0xe3:
64      cs_log ("[dre-reader] illegal command: %s.", cs_hexdump (0, cta_res, cta_lr)); 
65      break;
66    case 0xec:
67      cs_log ("[dre-reader] wrong signature: %s.", cs_hexdump (0, cta_res, cta_lr));
68      break;
69    default:
70      cs_debug ("[dre-reader] unknown error: %s.", cs_hexdump (0, cta_res, cta_lr));
71      break;
72    }
73    return ERROR;           //error
74  }
75  int length_excl_leader = cta_lr;
76  if ((cta_res[cta_lr - 2] == 0x90) && (cta_res[cta_lr - 1] == 0x00))
77    length_excl_leader -= 2;
78
79  checksum = ~xor (cta_res + 2, length_excl_leader - 3);
80
81  if (cta_res[length_excl_leader - 1] != checksum) {
82    cs_log ("[dre-reader] checksum does not match, expected %02x received %02x:%s", checksum,
83        cta_res[length_excl_leader - 1], cs_hexdump (0, cta_res, cta_lr));
84    return ERROR;           //error
85  }
86  return OK;
87}
88
89#define dre_cmd(cmd) \
90{ \
91    dre_command(reader, cmd, sizeof(cmd),cta_res,&cta_lr); \
92}
93
94static int dre_set_provider_info (struct s_reader * reader)
95{
96  def_resp;
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  def_resp;
142  static uchar ua[] = { 0x43, 0x15 };   // get serial number (UA)
143  static uchar providers[] = { 0x49, 0x15 };    // get providers
144  int i;
145    char *card;
146
147  if ((atr[0] != 0x3b) || (atr[1] != 0x15) || (atr[2] != 0x11) || (atr[3] != 0x12 || atr[4] != 0xca || atr[5] != 0x07))
148    return ERROR;
149
150  provider = atr[6];
151  uchar checksum = xor (atr + 1, 6);
152
153  if (checksum != atr[7])
154    cs_log ("[dre-reader] 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->caid[0] = 0x4ae0;
160    mode = 41;
161    break;          //59 type card = MSP (74 type = ATMEL)
162  case 0x12:
163    card = "Cable TV";
164    reader->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->caid[0] = 0x4ae1;
170    mode = 51;
171    break;          //59 type card
172  case 0x15:
173    card = "Platforma HD / DW old";
174    reader->caid[0] = 0x4ae1;
175    mode = 51;
176    break;          //59 type card
177  default:
178    card = "Unknown";
179    reader->caid[0] = 0x4ae1;
180    mode = 51;
181    break;
182  }
183
184  memset (reader->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 ERROR;           //fatal error
205  if ((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
206    return ERROR;
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->hexserial[0] = 0;
222  reader->hexserial[1] = 0;
223  memcpy (reader->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("[dre-reader] type: DRE Crypt, caid: %04X, serial: %llu, card: v%x",
236  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",
237      reader->caid[0], cs_hexdump (0, reader->hexserial + 2, 4), dre_chksum, provider - 16,
238      major_version + 1, low_dre_id, geocode, card, major_version, minor_version);
239  cs_ri_log (reader, "[dre-reader] Provider name:%s.", provname);
240
241
242  memset (reader->sa, 0, sizeof (reader->sa));
243  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...
244
245  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],
246      reader->sa[0][3], cs_hexdump (0, reader->hexserial + 2, 4));
247
248  reader->nprov = 1;
249
250  if (!dre_set_provider_info (reader))
251    return ERROR;           //fatal error
252
253  cs_log ("[dre-reader] ready for requests");
254  return OK;
255}
256
257int dre_do_ecm (struct s_reader * reader, ECM_REQUEST * er)
258{
259  def_resp;
260  if (mode == 41) {
261    static uchar ecmcmd41[] = { 0x41,
262      0x58, 0x1f, 0x00,     //fixed part, dont change
263      0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,   //0x01 - 0x08: next key
264      0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,   //0x11 - 0x18: current key
265      0x3b, 0x59, 0x11      //0x3b = keynumber, can be a value 56 ;; 0x59 number of package = 58+1 - Pay Package ;; 0x11 = provider
266    };
267    ecmcmd41[22] = provider;
268    memcpy (ecmcmd41 + 4, er->ecm + 8, 16);
269    ecmcmd41[20] = er->ecm[6];  //keynumber
270    ecmcmd41[21] = 0x58 + er->ecm[25];  //package number
271    cs_debug ("[dre-reader] unused ECM info front:%s", cs_hexdump (0, er->ecm, 8));
272    cs_debug ("[dre-reader] unused ECM info back:%s", cs_hexdump (0, er->ecm + 24, er->ecm[2] + 2 - 24));
273    if ((dre_cmd (ecmcmd41))) { //ecm request
274      if ((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
275                return ERROR;       //exit if response is not 90 00
276      memcpy (er->cw, cta_res + 11, 8);
277      memcpy (er->cw + 8, cta_res + 3, 8);
278
279      return OK;
280    }
281  }
282  else {
283
284    static uchar ecmcmd51[] = { 0x51, 0x02, 0x56, 0x05, 0x00, 0x4A, 0xE3,   //fixed header?
285      0x9C, 0xDA,       //first three nibbles count up, fourth nibble counts down; all ECMs sent twice
286      0xC1, 0x71, 0x21, 0x06, 0xF0, 0x14, 0xA7, 0x0E,   //next key?
287      0x89, 0xDA, 0xC9, 0xD7, 0xFD, 0xB9, 0x06, 0xFD,   //current key?
288      0xD5, 0x1E, 0x2A, 0xA3, 0xB5, 0xA0, 0x82, 0x11,   //key or signature?
289      0x14          //provider
290    };
291    memcpy (ecmcmd51 + 1, er->ecm + 5, 0x21);
292    cs_debug ("[dre-reader] unused ECM info front:%s", cs_hexdump (0, er->ecm, 5));
293    cs_debug ("[dre-reader] unused ECM info back:%s", cs_hexdump (0, er->ecm + 37, 4));
294    ecmcmd51[33] = provider;    //no part of sig
295    if ((dre_cmd (ecmcmd51))) { //ecm request
296      if ((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
297                return ERROR;       //exit if response is not 90 00
298      memcpy (er->cw, cta_res + 11, 8);
299      memcpy (er->cw + 8, cta_res + 3, 8);
300      return OK;
301    }
302  }
303  return ERROR;
304}
305
306int dre_get_emm_type(EMM_PACKET *ep, struct s_reader * rdr)
307{
308  rdr=rdr;
309  switch (ep->emm[0]) {
310        case 0x87:
311            ep->type = UNIQUE; //FIXME no filling of ep->hexserial
312            break;
313        case 0x89:
314            ep->type = SHARED; //FIXME no filling of ep->hexserial
315            break;
316        default:
317            ep->type = UNKNOWN;
318    }
319    return TRUE; //FIXME no checking of serial or SA
320}
321   
322
323int dre_do_emm (struct s_reader * reader, EMM_PACKET * ep)
324{
325  def_resp;
326  int emm_length = ((ep->emm[1] & 0x0f) << 8) + ep->emm[2];
327
328  cs_ddump (ep->emm, emm_length + 3, "EMM:");
329  ep->type = ep->emm[0];
330
331  if (mode == 51) {
332    static uchar emmcmd52[0x3a];
333    emmcmd52[0] = 0x52;
334    int i;
335    for (i = 0; i < 2; i++) {
336      memcpy (emmcmd52 + 1, ep->emm + 5 + 32 + i * 56, 56);
337      // check for shared address
338      if(ep->emm[3]!=reader->sa[0][0]) 
339        return OK; // ignore, wrong address
340      emmcmd52[0x39] = provider;
341      if ((dre_cmd (emmcmd52)))
342                if ((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
343                return ERROR;       //exit if response is not 90 00
344        }
345  }
346  else {
347    static uchar emmcmd42[] =
348      { 0x42, 0x85, 0x58, 0x01, 0xC8, 0x00, 0x00, 0x00, 0x05, 0xB8, 0x0C, 0xBD, 0x7B, 0x07, 0x04, 0xC8,
349      0x77, 0x31, 0x95, 0xF2, 0x30, 0xB7, 0xE9, 0xEE, 0x0F, 0x81, 0x39, 0x1C, 0x1F, 0xA9, 0x11, 0x3E,
350      0xE5, 0x0E, 0x8E, 0x50, 0xA4, 0x31, 0xBB, 0x01, 0x00, 0xD6, 0xAF, 0x69, 0x60, 0x04, 0x70, 0x3A,
351      0x91,
352      0x56, 0x58, 0x11
353    };
354        int i;
355        switch (ep->type) {
356            case UNIQUE: 
357            for (i = 0; i < 2; i++) {
358                    memcpy (emmcmd42 + 1, ep->emm + 42 + i*49, 48);
359                    emmcmd42[49] = ep->emm[i*49 + 41]; //keynr
360                    emmcmd42[50] = 0x58 + ep->emm[40]; //package nr
361                emmcmd42[51] = provider;
362                if ((dre_cmd (emmcmd42))) {
363                  if ((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
364                            return ERROR;       //exit if response is not 90 00
365                    }
366                }
367                break;
368            case SHARED:
369            default:
370            memcpy (emmcmd42 + 1, ep->emm + 6, 48);
371            emmcmd42[51] = provider;
372            //emmcmd42[50] = ecmcmd42[2]; //TODO package nr could also be fixed 0x58
373            emmcmd42[50] = 0x58;
374            emmcmd42[49] = ep->emm[5];  //keynr
375            /* response:
376               59 05 A2 02 05 01 5B
377               90 00 */
378            if ((dre_cmd (emmcmd42))) { //first emm request
379              if ((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
380                        return ERROR;       //exit if response is not 90 00
381       
382              memcpy (emmcmd42 + 1, ep->emm + 55, 7);   //TODO OR next two lines?
383              /*memcpy (emmcmd42 + 1, ep->emm + 55, 7);  //FIXME either I cant count or my EMM log contains errors
384                 memcpy (emmcmd42 + 8, ep->emm + 67, 41); */
385              emmcmd42[51] = provider;
386              //emmcmd42[50] = ecmcmd42[2]; //TODO package nr could also be fixed 0x58
387              emmcmd42[50] = 0x58;
388              emmcmd42[49] = ep->emm[54];   //keynr
389              if ((dre_cmd (emmcmd42))) {   //second emm request
390                        if ((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
391                            return ERROR;       //exit if response is not 90 00
392              }
393            }
394        }
395  }
396  return OK;            //success
397}
398
399int dre_card_info (void)
400{
401  return OK;
402}
Note: See TracBrowser for help on using the repository browser.