source: trunk/reader-dre.c

Last change on this file was 11478, checked in by Gorgone Impertinence, 18 months ago

big cleanup pack 4

  • Property svn:eol-style set to LF
File size: 32.4 KB
Line 
1#include "globals.h"
2#ifdef READER_DRE
3#include "cscrypt/des.h"
4#include "reader-common.h"
5#include "reader-dre-common.h"
6
7struct dre_data
8{
9 uint8_t provider;
10};
11
12#define OK_RESPONSE 0x61
13#define CMD_BYTE 0x59
14
15static uint8_t xor(const uint8_t *cmd, int32_t cmdlen)
16{
17 int32_t i;
18 uint8_t checksum = 0x00;
19 for(i = 0; i < cmdlen; i++)
20 { checksum ^= cmd[i]; }
21 return checksum;
22}
23
24static int8_t isValidDCW(uint8_t *dw)
25{
26 if (((dw[0] + dw[1] + dw[2]) & 0xFF) != dw[3])
27 {
28 return 0;
29 }
30 if (((dw[4] + dw[5] + dw[6]) & 0xFF) != dw[7])
31 {
32 return 0;
33 }
34 if (((dw[8] + dw[9] + dw[10]) & 0xFF) != dw[11])
35 {
36 return 0;
37 }
38 if (((dw[12] + dw[13] + dw[14]) & 0xFF) != dw[15])
39 {
40 return 0;
41 }
42 return 1;
43}
44
45static int32_t dre_command(struct s_reader *reader, const uint8_t *cmd, int32_t cmdlen, uint8_t *cta_res,
46 uint16_t *p_cta_lr, uint8_t crypted, uint8_t keynum, uint8_t dre_v, uint8_t cmd_type)
47{
48 // attention: inputcommand will be changed!!!!
49 //answer will be in cta_res, length cta_lr ; returning 1 = no error, return ERROR = err
50
51 uint8_t startcmd[] = { 0x80, 0xFF, 0x10, 0x01, 0x05 }; // any command starts with this,
52 // last byte is nr of bytes of the command that will be sent
53 // after the startcmd
54 // response on startcmd+cmd: = { 0x61, 0x05 } // 0x61 = "OK", last byte is nr. of bytes card will send
55 uint8_t reqans[] = { 0x00, 0xC0, 0x00, 0x00, 0x08 }; // after command answer has to be requested,
56 // last byte must be nr. of bytes that card has reported to send
57 uint8_t command[256];
58 uint8_t checksum;
59 char tmp[256];
60 int32_t headerlen = sizeof(startcmd);
61
62 if(dre_v > 0)
63 {
64 startcmd[1] = 0;
65 startcmd[2] = crypted;
66 startcmd[3] = keynum;
67 }
68
69 startcmd[4] = cmdlen + 3 - cmd_type; // commandlength + type + len + checksum bytes
70 memcpy(command, startcmd, headerlen);
71 command[headerlen++] = cmd_type ? 0x86 : CMD_BYTE; // type
72 command[headerlen++] = cmdlen + (cmd_type == 1 ? 0 : 1); // len = command + 1 checksum byte
73 memcpy(command + headerlen, cmd, cmdlen);
74
75 if(!cmd_type)
76 {
77 checksum = ~xor(cmd, cmdlen);
78 //rdr_log_dbg(reader, D_READER, "Checksum: %02x", checksum);
79 cmdlen += headerlen;
80 command[cmdlen++] = checksum;
81 }
82 else cmdlen += headerlen;
83
84 reader_cmd2icc(reader, command, cmdlen, cta_res, p_cta_lr);
85
86 if((*p_cta_lr != 2) || (cta_res[0] != OK_RESPONSE))
87 {
88 rdr_log(reader, "command sent to card: %s", cs_hexdump(0, command, cmdlen, tmp, sizeof(tmp)));
89 rdr_log(reader, "unexpected answer from card: %s", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
90 return ERROR; // error
91 }
92
93 rdr_log_dbg(reader, D_READER, "command sent to card: %s", cs_hexdump(0, command, cmdlen, tmp, sizeof(tmp)));
94 rdr_log_dbg(reader, D_READER, "answer from card: %s", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
95
96 reqans[4] = cta_res[1]; // adapt length byte
97 reader_cmd2icc(reader, reqans, 5, cta_res, p_cta_lr);
98
99 if(cta_res[0] != CMD_BYTE)
100 {
101 rdr_log(reader, "unknown response: cta_res[0] expected to be %02x, is %02x", CMD_BYTE, cta_res[0]);
102 return ERROR;
103 }
104
105 if((cta_res[1] == 0x03) && (cta_res[2] == 0xe2))
106 {
107 switch(cta_res[3 + dre_v])
108 {
109 case 0xe1:
110 rdr_log(reader, "checksum error: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
111 break;
112
113 case 0xe2:
114 rdr_log(reader, "wrong cmd len: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
115 break;
116
117 case 0xe3:
118 rdr_log(reader, "illegal command: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
119 break;
120
121 case 0xe4:
122 rdr_log(reader, "wrong adress type: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
123 break;
124
125 case 0xe5:
126 rdr_log(reader, "wrong CMD param: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
127 break;
128
129 case 0xe6:
130 rdr_log(reader, "wrong UA: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
131 break;
132
133 case 0xe7:
134 rdr_log(reader, "wrong group: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
135 break;
136
137 case 0xe8:
138 rdr_log(reader, "wrong key num: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
139 break;
140
141 case 0xeb:
142 rdr_log(reader, "No key or subscribe: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
143 break;
144
145 case 0xec:
146 rdr_log(reader, "wrong signature: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
147 break;
148
149 case 0xed:
150 rdr_log(reader, "wrong provider: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
151 break;
152
153 case 0xef:
154 rdr_log(reader, "wrong GEO code: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
155 break;
156
157 default:
158 rdr_log_dbg(reader, D_READER, "unknown error: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
159 break;
160 }
161 return ERROR; // error
162 }
163
164 int32_t length_excl_leader = *p_cta_lr;
165
166 if((cta_res[*p_cta_lr - 2] == 0x90) && (cta_res[*p_cta_lr - 1] == 0x00))
167 { length_excl_leader -= 2; }
168
169 checksum = ~xor(cta_res + 2, length_excl_leader - 3);
170
171 if(cta_res[length_excl_leader - 1] != checksum)
172 {
173 rdr_log(reader, "checksum does not match, expected %02x received %02x:%s", checksum,
174 cta_res[length_excl_leader - 1], cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
175 return ERROR; // error
176 }
177 return OK;
178}
179
180#define dre_script(cmd, len, cmd_type, crypted, keynum) \
181 { \
182 dre_command(reader, cmd, len, cta_res, &cta_lr, crypted, keynum, crypted, cmd_type); \
183 }
184
185#define dre_cmd(cmd) \
186 { \
187 dre_command(reader, cmd, sizeof(cmd), cta_res, &cta_lr, 0, 0, 0, 0); \
188 }
189
190#define dre_cmd_c(cmd,crypted,keynum) \
191 { \
192 dre_command(reader, cmd, sizeof(cmd),cta_res,&cta_lr, crypted, keynum, 1, 0); \
193 }
194
195static int32_t dre_set_provider_info(struct s_reader *reader)
196{
197 def_resp;
198 int32_t i;
199 int subscr_cmd_len = 4;
200 uint8_t subscr[4]; // = { 0x59, 0x14 }; // subscriptions
201 uint8_t dates[] = { 0x5b, 0x00, 0x14 }; // validity dates
202 uint8_t subscr_len = 0, n = 0;
203 struct dre_data *csystem_data = reader->csystem_data;
204
205 cs_clear_entitlement(reader);
206
207 switch(csystem_data->provider)
208 {
209 case 0x02:
210 case 0x03:
211 subscr[0] = 0x84;
212 subscr[1] = 0;
213 subscr[2] = 0x5F;
214 subscr[3] = csystem_data->provider;
215 dates[0] = 0x85;
216 subscr_len = 0x5F;
217 break;
218
219 case 0x18:
220 case 0x19:
221 case 0x1A:
222 subscr[0] = 0x94;
223 subscr[1] = 0;
224 subscr[2] = 0x5F;
225 subscr[3] = csystem_data->provider;
226 dates[0] = 0x95;
227 subscr_len = 0x5F;
228 break;
229
230 default:
231 subscr[0] = 0x59;
232 subscr[1] = csystem_data->provider;
233 subscr_len = 0x20;
234 subscr_cmd_len = 2;
235 }
236
237chk_subscr:
238
239 if((dre_script(subscr, subscr_cmd_len, 0, 0, 0))) // ask subscription packages, returns error on 0x11 card
240 {
241 uint8_t pbm[subscr_len];
242 char tmp_dbg[subscr_len*2+1];
243 memcpy(pbm, cta_res + 3, cta_lr - 6);
244 rdr_log_dbg(reader, D_READER, "pbm: %s", cs_hexdump(0, pbm, subscr_len, tmp_dbg, sizeof(tmp_dbg)));
245
246 for(i = 0; i < subscr_len; i++)
247 {
248 if(pbm[i] != 0xff)
249 {
250 dates[1] = i;
251 dates[2] = csystem_data->provider;
252 dre_cmd(dates); // ask for validity dates
253
254 time_t start;
255 time_t end;
256 start = (cta_res[3] << 24) | (cta_res[4] << 16) | (cta_res[5] << 8) | cta_res[6];
257 end = (cta_res[7] << 24) | (cta_res[8] << 16) | (cta_res[9] << 8) | cta_res[10];
258
259 struct tm temp;
260
261 localtime_r(&start, &temp);
262 int32_t startyear = temp.tm_year + 1900;
263 int32_t startmonth = temp.tm_mon + 1;
264 int32_t startday = temp.tm_mday;
265 localtime_r(&end, &temp);
266 int32_t endyear = temp.tm_year + 1900;
267 int32_t endmonth = temp.tm_mon + 1;
268 int32_t endday = temp.tm_mday;
269 rdr_log(reader, "active package %i valid from %04i/%02i/%02i to %04i/%02i/%02i",
270 i + n, startyear, startmonth, startday, endyear, endmonth, endday);
271 cs_add_entitlement(reader, reader->caid, b2ll(4, reader->prid[0]), 0, i + n, start, end, 5, 1);
272 }
273 }
274 }
275
276 if(subscr_len == 0x5F) // read second part subscription packages, for DRE3 and DRE4
277 {
278 subscr[1] = 0x5F;
279 subscr[2] = 0x21;
280 subscr_len = 0x21;
281 n = 0x5F;
282 goto chk_subscr;
283 }
284
285 return OK;
286}
287
288static void dre_read_ee(struct s_reader *reader, const char *path, uint8_t provid)
289{
290 def_resp;
291 int i, n;
292 uint8_t *ee = malloc(2048);
293 if(ee == NULL) return;
294
295 uint8_t drecmd43[] = { 0x80, 0x00, 0x00, 0x00, 0x05, 0x59, 0x03, 0x43, 0x11, 0xAD };
296 uint8_t drecmd45[] = { 0x45, 0x11 };
297
298 drecmd43[8] = drecmd45[1] = provid;
299 drecmd43[9] = ~xor(&drecmd43[7], 2);
300
301 for(i = 0; i < 8; i++)
302 {
303 for(n = 0; n < 8; n++)
304 {
305 reader_cmd2icc(reader, drecmd43, 10, cta_res, &cta_lr);
306
307 dre_cmd_c(drecmd45, n, i * 32);
308
309 if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
310 {
311 free(ee);
312 rdr_log(reader, "ERROR read ee.bin from card");
313 return;
314 }
315
316 memcpy(&ee[((n * 8) + i) * 32] ,&cta_res[2] ,32);
317
318 }
319 }
320
321 FILE *pFile = fopen(path, "wb");
322
323 if(pFile == NULL)
324 {
325 free(ee);
326 return ;
327 }
328
329 fwrite(ee, 2048, 1, pFile);
330 fclose(pFile);
331 free(ee);
332 rdr_log(reader, "ee.bin saved to %s", path);
333}
334/*
335static void cmd_test(struct s_reader *reader)
336{
337 def_resp;
338 int i;
339 uint8_t drecmd[] = { 0x00, 0x02 };
340 char tmp[64];
341
342 for(i = 0; i <= 0xFF; i++)
343 {
344 if(i == 0x45) continue;
345 drecmd[0] = i;
346 dre_cmd(drecmd);
347 if(cta_res[2] == 0xE2)
348 {
349 if(cta_res[3] != 0xE3) rdr_log(reader, "cmd %02X error %02X",i ,cta_res[3]);
350 }
351 else
352 {
353 rdr_log(reader, "cmd %02X answer %s",i ,cs_hexdump(0, cta_res, cta_res[1]+2, tmp, sizeof(tmp)));
354 }
355 }
356
357 uint8_t drecmd[64];
358
359 //memset(drecmd, 0, 64);
360 //drecmd[0] = 0x71;
361 for(i = 2; i <= 64; i++)
362 {
363 memset(drecmd, 0, 64);
364 drecmd[i-1] = 0x02;
365 drecmd[0] = 0x71;
366
367 dre_script(drecmd, i, 0, 0, 0);
368
369 if(cta_res[2] == 0xE2)
370 {
371 if((cta_res[3] != 0xE2) & (cta_res[3] != 0xED)) rdr_log(reader, "Len %02X error %02X",i ,cta_res[3]);
372 if((cta_res[3] & 0xF0) != 0xE0) rdr_log(reader, "Len %02X answer %s",i ,cs_hexdump(0, cta_res, cta_res[1]+2, tmp, sizeof(tmp)));
373 }
374 else
375 {
376 rdr_log(reader, "Len %02X answer %s",i ,cs_hexdump(0, cta_res, cta_res[1]+2, tmp, sizeof(tmp)));
377 }
378 }
379}
380*/
381static int32_t dre_card_init(struct s_reader *reader, ATR *newatr)
382{
383 get_atr;
384 def_resp;
385 uint8_t ua[] = { 0x43, 0x15 }; // get serial number (UA)
386 uint8_t providers[] = { 0x49, 0x15 }; // get providers
387 uint8_t cmd56[] = { 0x56, 0x00 };
388 int32_t i;
389 char *card;
390 char tmp[9];
391
392 if((atr[0] != 0x3b) || (atr[1] != 0x15) || (atr[2] != 0x11) || (atr[3] != 0x12) || (
393 ((atr[4] != 0x01) || (atr[5] != 0x01)) &&
394 ((atr[4] != 0xca) || (atr[5] != 0x07)) &&
395 ((atr[4] != 0xcb) || (atr[5] != 0x07)) &&
396 ((atr[4] != 0xcc) || (atr[5] != 0x07)) &&
397 ((atr[4] != 0xcd) || (atr[5] != 0x07))
398 ))
399 { return ERROR; }
400
401 if(!cs_malloc(&reader->csystem_data, sizeof(struct dre_data)))
402 { return ERROR; }
403 struct dre_data *csystem_data = reader->csystem_data;
404
405 csystem_data->provider = atr[6];
406 uint8_t checksum = xor(atr + 1, 6);
407
408 if(checksum != atr[7])
409 { rdr_log(reader, "warning: expected ATR checksum %02x, smartcard reports %02x", checksum, atr[7]); }
410
411 switch(atr[6])
412 {
413 case 0:
414 if(!(dre_cmd(cmd56))) { return ERROR; }
415 if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00)) { return ERROR; }
416
417 switch(cta_res[4])
418 {
419 case 0x02:
420 card = "Tricolor Centr DRE3";
421 reader->caid = 0x4ae1;
422 break;
423
424 case 0x03:
425 card = "Tricolor Syberia DRE3";
426 reader->caid = 0x4ae1;
427 break;
428
429 case 0x18:
430 case 0x19:
431 card = "Tricolor Centr DRE4";
432 reader->caid = 0x2710;
433 break;
434
435 case 0x1A:
436 card = "Tricolor Syberia DRE4";
437 reader->caid = 0x2710;
438 break;
439
440 default:
441 return ERROR;
442 }
443 csystem_data->provider = cta_res[4];
444 providers[0] = 0x83;
445 break;
446
447 case 0x11:
448 card = "Tricolor Centr DRE2";
449 reader->caid = 0x4ae1;
450 break; // 59 type card = MSP (74 type = ATMEL)
451
452 case 0x12:
453 card = "Cable TV";
454 reader->caid = 0x4ae1; // TODO not sure about this one
455 break;
456
457 case 0x14:
458 card = "Tricolor Syberia DRE2";
459 reader->caid = 0x4ae1;
460 break; // 59 type card
461
462 case 0x15:
463 card = "Platforma HD / DW old";
464 reader->caid = 0x4ae1;
465 break; // 59 type card
466
467 default:
468 return ERROR;
469 }
470
471 memset(reader->prid, 0x00, 8);
472
473 if(atr[6] > 0)
474 {
475 reader->prid[0][3] = atr[6];
476 }
477 else
478 {
479 reader->prid[0][3] = csystem_data->provider;
480 }
481
482 uint8_t cmd54[] = { 0x54, 0x14 }; // geocode
483 cmd54[1] = csystem_data->provider;
484 uint8_t geocode = 0;
485
486 if((dre_cmd(cmd54))) // error would not be fatal, like on 0x11 cards
487 { geocode = cta_res[3]; }
488
489 providers[1] = csystem_data->provider;
490 if(!(dre_cmd(providers)))
491 { return ERROR; } // fatal error
492
493 if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
494 { return ERROR; }
495
496 uint8_t provname[128];
497
498 for(i = 0; ((i < cta_res[2] - 6) && (i < 128)); i++)
499 {
500 provname[i] = cta_res[6 + i];
501 if(provname[i] == 0x00)
502 { break; }
503 }
504
505 int32_t major_version = cta_res[3];
506 int32_t minor_version = cta_res[4];
507
508 ua[1] = csystem_data->provider;
509 dre_cmd(ua); // error would not be fatal
510
511 int32_t hexlength = cta_res[1] - 2; // discard first and last byte, last byte is always checksum, first is answer code
512
513 if(reader->force_ua)
514 {
515 rdr_log(reader, "WARNING!!! used UA from force_ua %08X", reader->force_ua);
516 memcpy(cta_res + 3, &reader->force_ua, 4);
517 }
518
519 reader->hexserial[0] = 0;
520 reader->hexserial[1] = 0;
521 memcpy(reader->hexserial + 2, cta_res + 3, hexlength);
522
523 int32_t low_dre_id, dre_chksum;
524 uint8_t buf[32];
525
526 if(major_version < 0x3)
527 {
528 low_dre_id = ((cta_res[4] << 16) | (cta_res[5] << 8) | cta_res[6]) - 48608;
529 dre_chksum = 0;
530 snprintf((char *)buf, sizeof(buf), "%i%i%08i", csystem_data->provider - 16, major_version + 1, low_dre_id);
531
532 for(i = 0; i < 32; i++)
533 {
534 if(buf[i] == 0x00)
535 { break; }
536 dre_chksum += buf[i] - 48;
537 }
538
539 if(major_version < 2)
540 {
541 reader->caid = 0x4ae0;
542 card = csystem_data->provider == 0x11 ? "Tricolor Centr DRE1" : "Tricolor Syberia DRE1";
543 }
544
545 rdr_log(reader, "type: DRE Crypt, caid: %04X, serial: {%s}, dre id: %i%i%i%08i, geocode %i, card: %s v%i.%i",
546 reader->caid, cs_hexdump(0, reader->hexserial + 2, 4, tmp, sizeof(tmp)), dre_chksum,
547 csystem_data->provider - 16, major_version + 1, low_dre_id, geocode, card, major_version, minor_version);
548 }
549 else
550 {
551 low_dre_id = ((cta_res[4] << 16) | (cta_res[5] << 8) | cta_res[6]);
552 dre_chksum = 0;
553 snprintf((char *)buf, sizeof(buf), "%i%i%08i", csystem_data->provider, major_version, low_dre_id);
554
555 for(i = 0; i < 32; i++)
556 {
557 if(buf[i] == 0x00)
558 { break; }
559 dre_chksum += buf[i] - 48;
560 }
561 rdr_log(reader, "type: DRE Crypt, caid: %04X, serial: {%s}, dre id: %i%03i%i%08i, geocode %i, card: %s v%i.%i",
562 reader->caid, cs_hexdump(0, reader->hexserial + 2, 4, tmp, sizeof(tmp)), dre_chksum, csystem_data->provider,
563 major_version, low_dre_id, geocode, card, major_version, minor_version);
564 }
565
566 rdr_log(reader, "Provider name:%s.", provname);
567
568
569 memset(reader->sa, 0, sizeof(reader->sa));
570 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...
571
572 rdr_log_sensitive(reader, "SA = %02X%02X%02X%02X, UA = {%s}", reader->sa[0][0], reader->sa[0][1], reader->sa[0][2],
573 reader->sa[0][3], cs_hexdump(0, reader->hexserial + 2, 4, tmp, sizeof(tmp)));
574
575 reader->nprov = 1;
576
577 //cmd_test(reader);
578
579 // exec user script, wicardd format
580 if(reader->userscript != NULL)
581 {
582 uint8_t *usercmd = NULL;
583 int cmd_len;
584 int n;
585 char *tempbuf = malloc(2048);
586 trim2(reader->userscript);
587 FILE *pFile = fopen(reader->userscript, "rt");
588
589 if(pFile != NULL)
590 {
591 uint8_t ignoreProvid = 0;
592 uint8_t crypted = 0;
593 uint8_t cryptkey = 0;
594 do
595 {
596 tempbuf[0] = '\0';
597 if(usercmd != NULL) free(usercmd);
598
599 if(fgets(tempbuf, 2048, pFile) == NULL) continue;
600
601 if(strlen(tempbuf) < 10) continue;
602
603 trim2(tempbuf);
604
605 ignoreProvid = 0;
606 crypted = 0;
607 cryptkey = 0;
608
609 if(tempbuf[0] == '8' && tempbuf[1] == '6' && csystem_data->provider == 0x11) ignoreProvid = 1;
610 else if(strncmp(tempbuf ,"REG2" ,4) == 0)
611 {
612 dre_read_ee(reader, &tempbuf[4] ,csystem_data->provider);
613 continue;
614 }
615 else if(strncmp(tempbuf ,"CR" ,2) == 0)
616 {
617 crypted = 1;
618 cryptkey = ((tempbuf[2] - (tempbuf[2] > 0x39 ? 0x37:0x30)) << 4) + ((tempbuf[3] - (tempbuf[3] > 0x39 ? 0x37:0x30)) & 0xF);
619 }
620 else if(tempbuf[0] != '5' && tempbuf[1] != '9') continue;
621
622 strtoupper(tempbuf);
623
624 cmd_len = strlen(tempbuf) / 2 - 3 + ignoreProvid - (crypted * 2);
625 usercmd = malloc(cmd_len);
626
627 for(i = 0, n = 4 + (crypted * 4); i < cmd_len; i++, n += 2)
628 {
629 usercmd[i] = ((tempbuf[n] - (tempbuf[n] > 0x39 ? 0x37 : 0x30)) << 4) + ((tempbuf[n + 1] - (tempbuf[n + 1] > 0x39 ? 0x37 : 0x30)) & 0xF);
630 }
631
632 /*if(usercmd[cmd_len-1] != csystem_data->provider && !ignoreProvid)
633 {
634 rdr_log(reader, "Skip script: current provid %02X , script provid %02X", csystem_data->provider, usercmd[cmd_len-1]);
635 continue;
636 }
637 */
638 rdr_log(reader, "User script: %s", tempbuf);
639
640 /*ret =*/
641
642 rdr_log(reader, "Script %s", (dre_script(usercmd, cmd_len, ignoreProvid, crypted, cryptkey)) ? "done" : "error");
643 }
644 while(!feof(pFile));
645 }
646 else
647 {
648 rdr_log(reader, "Can't open script file (%s)", reader->userscript);
649 }
650
651 //if(usercmd != NULL) free(usercmd);
652 if(tempbuf != NULL) free(tempbuf);
653 }
654
655 if(csystem_data->provider == 0x11)
656 {
657 memset(reader->prid[1], 0x00, 8);
658 reader->prid[1][3] = 0xFE;
659 reader->nprov = 2;
660 }
661
662 if(!dre_set_provider_info(reader))
663 { return ERROR; } // fatal error
664
665
666 rdr_log(reader, "ready for requests");
667 return OK;
668}
669
670static void DREover(struct s_reader *reader, const uint8_t *ECMdata, uint8_t *DW)
671{
672 uint32_t key_schedule[32];
673
674 if(reader->des_key_length < 128)
675 {
676 rdr_log(reader, "error: deskey is missing or too short");
677 return;
678 }
679
680 if(ECMdata[2] >= (43 + 4) && ECMdata[40] == 0x3A && ECMdata[41] == 0x4B)
681 {
682 des_set_key(&reader->des_key[(ECMdata[42] & 0x0F) * 8], key_schedule);
683
684 des(DW, key_schedule, 0); // even DW post-process
685 des(DW + 8, key_schedule, 0); // odd DW post-process
686 };
687};
688
689static int32_t dre_do_ecm(struct s_reader *reader, const ECM_REQUEST *er, struct s_ecm_answer *ea)
690{
691 def_resp;
692 uint16_t overcryptId;
693 uint8_t tmp[16];
694 char tmp_dbg[256];
695 struct dre_data *csystem_data = reader->csystem_data;
696 if(reader->caid == 0x4ae0)
697 {
698 uint8_t ecmcmd41[] = { 0x41,
699 0x58, 0x1f, 0x00, // fixed part, dont change
700 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // 0x01 - 0x08: next key
701 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, // 0x11 - 0x18: current key
702 0x3b, 0x59, 0x11 }; // 0x3b = keynumber, can be a value 56 ;; 0x59 number of package = 58+1 - Pay Package ;; 0x11 = provider
703
704 ecmcmd41[22] = csystem_data->provider;
705 memcpy(ecmcmd41 + 4, er->ecm + 8, 16);
706 ecmcmd41[20] = er->ecm[6]; // keynumber
707 ecmcmd41[21] = 0x58 + er->ecm[25]; // package number
708 rdr_log_dbg(reader, D_READER, "unused ECM info front:%s", cs_hexdump(0, er->ecm, 8, tmp_dbg, sizeof(tmp_dbg)));
709 rdr_log_dbg(reader, D_READER, "unused ECM info back:%s", cs_hexdump(0, er->ecm + 24, er->ecm[2] + 2 - 24, tmp_dbg, sizeof(tmp_dbg)));
710
711 if((dre_cmd(ecmcmd41))) // ecm request
712 {
713 if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
714 { return ERROR; } // exit if response is not 90 00
715 memcpy(ea->cw, cta_res + 11, 8);
716 memcpy(ea->cw + 8, cta_res + 3, 8);
717
718 return OK;
719 }
720 }
721 else if(reader->caid == 0x4ae1)
722 {
723 if(csystem_data->provider == 0x11 || csystem_data->provider == 0x14)
724 {
725 uint8_t ecmcmd51[] = { 0x51, 0x02, 0x56, 0x05, 0x00, 0x4A, 0xE3, // fixed header?
726 0x9C, 0xDA, // first three nibbles count up, fourth nibble counts down; all ECMs sent twice
727 0xC1, 0x71, 0x21, 0x06, 0xF0, 0x14, 0xA7, 0x0E, // next key?
728 0x89, 0xDA, 0xC9, 0xD7, 0xFD, 0xB9, 0x06, 0xFD, // current key?
729 0xD5, 0x1E, 0x2A, 0xA3, 0xB5, 0xA0, 0x82, 0x11, // key or signature?
730 0x14 }; // provider
731
732 memcpy(ecmcmd51 + 1, er->ecm + 5, 0x21);
733 rdr_log_dbg(reader, D_READER, "unused ECM info front:%s", cs_hexdump(0, er->ecm, 5, tmp_dbg, sizeof(tmp_dbg)));
734 rdr_log_dbg(reader, D_READER, "unused ECM info back:%s", cs_hexdump(0, er->ecm + 37, 4, tmp_dbg, sizeof(tmp_dbg)));
735 ecmcmd51[33] = csystem_data->provider; // no part of sig
736
737 if((dre_cmd(ecmcmd51))) // ecm request
738 {
739 if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
740 { return ERROR; } // exit if response is not 90 00
741
742 if(er->ecm[2] >= 46 && er->ecm[43] == 1 && csystem_data->provider == 0x11)
743 {
744 memcpy(tmp, cta_res + 11, 8);
745 memcpy(tmp + 8, cta_res + 3, 8);
746 overcryptId = b2i(2, &er->ecm[44]);
747 rdr_log_dbg(reader, D_READER, "ICG ID: %04X", overcryptId);
748
749 Drecrypt2OverCW(overcryptId,tmp);
750
751 if(isValidDCW(tmp))
752 {
753 memcpy(ea->cw, tmp, 16);
754 return OK;
755 }
756 return ERROR;
757 }
758
759 DREover(reader, er->ecm, cta_res + 3);
760
761 if(isValidDCW(cta_res + 3))
762 {
763 memcpy(ea->cw, cta_res + 11, 8);
764 memcpy(ea->cw + 8, cta_res + 3, 8);
765 return OK;
766 }
767 }
768 }
769 else if((csystem_data->provider == 0x02 || csystem_data->provider == 0x03) && er->ecm[3] == 3)
770 {
771 // DRE 3
772
773 if (er->ecm[4] == 2)
774 {
775 memcpy(ea->cw, &er->ecm[42], 8);
776 memcpy(&ea->cw[8], &er->ecm[34], 8);
777 return OK;
778 }
779
780 uint8_t cmdlen;
781 uint8_t crypted = er->ecm[8] & 1;
782 uint8_t cryptkey = (er->ecm[8] & 6) >> 1;
783
784 if (crypted == 0)
785 {
786 cmdlen = 50;
787 }
788 else
789 {
790 cmdlen = 57;
791 }
792
793 uint8_t ecmcmd[cmdlen];
794
795 memcpy(ecmcmd, &er->ecm[17], cmdlen - 1);
796 ecmcmd[cmdlen - 1] = csystem_data->provider;
797
798 dre_cmd_c(ecmcmd, crypted, cryptkey);
799
800 if(cta_res[2] == 0xD2 && isValidDCW(cta_res + 3))
801 {
802 memcpy(ea->cw, cta_res + 11, 8);
803 memcpy(ea->cw + 8, cta_res + 3, 8);
804 return OK;
805 }
806 }
807 }
808 else if(reader->caid == 0x2710 && er->ecm[3] == 4)
809 {
810 // DRE 4
811
812 if (er->ecm[4] == 4)
813 {
814 memcpy(ea->cw, &er->ecm[22], 8);
815 memcpy(&ea->cw[8], &er->ecm[14], 8);
816 return OK;
817 }
818
819 uint8_t cmdlen;
820 uint8_t crypted = er->ecm[8] & 1;
821 uint8_t cryptkey = (er->ecm[8] & 6) >> 1;
822
823 if (crypted == 0)
824 {
825 cmdlen = 58;
826 }
827 else
828 {
829 cmdlen = 65;
830 }
831
832 uint8_t ecmcmd[cmdlen];
833
834 memcpy(ecmcmd, &er->ecm[9], cmdlen - 1);
835 ecmcmd[cmdlen - 1] = csystem_data->provider;
836
837 dre_cmd_c(ecmcmd, crypted, cryptkey);
838
839 if(cta_res[2] == 0xD2 && isValidDCW(cta_res + 3))
840 {
841 memcpy(ea->cw, cta_res + 11, 8);
842 memcpy(ea->cw + 8, cta_res + 3, 8);
843 return OK;
844 }
845 }
846 return ERROR;
847}
848
849static int32_t dre_do_emm(struct s_reader *reader, EMM_PACKET *ep)
850{
851 def_resp;
852 struct dre_data *csystem_data = reader->csystem_data;
853
854 if(reader->caid == 0x4ae1)
855 {
856 if(reader->caid != b2i(2, ep->caid)) return ERROR;
857
858 if(ep->type == UNIQUE && ep->emm[39] == 0x3d)
859 {
860 /* For new package activation. */
861 uint8_t emmcmd58[26];
862 emmcmd58[0] = 0x58;
863 memcpy(&emmcmd58[1], &ep->emm[40], 24);
864 emmcmd58[25] = csystem_data->provider;
865
866 if((dre_cmd(emmcmd58)))
867 if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
868 { return ERROR; }
869 }
870 else if(ep->emm[0] == 0x86 && ep->emm[4] == 0x02 /*&& csystem_data->provider != 0x11*/)
871 {
872 uint8_t emmcmd52[0x3a];
873 emmcmd52[0] = 0x52;
874 int32_t i;
875 for(i = 0; i < 2; i++)
876 {
877 memcpy(emmcmd52 + 1, ep->emm + 5 + 32 + i * 56, 56);
878
879 // check for shared address
880 if(ep->emm[3] != reader->sa[0][0])
881 { return OK; } // ignore, wrong address
882
883 emmcmd52[0x39] = csystem_data->provider;
884
885 if((dre_cmd(emmcmd52)))
886 if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
887 { return ERROR; } // exit if response is not 90 00
888 }
889 }
890 else if(ep->emm[0] == 0x86 && ep->emm[4] == 0x4D && csystem_data->provider == 0x11)
891 {
892 uint8_t emmcmd52[0x3a];
893
894 emmcmd52[0] = 0x52;
895 emmcmd52[1] = 0x01;
896 emmcmd52[2] = ep->emm[5];
897 emmcmd52[3] = 0x01;
898 emmcmd52[4] = ep->emm[3];
899 emmcmd52[5] = 0;
900 emmcmd52[6] = 0;
901 emmcmd52[7] = 0;
902 emmcmd52[9] = 0x01;
903 emmcmd52[10] = 0x01;
904 emmcmd52[11] = 0;
905 memcpy(emmcmd52 + 13, ep->emm + 0x5C, 4);
906 int32_t i;
907
908 for(i = 0; i < 2; i++)
909 {
910 emmcmd52[8] = ep->emm[0x61 + i * 0x29];
911 if(i == 0) emmcmd52[12] = ep->emm[0x60] == 0x56 ? 0x56 : 0x3B;
912 else emmcmd52[12] = ep->emm[0x60] == 0x56 ? 0x3B : 0x56;
913 memcpy(emmcmd52 + 0x11, ep->emm + 0x62 + i * 0x29, 40);
914
915 // check for shared address
916 if(ep->emm[3] != reader->sa[0][0])
917 { return OK; } // ignore, wrong address
918
919 emmcmd52[0x39] = csystem_data->provider;
920
921 if((dre_cmd(emmcmd52)))
922 if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
923 { return ERROR; } // exit if response is not 90 00
924 }
925 }
926 else if (ep->emm[0] == 0x8c && (csystem_data->provider == 0x02 || csystem_data->provider == 0x03)) // dre3 group emm
927 {
928 if(ep->emm[3] != reader->sa[0][0])
929 { return OK; } // ignore, wrong address
930
931 uint8_t crypted = ep->emm[10];
932
933 if ((crypted & 1) == 1)
934 {
935 uint8_t emmcmd[0x49];
936
937 memcpy(emmcmd, &ep->emm[0x13], 0x48);
938
939 emmcmd[0x48] = csystem_data->provider;
940
941 dre_cmd_c(emmcmd, crypted & 1, (crypted & 6) >> 1);
942
943 if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
944 { return ERROR; } //exit if response is not 90 00
945
946 memcpy(emmcmd, &ep->emm[0x5B], 0x48);
947
948 emmcmd[0x48] = csystem_data->provider;
949
950 dre_cmd_c(emmcmd, crypted & 1, (crypted & 6) >> 1);
951
952 if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
953 { return ERROR; } //exit if response is not 90 00
954
955 return OK;
956 }
957 else
958 {
959 uint8_t emmcmd[0x42];
960
961 memcpy(emmcmd, &ep->emm[0x13], 0x41);
962
963 emmcmd[0x41] = csystem_data->provider;
964
965 dre_cmd_c(emmcmd, crypted & 1, (crypted & 6) >> 1);
966
967 if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
968 { return ERROR; } // exit if response is not 90 00
969
970 memcpy(emmcmd, &ep->emm[0x5B], 0x41);
971
972 emmcmd[0x41] = csystem_data->provider;
973
974 dre_cmd_c(emmcmd, crypted & 1, (crypted & 6) >> 1);
975
976 if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
977 { return ERROR; } // exit if response is not 90 00
978
979 return OK;
980 }
981 }
982 else if(ep->type == GLOBAL && ep->emm[0] == 0x91)
983 {
984 Drecrypt2OverEMM(ep->emm);
985 return OK;
986 }
987 else return OK;
988 }
989 else if(reader->caid == 0x2710)
990 {
991 // DRE 4
992 if(ep->type == UNIQUE)
993 {
994 uint16_t cmdlen;
995 uint8_t class, hlbUA, KEYindex;
996 int i, keycount;
997 uint8_t CMDtype = ep->emm[7];
998 uint16_t EMMlen = ep->emm[2] | ((ep->emm[1] & 0xF) << 8);
999 uint8_t cryptflag = ep->emm[10];
1000 uint8_t crypted = cryptflag & 1;
1001 uint8_t cryptkey = (cryptflag & 6) >> 1;
1002
1003 if (CMDtype == 0x61)
1004 {
1005 uint8_t emmcmd91[19];
1006
1007 emmcmd91[0] = 0x91;
1008 emmcmd91[1] = ep->emm[19];
1009 emmcmd91[2] = ep->emm[8];
1010 emmcmd91[3] = ep->emm[20];
1011 if(reader->force_ua) emmcmd91[3] += 2;
1012 memcpy(&emmcmd91[4], &reader->hexserial[2], 4);
1013 emmcmd91[8] = 0xF0;
1014 emmcmd91[17] = ep->emm[22];
1015 emmcmd91[18] = csystem_data->provider;
1016
1017 if ((EMMlen - 24) > 16)
1018 {
1019 hlbUA = reader->hexserial[5] & 0xF;
1020
1021 uint16_t keypos = cryptflag == 2 ? 17 : 9;
1022 keycount = (EMMlen - 24) / keypos;
1023
1024 for(i = 0; i <= keycount ;i++)
1025 {
1026 if (i == keycount) return OK;
1027 if (hlbUA == (ep->emm[23 + (keypos * i)] & 0xF) ) break;
1028 }
1029
1030 keypos = 24 + (keypos * i);
1031
1032 memcpy(&emmcmd91[9], &ep->emm[keypos], 8);
1033
1034 if((dre_cmd(emmcmd91)))
1035 if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00) || (cta_res[2] != 0xA2))
1036 return ERROR; // exit if response is not 90 00
1037
1038 if (cryptflag == 2)
1039 {
1040 if (emmcmd91[17] == 0x56) KEYindex = 0x3B;
1041 else KEYindex = 0x56;
1042
1043 keypos += 8;
1044 memcpy(&emmcmd91[9], &ep->emm[keypos], 8);
1045 emmcmd91[17] = KEYindex;
1046
1047 dre_cmd(emmcmd91);
1048
1049 if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00) || (cta_res[2] != 0xA2))
1050 { return ERROR; } // exit if response is not 90 00
1051
1052 return OK;
1053 }
1054 }
1055 return ERROR;
1056 }
1057 else if (CMDtype == 0x62)
1058 {
1059 if (!memcmp(&reader->hexserial[2], &ep->emm[3], 4))
1060 {
1061 if (crypted)
1062 {
1063 cmdlen = 49;
1064 }
1065 else
1066 {
1067 cmdlen = 42;
1068 }
1069
1070 uint8_t emmcmd92[cmdlen];
1071
1072 memcpy(emmcmd92, &ep->emm[19], cmdlen - 1);
1073 emmcmd92[cmdlen - 1] = csystem_data->provider;
1074
1075 if (crypted)
1076 {
1077 dre_cmd_c(emmcmd92, crypted, cryptkey);
1078 }
1079 else
1080 {
1081 dre_cmd(emmcmd92);
1082 }
1083
1084 if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
1085 { return ERROR; } // exit if response is not 90 00
1086
1087 class = ep->emm[8];
1088
1089 uint8_t emmcmd95[3];
1090
1091 emmcmd95[0] = 0x95;
1092 emmcmd95[1] = class;
1093 emmcmd95[2] = csystem_data->provider;
1094
1095 dre_cmd(emmcmd95);
1096
1097 uint8_t emmcmd91[19];
1098
1099 emmcmd91[0] = 0x91;
1100 emmcmd91[1] = ep->emm[102];
1101 emmcmd91[2] = ep->emm[8];
1102 emmcmd91[3] = ep->emm[103];
1103 if(reader->force_ua) emmcmd91[3] += 2;
1104 memcpy(&emmcmd91[4], &reader->hexserial[2], 4);
1105 emmcmd91[8] = ep->emm[104];
1106 memcpy(&emmcmd91[9], &ep->emm[72], 8);
1107 emmcmd91[17] = ep->emm[105];
1108 emmcmd91[18] = csystem_data->provider;
1109
1110 dre_cmd(emmcmd91);
1111
1112 if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00) || (cta_res[2] != 0xA2) )
1113 { return ERROR; } // exit if response is not 90 00
1114
1115 if (emmcmd91[17] == 0x56) KEYindex = 0x3B;
1116 else KEYindex = 0x56;
1117
1118 memcpy(&emmcmd91[9], &ep->emm[86], 8);
1119 emmcmd91[17] = KEYindex;
1120
1121 dre_cmd(emmcmd91);
1122
1123 if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
1124 { return ERROR; } // exit if response is not 90 00
1125 }
1126 return OK;
1127 }
1128 else
1129 {
1130 if (memcmp(&reader->hexserial[2], &ep->emm[3], 4)) return OK;
1131
1132 if (CMDtype == 0x63)
1133 {
1134 uint8_t emmcmdA5[7];
1135
1136 emmcmdA5[0] = 0xA5;
1137 emmcmdA5[1] = 0;
1138 memcpy(&emmcmdA5[2], &reader->hexserial[2], 4);
1139 emmcmdA5[6] = csystem_data->provider;
1140
1141 dre_cmd(emmcmdA5);
1142
1143 if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
1144 { return ERROR; } //exit if response is not 90 00
1145 }
1146
1147 if (crypted) cmdlen = EMMlen - 19;
1148 else cmdlen = ep->emm[11] + 1;
1149
1150 uint8_t emmcmd[cmdlen];
1151
1152 memcpy(emmcmd, &ep->emm[19], cmdlen - 1);
1153 emmcmd[cmdlen - 1] = csystem_data->provider;
1154
1155 if(emmcmd[0] == 0x45)
1156 {
1157 cs_log("TRICOLOR Send KILL command for your card");
1158 return ERROR;
1159 }
1160
1161 dre_cmd_c(emmcmd, crypted, cryptkey);
1162
1163 if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
1164 { return ERROR; } //exit if response is not 90 00
1165 }
1166 return OK;
1167 }
1168 return ERROR;
1169 }
1170 else if(reader->caid != 0x2710 && reader->caid != 0x4AE1)
1171 {
1172 uint8_t emmcmd42[] =
1173 {
1174 0x42, 0x85, 0x58, 0x01, 0xC8, 0x00, 0x00, 0x00, 0x05, 0xB8, 0x0C, 0xBD, 0x7B, 0x07, 0x04, 0xC8,
1175 0x77, 0x31, 0x95, 0xF2, 0x30, 0xB7, 0xE9, 0xEE, 0x0F, 0x81, 0x39, 0x1C, 0x1F, 0xA9, 0x11, 0x3E,
1176 0xE5, 0x0E, 0x8E, 0x50, 0xA4, 0x31, 0xBB, 0x01, 0x00, 0xD6, 0xAF, 0x69, 0x60, 0x04, 0x70, 0x3A,
1177 0x91,
1178 0x56, 0x58, 0x11
1179 };
1180 int32_t i;
1181
1182 switch(ep->type)
1183 {
1184 case UNIQUE:
1185 for(i = 0; i < 2; i++)
1186 {
1187 memcpy(emmcmd42 + 1, ep->emm + 42 + i * 49, 48);
1188 emmcmd42[49] = ep->emm[i * 49 + 41]; // keynr
1189 emmcmd42[50] = 0x58 + ep->emm[40]; // package nr
1190 emmcmd42[51] = csystem_data->provider;
1191 if((dre_cmd(emmcmd42)))
1192 {
1193 if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
1194 { return ERROR; } // exit if response is not 90 00
1195 }
1196 }
1197 break;
1198
1199 case SHARED:
1200 default:
1201 memcpy(emmcmd42 + 1, ep->emm + 6, 48);
1202 emmcmd42[51] = csystem_data->provider;
1203 //emmcmd42[50] = ecmcmd42[2]; // TODO package nr could also be fixed 0x58
1204 emmcmd42[50] = 0x58;
1205 emmcmd42[49] = ep->emm[5]; // keynr
1206
1207 /* response:
1208 59 05 A2 02 05 01 5B
1209 90 00 */
1210
1211 if((dre_cmd(emmcmd42))) // first emm request
1212 {
1213 if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
1214 { return ERROR; } // exit if response is not 90 00
1215
1216 memcpy(emmcmd42 + 1, ep->emm + 55, 7); // TODO OR next two lines?
1217 //memcpy (emmcmd42 + 1, ep->emm + 55, 7); // FIXME either I cant count or my EMM log contains errors
1218 //memcpy (emmcmd42 + 8, ep->emm + 67, 41);
1219 emmcmd42[51] = csystem_data->provider;
1220 //emmcmd42[50] = ecmcmd42[2]; // TODO package nr could also be fixed 0x58
1221 emmcmd42[50] = 0x58;
1222 emmcmd42[49] = ep->emm[54]; // keynr
1223
1224 if((dre_cmd(emmcmd42))) // second emm request
1225 {
1226 if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
1227 { return ERROR; } // exit if response is not 90 00
1228 }
1229 }
1230 }
1231 return OK;
1232 }
1233 return ERROR;
1234}
1235
1236static int32_t dre_card_info(struct s_reader *UNUSED(rdr))
1237{
1238 return OK;
1239}
1240
1241const struct s_cardsystem reader_dre =
1242{
1243 .desc = "dre",
1244 .caids = (uint16_t[]){ 0x4AE0, 0x4AE1, 0x7BE0, 0x7BE1, 0x2710, 0 },
1245 .do_emm = dre_do_emm,
1246 .do_ecm = dre_do_ecm,
1247 .card_info = dre_card_info,
1248 .card_init = dre_card_init,
1249 .get_emm_type = dre_common_get_emm_type,
1250 .get_emm_filter = dre_common_get_emm_filter,
1251};
1252
1253#endif
Note: See TracBrowser for help on using the repository browser.