3 #include "cscrypt/des.h"
4 #include "reader-common.h"
5 #include "reader-dre-common.h"
12 #define OK_RESPONSE 0x61
15 static uchar
xor(const uchar
*cmd
, int32_t cmdlen
)
18 uchar checksum
= 0x00;
19 for(i
= 0; i
< cmdlen
; i
++)
20 { checksum
^= cmd
[i
]; }
24 static int8_t isValidDCW(uint8_t *dw
)
26 if (((dw
[0]+dw
[1]+dw
[2]) & 0xFF) != dw
[3])
30 if (((dw
[4]+dw
[5]+dw
[6]) & 0xFF) != dw
[7])
34 if (((dw
[8]+dw
[9]+dw
[10]) & 0xFF) != dw
[11])
38 if (((dw
[12]+dw
[13]+dw
[14]) & 0xFF) != dw
[15])
45 static int32_t dre_command(struct s_reader
*reader
, const uchar
*cmd
, int32_t cmdlen
, unsigned char *cta_res
, uint16_t *p_cta_lr
,
46 uint8_t crypted
, uint8_t keynum
, uint8_t dre_v
, uint8_t cmd_type
)
47 //attention: inputcommand will be changed!!!! answer will be in cta_res, length cta_lr ; returning 1 = no error, return ERROR = err
49 uchar startcmd
[] = { 0x80, 0xFF, 0x10, 0x01, 0x05 }; //any command starts with this,
50 //last byte is nr of bytes of the command that will be sent
52 //response on startcmd+cmd: = { 0x61, 0x05 } //0x61 = "OK", last byte is nr. of bytes card will send
53 uchar reqans
[] = { 0x00, 0xC0, 0x00, 0x00, 0x08 }; //after command answer has to be requested,
54 //last byte must be nr. of bytes that card has reported to send
58 int32_t headerlen
= sizeof(startcmd
);
63 startcmd
[2] = crypted
;
67 startcmd
[4] = cmdlen
+ 3 - cmd_type
; //commandlength + type + len + checksum bytes
68 memcpy(command
, startcmd
, headerlen
);
69 command
[headerlen
++] = cmd_type
? 0x86 : CMD_BYTE
; //type
70 command
[headerlen
++] = cmdlen
+ (cmd_type
== 1 ? 0 : 1); //len = command + 1 checksum byte
71 memcpy(command
+ headerlen
, cmd
, cmdlen
);
75 checksum
= ~xor(cmd
, cmdlen
);
76 //rdr_log_dbg(reader, D_READER, "Checksum: %02x", checksum);
78 command
[cmdlen
++] = checksum
;
80 else cmdlen
+= headerlen
;
82 reader_cmd2icc(reader
, command
, cmdlen
, cta_res
, p_cta_lr
);
84 if((*p_cta_lr
!= 2) || (cta_res
[0] != OK_RESPONSE
))
86 rdr_log(reader
, "command sent to card: %s", cs_hexdump(0, command
, cmdlen
, tmp
, sizeof(tmp
)));
87 rdr_log(reader
, "unexpected answer from card: %s", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
91 rdr_log_dbg(reader
, D_READER
, "command sent to card: %s", cs_hexdump(0, command
, cmdlen
, tmp
, sizeof(tmp
)));
92 rdr_log_dbg(reader
, D_READER
, "answer from card: %s", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
94 reqans
[4] = cta_res
[1]; //adapt length byte
95 reader_cmd2icc(reader
, reqans
, 5, cta_res
, p_cta_lr
);
97 if(cta_res
[0] != CMD_BYTE
)
99 rdr_log(reader
, "unknown response: cta_res[0] expected to be %02x, is %02x", CMD_BYTE
, cta_res
[0]);
103 if((cta_res
[1] == 0x03) && (cta_res
[2] == 0xe2))
105 switch(cta_res
[3+dre_v
])
108 rdr_log(reader
, "checksum error: %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
111 rdr_log(reader
, "wrong cmd len: %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
114 rdr_log(reader
, "illegal command: %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
117 rdr_log(reader
, "wrong adress type: %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
120 rdr_log(reader
, "wrong CMD param: %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
123 rdr_log(reader
, "wrong UA: %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
126 rdr_log(reader
, "wrong group: %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
129 rdr_log(reader
, "wrong key num: %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
132 rdr_log(reader
, "No key or subscribe : %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
135 rdr_log(reader
, "wrong signature: %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
138 rdr_log(reader
, "wrong provider: %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
141 rdr_log(reader
, "wrong GEO code: %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
144 rdr_log_dbg(reader
, D_READER
, "unknown error: %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
147 return ERROR
; //error
150 int32_t length_excl_leader
= *p_cta_lr
;
152 if((cta_res
[*p_cta_lr
- 2] == 0x90) && (cta_res
[*p_cta_lr
- 1] == 0x00))
153 { length_excl_leader
-= 2; }
155 checksum
= ~xor(cta_res
+ 2, length_excl_leader
- 3);
157 if(cta_res
[length_excl_leader
- 1] != checksum
)
159 rdr_log(reader
, "checksum does not match, expected %02x received %02x:%s", checksum
,
160 cta_res
[length_excl_leader
- 1], cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
161 return ERROR
; //error
166 #define dre_script(cmd, len, cmd_type, crypted, keynum) \
168 dre_command(reader, cmd, len, cta_res, &cta_lr, crypted, keynum, crypted, cmd_type); \
171 #define dre_cmd(cmd) \
173 dre_command(reader, cmd, sizeof(cmd), cta_res, &cta_lr, 0, 0, 0, 0); \
176 #define dre_cmd_c(cmd,crypted,keynum) \
178 dre_command(reader, cmd, sizeof(cmd),cta_res,&cta_lr, crypted, keynum, 1, 0); \
181 static int32_t dre_set_provider_info(struct s_reader
*reader
)
185 int subscr_cmd_len
= 4;
186 uchar subscr
[4];// = { 0x59, 0x14 }; // subscriptions
187 uchar dates
[] = { 0x5b, 0x00, 0x14 }; //validity dates
188 uchar subscr_len
= 0, n
= 0;
189 struct dre_data
*csystem_data
= reader
->csystem_data
;
191 cs_clear_entitlement(reader
);
193 switch(csystem_data
->provider
)
200 subscr
[3] = csystem_data
->provider
;
210 subscr
[3] = csystem_data
->provider
;
216 subscr
[1] = csystem_data
->provider
;
223 if((dre_script(subscr
, subscr_cmd_len
, 0, 0, 0))) //ask subscription packages, returns error on 0x11 card
225 uchar pbm
[subscr_len
];
226 char tmp_dbg
[subscr_len
*2+1];
227 memcpy(pbm
, cta_res
+ 3, cta_lr
- 6);
228 rdr_log_dbg(reader
, D_READER
, "pbm: %s", cs_hexdump(0, pbm
, subscr_len
, tmp_dbg
, sizeof(tmp_dbg
)));
230 for(i
= 0; i
< subscr_len
; i
++)
234 dates
[2] = csystem_data
->provider
;
235 dre_cmd(dates
); //ask for validity dates
239 start
= (cta_res
[3] << 24) | (cta_res
[4] << 16) | (cta_res
[5] << 8) | cta_res
[6];
240 end
= (cta_res
[7] << 24) | (cta_res
[8] << 16) | (cta_res
[9] << 8) | cta_res
[10];
244 localtime_r(&start
, &temp
);
245 int32_t startyear
= temp
.tm_year
+ 1900;
246 int32_t startmonth
= temp
.tm_mon
+ 1;
247 int32_t startday
= temp
.tm_mday
;
248 localtime_r(&end
, &temp
);
249 int32_t endyear
= temp
.tm_year
+ 1900;
250 int32_t endmonth
= temp
.tm_mon
+ 1;
251 int32_t endday
= temp
.tm_mday
;
252 rdr_log(reader
, "active package %i valid from %04i/%02i/%02i to %04i/%02i/%02i", i
+n
, startyear
, startmonth
, startday
,
253 endyear
, endmonth
, endday
);
254 cs_add_entitlement(reader
, reader
->caid
, b2ll(4, reader
->prid
[0]), 0, i
+n
, start
, end
, 5, 1);
258 if(subscr_len
== 0x5F) // read second part subscription packages, for DRE3 and DRE4
270 static void dre_read_ee(struct s_reader
*reader
, const char *path
, uchar provid
)
274 uchar
*ee
= malloc(2048);
275 if(ee
== NULL
) return;
277 uchar drecmd43
[] = { 0x80, 0x00, 0x00, 0x00, 0x05, 0x59, 0x03, 0x43, 0x11, 0xAD };
278 uchar drecmd45
[] = { 0x45, 0x11 };
280 drecmd43
[8] = drecmd45
[1] = provid
;
281 drecmd43
[9] = ~xor(&drecmd43
[7], 2);
284 for(i
= 0; i
< 8; i
++)
286 for(n
= 0; n
< 8; n
++)
288 reader_cmd2icc(reader
, drecmd43
, 10, cta_res
, &cta_lr
);
290 dre_cmd_c(drecmd45
, n
, i
*32);
292 if((cta_res
[cta_lr
- 2] != 0x90) || (cta_res
[cta_lr
- 1] != 0x00))
295 rdr_log(reader
, "ERROR read ee.bin from card");
299 memcpy(&ee
[((n
*8)+i
)*32] ,&cta_res
[2] ,32);
304 FILE *pFile
= fopen(path
, "wb");
312 fwrite(ee
, 2048, 1, pFile
);
315 rdr_log(reader
, "ee.bin saved to %s", path
);
318 static void cmd_test(struct s_reader *reader)
322 uchar drecmd[] = { 0x00, 0x02 };
325 for(i = 0; i <= 0xFF; i++)
327 if(i == 0x45) continue;
330 if(cta_res[2] == 0xE2)
332 if(cta_res[3] != 0xE3) rdr_log(reader, "cmd %02X error %02X",i ,cta_res[3]);
336 rdr_log(reader, "cmd %02X answer %s",i ,cs_hexdump(0, cta_res, cta_res[1]+2, tmp, sizeof(tmp)));
342 //memset(drecmd, 0, 64);
344 for(i = 2; i <= 64; i++)
346 memset(drecmd, 0, 64);
350 dre_script(drecmd, i, 0, 0, 0);
352 if(cta_res[2] == 0xE2)
354 if((cta_res[3] != 0xE2) & (cta_res[3] != 0xED)) rdr_log(reader, "Len %02X error %02X",i ,cta_res[3]);
355 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)));
359 rdr_log(reader, "Len %02X answer %s",i ,cs_hexdump(0, cta_res, cta_res[1]+2, tmp, sizeof(tmp)));
364 static int32_t dre_card_init(struct s_reader
*reader
, ATR
*newatr
)
368 uchar ua
[] = { 0x43, 0x15 }; // get serial number (UA)
369 uchar providers
[] = { 0x49, 0x15 }; // get providers
370 uchar cmd56
[] = { 0x56, 0x00 };
375 if((atr
[0] != 0x3b) || (atr
[1] != 0x15) || (atr
[2] != 0x11) || (atr
[3] != 0x12) || (
376 ((atr
[4] != 0x01) || (atr
[5] != 0x01)) &&
377 ((atr
[4] != 0xca) || (atr
[5] != 0x07)) &&
378 ((atr
[4] != 0xcb) || (atr
[5] != 0x07)) &&
379 ((atr
[4] != 0xcc) || (atr
[5] != 0x07)) &&
380 ((atr
[4] != 0xcd) || (atr
[5] != 0x07))
384 if(!cs_malloc(&reader
->csystem_data
, sizeof(struct dre_data
)))
386 struct dre_data
*csystem_data
= reader
->csystem_data
;
388 csystem_data
->provider
= atr
[6];
389 uchar checksum
= xor(atr
+ 1, 6);
391 if(checksum
!= atr
[7])
392 { rdr_log(reader
, "warning: expected ATR checksum %02x, smartcard reports %02x", checksum
, atr
[7]); }
398 if(!(dre_cmd(cmd56
))) { return ERROR
; }
399 if((cta_res
[cta_lr
- 2] != 0x90) || (cta_res
[cta_lr
- 1] != 0x00)) { return ERROR
; }
404 card
= "Tricolor Centr DRE3";
405 reader
->caid
= 0x4ae1;
408 card
= "Tricolor Syberia DRE3";
409 reader
->caid
= 0x4ae1;
413 card
= "Tricolor Centr DRE4";
414 reader
->caid
= 0x2710;
417 card
= "Tricolor Syberia DRE4";
418 reader
->caid
= 0x2710;
423 csystem_data
->provider
= cta_res
[4];
427 card
= "Tricolor Centr DRE2";
428 reader
->caid
= 0x4ae1;
429 break; //59 type card = MSP (74 type = ATMEL)
432 reader
->caid
= 0x4ae1; //TODO not sure about this one
435 card
= "Tricolor Syberia DRE2";
436 reader
->caid
= 0x4ae1;
437 break; //59 type card
439 card
= "Platforma HD / DW old";
440 reader
->caid
= 0x4ae1;
441 break; //59 type card
446 memset(reader
->prid
, 0x00, 8);
450 reader
->prid
[0][3] = atr
[6];
454 reader
->prid
[0][3] = csystem_data
->provider
;
457 uchar cmd54
[] = { 0x54, 0x14 }; // geocode
458 cmd54
[1] = csystem_data
->provider
;
460 if((dre_cmd(cmd54
))) //error would not be fatal, like on 0x11 cards
461 { geocode
= cta_res
[3]; }
463 providers
[1] = csystem_data
->provider
;
464 if(!(dre_cmd(providers
)))
465 { return ERROR
; } //fatal error
466 if((cta_res
[cta_lr
- 2] != 0x90) || (cta_res
[cta_lr
- 1] != 0x00))
470 for(i
= 0; ((i
< cta_res
[2] - 6) && (i
< 128)); i
++)
472 provname
[i
] = cta_res
[6 + i
];
473 if(provname
[i
] == 0x00)
477 int32_t major_version
= cta_res
[3];
478 int32_t minor_version
= cta_res
[4];
480 ua
[1] = csystem_data
->provider
;
481 dre_cmd(ua
); //error would not be fatal
483 int32_t hexlength
= cta_res
[1] - 2; //discard first and last byte, last byte is always checksum, first is answer code
487 rdr_log(reader
, "WARNING!!!! used UA from force_ua %08X", reader
->force_ua
);
488 memcpy(cta_res
+ 3, &reader
->force_ua
, 4);
491 reader
->hexserial
[0] = 0;
492 reader
->hexserial
[1] = 0;
493 memcpy(reader
->hexserial
+ 2, cta_res
+ 3, hexlength
);
495 int32_t low_dre_id
, dre_chksum
;
498 if(major_version
< 0x3)
500 low_dre_id
= ((cta_res
[4] << 16) | (cta_res
[5] << 8) | cta_res
[6]) - 48608;
502 snprintf((char *)buf
, sizeof(buf
), "%i%i%08i", csystem_data
->provider
- 16, major_version
+ 1, low_dre_id
);
504 for(i
= 0; i
< 32; i
++)
508 dre_chksum
+= buf
[i
] - 48;
511 if(major_version
< 2)
513 reader
->caid
= 0x4ae0;
514 card
= csystem_data
->provider
== 0x11 ? "Tricolor Centr DRE1" : "Tricolor Syberia DRE1";
517 rdr_log(reader
, "type: DRE Crypt, caid: %04X, serial: {%s}, dre id: %i%i%i%08i, geocode %i, card: %s v%i.%i",
518 reader
->caid
, cs_hexdump(0, reader
->hexserial
+ 2, 4, tmp
, sizeof(tmp
)), dre_chksum
, csystem_data
->provider
- 16,
519 major_version
+ 1, low_dre_id
, geocode
, card
, major_version
, minor_version
);
523 low_dre_id
= ((cta_res
[4] << 16) | (cta_res
[5] << 8) | cta_res
[6]);
525 snprintf((char *)buf
, sizeof(buf
), "%i%i%08i", csystem_data
->provider
, major_version
, low_dre_id
);
527 for(i
= 0; i
< 32; i
++)
531 dre_chksum
+= buf
[i
] - 48;
533 rdr_log(reader
, "type: DRE Crypt, caid: %04X, serial: {%s}, dre id: %i%03i%i%08i, geocode %i, card: %s v%i.%i",
534 reader
->caid
, cs_hexdump(0, reader
->hexserial
+ 2, 4, tmp
, sizeof(tmp
)), dre_chksum
, csystem_data
->provider
,
535 major_version
, low_dre_id
, geocode
, card
, major_version
, minor_version
);
538 rdr_log(reader
, "Provider name:%s.", provname
);
541 memset(reader
->sa
, 0, sizeof(reader
->sa
));
542 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...
544 rdr_log_sensitive(reader
, "SA = %02X%02X%02X%02X, UA = {%s}", reader
->sa
[0][0], reader
->sa
[0][1], reader
->sa
[0][2],
545 reader
->sa
[0][3], cs_hexdump(0, reader
->hexserial
+ 2, 4, tmp
, sizeof(tmp
)));
551 // exec user script, wicardd format
552 if(reader
->userscript
!= NULL
)
554 uint8_t *usercmd
= NULL
;
557 char *tempbuf
= malloc(2048);
558 trim2(reader
->userscript
);
559 FILE *pFile
= fopen(reader
->userscript
, "rt");
563 uchar ignoreProvid
= 0;
569 if(usercmd
!= NULL
) free(usercmd
);
571 if(fgets(tempbuf
, 2048, pFile
) == NULL
) continue;
573 if(strlen(tempbuf
) < 10) continue;
581 if(tempbuf
[0] == '8' && tempbuf
[1] == '6' && csystem_data
->provider
== 0x11) ignoreProvid
= 1;
582 else if(strncmp(tempbuf
,"REG2" ,4) == 0)
584 dre_read_ee(reader
, &tempbuf
[4] ,csystem_data
->provider
);
587 else if(strncmp(tempbuf
,"CR" ,2) == 0)
590 cryptkey
= ((tempbuf
[2] - (tempbuf
[2] > 0x39 ? 0x37:0x30)) << 4) + ((tempbuf
[3] - (tempbuf
[3] > 0x39 ? 0x37:0x30)) & 0xF);
592 else if(tempbuf
[0] != '5' && tempbuf
[1] != '9') continue;
596 cmd_len
= strlen(tempbuf
) / 2 - 3 + ignoreProvid
- (crypted
* 2);
597 usercmd
= malloc(cmd_len
);
599 for(i
=0,n
= 4+(crypted
* 4);i
<cmd_len
;i
++,n
+=2)
601 usercmd
[i
] = ((tempbuf
[n
] - (tempbuf
[n
] > 0x39 ? 0x37:0x30)) << 4) + ((tempbuf
[n
+1] - (tempbuf
[n
+1] > 0x39 ? 0x37:0x30)) & 0xF);
604 /*if(usercmd[cmd_len-1] != csystem_data->provider && !ignoreProvid)
606 rdr_log(reader, "Skip script: current provid %02X , script provid %02X", csystem_data->provider, usercmd[cmd_len-1]);
610 rdr_log(reader
, "User script: %s", tempbuf
);
614 rdr_log(reader
, "Script %s", (dre_script(usercmd
, cmd_len
, ignoreProvid
, crypted
, cryptkey
)) ? "done" : "error");
620 rdr_log(reader
, "Can't open script file (%s)", reader
->userscript
);
623 //if(usercmd != NULL) free(usercmd);
624 if(tempbuf
!= NULL
) free(tempbuf
);
627 if(csystem_data
->provider
== 0x11)
629 memset(reader
->prid
[1], 0x00, 8);
630 reader
->prid
[1][3] = 0xFE;
634 if(!dre_set_provider_info(reader
))
635 { return ERROR
; } //fatal error
638 rdr_log(reader
, "ready for requests");
643 static void DREover(struct s_reader
*reader
, const uint8_t *ECMdata
, uint8_t *DW
)
645 uint32_t key_schedule
[32];
647 if(reader
->des_key_length
< 128)
649 rdr_log(reader
, "error: deskey is missing or too short");
653 if(ECMdata
[2] >= (43 + 4) && ECMdata
[40] == 0x3A && ECMdata
[41] == 0x4B)
655 des_set_key(&reader
->des_key
[(ECMdata
[42] & 0x0F) * 8], key_schedule
);
657 des(DW
, key_schedule
, 0); // even DW post-process
658 des(DW
+ 8, key_schedule
, 0); // odd DW post-process
662 static int32_t dre_do_ecm(struct s_reader
*reader
, const ECM_REQUEST
*er
, struct s_ecm_answer
*ea
)
665 uint16_t overcryptId
;
668 struct dre_data
*csystem_data
= reader
->csystem_data
;
669 if(reader
->caid
== 0x4ae0)
671 uchar ecmcmd41
[] = { 0x41,
672 0x58, 0x1f, 0x00, //fixed part, dont change
673 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, //0x01 - 0x08: next key
674 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, //0x11 - 0x18: current key
675 0x3b, 0x59, 0x11 //0x3b = keynumber, can be a value 56 ;; 0x59 number of package = 58+1 - Pay Package ;; 0x11 = provider
677 ecmcmd41
[22] = csystem_data
->provider
;
678 memcpy(ecmcmd41
+ 4, er
->ecm
+ 8, 16);
679 ecmcmd41
[20] = er
->ecm
[6]; //keynumber
680 ecmcmd41
[21] = 0x58 + er
->ecm
[25]; //package number
681 rdr_log_dbg(reader
, D_READER
, "unused ECM info front:%s", cs_hexdump(0, er
->ecm
, 8, tmp_dbg
, sizeof(tmp_dbg
)));
682 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
)));
683 if((dre_cmd(ecmcmd41
))) //ecm request
685 if((cta_res
[cta_lr
- 2] != 0x90) || (cta_res
[cta_lr
- 1] != 0x00))
686 { return ERROR
; } //exit if response is not 90 00
687 memcpy(ea
->cw
, cta_res
+ 11, 8);
688 memcpy(ea
->cw
+ 8, cta_res
+ 3, 8);
693 else if(reader
->caid
== 0x4ae1)
695 if(csystem_data
->provider
== 0x11 || csystem_data
->provider
== 0x14)
697 uchar ecmcmd51
[] = { 0x51, 0x02, 0x56, 0x05, 0x00, 0x4A, 0xE3, //fixed header?
698 0x9C, 0xDA, //first three nibbles count up, fourth nibble counts down; all ECMs sent twice
699 0xC1, 0x71, 0x21, 0x06, 0xF0, 0x14, 0xA7, 0x0E, //next key?
700 0x89, 0xDA, 0xC9, 0xD7, 0xFD, 0xB9, 0x06, 0xFD, //current key?
701 0xD5, 0x1E, 0x2A, 0xA3, 0xB5, 0xA0, 0x82, 0x11, //key or signature?
704 memcpy(ecmcmd51
+ 1, er
->ecm
+ 5, 0x21);
705 rdr_log_dbg(reader
, D_READER
, "unused ECM info front:%s", cs_hexdump(0, er
->ecm
, 5, tmp_dbg
, sizeof(tmp_dbg
)));
706 rdr_log_dbg(reader
, D_READER
, "unused ECM info back:%s", cs_hexdump(0, er
->ecm
+ 37, 4, tmp_dbg
, sizeof(tmp_dbg
)));
707 ecmcmd51
[33] = csystem_data
->provider
; //no part of sig
709 if((dre_cmd(ecmcmd51
))) //ecm request
711 if((cta_res
[cta_lr
- 2] != 0x90) || (cta_res
[cta_lr
- 1] != 0x00))
712 { return ERROR
; } //exit if response is not 90 00
714 if(er
->ecm
[2] >= 46 && er
->ecm
[43] == 1 && csystem_data
->provider
== 0x11)
716 memcpy(tmp
, cta_res
+ 11, 8);
717 memcpy(tmp
+ 8, cta_res
+ 3, 8);
718 overcryptId
= b2i(2, &er
->ecm
[44]);
719 rdr_log_dbg(reader
, D_READER
, "ICG ID: %04X", overcryptId
);
720 Drecrypt2OverCW(overcryptId
,tmp
);
723 memcpy(ea
->cw
, tmp
, 16);
729 DREover(reader
, er
->ecm
, cta_res
+ 3);
731 if(isValidDCW(cta_res
+ 3))
733 memcpy(ea
->cw
, cta_res
+ 11, 8);
734 memcpy(ea
->cw
+ 8, cta_res
+ 3, 8);
739 else if((csystem_data
->provider
== 0x02 || csystem_data
->provider
== 0x03) && er
->ecm
[3] == 3)
745 memcpy( ea
->cw
, &er
->ecm
[42], 8);
746 memcpy(&ea
->cw
[8], &er
->ecm
[34], 8);
751 uchar crypted
= er
->ecm
[8] & 1;
752 uchar cryptkey
= (er
->ecm
[8] & 6) >> 1;
763 uchar ecmcmd
[cmdlen
];
765 memcpy(ecmcmd
, &er
->ecm
[17], cmdlen
-1);
766 ecmcmd
[cmdlen
-1] = csystem_data
->provider
;
768 dre_cmd_c(ecmcmd
, crypted
, cryptkey
);
770 if(cta_res
[2] == 0xD2 && isValidDCW(cta_res
+ 3))
772 memcpy(ea
->cw
, cta_res
+11, 8);
773 memcpy(ea
->cw
+8, cta_res
+3, 8);
778 else if(reader
->caid
== 0x2710 && er
->ecm
[3] == 4)
784 memcpy( ea
->cw
, &er
->ecm
[22], 8);
785 memcpy(&ea
->cw
[8], &er
->ecm
[14], 8);
790 uchar crypted
= er
->ecm
[8] & 1;
791 uchar cryptkey
= (er
->ecm
[8] & 6) >> 1;
802 uchar ecmcmd
[cmdlen
];
804 memcpy(ecmcmd
, &er
->ecm
[9], cmdlen
-1);
805 ecmcmd
[cmdlen
-1] = csystem_data
->provider
;
807 dre_cmd_c(ecmcmd
, crypted
, cryptkey
);
809 if(cta_res
[2] == 0xD2 && isValidDCW(cta_res
+ 3))
811 memcpy(ea
->cw
, cta_res
+11, 8);
812 memcpy(ea
->cw
+8, cta_res
+3, 8);
819 static int32_t dre_do_emm(struct s_reader
*reader
, EMM_PACKET
*ep
)
822 struct dre_data
*csystem_data
= reader
->csystem_data
;
824 if(reader
->caid
== 0x4ae1)
826 if(reader
->caid
!= b2i(2, ep
->caid
)) return ERROR
;
828 if(ep
->type
== UNIQUE
&& ep
->emm
[39] == 0x3d)
830 /* For new package activation. */
833 memcpy(&emmcmd58
[1], &ep
->emm
[40], 24);
834 emmcmd58
[25] = csystem_data
->provider
;
835 if((dre_cmd(emmcmd58
)))
836 if((cta_res
[cta_lr
- 2] != 0x90) || (cta_res
[cta_lr
- 1] != 0x00))
839 else if(ep
->emm
[0] == 0x86 && ep
->emm
[4] == 0x02 /*&& csystem_data->provider != 0x11*/)
841 uchar emmcmd52
[0x3a];
844 for(i
= 0; i
< 2; i
++)
846 memcpy(emmcmd52
+ 1, ep
->emm
+ 5 + 32 + i
* 56, 56);
847 // check for shared address
848 if(ep
->emm
[3] != reader
->sa
[0][0])
849 { return OK
; } // ignore, wrong address
850 emmcmd52
[0x39] = csystem_data
->provider
;
851 if((dre_cmd(emmcmd52
)))
852 if((cta_res
[cta_lr
- 2] != 0x90) || (cta_res
[cta_lr
- 1] != 0x00))
853 { return ERROR
; } //exit if response is not 90 00
856 else if(ep
->emm
[0] == 0x86 && ep
->emm
[4] == 0x4D && csystem_data
->provider
== 0x11)
858 uchar emmcmd52
[0x3a];
861 emmcmd52
[2] = ep
->emm
[5];
863 emmcmd52
[4] = ep
->emm
[3];
870 memcpy(emmcmd52
+ 13, ep
->emm
+ 0x5C, 4);
873 for(i
= 0; i
< 2; i
++)
875 emmcmd52
[8] = ep
->emm
[0x61+i
*0x29];
876 if(i
== 0) emmcmd52
[12] = ep
->emm
[0x60] == 0x56 ? 0x56:0x3B;
877 else emmcmd52
[12] = ep
->emm
[0x60] == 0x56 ? 0x3B:0x56;
878 memcpy(emmcmd52
+ 0x11, ep
->emm
+ 0x62 + i
* 0x29, 40);
880 // check for shared address
881 if(ep
->emm
[3] != reader
->sa
[0][0])
882 { return OK
; } // ignore, wrong address
883 emmcmd52
[0x39] = csystem_data
->provider
;
884 if((dre_cmd(emmcmd52
)))
885 if((cta_res
[cta_lr
- 2] != 0x90) || (cta_res
[cta_lr
- 1] != 0x00))
886 { return ERROR
; } //exit if response is not 90 00
889 else if (ep
->emm
[0] == 0x8c && (csystem_data
->provider
== 0x02 || csystem_data
->provider
== 0x03)) //dre3 group emm
891 if(ep
->emm
[3] != reader
->sa
[0][0])
892 { return OK
; } // ignore, wrong address
894 uchar crypted
= ep
->emm
[10];
896 if ((crypted
& 1) == 1)
900 memcpy(emmcmd
, &ep
->emm
[0x13], 0x48);
902 emmcmd
[0x48] = csystem_data
->provider
;
904 dre_cmd_c(emmcmd
, crypted
& 1, (crypted
& 6) >> 1);
906 if((cta_res
[cta_lr
- 2] != 0x90) || (cta_res
[cta_lr
- 1] != 0x00))
907 { return ERROR
; } //exit if response is not 90 00
909 memcpy(emmcmd
, &ep
->emm
[0x5B], 0x48);
911 emmcmd
[0x48] = csystem_data
->provider
;
913 dre_cmd_c(emmcmd
, crypted
& 1, (crypted
& 6) >>1);
915 if((cta_res
[cta_lr
- 2] != 0x90) || (cta_res
[cta_lr
- 1] != 0x00))
916 { return ERROR
; } //exit if response is not 90 00
924 memcpy(emmcmd
, &ep
->emm
[0x13], 0x41);
926 emmcmd
[0x41] = csystem_data
->provider
;
928 dre_cmd_c(emmcmd
, crypted
& 1, (crypted
& 6) >>1);
930 if((cta_res
[cta_lr
- 2] != 0x90) || (cta_res
[cta_lr
- 1] != 0x00))
931 { return ERROR
; } //exit if response is not 90 00
933 memcpy(emmcmd
, &ep
->emm
[0x5B], 0x41);
935 emmcmd
[0x41] = csystem_data
->provider
;
937 dre_cmd_c(emmcmd
, crypted
& 1, (crypted
& 6) >>1);
939 if((cta_res
[cta_lr
- 2] != 0x90) || (cta_res
[cta_lr
- 1] != 0x00))
940 { return ERROR
; } //exit if response is not 90 00
945 else if(ep
->type
== GLOBAL
&& ep
->emm
[0] == 0x91)
947 Drecrypt2OverEMM(ep
->emm
);
952 else if(reader
->caid
== 0x2710)
955 if(ep
->type
== UNIQUE
)
958 uchar
class, hlbUA
, KEYindex
;
960 uchar CMDtype
= ep
->emm
[7];
961 uint16_t EMMlen
= ep
->emm
[2] | ((ep
->emm
[1] & 0xF) << 8);
962 uchar cryptflag
= ep
->emm
[10];
963 uchar crypted
= cryptflag
& 1;
964 uchar cryptkey
= (cryptflag
& 6) >> 1;
966 if ( CMDtype
== 0x61 )
971 emmcmd91
[1] = ep
->emm
[19];
972 emmcmd91
[2] = ep
->emm
[8];
973 emmcmd91
[3] = ep
->emm
[20];
974 if(reader
->force_ua
) emmcmd91
[3] += 2;
975 memcpy(&emmcmd91
[4], &reader
->hexserial
[2], 4);
977 emmcmd91
[17] = ep
->emm
[22];
978 emmcmd91
[18] = csystem_data
->provider
;
980 if ( (EMMlen
- 24) > 16 )
982 hlbUA
= reader
->hexserial
[5] & 0xF;
984 uint16_t keypos
= cryptflag
== 2 ? 17 : 9;
985 keycount
= (EMMlen
- 24) / keypos
;
987 for(i
=0; i
<= keycount
;i
++)
989 if ( i
== keycount
) return OK
;
990 if ( hlbUA
== (ep
->emm
[23+(keypos
*i
)] & 0xF) ) break;
993 keypos
= 24 + (keypos
*i
);
995 memcpy(&emmcmd91
[9], &ep
->emm
[keypos
], 8);
997 if((dre_cmd(emmcmd91
)))
998 if((cta_res
[cta_lr
- 2] != 0x90) || (cta_res
[cta_lr
- 1] != 0x00) || (cta_res
[2] != 0xA2) )
999 return ERROR
; //exit if response is not 90 00
1001 if ( cryptflag
== 2 )
1003 if ( emmcmd91
[17] == 0x56 ) KEYindex
= 0x3B;
1004 else KEYindex
= 0x56;
1007 memcpy(&emmcmd91
[9], &ep
->emm
[keypos
], 8);
1008 emmcmd91
[17] = KEYindex
;
1012 if((cta_res
[cta_lr
- 2] != 0x90) || (cta_res
[cta_lr
- 1] != 0x00) || (cta_res
[2] != 0xA2))
1013 { return ERROR
; } //exit if response is not 90 00
1020 else if ( CMDtype
== 0x62 )
1022 if ( !memcmp(&reader
->hexserial
[2], &ep
->emm
[3], 4) )
1033 uchar emmcmd92
[cmdlen
];
1035 memcpy(emmcmd92
, &ep
->emm
[19], cmdlen
- 1);
1036 emmcmd92
[cmdlen
-1] = csystem_data
->provider
;
1040 dre_cmd_c(emmcmd92
, crypted
, cryptkey
);
1047 if((cta_res
[cta_lr
- 2] != 0x90) || (cta_res
[cta_lr
- 1] != 0x00))
1048 { return ERROR
; } //exit if response is not 90 00
1056 emmcmd95
[1] = class;
1057 emmcmd95
[2] = csystem_data
->provider
;
1064 emmcmd91
[1] = ep
->emm
[102];
1065 emmcmd91
[2] = ep
->emm
[8];
1066 emmcmd91
[3] = ep
->emm
[103];
1067 if(reader
->force_ua
) emmcmd91
[3] += 2;
1068 memcpy(&emmcmd91
[4], &reader
->hexserial
[2], 4);
1069 emmcmd91
[8] = ep
->emm
[104];
1070 memcpy(&emmcmd91
[9], &ep
->emm
[72], 8);
1071 emmcmd91
[17] = ep
->emm
[105];
1072 emmcmd91
[18] = csystem_data
->provider
;
1076 if((cta_res
[cta_lr
- 2] != 0x90) || (cta_res
[cta_lr
- 1] != 0x00) || (cta_res
[2] != 0xA2) )
1077 { return ERROR
; } //exit if response is not 90 00
1079 if ( emmcmd91
[17] == 0x56 ) KEYindex
= 0x3B;
1080 else KEYindex
= 0x56;
1082 memcpy(&emmcmd91
[9], &ep
->emm
[86], 8);
1083 emmcmd91
[17] = KEYindex
;
1087 if((cta_res
[cta_lr
- 2] != 0x90) || (cta_res
[cta_lr
- 1] != 0x00) )
1088 { return ERROR
; } //exit if response is not 90 00
1094 if ( memcmp(&reader
->hexserial
[2], &ep
->emm
[3], 4) ) return OK
;
1096 if ( CMDtype
== 0x63 )
1102 memcpy(&emmcmdA5
[2], &reader
->hexserial
[2], 4);
1103 emmcmdA5
[6] = csystem_data
->provider
;
1107 if((cta_res
[cta_lr
- 2] != 0x90) || (cta_res
[cta_lr
- 1] != 0x00))
1108 { return ERROR
; } //exit if response is not 90 00
1111 if ( crypted
) cmdlen
= EMMlen
- 19;
1112 else cmdlen
= ep
->emm
[11] + 1;
1114 uchar emmcmd
[cmdlen
];
1116 memcpy(emmcmd
, &ep
->emm
[19], cmdlen
-1);
1117 emmcmd
[cmdlen
-1] = csystem_data
->provider
;
1119 if(emmcmd
[0] == 0x45)
1121 cs_log("TRICOLOR Send KILL command for your card");
1125 dre_cmd_c(emmcmd
, crypted
, cryptkey
);
1127 if((cta_res
[cta_lr
- 2] != 0x90) || (cta_res
[cta_lr
- 1] != 0x00))
1128 { return ERROR
; } //exit if response is not 90 00
1134 else if(reader
->caid
!= 0x2710 && reader
->caid
!= 0x4AE1)
1138 0x42, 0x85, 0x58, 0x01, 0xC8, 0x00, 0x00, 0x00, 0x05, 0xB8, 0x0C, 0xBD, 0x7B, 0x07, 0x04, 0xC8,
1139 0x77, 0x31, 0x95, 0xF2, 0x30, 0xB7, 0xE9, 0xEE, 0x0F, 0x81, 0x39, 0x1C, 0x1F, 0xA9, 0x11, 0x3E,
1140 0xE5, 0x0E, 0x8E, 0x50, 0xA4, 0x31, 0xBB, 0x01, 0x00, 0xD6, 0xAF, 0x69, 0x60, 0x04, 0x70, 0x3A,
1148 for(i
= 0; i
< 2; i
++)
1150 memcpy(emmcmd42
+ 1, ep
->emm
+ 42 + i
* 49, 48);
1151 emmcmd42
[49] = ep
->emm
[i
* 49 + 41]; //keynr
1152 emmcmd42
[50] = 0x58 + ep
->emm
[40]; //package nr
1153 emmcmd42
[51] = csystem_data
->provider
;
1154 if((dre_cmd(emmcmd42
)))
1156 if((cta_res
[cta_lr
- 2] != 0x90) || (cta_res
[cta_lr
- 1] != 0x00))
1157 { return ERROR
; } //exit if response is not 90 00
1163 memcpy(emmcmd42
+ 1, ep
->emm
+ 6, 48);
1164 emmcmd42
[51] = csystem_data
->provider
;
1165 //emmcmd42[50] = ecmcmd42[2]; //TODO package nr could also be fixed 0x58
1166 emmcmd42
[50] = 0x58;
1167 emmcmd42
[49] = ep
->emm
[5]; //keynr
1169 59 05 A2 02 05 01 5B
1171 if((dre_cmd(emmcmd42
))) //first emm request
1173 if((cta_res
[cta_lr
- 2] != 0x90) || (cta_res
[cta_lr
- 1] != 0x00))
1174 { return ERROR
; } //exit if response is not 90 00
1176 memcpy(emmcmd42
+ 1, ep
->emm
+ 55, 7); //TODO OR next two lines?
1177 /*memcpy (emmcmd42 + 1, ep->emm + 55, 7); //FIXME either I cant count or my EMM log contains errors
1178 memcpy (emmcmd42 + 8, ep->emm + 67, 41); */
1179 emmcmd42
[51] = csystem_data
->provider
;
1180 //emmcmd42[50] = ecmcmd42[2]; //TODO package nr could also be fixed 0x58
1181 emmcmd42
[50] = 0x58;
1182 emmcmd42
[49] = ep
->emm
[54]; //keynr
1183 if((dre_cmd(emmcmd42
))) //second emm request
1185 if((cta_res
[cta_lr
- 2] != 0x90) || (cta_res
[cta_lr
- 1] != 0x00))
1186 { return ERROR
; } //exit if response is not 90 00
1195 static int32_t dre_card_info(struct s_reader
*UNUSED(rdr
))
1200 const struct s_cardsystem reader_dre
=
1203 .caids
= (uint16_t[]){ 0x4AE0, 0x4AE1, 0x7BE0, 0x7BE1, 0x2710, 0 },
1204 .do_emm
= dre_do_emm
,
1205 .do_ecm
= dre_do_ecm
,
1206 .card_info
= dre_card_info
,
1207 .card_init
= dre_card_init
,
1208 .get_emm_type
= dre_common_get_emm_type
,
1209 .get_emm_filter
= dre_common_get_emm_filter
,