source: trunk/reader-dre.c @ 1635

Last change on this file since 1635 was 1635, checked in by landlord, 10 years ago

Fill init_history with useful entitlement info for dre, seca and videoguard2 card reader

  • Property svn:eol-style set to native
File size: 12.8 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 (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 (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 (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(cmd, sizeof(cmd)); \
93}
94
95static int dre_set_provider_info (void)
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 ("[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 ("[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 (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[ridx].caid[0] = 0x4ae0;
159    mode = 41;
160    break;          //59 type card = MSP (74 type = ATMEL)
161  case 0x12:
162    card = "Cable TV";
163    reader[ridx].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[ridx].caid[0] = 0x4ae1;
169    mode = 51;
170    break;          //59 type card
171  case 0x15:
172    card = "Platforma HD / DW old";
173    reader[ridx].caid[0] = 0x4ae1;
174    mode = 51;
175    break;          //59 type card
176  default:
177    card = "Unknown";
178    reader[ridx].caid[0] = 0x4ae1;
179    mode = 51;
180    break;
181  }
182
183  memset (reader[ridx].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[ridx].hexserial[0] = 0;
221  reader[ridx].hexserial[1] = 0;
222  memcpy (reader[ridx].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 ("[dre-reader] type: DRE Crypt, caid: %04X, serial: %s, dre id: %i%i%i%08i, geocode %i, card: %s v%i.%i",
236      reader[ridx].caid[0], cs_hexdump (0, reader[ridx].hexserial + 2, 4), dre_chksum, provider - 16,
237      major_version + 1, low_dre_id, geocode, card, major_version, minor_version);
238  cs_ri_log ("[dre-reader] Provider name:%s.", provname);
239
240
241  memset (reader[ridx].sa, 0, sizeof (reader[ridx].sa));
242  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...
243
244  cs_ri_log ("[dre-reader] SA = %02X%02X%02X%02X, UA = %s", reader[ridx].sa[0][0], reader[ridx].sa[0][1], reader[ridx].sa[0][2],
245      reader[ridx].sa[0][3], cs_hexdump (0, reader[ridx].hexserial + 2, 4));
246
247  //reader[ridx].nprov = 1; TODO doesnt seem necessary
248
249  if (!dre_set_provider_info ())
250    return ERROR;           //fatal error
251
252  cs_log ("[dre-reader] ready for requests");
253  return OK;
254}
255
256int dre_do_ecm (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_do_emm (EMM_PACKET * ep)
305{
306
307  int emm_length = ((ep->emm[1] & 0x0f) << 8) + ep->emm[2];
308
309  cs_ddump (ep->emm, emm_length + 3, "EMM:");
310  ep->type = ep->emm[0];
311
312  if (mode == 51) {
313    static uchar emmcmd52[0x3a];
314    emmcmd52[0] = 0x52;
315    int i;
316    for (i = 0; i < 2; i++) {
317      memcpy (emmcmd52 + 1, ep->emm + 5 + 32 + i * 56, 56);
318      // check for shared address
319      if(ep->emm[3]!=reader[ridx].sa[0][0]) 
320        return OK; // ignore, wrong address
321      emmcmd52[0x39] = provider;
322      if ((dre_cmd (emmcmd52)))
323                if ((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
324                return ERROR;       //exit if response is not 90 00
325        }
326  }
327  else {
328    static uchar emmcmd42[] =
329      { 0x42, 0x85, 0x58, 0x01, 0xC8, 0x00, 0x00, 0x00, 0x05, 0xB8, 0x0C, 0xBD, 0x7B, 0x07, 0x04, 0xC8,
330      0x77, 0x31, 0x95, 0xF2, 0x30, 0xB7, 0xE9, 0xEE, 0x0F, 0x81, 0x39, 0x1C, 0x1F, 0xA9, 0x11, 0x3E,
331      0xE5, 0x0E, 0x8E, 0x50, 0xA4, 0x31, 0xBB, 0x01, 0x00, 0xD6, 0xAF, 0x69, 0x60, 0x04, 0x70, 0x3A,
332      0x91,
333      0x56, 0x58, 0x11
334    };
335        int i;
336        switch (ep->emm[0]) {
337            case 0x87: //unique EMM
338            for (i = 0; i < 2; i++) {
339                    memcpy (emmcmd42 + 1, ep->emm + 42 + i*49, 48);
340                    emmcmd42[49] = ep->emm[i*49 + 41]; //keynr
341                    emmcmd42[50] = 0x58 + ep->emm[40]; //package nr
342                emmcmd42[51] = provider;
343                if ((dre_cmd (emmcmd42))) {
344                  if ((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
345                            return ERROR;       //exit if response is not 90 00
346                    }
347                }
348                break;
349            case 0x89: //shared EMM
350            default:
351            memcpy (emmcmd42 + 1, ep->emm + 6, 48);
352            emmcmd42[51] = provider;
353            //emmcmd42[50] = ecmcmd42[2]; //TODO package nr could also be fixed 0x58
354            emmcmd42[50] = 0x58;
355            emmcmd42[49] = ep->emm[5];  //keynr
356            /* response:
357               59 05 A2 02 05 01 5B
358               90 00 */
359            if ((dre_cmd (emmcmd42))) { //first emm request
360              if ((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
361                        return ERROR;       //exit if response is not 90 00
362       
363              memcpy (emmcmd42 + 1, ep->emm + 55, 7);   //TODO OR next two lines?
364              /*memcpy (emmcmd42 + 1, ep->emm + 55, 7);  //FIXME either I cant count or my EMM log contains errors
365                 memcpy (emmcmd42 + 8, ep->emm + 67, 41); */
366              emmcmd42[51] = provider;
367              //emmcmd42[50] = ecmcmd42[2]; //TODO package nr could also be fixed 0x58
368              emmcmd42[50] = 0x58;
369              emmcmd42[49] = ep->emm[54];   //keynr
370              if ((dre_cmd (emmcmd42))) {   //second emm request
371                        if ((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
372                            return ERROR;       //exit if response is not 90 00
373              }
374            }
375        }
376  }
377  return OK;            //success
378}
379
380int dre_card_info (void)
381{
382  return OK;
383}
Note: See TracBrowser for help on using the repository browser.