source: trunk/reader-dre.c@ 3181

Last change on this file since 3181 was 3181, checked in by dingo35, 10 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.