revert breaks some stupid old compilers
[oscam.git] / reader-dre-cas.c
blobbadbc2eb41bc03aca3e173dd71cf0201d7f0126c
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 uchar xor(const uchar *cmd, int32_t cmdlen)
72 int32_t i;
73 uchar 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, 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
104 uchar command[260];
105 uchar checksum;
106 char tmp[256];
108 startcmd[1] = cmdlen + 2; //command+length + len + checksum bytes
109 startcmd[2] = dest;
111 memcpy(command, startcmd, 3);
112 memcpy(command + 3, cmd, cmdlen);
113 cmdlen += 3;
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
136 return OK;
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,
143 uchar command[256];
144 uchar checksum;
145 char tmp[256];
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);
155 cmdlen += 7;
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))
164 switch(cta_res[7])
166 case 0xe1:
167 rdr_log(reader, "checksum error: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
168 break;
169 case 0xe2:
170 rdr_log(reader, "wrong cmd len: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
171 break;
172 case 0xe3:
173 rdr_log(reader, "illegal command: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
174 break;
175 case 0xe4:
176 rdr_log(reader, "wrong adress type: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
177 break;
178 case 0xe5:
179 rdr_log(reader, "wrong CMD param: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
180 break;
181 case 0xe6:
182 rdr_log(reader, "wrong UA: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
183 break;
184 case 0xe7:
185 rdr_log(reader, "wrong group: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
186 break;
187 case 0xe8:
188 rdr_log(reader, "wrong key num: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
189 break;
190 case 0xeb:
191 rdr_log(reader, "No key or subscribe : %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
192 break;
193 case 0xec:
194 rdr_log(reader, "wrong signature: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
195 break;
196 case 0xed:
197 rdr_log(reader, "wrong provider: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
198 break;
199 case 0xef:
200 rdr_log(reader, "wrong GEO code: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
201 break;
202 default:
203 rdr_log_dbg(reader, D_READER, "unknown error: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
204 break;
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
220 return OK;
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
236 uchar command[256];
237 uchar checksum;
238 char tmp[256];
240 command[0] = 0xC2;
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);
247 cmdlen += 3;
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))
256 switch(cta_res[7])
258 case 0xe1:
259 rdr_log(reader, "checksum error: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
260 break;
261 case 0xe2:
262 rdr_log(reader, "wrong cmd len: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
263 break;
264 case 0xe3:
265 rdr_log(reader, "illegal command: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
266 break;
267 case 0xe4:
268 rdr_log(reader, "wrong adress type: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
269 break;
270 case 0xe5:
271 rdr_log(reader, "wrong CMD param: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
272 break;
273 case 0xe6:
274 rdr_log(reader, "wrong UA: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
275 break;
276 case 0xe7:
277 rdr_log(reader, "wrong group: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
278 break;
279 case 0xe8:
280 rdr_log(reader, "wrong key num: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
281 break;
282 case 0xeb:
283 rdr_log(reader, "No key or subscribe : %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
284 break;
285 case 0xec:
286 rdr_log(reader, "wrong signature: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
287 break;
288 case 0xed:
289 rdr_log(reader, "wrong provider: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
290 break;
291 case 0xef:
292 rdr_log(reader, "wrong GEO code: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
293 break;
294 default:
295 rdr_log_dbg(reader, D_READER, "unknown error: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
296 break;
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
312 return OK;
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)
327 def_resp;
328 int32_t i;
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
338 uchar pbm[32];
339 char tmp_dbg[65];
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++)
344 if(pbm[i] != 0xff)
346 dates[1] = i;
347 dates[2] = csystem_data->provider;
348 drecas_MSP_cmd(dates); //ask for validity dates
350 time_t start;
351 time_t end;
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];
355 struct tm temp;
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);
371 return OK;
374 static int32_t drecas_card_init(struct s_reader *reader, ATR *newatr)
376 get_atr;
377 def_resp;
378 uchar ua[] = { 0x43, 0x15 }; // get serial number (UA)
379 uchar providers[] = { 0x49, 0x15 }; // get providers
380 int32_t i;
381 char *card;
382 char tmp[9];
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)
386 { return ERROR; }
388 if(!cs_malloc(&reader->csystem_data, sizeof(struct dre_data)))
389 { return ERROR; }
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]); }
398 switch(atr[10])
400 case 0x11:
401 card = "Tricolor Centr DRE2";
402 reader->caid = 0x4ae1;
403 break; //59 type card = MSP (74 type = ATMEL)
405 case 0x14:
406 card = "Tricolor Syberia DRE2";
407 reader->caid = 0x4ae1;
408 break; //59 type card
410 default:
411 return ERROR;
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;
420 uchar geocode = 0;
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))
428 { return ERROR; }
430 uchar provname[128];
431 for(i = 0; ((i < cta_res[6] - 6) && (i < 128)); i++)
433 provname[i] = cta_res[10 + i];
434 if(provname[i] == 0x00)
435 { break; }
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
446 if(reader->force_ua)
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;
457 uchar buf[32];
459 low_dre_id = ((cta_res[8] << 16) | (cta_res[9] << 8) | cta_res[10]) - 48608;
460 dre_chksum = 0;
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++)
465 if(buf[i] == 0x00)
466 { break; }
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)));
483 reader->nprov = 1;
485 // exec user script, wicardd format
486 if(reader->userscript != NULL)
488 uint8_t *usercmd = NULL;
489 int cmd_len;
490 int n;
491 char *tempbuf = malloc(2048);
492 trim2(reader->userscript);
493 FILE *pFile = fopen(reader->userscript, "rt");
495 if(pFile != NULL)
499 tempbuf[0] = '\0';
500 if(usercmd != NULL) free(usercmd);
502 if(fgets(tempbuf, 2048, pFile) == NULL) continue;
504 if(strlen(tempbuf) < 10) continue;
506 trim2(tempbuf);
508 if((tempbuf[0] != '5' && tempbuf[1] != '9') && (tempbuf[0] != '7' && tempbuf[1] != '4')) continue;
510 strtoupper(tempbuf);
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");
524 else
526 rdr_log(reader, "Script %s", (drecas_STM_script(usercmd, cmd_len)) ? "done" : "error");
529 while(!feof(pFile));
531 else
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;
544 reader->nprov = 2;
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");
553 return OK;
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");
563 return;
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)
577 def_resp;
578 uint16_t overcryptId;
579 uint8_t tmp[16];
580 char tmp_dbg[256];
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?
592 0x14 //provider
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,
614 int i;
616 for(i=0; i<16; i++)
618 ecmcmd33[i+2] = cta_res[7+(i^3)];
621 if(er->ecm[5] != stm_curkey[0] || er->ecm[6] != stm_curkey[1])
623 uchar blank[0x30];
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");
629 return ERROR;
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)));
635 return ERROR;
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)));
641 return ERROR;
645 stm_curkey[0] = er->ecm[5];
646 stm_curkey[1] = er->ecm[6];
648 if(!(drecas_STM_cmd(ecmcmd33)))
649 { return ERROR; }
651 if(cta_res[1] != 0x17 || cta_res[6] != 0xD2)
652 { return ERROR; }
654 memcpy(tmp, &cta_res[7], 16);
656 for(i=0; i<16; i++)
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);
673 if(isValidDCW(tmp))
675 memcpy(ea->cw, tmp, 16);
676 return OK;
678 return ERROR;
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);
687 return OK;
692 return ERROR;
695 static int32_t drecas_do_emm(struct s_reader *reader, EMM_PACKET *ep)
697 def_resp;
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. */
707 uchar emmcmd58[26];
708 emmcmd58[0] = 0x58;
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))
713 { return ERROR; }
715 else if(ep->emm[0] == 0x86 && ep->emm[4] == 0x02 /*&& csystem_data->provider != 0x11*/)
717 uchar emmcmd52[0x3a];
718 emmcmd52[0] = 0x52;
719 int32_t i;
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];
735 emmcmd52[0] = 0x52;
736 emmcmd52[1] = 0x01;
737 emmcmd52[2] = ep->emm[5];
738 emmcmd52[3] = 0x01;
739 emmcmd52[4] = ep->emm[3];
740 emmcmd52[5] = 0;
741 emmcmd52[6] = 0;
742 emmcmd52[7] = 0;
743 emmcmd52[9] = 0x01;
744 emmcmd52[10] = 0x01;
745 emmcmd52[11] = 0;
746 memcpy(emmcmd52 + 13, ep->emm + 0x5C, 4);
747 int32_t i;
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);
785 need_save = 1;
788 if(need_save == 1) stm_key_operaion(reader, WRITE);
790 else if(ep->type == GLOBAL && ep->emm[0] == 0x91)
792 Drecrypt2OverEMM(ep->emm);
793 return OK;
795 else return OK;
798 return ERROR;
801 static int32_t drecas_card_info(struct s_reader *UNUSED(rdr))
803 return OK;
806 const struct s_cardsystem reader_drecas =
808 .desc = "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,
818 #endif