3 #include "cscrypt/des.h"
4 #include "reader-common.h"
5 #include "reader-dre-common.h"
6 #include "csctapi/icc_async.h"
15 uint8_t stmcmd34
[64][0x30];
18 uint8_t stm_curkey
[2] = {0,0};
19 extern char cs_confdir
[128];
21 #define MSP_CMD_BYTE 0x59
22 #define STM_CMD_BYTE 0x74
23 #define MOD_CMD_BYTE 0xDB
28 static void stm_key_operaion(struct s_reader
*reader
, int operation
)
34 if(reader
->stmkeys
== NULL
)
36 snprintf(stmkeyfile
,256,"%sstmkeys.bin",cs_confdir
);
40 if(strchr(reader
->stmkeys
, '/') == NULL
)
42 snprintf(stmkeyfile
,256,"%s%s",cs_confdir
, reader
->stmkeys
);
46 snprintf(stmkeyfile
,256,"%s",reader
->stmkeys
);
50 if((file
= fopen(stmkeyfile
, operation
== READ
? "rb":"wb")) == NULL
)
52 cs_log("Error: can't' open stm key file (%s)", stmkeyfile
);
56 if(operation
== WRITE
)
58 i
= fwrite(&stm_keys_t
, sizeof(stm_keys_t
), 1, file
);
62 i
= fread(&stm_keys_t
, sizeof(stm_keys_t
), 1, file
);
67 if(!i
) cs_log("Error read/write stm key file (%s)", stmkeyfile
);
70 static uchar
xor(const uchar
*cmd
, int32_t cmdlen
)
73 uchar checksum
= 0x00;
74 for(i
= 0; i
< cmdlen
; i
++)
75 { checksum
^= cmd
[i
]; }
79 static int8_t isValidDCW(uint8_t *dw
)
81 if (((dw
[0]+dw
[1]+dw
[2]) & 0xFF) != dw
[3])
85 if (((dw
[4]+dw
[5]+dw
[6]) & 0xFF) != dw
[7])
89 if (((dw
[8]+dw
[9]+dw
[10]) & 0xFF) != dw
[11])
93 if (((dw
[12]+dw
[13]+dw
[14]) & 0xFF) != dw
[15])
100 static int32_t drecas_send_cmd(struct s_reader
*reader
, uchar
*cmd
, int32_t cmdlen
, unsigned char *cta_res
, uint16_t *p_cta_lr
, uint8_t dest
)
102 uchar startcmd
[3] = { 0xDB, 0x00, 0x00 }; //any command starts with this,
103 //last byte is nr of bytes of the command that will be sent
108 startcmd
[1] = cmdlen
+ 2; //command+length + len + checksum bytes
111 memcpy(command
, startcmd
, 3);
112 memcpy(command
+ 3, cmd
, cmdlen
);
114 checksum
= xor(command
+2, cmdlen
-2);
115 command
[cmdlen
++] = checksum
;
117 rdr_log_dbg(reader
, D_READER
, "write to module: %s", cs_hexdump(0, command
, cmdlen
, tmp
, sizeof(tmp
)));
119 ICC_Async_Transmit(reader
, (uint32_t) cmdlen
, 0, command
, 0, 200);
120 ICC_Async_Receive(reader
, 2, cta_res
, 50, 3000000);
122 ICC_Async_Receive(reader
, cta_res
[1], cta_res
+2, 50, 3000000);
123 *p_cta_lr
= cta_res
[1] + 2;
125 rdr_log_dbg(reader
, D_READER
, "answer from module: %s", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
127 checksum
= xor(cta_res
+ 2, *p_cta_lr
- 3);
129 if(cta_res
[*p_cta_lr
- 1] != checksum
)
131 rdr_log(reader
, "checksum does not match, expected %02x received %02x:%s", checksum
,
132 cta_res
[*p_cta_lr
- 1], cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
133 return ERROR
; //error
139 static int32_t drecas_MSP_command(struct s_reader
*reader
, const uchar
*cmd
, int32_t cmdlen
, unsigned char *cta_res
, uint16_t *p_cta_lr
)
140 //attention: inputcommand will be changed!!!! answer will be in cta_res, length cta_lr ; returning 1 = no error, return ERROR = err
142 uchar startcmd
[] = { 0x80, 0xFF, 0x10, 0x01, 0x05 }; //any command starts with this,
147 startcmd
[4] = cmdlen
+ 3; //command+length + len + checksum bytes
148 memcpy(command
, startcmd
, 5);
149 command
[5] = MSP_CMD_BYTE
; //type
150 command
[6] = cmdlen
+ 1; //len = command + 1 checksum byte
151 memcpy(command
+ 7, cmd
, cmdlen
);
153 checksum
= ~xor(cmd
, cmdlen
);
156 command
[cmdlen
++] = checksum
;
158 if(drecas_send_cmd(reader
, command
, cmdlen
, cta_res
, p_cta_lr
, 1) != OK
) return ERROR
;
160 if(cta_res
[4] != MSP_CMD_BYTE
) return ERROR
;
162 if((cta_res
[5] == 0x03) && (cta_res
[6] == 0xe2))
167 rdr_log(reader
, "checksum error: %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
170 rdr_log(reader
, "wrong cmd len: %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
173 rdr_log(reader
, "illegal command: %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
176 rdr_log(reader
, "wrong adress type: %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
179 rdr_log(reader
, "wrong CMD param: %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
182 rdr_log(reader
, "wrong UA: %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
185 rdr_log(reader
, "wrong group: %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
188 rdr_log(reader
, "wrong key num: %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
191 rdr_log(reader
, "No key or subscribe : %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
194 rdr_log(reader
, "wrong signature: %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
197 rdr_log(reader
, "wrong provider: %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
200 rdr_log(reader
, "wrong GEO code: %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
203 rdr_log_dbg(reader
, D_READER
, "unknown error: %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
206 return ERROR
; //error
209 int32_t length_excl_leader
= *p_cta_lr
;
211 checksum
= ~xor(cta_res
+ 6, length_excl_leader
- 8);
213 if(cta_res
[length_excl_leader
- 2] != checksum
)
215 rdr_log(reader
, "checksum does not match, expected %02x received %02x:%s", checksum
,
216 cta_res
[length_excl_leader
- 2], cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
217 return ERROR
; //error
223 #define drecas_MSP_script(cmd, len) \
225 drecas_MSP_command(reader, cmd, len, cta_res, &cta_lr); \
228 #define drecas_MSP_cmd(cmd) \
230 drecas_MSP_command(reader, cmd, sizeof(cmd), cta_res, &cta_lr); \
233 static int32_t drecas_STM_command(struct s_reader
*reader
, const uchar
*cmd
, int32_t cmdlen
, unsigned char *cta_res
, uint16_t *p_cta_lr
)
234 //attention: inputcommand will be changed!!!! answer will be in cta_res, length cta_lr ; returning 1 = no error, return ERROR = err
241 command
[1] = STM_CMD_BYTE
; //type
242 command
[2] = cmdlen
+ 1; //len = command + 1 checksum byte
243 memcpy(command
+ 3, cmd
, cmdlen
);
245 checksum
= ~xor(cmd
, cmdlen
);
248 command
[cmdlen
++] = checksum
;
250 if(drecas_send_cmd(reader
, command
, cmdlen
, cta_res
, p_cta_lr
, 0) != OK
) return ERROR
;
252 if(cta_res
[4] != STM_CMD_BYTE
) return ERROR
;
254 if((cta_res
[5] == 0x03) && (cta_res
[6] == 0xe2))
259 rdr_log(reader
, "checksum error: %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
262 rdr_log(reader
, "wrong cmd len: %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
265 rdr_log(reader
, "illegal command: %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
268 rdr_log(reader
, "wrong adress type: %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
271 rdr_log(reader
, "wrong CMD param: %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
274 rdr_log(reader
, "wrong UA: %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
277 rdr_log(reader
, "wrong group: %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
280 rdr_log(reader
, "wrong key num: %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
283 rdr_log(reader
, "No key or subscribe : %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
286 rdr_log(reader
, "wrong signature: %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
289 rdr_log(reader
, "wrong provider: %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
292 rdr_log(reader
, "wrong GEO code: %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
295 rdr_log_dbg(reader
, D_READER
, "unknown error: %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
298 return ERROR
; //error
301 int32_t length_excl_leader
= *p_cta_lr
;
303 checksum
= ~xor(cta_res
+ 6, length_excl_leader
- 8);
305 if(cta_res
[length_excl_leader
- 2] != checksum
)
307 rdr_log(reader
, "checksum does not match, expected %02x received %02x:%s", checksum
,
308 cta_res
[length_excl_leader
- 2], cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
309 return ERROR
; //error
315 #define drecas_STM_script(cmd, len) \
317 drecas_STM_command(reader, cmd, len, cta_res, &cta_lr); \
320 #define drecas_STM_cmd(cmd) \
322 drecas_STM_command(reader, cmd, sizeof(cmd), cta_res, &cta_lr); \
325 static int32_t drecas_set_provider_info(struct s_reader
*reader
)
329 uchar subscr
[] = { 0x59, 0x14 }; // subscriptions
330 uchar dates
[] = { 0x5b, 0x00, 0x14 }; //validity dates
331 struct dre_data
*csystem_data
= reader
->csystem_data
;
332 subscr
[1] = csystem_data
->provider
;
334 cs_clear_entitlement(reader
);
336 if((drecas_MSP_cmd(subscr
))) //ask subscription packages, returns error on 0x11 card
340 memcpy(pbm
, cta_res
+ 7, 32);
341 rdr_log_dbg(reader
, D_READER
, "pbm: %s", cs_hexdump(0, pbm
, 32, tmp_dbg
, sizeof(tmp_dbg
)));
343 for(i
= 0; i
< 32; i
++)
347 dates
[2] = csystem_data
->provider
;
348 drecas_MSP_cmd(dates
); //ask for validity dates
352 start
= (cta_res
[7] << 24) | (cta_res
[8] << 16) | (cta_res
[9] << 8) | cta_res
[10];
353 end
= (cta_res
[11] << 24) | (cta_res
[12] << 16) | (cta_res
[13] << 8) | cta_res
[14];
357 localtime_r(&start
, &temp
);
358 int32_t startyear
= temp
.tm_year
+ 1900;
359 int32_t startmonth
= temp
.tm_mon
+ 1;
360 int32_t startday
= temp
.tm_mday
;
361 localtime_r(&end
, &temp
);
362 int32_t endyear
= temp
.tm_year
+ 1900;
363 int32_t endmonth
= temp
.tm_mon
+ 1;
364 int32_t endday
= temp
.tm_mday
;
365 rdr_log(reader
, "active package %i valid from %04i/%02i/%02i to %04i/%02i/%02i", i
, startyear
, startmonth
, startday
,
366 endyear
, endmonth
, endday
);
367 cs_add_entitlement(reader
, reader
->caid
, b2ll(4, reader
->prid
[0]), 0, i
, start
, end
, 5, 1);
374 static int32_t drecas_card_init(struct s_reader
*reader
, ATR
*newatr
)
378 uchar ua
[] = { 0x43, 0x15 }; // get serial number (UA)
379 uchar providers
[] = { 0x49, 0x15 }; // get providers
383 uint8_t module_atr
[] = { 0xDB ,0x0B ,0x08 ,0xA3 ,0x3B ,0x15 ,0x11 ,0x12 ,0x01 ,0x01 ,0x11 ,0x07 ,0x90 };
385 if(memcmp(atr
, module_atr
, sizeof(module_atr
)) != 0)
388 if(!cs_malloc(&reader
->csystem_data
, sizeof(struct dre_data
)))
390 struct dre_data
*csystem_data
= reader
->csystem_data
;
392 csystem_data
->provider
= atr
[10];
393 uchar checksum
= xor(atr
+ 5, 6);
395 if(checksum
!= atr
[11])
396 { rdr_log(reader
, "warning: expected ATR checksum %02x, smartcard reports %02x", checksum
, atr
[7]); }
401 card
= "Tricolor Centr DRE2";
402 reader
->caid
= 0x4ae1;
403 break; //59 type card = MSP (74 type = ATMEL)
406 card
= "Tricolor Syberia DRE2";
407 reader
->caid
= 0x4ae1;
408 break; //59 type card
414 memset(reader
->prid
, 0x00, 8);
416 reader
->prid
[0][3] = csystem_data
->provider
;
418 uchar cmd54
[] = { 0x54, 0x14 }; // geocode
419 cmd54
[1] = csystem_data
->provider
;
421 if((drecas_MSP_cmd(cmd54
))) //error would not be fatal, like on 0x11 cards
422 { geocode
= cta_res
[7]; }
424 providers
[1] = csystem_data
->provider
;
425 if(!(drecas_MSP_cmd(providers
)))
426 { return ERROR
; } //fatal error
427 if((cta_res
[2] != 0x09) || (cta_res
[3] != 0xC0))
431 for(i
= 0; ((i
< cta_res
[6] - 6) && (i
< 128)); i
++)
433 provname
[i
] = cta_res
[10 + i
];
434 if(provname
[i
] == 0x00)
438 int32_t major_version
= cta_res
[7];
439 int32_t minor_version
= cta_res
[8];
441 ua
[1] = csystem_data
->provider
;
442 drecas_MSP_cmd(ua
); //error would not be fatal
444 int32_t hexlength
= cta_res
[5] - 2; //discard first and last byte, last byte is always checksum, first is answer code
448 rdr_log(reader
, "WARNING!!!! used UA from force_ua %08X", reader
->force_ua
);
449 memcpy(cta_res
+ 7, &reader
->force_ua
, 8);
452 reader
->hexserial
[0] = 0;
453 reader
->hexserial
[1] = 0;
454 memcpy(reader
->hexserial
+ 2, cta_res
+ 7, hexlength
);
456 int32_t low_dre_id
, dre_chksum
;
459 low_dre_id
= ((cta_res
[8] << 16) | (cta_res
[9] << 8) | cta_res
[10]) - 48608;
461 snprintf((char *)buf
, sizeof(buf
), "%i%i%08i", csystem_data
->provider
- 16, major_version
+ 1, low_dre_id
);
463 for(i
= 0; i
< 32; i
++)
467 dre_chksum
+= buf
[i
] - 48;
470 rdr_log(reader
, "type: DRE Crypt, caid: %04X, serial: {%s}, dre id: %i%i%i%08i, geocode %i, card: %s v%i.%i",
471 reader
->caid
, cs_hexdump(0, reader
->hexserial
+ 2, 4, tmp
, sizeof(tmp
)), dre_chksum
, csystem_data
->provider
- 16,
472 major_version
+ 1, low_dre_id
, geocode
, card
, major_version
, minor_version
);
474 rdr_log(reader
, "Provider name:%s.", provname
);
477 memset(reader
->sa
, 0, sizeof(reader
->sa
));
478 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...
480 rdr_log_sensitive(reader
, "SA = %02X%02X%02X%02X, UA = {%s}", reader
->sa
[0][0], reader
->sa
[0][1], reader
->sa
[0][2],
481 reader
->sa
[0][3], cs_hexdump(0, reader
->hexserial
+ 2, 4, tmp
, sizeof(tmp
)));
485 // exec user script, wicardd format
486 if(reader
->userscript
!= NULL
)
488 uint8_t *usercmd
= NULL
;
491 char *tempbuf
= malloc(2048);
492 trim2(reader
->userscript
);
493 FILE *pFile
= fopen(reader
->userscript
, "rt");
500 if(usercmd
!= NULL
) free(usercmd
);
502 if(fgets(tempbuf
, 2048, pFile
) == NULL
) continue;
504 if(strlen(tempbuf
) < 10) continue;
508 if((tempbuf
[0] != '5' && tempbuf
[1] != '9') && (tempbuf
[0] != '7' && tempbuf
[1] != '4')) continue;
512 cmd_len
= strlen(tempbuf
) / 2 - 3;
513 usercmd
= malloc(cmd_len
);
515 for(i
=0,n
=4; i
<cmd_len
; i
++, n
+=2)
517 usercmd
[i
] = ((tempbuf
[n
] - (tempbuf
[n
] > 0x39 ? 0x37:0x30)) << 4) + ((tempbuf
[n
+1] - (tempbuf
[n
+1] > 0x39 ? 0x37:0x30)) & 0xF);
520 if(tempbuf
[0] != '7' && tempbuf
[1] != '4')
522 rdr_log(reader
, "Script %s", (drecas_MSP_script(usercmd
, cmd_len
)) ? "done" : "error");
526 rdr_log(reader
, "Script %s", (drecas_STM_script(usercmd
, cmd_len
)) ? "done" : "error");
533 rdr_log(reader
, "Can't open script file (%s)", reader
->userscript
);
536 //if(usercmd != NULL) free(usercmd);
537 if(tempbuf
!= NULL
) free(tempbuf
);
540 if(csystem_data
->provider
== 0x11)
542 memset(reader
->prid
[1], 0x00, 8);
543 reader
->prid
[1][3] = 0xFE;
547 if(!drecas_set_provider_info(reader
))
548 { return ERROR
; } //fatal error
550 stm_key_operaion(reader
, READ
);
552 rdr_log(reader
, "ready for requests");
556 static void DREover(struct s_reader
*reader
, const uint8_t *ECMdata
, uint8_t *DW
)
558 uint32_t key_schedule
[32];
560 if(reader
->des_key_length
< 128)
562 rdr_log(reader
, "error: deskey is missing or too short");
566 if(ECMdata
[2] >= (43 + 4) && ECMdata
[40] == 0x3A && ECMdata
[41] == 0x4B)
568 des_set_key(&reader
->des_key
[(ECMdata
[42] & 0x0F) * 8], key_schedule
);
570 des(DW
, key_schedule
, 0); // even DW post-process
571 des(DW
+ 8, key_schedule
, 0); // odd DW post-process
575 static int32_t drecas_do_ecm(struct s_reader
*reader
, const ECM_REQUEST
*er
, struct s_ecm_answer
*ea
)
578 uint16_t overcryptId
;
581 struct dre_data
*csystem_data
= reader
->csystem_data
;
583 if(reader
->caid
== 0x4ae1)
585 if(csystem_data
->provider
== 0x11 || csystem_data
->provider
== 0x14)
587 uchar ecmcmd51
[] = { 0x51, 0x02, 0x56, 0x05, 0x00, 0x4A, 0xE3, //fixed header?
588 0x9C, 0xDA, //first three nibbles count up, fourth nibble counts down; all ECMs sent twice
589 0xC1, 0x71, 0x21, 0x06, 0xF0, 0x14, 0xA7, 0x0E, //next key?
590 0x89, 0xDA, 0xC9, 0xD7, 0xFD, 0xB9, 0x06, 0xFD, //current key?
591 0xD5, 0x1E, 0x2A, 0xA3, 0xB5, 0xA0, 0x82, 0x11, //key or signature?
594 memcpy(ecmcmd51
+ 1, er
->ecm
+ 5, 0x21);
595 rdr_log_dbg(reader
, D_READER
, "unused ECM info front:%s", cs_hexdump(0, er
->ecm
, 5, tmp_dbg
, sizeof(tmp_dbg
)));
596 rdr_log_dbg(reader
, D_READER
, "unused ECM info back:%s", cs_hexdump(0, er
->ecm
+ 37, 4, tmp_dbg
, sizeof(tmp_dbg
)));
598 rdr_log_dbg(reader
, D_READER
, "ECM: %s",cs_hexdump(0, er
->ecm
, er
->ecm
[2]+3, tmp_dbg
, sizeof(tmp_dbg
)));
600 ecmcmd51
[33] = csystem_data
->provider
; //no part of sig
602 if((drecas_MSP_cmd(ecmcmd51
))) //ecm request
604 if((cta_res
[2] != 0x09) || (cta_res
[3] != 0xC0))
605 { return ERROR
; } //exit if response is not 90 00
607 if(er
->ecm
[3] == 0x01)
609 uchar ecmcmd33
[18] = { 0x33, 0x1F,
610 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
611 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
618 ecmcmd33
[i
+2] = cta_res
[7+(i
^3)];
621 if(er
->ecm
[5] != stm_curkey
[0] || er
->ecm
[6] != stm_curkey
[1])
624 memset(blank
, 0, 0x30);
626 if(memcmp(blank
, stm_keys_t
.stmcmd34
[er
->ecm
[5]+(er
->ecm
[6] == 0x3B?0:32)], 0x30) == 0)
628 rdr_log_dbg(reader
, D_READER
, "STM key not found");
632 if(!(drecas_STM_cmd(stm_keys_t
.stmcmd34
[er
->ecm
[5]+(er
->ecm
[6] == 0x3B?0:32)])))
634 rdr_log_dbg(reader
, D_READER
, "Error STM set key: %s",cs_hexdump(0, cta_res
, cta_lr
, tmp_dbg
, sizeof(tmp_dbg
)));
638 if((cta_res
[cta_lr
-4] != 0x02) || (cta_res
[cta_lr
-3] != 0xA2))
640 rdr_log_dbg(reader
, D_READER
, "Error STM set key: %s",cs_hexdump(0, cta_res
, cta_lr
, tmp_dbg
, sizeof(tmp_dbg
)));
645 stm_curkey
[0] = er
->ecm
[5];
646 stm_curkey
[1] = er
->ecm
[6];
648 if(!(drecas_STM_cmd(ecmcmd33
)))
651 if(cta_res
[1] != 0x17 || cta_res
[6] != 0xD2)
654 memcpy(tmp
, &cta_res
[7], 16);
658 cta_res
[i
+7] = tmp
[i
^3];
662 if(er
->ecm
[2] >= 46 && er
->ecm
[43] == 1 && csystem_data
->provider
== 0x11)
664 memcpy(&tmp
[0], &cta_res
[15], 8);
665 memcpy(&tmp
[8], &cta_res
[7], 8);
667 overcryptId
= b2i(2, &er
->ecm
[44]);
669 rdr_log_dbg(reader
, D_READER
, "ICG ID: %04X", overcryptId
);
671 Drecrypt2OverCW(overcryptId
,tmp
);
675 memcpy(ea
->cw
, tmp
, 16);
681 DREover(reader
, er
->ecm
, cta_res
+ 7);
683 if(isValidDCW(cta_res
+ 7))
685 memcpy(ea
->cw
, cta_res
+ 15, 8);
686 memcpy(ea
->cw
+ 8, cta_res
+ 7, 8);
695 static int32_t drecas_do_emm(struct s_reader
*reader
, EMM_PACKET
*ep
)
698 struct dre_data
*csystem_data
= reader
->csystem_data
;
700 if(reader
->caid
== 0x4ae1)
702 if(reader
->caid
!= b2i(2, ep
->caid
)) return ERROR
;
704 if(ep
->type
== UNIQUE
&& ep
->emm
[39] == 0x3d)
706 /* For new package activation. */
709 memcpy(&emmcmd58
[1], &ep
->emm
[40], 24);
710 emmcmd58
[25] = csystem_data
->provider
;
711 if((drecas_MSP_cmd(emmcmd58
)))
712 if((cta_res
[2] != 0x09) || (cta_res
[3] != 0xC0))
715 else if(ep
->emm
[0] == 0x86 && ep
->emm
[4] == 0x02 /*&& csystem_data->provider != 0x11*/)
717 uchar emmcmd52
[0x3a];
720 for(i
= 0; i
< 2; i
++)
722 memcpy(emmcmd52
+ 1, ep
->emm
+ 5 + 32 + i
* 56, 56);
723 // check for shared address
724 if(ep
->emm
[3] != reader
->sa
[0][0])
725 { return OK
; } // ignore, wrong address
726 emmcmd52
[0x39] = csystem_data
->provider
;
727 if((drecas_MSP_cmd(emmcmd52
)))
728 if((cta_res
[2] != 0x09) || (cta_res
[3] != 0xC0))
729 { return ERROR
; } //exit if response is not 90 00
732 else if(ep
->emm
[0] == 0x86 && ep
->emm
[4] == 0x4D && csystem_data
->provider
== 0x11)
734 uchar emmcmd52
[0x3a];
737 emmcmd52
[2] = ep
->emm
[5];
739 emmcmd52
[4] = ep
->emm
[3];
746 memcpy(emmcmd52
+ 13, ep
->emm
+ 0x5C, 4);
749 for(i
= 0; i
< 2; i
++)
751 emmcmd52
[8] = ep
->emm
[0x61+i
*0x29];
752 if(i
== 0) emmcmd52
[12] = ep
->emm
[0x60] == 0x56 ? 0x56 : 0x3B;
753 else emmcmd52
[12] = ep
->emm
[0x60] == 0x56 ? 0x3B : 0x56;
754 memcpy(emmcmd52
+ 0x11, ep
->emm
+ 0x62 + i
* 0x29, 40);
756 // check for shared address
757 if(ep
->emm
[3] != reader
->sa
[0][0])
758 { return OK
; } // ignore, wrong address
759 emmcmd52
[0x39] = csystem_data
->provider
;
760 if((drecas_MSP_cmd(emmcmd52
)))
761 if((cta_res
[2] != 0x09) || (cta_res
[3] != 0xC0))
762 { return ERROR
; } //exit if response is not 90 00
765 uchar emmcmd34
[0x30] = {
766 0x34, 0x00, 0x01, 0x20, 0x00, 0x00, 0x00, 0x10,
767 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
768 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
769 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
770 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
771 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
773 emmcmd34
[1] = ep
->emm
[0x05];
774 emmcmd34
[2] = ep
->emm
[0x5A];
775 emmcmd34
[3] = ep
->emm
[0x03];
776 uint8_t need_save
= 0;
778 for(i
= 0; i
< 2; i
++)
780 memcpy(&emmcmd34
[7], &ep
->emm
[(i
*0x29)+8] , 41);
782 if(memcmp(emmcmd34
, stm_keys_t
.stmcmd34
[ep
->emm
[0x05] + (ep
->emm
[7] == 0x3B ? i
*32 : (i
== 0 ? 32 : 0))], 0x30) != 0)
784 memcpy(stm_keys_t
.stmcmd34
[ep
->emm
[0x05] + (ep
->emm
[7] == 0x3B ? i
*32 : (i
== 0 ? 32 : 0))], emmcmd34
, 0x30);
788 if(need_save
== 1) stm_key_operaion(reader
, WRITE
);
790 else if(ep
->type
== GLOBAL
&& ep
->emm
[0] == 0x91)
792 Drecrypt2OverEMM(ep
->emm
);
801 static int32_t drecas_card_info(struct s_reader
*UNUSED(rdr
))
806 const struct s_cardsystem reader_drecas
=
809 .caids
= (uint16_t[]){ 0x4AE1, 0 },
810 .do_emm
= drecas_do_emm
,
811 .do_ecm
= drecas_do_ecm
,
812 .card_info
= drecas_card_info
,
813 .card_init
= drecas_card_init
,
814 .get_emm_type
= dre_common_get_emm_type
,
815 .get_emm_filter
= dre_common_get_emm_filter
,