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 uint8_t xor(const uint8_t *cmd
, int32_t cmdlen
)
73 uint8_t 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
, uint8_t *cmd
, int32_t cmdlen
, uint8_t *cta_res
, uint16_t *p_cta_lr
, uint8_t dest
)
102 // any command starts with this,
103 // last byte is nr of bytes of the command that will be sent
104 uint8_t startcmd
[3] = { 0xDB, 0x00, 0x00 };
106 uint8_t command
[260];
110 startcmd
[1] = cmdlen
+ 2; // command + length + len + checksum bytes
113 memcpy(command
, startcmd
, 3);
114 memcpy(command
+ 3, cmd
, cmdlen
);
116 checksum
= xor(command
+2, cmdlen
-2);
117 command
[cmdlen
++] = checksum
;
119 rdr_log_dbg(reader
, D_READER
, "write to module: %s", cs_hexdump(0, command
, cmdlen
, tmp
, sizeof(tmp
)));
121 ICC_Async_Transmit(reader
, (uint32_t) cmdlen
, 0, command
, 0, 200);
122 ICC_Async_Receive(reader
, 2, cta_res
, 50, 3000000);
124 ICC_Async_Receive(reader
, cta_res
[1], cta_res
+2, 50, 3000000);
125 *p_cta_lr
= cta_res
[1] + 2;
127 rdr_log_dbg(reader
, D_READER
, "answer from module: %s", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
129 checksum
= xor(cta_res
+ 2, *p_cta_lr
- 3);
131 if(cta_res
[*p_cta_lr
- 1] != checksum
)
133 rdr_log(reader
, "checksum does not match, expected %02x received %02x:%s", checksum
,
134 cta_res
[*p_cta_lr
- 1], cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
135 return ERROR
; // error
141 static int32_t drecas_MSP_command(struct s_reader
*reader
, const uint8_t *cmd
, int32_t cmdlen
, uint8_t *cta_res
, uint16_t *p_cta_lr
)
143 // attention: inputcommand will be changed!!!
144 // answer will be in cta_res, length cta_lr ; returning 1 = no error, return ERROR = err
146 uint8_t startcmd
[] = { 0x80, 0xFF, 0x10, 0x01, 0x05 }; // any command starts with this,
147 uint8_t command
[256];
151 startcmd
[4] = cmdlen
+ 3; // command + length + len + checksum bytes
152 memcpy(command
, startcmd
, 5);
153 command
[5] = MSP_CMD_BYTE
; // type
154 command
[6] = cmdlen
+ 1; // len = command + 1 checksum byte
155 memcpy(command
+ 7, cmd
, cmdlen
);
157 checksum
= ~xor(cmd
, cmdlen
);
160 command
[cmdlen
++] = checksum
;
162 if(drecas_send_cmd(reader
, command
, cmdlen
, cta_res
, p_cta_lr
, 1) != OK
) return ERROR
;
164 if(cta_res
[4] != MSP_CMD_BYTE
) return ERROR
;
166 if((cta_res
[5] == 0x03) && (cta_res
[6] == 0xe2))
171 rdr_log(reader
, "checksum error: %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
175 rdr_log(reader
, "wrong cmd len: %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
179 rdr_log(reader
, "illegal command: %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
183 rdr_log(reader
, "wrong adress type: %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
187 rdr_log(reader
, "wrong CMD param: %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
191 rdr_log(reader
, "wrong UA: %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
195 rdr_log(reader
, "wrong group: %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
199 rdr_log(reader
, "wrong key num: %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
203 rdr_log(reader
, "No key or subscribe : %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
207 rdr_log(reader
, "wrong signature: %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
211 rdr_log(reader
, "wrong provider: %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
215 rdr_log(reader
, "wrong GEO code: %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
219 rdr_log_dbg(reader
, D_READER
, "unknown error: %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
222 return ERROR
; // error
225 int32_t length_excl_leader
= *p_cta_lr
;
227 checksum
= ~xor(cta_res
+ 6, length_excl_leader
- 8);
229 if(cta_res
[length_excl_leader
- 2] != checksum
)
231 rdr_log(reader
, "checksum does not match, expected %02x received %02x:%s", checksum
,
232 cta_res
[length_excl_leader
- 2], cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
233 return ERROR
; // error
239 #define drecas_MSP_script_nb(cmd, len) \
240 drecas_MSP_command(reader, cmd, len, cta_res, &cta_lr); \
242 #define drecas_MSP_script(cmd, len) \
244 drecas_MSP_script_nb(cmd, len) \
247 #define drecas_MSP_cmd_nb(cmd) \
248 drecas_MSP_command(reader, cmd, sizeof(cmd), cta_res, &cta_lr); \
250 #define drecas_MSP_cmd(cmd) \
252 drecas_MSP_cmd_nb(cmd) \
255 static int32_t drecas_STM_command(struct s_reader
*reader
, const uint8_t *cmd
, int32_t cmdlen
, uint8_t *cta_res
, uint16_t *p_cta_lr
)
257 // attention: inputcommand will be changed!!!!
258 //answer will be in cta_res, length cta_lr ; returning 1 = no error, return ERROR = err
260 uint8_t command
[256];
265 command
[1] = STM_CMD_BYTE
; // type
266 command
[2] = cmdlen
+ 1; // len = command + 1 checksum byte
267 memcpy(command
+ 3, cmd
, cmdlen
);
269 checksum
= ~xor(cmd
, cmdlen
);
272 command
[cmdlen
++] = checksum
;
274 if(drecas_send_cmd(reader
, command
, cmdlen
, cta_res
, p_cta_lr
, 0) != OK
) return ERROR
;
276 if(cta_res
[4] != STM_CMD_BYTE
) return ERROR
;
278 if((cta_res
[5] == 0x03) && (cta_res
[6] == 0xe2))
283 rdr_log(reader
, "checksum error: %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
287 rdr_log(reader
, "wrong cmd len: %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
291 rdr_log(reader
, "illegal command: %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
295 rdr_log(reader
, "wrong adress type: %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
299 rdr_log(reader
, "wrong CMD param: %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
303 rdr_log(reader
, "wrong UA: %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
307 rdr_log(reader
, "wrong group: %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
311 rdr_log(reader
, "wrong key num: %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
315 rdr_log(reader
, "No key or subscribe : %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
319 rdr_log(reader
, "wrong signature: %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
323 rdr_log(reader
, "wrong provider: %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
327 rdr_log(reader
, "wrong GEO code: %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
331 rdr_log_dbg(reader
, D_READER
, "unknown error: %s.", cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
334 return ERROR
; // error
337 int32_t length_excl_leader
= *p_cta_lr
;
339 checksum
= ~xor(cta_res
+ 6, length_excl_leader
- 8);
341 if(cta_res
[length_excl_leader
- 2] != checksum
)
343 rdr_log(reader
, "checksum does not match, expected %02x received %02x:%s", checksum
,
344 cta_res
[length_excl_leader
- 2], cs_hexdump(0, cta_res
, *p_cta_lr
, tmp
, sizeof(tmp
)));
345 return ERROR
; // error
351 #define drecas_STM_script_nb(cmd, len) \
352 drecas_STM_command(reader, cmd, len, cta_res, &cta_lr); \
354 #define drecas_STM_script(cmd, len) \
356 drecas_STM_script_nb(cmd, len) \
359 #define drecas_STM_cmd_nb(cmd) \
360 drecas_STM_command(reader, cmd, sizeof(cmd), cta_res, &cta_lr); \
362 #define drecas_STM_cmd(cmd) \
364 drecas_STM_cmd_nb(cmd) \
367 static int32_t drecas_set_provider_info(struct s_reader
*reader
)
371 uint8_t subscr
[] = { 0x59, 0x14 }; // subscriptions
372 uint8_t dates
[] = { 0x5b, 0x00, 0x14 }; // validity dates
373 struct dre_data
*csystem_data
= reader
->csystem_data
;
374 subscr
[1] = csystem_data
->provider
;
376 cs_clear_entitlement(reader
);
378 if(({drecas_MSP_cmd_nb(subscr
)})) // ask subscription packages, returns error on 0x11 card
382 memcpy(pbm
, cta_res
+ 7, 32);
383 rdr_log_dbg(reader
, D_READER
, "pbm: %s", cs_hexdump(0, pbm
, 32, tmp_dbg
, sizeof(tmp_dbg
)));
385 for(i
= 0; i
< 32; i
++)
390 dates
[2] = csystem_data
->provider
;
391 drecas_MSP_cmd(dates
); // ask for validity dates
395 start
= (cta_res
[7] << 24) | (cta_res
[8] << 16) | (cta_res
[9] << 8) | cta_res
[10];
396 end
= (cta_res
[11] << 24) | (cta_res
[12] << 16) | (cta_res
[13] << 8) | cta_res
[14];
400 localtime_r(&start
, &temp
);
401 int32_t startyear
= temp
.tm_year
+ 1900;
402 int32_t startmonth
= temp
.tm_mon
+ 1;
403 int32_t startday
= temp
.tm_mday
;
404 localtime_r(&end
, &temp
);
405 int32_t endyear
= temp
.tm_year
+ 1900;
406 int32_t endmonth
= temp
.tm_mon
+ 1;
407 int32_t endday
= temp
.tm_mday
;
408 rdr_log(reader
, "active package %i valid from %04i/%02i/%02i to %04i/%02i/%02i",
409 i
, startyear
, startmonth
, startday
, endyear
, endmonth
, endday
);
410 cs_add_entitlement(reader
, reader
->caid
, b2ll(4, reader
->prid
[0]), 0, i
, start
, end
, 5, 1);
418 static int32_t drecas_card_init(struct s_reader
*reader
, ATR
*newatr
)
422 uint8_t ua
[] = { 0x43, 0x15 }; // get serial number (UA)
423 uint8_t providers
[] = { 0x49, 0x15 }; // get providers
427 uint8_t module_atr
[] = { 0xDB, 0x0B, 0x08, 0xA3, 0x3B, 0x15, 0x11, 0x12, 0x01, 0x01, 0x11, 0x07, 0x90 };
429 if(memcmp(atr
, module_atr
, sizeof(module_atr
)) != 0)
432 if(!cs_malloc(&reader
->csystem_data
, sizeof(struct dre_data
)))
434 struct dre_data
*csystem_data
= reader
->csystem_data
;
436 csystem_data
->provider
= atr
[10];
437 uint8_t checksum
= xor(atr
+ 5, 6);
439 if(checksum
!= atr
[11])
440 { rdr_log(reader
, "warning: expected ATR checksum %02x, smartcard reports %02x", checksum
, atr
[7]); }
445 card
= "Tricolor Centr DRE2";
446 reader
->caid
= 0x4ae1;
447 break; // 59 type card = MSP (74 type = ATMEL)
450 card
= "Tricolor Syberia DRE2";
451 reader
->caid
= 0x4ae1;
452 break; // 59 type card
458 memset(reader
->prid
, 0x00, 8);
460 reader
->prid
[0][3] = csystem_data
->provider
;
462 uint8_t cmd54
[] = { 0x54, 0x14 }; // geocode
463 cmd54
[1] = csystem_data
->provider
;
466 if(({drecas_MSP_cmd_nb(cmd54
)})) // error would not be fatal, like on 0x11 cards
467 { geocode
= cta_res
[7]; }
469 providers
[1] = csystem_data
->provider
;
471 if(!({drecas_MSP_cmd_nb(providers
)}))
472 { return ERROR
; } // fatal error
474 if((cta_res
[2] != 0x09) || (cta_res
[3] != 0xC0))
477 uint8_t provname
[128];
479 for(i
= 0; ((i
< cta_res
[6] - 6) && (i
< 128)); i
++)
481 provname
[i
] = cta_res
[10 + i
];
482 if(provname
[i
] == 0x00)
486 int32_t major_version
= cta_res
[7];
487 int32_t minor_version
= cta_res
[8];
489 ua
[1] = csystem_data
->provider
;
490 drecas_MSP_cmd(ua
); // error would not be fatal
492 // discard first and last byte, last byte is always checksum, first is answer code
493 int32_t hexlength
= cta_res
[5] - 2;
497 rdr_log(reader
, "WARNING!!!! used UA from force_ua %08X", reader
->force_ua
);
498 memcpy(cta_res
+ 7, &reader
->force_ua
, 8);
501 reader
->hexserial
[0] = 0;
502 reader
->hexserial
[1] = 0;
503 memcpy(reader
->hexserial
+ 2, cta_res
+ 7, hexlength
);
505 int32_t low_dre_id
, dre_chksum
;
508 low_dre_id
= ((cta_res
[8] << 16) | (cta_res
[9] << 8) | cta_res
[10]) - 48608;
510 snprintf((char *)buf
, sizeof(buf
), "%i%i%08i", csystem_data
->provider
- 16, major_version
+ 1, low_dre_id
);
512 for(i
= 0; i
< 32; i
++)
516 dre_chksum
+= buf
[i
] - 48;
519 rdr_log(reader
, "type: DRE Crypt, caid: %04X, serial: {%s}, dre id: %i%i%i%08i, geocode %i, card: %s v%i.%i",
520 reader
->caid
, cs_hexdump(0, reader
->hexserial
+ 2, 4, tmp
, sizeof(tmp
)), dre_chksum
, csystem_data
->provider
- 16,
521 major_version
+ 1, low_dre_id
, geocode
, card
, major_version
, minor_version
);
523 rdr_log(reader
, "Provider name:%s.", provname
);
526 memset(reader
->sa
, 0, sizeof(reader
->sa
));
527 // copy first byte of unique address also in shared address, because we don't know what it is...
528 memcpy(reader
->sa
[0], reader
->hexserial
+ 2, 1);
530 rdr_log_sensitive(reader
, "SA = %02X%02X%02X%02X, UA = {%s}", reader
->sa
[0][0], reader
->sa
[0][1], reader
->sa
[0][2],
531 reader
->sa
[0][3], cs_hexdump(0, reader
->hexserial
+ 2, 4, tmp
, sizeof(tmp
)));
535 // exec user script, wicardd format
536 if(reader
->userscript
!= NULL
)
538 uint8_t *usercmd
= NULL
;
541 char *tempbuf
= malloc(2048);
542 trim2(reader
->userscript
);
543 FILE *pFile
= fopen(reader
->userscript
, "rt");
550 if(usercmd
!= NULL
) NULLFREE(usercmd
);
552 if(fgets(tempbuf
, 2048, pFile
) == NULL
) continue;
554 if(cs_strlen(tempbuf
) < 10) continue;
558 if((tempbuf
[0] != '5' && tempbuf
[1] != '9') && (tempbuf
[0] != '7' && tempbuf
[1] != '4')) continue;
562 cmd_len
= cs_strlen(tempbuf
) / 2 - 3;
563 usercmd
= malloc(cmd_len
);
565 for(i
= 0, n
= 4; i
< cmd_len
; i
++, n
+= 2)
567 usercmd
[i
] = ((tempbuf
[n
] - (tempbuf
[n
] > 0x39 ? 0x37 : 0x30)) << 4) + ((tempbuf
[n
+ 1] - (tempbuf
[n
+ 1] > 0x39 ? 0x37 : 0x30)) & 0xF);
570 if(tempbuf
[0] != '7' && tempbuf
[1] != '4')
572 rdr_log(reader
, "Script %s", ({drecas_MSP_script_nb(usercmd
, cmd_len
)}) ? "done" : "error");
576 rdr_log(reader
, "Script %s", ({drecas_STM_script_nb(usercmd
, cmd_len
)}) ? "done" : "error");
583 rdr_log(reader
, "Can't open script file (%s)", reader
->userscript
);
586 if(usercmd
!= NULL
) free(usercmd
);
587 if(tempbuf
!= NULL
) free(tempbuf
);
590 if(csystem_data
->provider
== 0x11)
592 memset(reader
->prid
[1], 0x00, 8);
593 reader
->prid
[1][3] = 0xFE;
597 if(!drecas_set_provider_info(reader
))
598 { return ERROR
; } // fatal error
600 stm_key_operaion(reader
, READ
);
602 rdr_log(reader
, "ready for requests");
606 static void DREover(struct s_reader
*reader
, const uint8_t *ECMdata
, uint8_t *DW
)
608 uint32_t key_schedule
[32];
610 if(reader
->des_key_length
< 128)
612 rdr_log(reader
, "error: deskey is missing or too short");
616 if(ECMdata
[2] >= (43 + 4) && ECMdata
[40] == 0x3A && ECMdata
[41] == 0x4B)
618 des_set_key(&reader
->des_key
[(ECMdata
[42] & 0x0F) * 8], key_schedule
);
620 des(DW
, key_schedule
, 0); // even DW post-process
621 des(DW
+ 8, key_schedule
, 0); // odd DW post-process
625 static int32_t drecas_do_ecm(struct s_reader
*reader
, const ECM_REQUEST
*er
, struct s_ecm_answer
*ea
)
628 uint16_t overcryptId
;
631 struct dre_data
*csystem_data
= reader
->csystem_data
;
633 if(reader
->caid
== 0x4ae1)
635 if(csystem_data
->provider
== 0x11 || csystem_data
->provider
== 0x14)
637 uint8_t ecmcmd51
[] = { 0x51, 0x02, 0x56, 0x05, 0x00, 0x4A, 0xE3, // fixed header?
638 0x9C, 0xDA, // first three nibbles count up, fourth nibble counts down; all ECMs sent twice
639 0xC1, 0x71, 0x21, 0x06, 0xF0, 0x14, 0xA7, 0x0E, // next key?
640 0x89, 0xDA, 0xC9, 0xD7, 0xFD, 0xB9, 0x06, 0xFD, // current key?
641 0xD5, 0x1E, 0x2A, 0xA3, 0xB5, 0xA0, 0x82, 0x11, // key or signature?
644 memcpy(ecmcmd51
+ 1, er
->ecm
+ 5, 0x21);
645 rdr_log_dbg(reader
, D_READER
, "unused ECM info front:%s", cs_hexdump(0, er
->ecm
, 5, tmp_dbg
, sizeof(tmp_dbg
)));
646 rdr_log_dbg(reader
, D_READER
, "unused ECM info back:%s", cs_hexdump(0, er
->ecm
+ 37, 4, tmp_dbg
, sizeof(tmp_dbg
)));
648 rdr_log_dbg(reader
, D_READER
, "ECM: %s",cs_hexdump(0, er
->ecm
, er
->ecm
[2] + 3, tmp_dbg
, sizeof(tmp_dbg
)));
650 ecmcmd51
[33] = csystem_data
->provider
; // no part of sig
652 if(({drecas_MSP_cmd_nb(ecmcmd51
)})) // ecm request
654 if((cta_res
[2] != 0x09) || (cta_res
[3] != 0xC0))
655 { return ERROR
; } // exit if response is not 90 00
657 if(er
->ecm
[3] == 0x01)
659 uint8_t ecmcmd33
[18] = { 0x33, 0x1F,
660 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
661 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
664 for(i
= 0; i
< 16; i
++)
666 ecmcmd33
[i
+ 2] = cta_res
[7 + (i
^ 3)];
669 if(er
->ecm
[5] != stm_curkey
[0] || er
->ecm
[6] != stm_curkey
[1])
672 memset(blank
, 0, 0x30);
674 if(memcmp(blank
, stm_keys_t
.stmcmd34
[er
->ecm
[5] + (er
->ecm
[6] == 0x3B ? 0 : 32)], 0x30) == 0)
676 rdr_log_dbg(reader
, D_READER
, "STM key not found");
680 if(!({drecas_STM_cmd_nb(stm_keys_t
.stmcmd34
[er
->ecm
[5] + (er
->ecm
[6] == 0x3B ? 0 : 32)])}))
682 rdr_log_dbg(reader
, D_READER
, "Error STM set key: %s",cs_hexdump(0, cta_res
, cta_lr
, tmp_dbg
, sizeof(tmp_dbg
)));
686 if((cta_res
[cta_lr
- 4] != 0x02) || (cta_res
[cta_lr
- 3] != 0xA2))
688 rdr_log_dbg(reader
, D_READER
, "Error STM set key: %s",cs_hexdump(0, cta_res
, cta_lr
, tmp_dbg
, sizeof(tmp_dbg
)));
693 stm_curkey
[0] = er
->ecm
[5];
694 stm_curkey
[1] = er
->ecm
[6];
696 if(!({drecas_STM_cmd_nb(ecmcmd33
)}))
699 if(cta_res
[1] != 0x17 || cta_res
[6] != 0xD2)
702 memcpy(tmp
, &cta_res
[7], 16);
704 for(i
= 0; i
< 16; i
++)
706 cta_res
[i
+ 7] = tmp
[i
^ 3];
710 if(er
->ecm
[2] >= 46 && er
->ecm
[43] == 1 && csystem_data
->provider
== 0x11)
712 memcpy(&tmp
[0], &cta_res
[15], 8);
713 memcpy(&tmp
[8], &cta_res
[7], 8);
715 overcryptId
= b2i(2, &er
->ecm
[44]);
717 rdr_log_dbg(reader
, D_READER
, "ICG ID: %04X", overcryptId
);
719 Drecrypt2OverCW(overcryptId
,tmp
);
723 memcpy(ea
->cw
, tmp
, 16);
729 DREover(reader
, er
->ecm
, cta_res
+ 7);
731 if(isValidDCW(cta_res
+ 7))
733 memcpy(ea
->cw
, cta_res
+ 15, 8);
734 memcpy(ea
->cw
+ 8, cta_res
+ 7, 8);
743 static int32_t drecas_do_emm(struct s_reader
*reader
, EMM_PACKET
*ep
)
746 struct dre_data
*csystem_data
= reader
->csystem_data
;
748 if(reader
->caid
== 0x4ae1)
750 if(reader
->caid
!= b2i(2, ep
->caid
)) return ERROR
;
752 if(ep
->type
== UNIQUE
&& ep
->emm
[39] == 0x3d)
754 /* For new package activation. */
755 uint8_t emmcmd58
[26];
757 memcpy(&emmcmd58
[1], &ep
->emm
[40], 24);
758 emmcmd58
[25] = csystem_data
->provider
;
760 if(({drecas_MSP_cmd_nb(emmcmd58
)}))
761 if((cta_res
[2] != 0x09) || (cta_res
[3] != 0xC0))
764 else if(ep
->emm
[0] == 0x86 && ep
->emm
[4] == 0x02 /*&& csystem_data->provider != 0x11*/)
766 uint8_t emmcmd52
[0x3a];
770 for(i
= 0; i
< 2; i
++)
772 memcpy(emmcmd52
+ 1, ep
->emm
+ 5 + 32 + i
* 56, 56);
774 // check for shared address
775 if(ep
->emm
[3] != reader
->sa
[0][0])
776 { return OK
; } // ignore, wrong address
778 emmcmd52
[0x39] = csystem_data
->provider
;
780 if(({drecas_MSP_cmd_nb(emmcmd52
)}))
781 if((cta_res
[2] != 0x09) || (cta_res
[3] != 0xC0))
782 { return ERROR
; } // exit if response is not 90 00
785 else if(ep
->emm
[0] == 0x86 && ep
->emm
[4] == 0x4D && csystem_data
->provider
== 0x11)
787 uint8_t emmcmd52
[0x3a];
790 emmcmd52
[2] = ep
->emm
[5];
792 emmcmd52
[4] = ep
->emm
[3];
799 memcpy(emmcmd52
+ 13, ep
->emm
+ 0x5C, 4);
802 for(i
= 0; i
< 2; i
++)
804 emmcmd52
[8] = ep
->emm
[0x61 + i
* 0x29];
806 if(i
== 0) emmcmd52
[12] = ep
->emm
[0x60] == 0x56 ? 0x56 : 0x3B;
807 else emmcmd52
[12] = ep
->emm
[0x60] == 0x56 ? 0x3B : 0x56;
809 memcpy(emmcmd52
+ 0x11, ep
->emm
+ 0x62 + i
* 0x29, 40);
811 // check for shared address
812 if(ep
->emm
[3] != reader
->sa
[0][0])
813 { return OK
; } // ignore, wrong address
815 emmcmd52
[0x39] = csystem_data
->provider
;
817 if(({drecas_MSP_cmd_nb(emmcmd52
)}))
818 if((cta_res
[2] != 0x09) || (cta_res
[3] != 0xC0))
819 { return ERROR
; } // exit if response is not 90 00
822 uint8_t emmcmd34
[0x30] = {
823 0x34, 0x00, 0x01, 0x20, 0x00, 0x00, 0x00, 0x10,
824 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
825 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
826 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
827 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
828 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
830 emmcmd34
[1] = ep
->emm
[0x05];
831 emmcmd34
[2] = ep
->emm
[0x5A];
832 emmcmd34
[3] = ep
->emm
[0x03];
833 uint8_t need_save
= 0;
835 for(i
= 0; i
< 2; i
++)
837 memcpy(&emmcmd34
[7], &ep
->emm
[(i
* 0x29) + 8] , 41);
839 if(memcmp(emmcmd34
, stm_keys_t
.stmcmd34
[ep
->emm
[0x05] + (ep
->emm
[7] == 0x3B ? i
* 32 : (i
== 0 ? 32 : 0))], 0x30) != 0)
841 memcpy(stm_keys_t
.stmcmd34
[ep
->emm
[0x05] + (ep
->emm
[7] == 0x3B ? i
* 32 : (i
== 0 ? 32 : 0))], emmcmd34
, 0x30);
846 if(need_save
== 1) stm_key_operaion(reader
, WRITE
);
848 else if(ep
->type
== GLOBAL
&& ep
->emm
[0] == 0x91)
850 Drecrypt2OverEMM(ep
->emm
);
859 static int32_t drecas_card_info(struct s_reader
*UNUSED(rdr
))
864 const struct s_cardsystem reader_drecas
=
867 .caids
= (uint16_t[]){ 0x4AE1, 0 },
868 .do_emm
= drecas_do_emm
,
869 .do_ecm
= drecas_do_ecm
,
870 .card_info
= drecas_card_info
,
871 .card_init
= drecas_card_init
,
872 .get_emm_type
= dre_common_get_emm_type
,
873 .get_emm_filter
= dre_common_get_emm_filter
,