source: trunk/reader-dre.c@ 4149

Last change on this file since 4149 was 4141, checked in by dingo35, 13 years ago

all: simplify debug system, add D_DVBAPI = -d128, eliminate cs_ptyp which complicates stuff unnecc

  • Property svn:eol-style set to native
File size: 14.8 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 (const 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, 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
17{
18 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 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_mask(D_READER, "[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_mask(D_READER, "[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 uchar cmd59[] = { 0x59, 0x14 }; // subscriptions
95 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_mask(D_READER, "[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
134static int dre_card_init (struct s_reader * reader, ATR newatr)
135{
136 get_atr;
137 def_resp;
138 uchar ua[] = { 0x43, 0x15 }; // get serial number (UA)
139 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] = 0x4ae1;
156 break; //59 type card = MSP (74 type = ATMEL)
157 case 0x12:
158 card = "Cable TV";
159 reader->caid[0] = 0x4ae1; //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 const 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 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
248static int dre_do_ecm (struct s_reader * reader, ECM_REQUEST * er)
249{
250 def_resp;
251 if (reader->caid[0] == 0x4ae0) {
252 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_mask(D_READER, "[dre-reader] unused ECM info front:%s", cs_hexdump (0, er->ecm, 8));
263 cs_debug_mask(D_READER, "[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 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_mask(D_READER, "[dre-reader] unused ECM info front:%s", cs_hexdump (0, er->ecm, 5));
284 cs_debug_mask(D_READER, "[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
297static int dre_get_emm_type(EMM_PACKET *ep, struct s_reader * rdr)
298{
299 switch (ep->emm[0]) {
300 case 0x87:
301 ep->type = UNIQUE;
302 return TRUE; //FIXME: no filling of ep->hexserial
303
304 case 0x89:
305 ep->type = SHARED;
306 // FIXME: Seems to be that SA is only used with caid 0x4ae1
307 if (rdr->caid[0] == 0x4ae1) {
308 memset(ep->hexserial, 0, 8);
309 memcpy(ep->hexserial, ep->emm + 3, 4);
310 return (!memcmp(&rdr->sa[0][0], ep->emm + 3, 4));
311 }
312 else
313 return TRUE;
314 default:
315 ep->type = UNKNOWN;
316 return TRUE;
317 }
318}
319
320void dre_get_emm_filter(struct s_reader * rdr, uchar *filter)
321{
322 filter[0]=0xFF;
323 filter[1]=3;
324
325 filter[2]=GLOBAL;
326 filter[3]=1; //not active
327
328 //FIXME: Dont now how to filter GLOBAL EMM's
329 filter[4+0] = 0xFF; //dummy
330 filter[4+0+16] = 0xFF;
331
332
333 filter[36]=SHARED;
334 filter[37]=0;
335
336 filter[38+0] = 0x89;
337 filter[38+0+16] = 0xFF;
338 // FIXME: Seems to be that SA is only used with caid 0x4ae1
339 if (rdr->caid[0] == 0x4ae1) {
340 memcpy(filter+38+1, &rdr->sa[0][0], 4);
341 memset(filter+38+1+16, 0xFF, 4);
342 }
343
344
345 //FIXME: No filter for hexserial
346 filter[70]=UNIQUE;
347 filter[71]=0;
348
349 filter[72+0] = 0x87;
350 filter[72+0+16] = 0xFF;
351
352 return;
353}
354
355static int dre_do_emm (struct s_reader * reader, EMM_PACKET * ep)
356{
357 def_resp;
358
359 cs_ddump_mask(D_READER, ep->emm, ((ep->emm[1] & 0x0f) << 8) + ep->emm[2] + 3, "EMM:");
360
361 if (reader->caid[0] == 0x4ae1) {
362 if(ep->type == UNIQUE && ep->emm[39] == 0x3d)
363 { /* For new package activation. */
364 uchar emmcmd58[26];
365 emmcmd58[0] = 0x58;
366 memcpy(&emmcmd58[1], &ep->emm[40], 24);
367 emmcmd58[25] = 0x15;
368 if ((dre_cmd (emmcmd58)))
369 if ((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
370 return ERROR;
371 }
372 else
373 {
374 uchar emmcmd52[0x3a];
375 emmcmd52[0] = 0x52;
376 int i;
377 for (i = 0; i < 2; i++) {
378 memcpy (emmcmd52 + 1, ep->emm + 5 + 32 + i * 56, 56);
379 // check for shared address
380 if(ep->emm[3]!=reader->sa[0][0])
381 return OK; // ignore, wrong address
382 emmcmd52[0x39] = reader->provider;
383 if ((dre_cmd (emmcmd52)))
384 if ((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
385 return ERROR; //exit if response is not 90 00
386 }
387 }
388 }
389 else {
390 uchar emmcmd42[] =
391 { 0x42, 0x85, 0x58, 0x01, 0xC8, 0x00, 0x00, 0x00, 0x05, 0xB8, 0x0C, 0xBD, 0x7B, 0x07, 0x04, 0xC8,
392 0x77, 0x31, 0x95, 0xF2, 0x30, 0xB7, 0xE9, 0xEE, 0x0F, 0x81, 0x39, 0x1C, 0x1F, 0xA9, 0x11, 0x3E,
393 0xE5, 0x0E, 0x8E, 0x50, 0xA4, 0x31, 0xBB, 0x01, 0x00, 0xD6, 0xAF, 0x69, 0x60, 0x04, 0x70, 0x3A,
394 0x91,
395 0x56, 0x58, 0x11
396 };
397 int i;
398 switch (ep->type) {
399 case UNIQUE:
400 for (i = 0; i < 2; i++) {
401 memcpy (emmcmd42 + 1, ep->emm + 42 + i*49, 48);
402 emmcmd42[49] = ep->emm[i*49 + 41]; //keynr
403 emmcmd42[50] = 0x58 + ep->emm[40]; //package nr
404 emmcmd42[51] = reader->provider;
405 if ((dre_cmd (emmcmd42))) {
406 if ((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
407 return ERROR; //exit if response is not 90 00
408 }
409 }
410 break;
411 case SHARED:
412 default:
413 memcpy (emmcmd42 + 1, ep->emm + 6, 48);
414 emmcmd42[51] = reader->provider;
415 //emmcmd42[50] = ecmcmd42[2]; //TODO package nr could also be fixed 0x58
416 emmcmd42[50] = 0x58;
417 emmcmd42[49] = ep->emm[5]; //keynr
418 /* response:
419 59 05 A2 02 05 01 5B
420 90 00 */
421 if ((dre_cmd (emmcmd42))) { //first emm request
422 if ((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
423 return ERROR; //exit if response is not 90 00
424
425 memcpy (emmcmd42 + 1, ep->emm + 55, 7); //TODO OR next two lines?
426 /*memcpy (emmcmd42 + 1, ep->emm + 55, 7); //FIXME either I cant count or my EMM log contains errors
427 memcpy (emmcmd42 + 8, ep->emm + 67, 41); */
428 emmcmd42[51] = reader->provider;
429 //emmcmd42[50] = ecmcmd42[2]; //TODO package nr could also be fixed 0x58
430 emmcmd42[50] = 0x58;
431 emmcmd42[49] = ep->emm[54]; //keynr
432 if ((dre_cmd (emmcmd42))) { //second emm request
433 if ((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
434 return ERROR; //exit if response is not 90 00
435 }
436 }
437 }
438 }
439 return OK; //success
440}
441
442static int dre_card_info (void)
443{
444 return OK;
445}
446
447void reader_dre(struct s_cardsystem *ph)
448{
449 ph->do_emm=dre_do_emm;
450 ph->do_ecm=dre_do_ecm;
451 ph->card_info=dre_card_info;
452 ph->card_init=dre_card_init;
453 ph->get_emm_type=dre_get_emm_type;
454 ph->get_emm_filter=dre_get_emm_filter;
455 ph->caids[0]=0x4A;
456 ph->desc="dre";
457}
Note: See TracBrowser for help on using the repository browser.