- git-svn-diff.sh changed permission to 755 (thanks to WXbet)
[oscam.git] / reader-dre-cas.c
blob642a27e85eb0adef319e052cef728d864d698ad3
1 #include "globals.h"
2 #ifdef READER_DRECAS
3 #include "cscrypt/des.h"
4 #include "reader-common.h"
5 #include "reader-dre-common.h"
6 #include "csctapi/icc_async.h"
8 struct dre_data
10 uint8_t provider;
13 struct stm_keys
15 uint8_t stmcmd34[64][0x30];
16 } stm_keys_t;
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
25 #define READ 0
26 #define WRITE 1
28 static void stm_key_operaion(struct s_reader *reader, int operation)
30 FILE *file = NULL;
31 char stmkeyfile[256];
32 int i;
34 if(reader->stmkeys == NULL)
36 snprintf(stmkeyfile,256,"%sstmkeys.bin",cs_confdir);
38 else
40 if(strchr(reader->stmkeys, '/') == NULL)
42 snprintf(stmkeyfile,256,"%s%s",cs_confdir, reader->stmkeys);
44 else
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);
53 return;
56 if(operation == WRITE)
58 i = fwrite(&stm_keys_t, sizeof(stm_keys_t), 1, file);
60 else
62 i = fread(&stm_keys_t, sizeof(stm_keys_t), 1, file);
65 fclose(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)
72 int32_t i;
73 uint8_t checksum = 0x00;
74 for(i = 0; i < cmdlen; i++)
75 { checksum ^= cmd[i]; }
76 return checksum;
79 static int8_t isValidDCW(uint8_t *dw)
81 if (((dw[0] + dw[1] + dw[2]) & 0xFF) != dw[3])
83 return 0;
85 if (((dw[4] + dw[5] + dw[6]) & 0xFF) != dw[7])
87 return 0;
89 if (((dw[8] + dw[9] + dw[10]) & 0xFF) != dw[11])
91 return 0;
93 if (((dw[12] + dw[13] + dw[14]) & 0xFF) != dw[15])
95 return 0;
97 return 1;
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];
107 uint8_t checksum;
108 char tmp[256];
110 startcmd[1] = cmdlen + 2; // command + length + len + checksum bytes
111 startcmd[2] = dest;
113 memcpy(command, startcmd, 3);
114 memcpy(command + 3, cmd, cmdlen);
115 cmdlen += 3;
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
138 return OK;
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];
148 uint8_t checksum;
149 char tmp[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);
159 cmdlen += 7;
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))
168 switch(cta_res[7])
170 case 0xe1:
171 rdr_log(reader, "checksum error: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
172 break;
174 case 0xe2:
175 rdr_log(reader, "wrong cmd len: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
176 break;
178 case 0xe3:
179 rdr_log(reader, "illegal command: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
180 break;
182 case 0xe4:
183 rdr_log(reader, "wrong adress type: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
184 break;
186 case 0xe5:
187 rdr_log(reader, "wrong CMD param: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
188 break;
190 case 0xe6:
191 rdr_log(reader, "wrong UA: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
192 break;
194 case 0xe7:
195 rdr_log(reader, "wrong group: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
196 break;
198 case 0xe8:
199 rdr_log(reader, "wrong key num: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
200 break;
202 case 0xeb:
203 rdr_log(reader, "No key or subscribe : %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
204 break;
206 case 0xec:
207 rdr_log(reader, "wrong signature: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
208 break;
210 case 0xed:
211 rdr_log(reader, "wrong provider: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
212 break;
214 case 0xef:
215 rdr_log(reader, "wrong GEO code: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
216 break;
218 default:
219 rdr_log_dbg(reader, D_READER, "unknown error: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
220 break;
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
236 return OK;
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];
261 uint8_t checksum;
262 char tmp[256];
264 command[0] = 0xC2;
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);
271 cmdlen += 3;
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))
280 switch(cta_res[7])
282 case 0xe1:
283 rdr_log(reader, "checksum error: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
284 break;
286 case 0xe2:
287 rdr_log(reader, "wrong cmd len: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
288 break;
290 case 0xe3:
291 rdr_log(reader, "illegal command: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
292 break;
294 case 0xe4:
295 rdr_log(reader, "wrong adress type: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
296 break;
298 case 0xe5:
299 rdr_log(reader, "wrong CMD param: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
300 break;
302 case 0xe6:
303 rdr_log(reader, "wrong UA: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
304 break;
306 case 0xe7:
307 rdr_log(reader, "wrong group: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
308 break;
310 case 0xe8:
311 rdr_log(reader, "wrong key num: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
312 break;
314 case 0xeb:
315 rdr_log(reader, "No key or subscribe : %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
316 break;
318 case 0xec:
319 rdr_log(reader, "wrong signature: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
320 break;
322 case 0xed:
323 rdr_log(reader, "wrong provider: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
324 break;
326 case 0xef:
327 rdr_log(reader, "wrong GEO code: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
328 break;
330 default:
331 rdr_log_dbg(reader, D_READER, "unknown error: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
332 break;
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
348 return OK;
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)
369 def_resp;
370 int32_t i;
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
380 uint8_t pbm[32];
381 char tmp_dbg[65];
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++)
387 if(pbm[i] != 0xff)
389 dates[1] = i;
390 dates[2] = csystem_data->provider;
391 drecas_MSP_cmd(dates); // ask for validity dates
393 time_t start;
394 time_t end;
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];
398 struct tm temp;
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);
415 return OK;
418 static int32_t drecas_card_init(struct s_reader *reader, ATR *newatr)
420 get_atr;
421 def_resp;
422 uint8_t ua[] = { 0x43, 0x15 }; // get serial number (UA)
423 uint8_t providers[] = { 0x49, 0x15 }; // get providers
424 int32_t i;
425 char *card;
426 char tmp[9];
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)
430 { return ERROR; }
432 if(!cs_malloc(&reader->csystem_data, sizeof(struct dre_data)))
433 { return ERROR; }
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]); }
442 switch(atr[10])
444 case 0x11:
445 card = "Tricolor Centr DRE2";
446 reader->caid = 0x4ae1;
447 break; // 59 type card = MSP (74 type = ATMEL)
449 case 0x14:
450 card = "Tricolor Syberia DRE2";
451 reader->caid = 0x4ae1;
452 break; // 59 type card
454 default:
455 return ERROR;
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;
464 uint8_t geocode = 0;
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))
475 { return ERROR; }
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)
483 { break; }
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;
495 if(reader->force_ua)
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;
506 uint8_t buf[32];
508 low_dre_id = ((cta_res[8] << 16) | (cta_res[9] << 8) | cta_res[10]) - 48608;
509 dre_chksum = 0;
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++)
514 if(buf[i] == 0x00)
515 { break; }
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)));
533 reader->nprov = 1;
535 // exec user script, wicardd format
536 if(reader->userscript != NULL)
538 uint8_t *usercmd = NULL;
539 int cmd_len;
540 int n;
541 char *tempbuf = malloc(2048);
542 trim2(reader->userscript);
543 FILE *pFile = fopen(reader->userscript, "rt");
545 if(pFile != NULL)
549 tempbuf[0] = '\0';
550 if(usercmd != NULL) NULLFREE(usercmd);
552 if(fgets(tempbuf, 2048, pFile) == NULL) continue;
554 if(cs_strlen(tempbuf) < 10) continue;
556 trim2(tempbuf);
558 if((tempbuf[0] != '5' && tempbuf[1] != '9') && (tempbuf[0] != '7' && tempbuf[1] != '4')) continue;
560 strtoupper(tempbuf);
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");
574 else
576 rdr_log(reader, "Script %s", ({drecas_STM_script_nb(usercmd, cmd_len)}) ? "done" : "error");
579 while(!feof(pFile));
581 else
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;
594 reader->nprov = 2;
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");
603 return OK;
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");
613 return;
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)
627 def_resp;
628 uint16_t overcryptId;
629 uint8_t tmp[16];
630 char tmp_dbg[256];
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?
642 0x14 }; // provider
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 };
663 int i;
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])
671 uint8_t blank[0x30];
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");
677 return ERROR;
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)));
683 return ERROR;
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)));
689 return ERROR;
693 stm_curkey[0] = er->ecm[5];
694 stm_curkey[1] = er->ecm[6];
696 if(!({drecas_STM_cmd_nb(ecmcmd33)}))
697 { return ERROR; }
699 if(cta_res[1] != 0x17 || cta_res[6] != 0xD2)
700 { return ERROR; }
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);
721 if(isValidDCW(tmp))
723 memcpy(ea->cw, tmp, 16);
724 return OK;
726 return ERROR;
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);
735 return OK;
740 return ERROR;
743 static int32_t drecas_do_emm(struct s_reader *reader, EMM_PACKET *ep)
745 def_resp;
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];
756 emmcmd58[0] = 0x58;
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))
762 { return ERROR; }
764 else if(ep->emm[0] == 0x86 && ep->emm[4] == 0x02 /*&& csystem_data->provider != 0x11*/)
766 uint8_t emmcmd52[0x3a];
767 emmcmd52[0] = 0x52;
768 int32_t i;
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];
788 emmcmd52[0] = 0x52;
789 emmcmd52[1] = 0x01;
790 emmcmd52[2] = ep->emm[5];
791 emmcmd52[3] = 0x01;
792 emmcmd52[4] = ep->emm[3];
793 emmcmd52[5] = 0;
794 emmcmd52[6] = 0;
795 emmcmd52[7] = 0;
796 emmcmd52[9] = 0x01;
797 emmcmd52[10] = 0x01;
798 emmcmd52[11] = 0;
799 memcpy(emmcmd52 + 13, ep->emm + 0x5C, 4);
800 int32_t i;
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);
842 need_save = 1;
846 if(need_save == 1) stm_key_operaion(reader, WRITE);
848 else if(ep->type == GLOBAL && ep->emm[0] == 0x91)
850 Drecrypt2OverEMM(ep->emm);
851 return OK;
853 else return OK;
856 return ERROR;
859 static int32_t drecas_card_info(struct s_reader *UNUSED(rdr))
861 return OK;
864 const struct s_cardsystem reader_drecas =
866 .desc = "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,
876 #endif