1 | #include "globals.h"
|
---|
2 | #ifdef READER_DRE
|
---|
3 | #include "cscrypt/des.h"
|
---|
4 | #include "reader-common.h"
|
---|
5 | #include "reader-dre-common.h"
|
---|
6 |
|
---|
7 | struct dre_data
|
---|
8 | {
|
---|
9 | uint8_t provider;
|
---|
10 | };
|
---|
11 |
|
---|
12 | #define OK_RESPONSE 0x61
|
---|
13 | #define CMD_BYTE 0x59
|
---|
14 |
|
---|
15 | static uint8_t xor(const uint8_t *cmd, int32_t cmdlen)
|
---|
16 | {
|
---|
17 | int32_t i;
|
---|
18 | uint8_t checksum = 0x00;
|
---|
19 | for(i = 0; i < cmdlen; i++)
|
---|
20 | { checksum ^= cmd[i]; }
|
---|
21 | return checksum;
|
---|
22 | }
|
---|
23 |
|
---|
24 | static int8_t isValidDCW(uint8_t *dw)
|
---|
25 | {
|
---|
26 | if (((dw[0] + dw[1] + dw[2]) & 0xFF) != dw[3])
|
---|
27 | {
|
---|
28 | return 0;
|
---|
29 | }
|
---|
30 | if (((dw[4] + dw[5] + dw[6]) & 0xFF) != dw[7])
|
---|
31 | {
|
---|
32 | return 0;
|
---|
33 | }
|
---|
34 | if (((dw[8] + dw[9] + dw[10]) & 0xFF) != dw[11])
|
---|
35 | {
|
---|
36 | return 0;
|
---|
37 | }
|
---|
38 | if (((dw[12] + dw[13] + dw[14]) & 0xFF) != dw[15])
|
---|
39 | {
|
---|
40 | return 0;
|
---|
41 | }
|
---|
42 | return 1;
|
---|
43 | }
|
---|
44 |
|
---|
45 | static int32_t dre_command(struct s_reader *reader, const uint8_t *cmd, int32_t cmdlen, uint8_t *cta_res,
|
---|
46 | uint16_t *p_cta_lr, uint8_t crypted, uint8_t keynum, uint8_t dre_v, uint8_t cmd_type)
|
---|
47 | {
|
---|
48 | // attention: inputcommand will be changed!!!!
|
---|
49 | //answer will be in cta_res, length cta_lr ; returning 1 = no error, return ERROR = err
|
---|
50 |
|
---|
51 | uint8_t startcmd[] = { 0x80, 0xFF, 0x10, 0x01, 0x05 }; // any command starts with this,
|
---|
52 | // last byte is nr of bytes of the command that will be sent
|
---|
53 | // after the startcmd
|
---|
54 | // response on startcmd+cmd: = { 0x61, 0x05 } // 0x61 = "OK", last byte is nr. of bytes card will send
|
---|
55 | uint8_t reqans[] = { 0x00, 0xC0, 0x00, 0x00, 0x08 }; // after command answer has to be requested,
|
---|
56 | // last byte must be nr. of bytes that card has reported to send
|
---|
57 | uint8_t command[256];
|
---|
58 | uint8_t checksum;
|
---|
59 | char tmp[256];
|
---|
60 | int32_t headerlen = sizeof(startcmd);
|
---|
61 |
|
---|
62 | if(dre_v > 0)
|
---|
63 | {
|
---|
64 | startcmd[1] = 0;
|
---|
65 | startcmd[2] = crypted;
|
---|
66 | startcmd[3] = keynum;
|
---|
67 | }
|
---|
68 |
|
---|
69 | startcmd[4] = cmdlen + 3 - cmd_type; // commandlength + type + len + checksum bytes
|
---|
70 | memcpy(command, startcmd, headerlen);
|
---|
71 | command[headerlen++] = cmd_type ? 0x86 : CMD_BYTE; // type
|
---|
72 | command[headerlen++] = cmdlen + (cmd_type == 1 ? 0 : 1); // len = command + 1 checksum byte
|
---|
73 | memcpy(command + headerlen, cmd, cmdlen);
|
---|
74 |
|
---|
75 | if(!cmd_type)
|
---|
76 | {
|
---|
77 | checksum = ~xor(cmd, cmdlen);
|
---|
78 | //rdr_log_dbg(reader, D_READER, "Checksum: %02x", checksum);
|
---|
79 | cmdlen += headerlen;
|
---|
80 | command[cmdlen++] = checksum;
|
---|
81 | }
|
---|
82 | else cmdlen += headerlen;
|
---|
83 |
|
---|
84 | reader_cmd2icc(reader, command, cmdlen, cta_res, p_cta_lr);
|
---|
85 |
|
---|
86 | if((*p_cta_lr != 2) || (cta_res[0] != OK_RESPONSE))
|
---|
87 | {
|
---|
88 | rdr_log(reader, "command sent to card: %s", cs_hexdump(0, command, cmdlen, tmp, sizeof(tmp)));
|
---|
89 | rdr_log(reader, "unexpected answer from card: %s", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
|
---|
90 | return ERROR; // error
|
---|
91 | }
|
---|
92 |
|
---|
93 | rdr_log_dbg(reader, D_READER, "command sent to card: %s", cs_hexdump(0, command, cmdlen, tmp, sizeof(tmp)));
|
---|
94 | rdr_log_dbg(reader, D_READER, "answer from card: %s", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
|
---|
95 |
|
---|
96 | reqans[4] = cta_res[1]; // adapt length byte
|
---|
97 | reader_cmd2icc(reader, reqans, 5, cta_res, p_cta_lr);
|
---|
98 |
|
---|
99 | if(cta_res[0] != CMD_BYTE)
|
---|
100 | {
|
---|
101 | rdr_log(reader, "unknown response: cta_res[0] expected to be %02x, is %02x", CMD_BYTE, cta_res[0]);
|
---|
102 | return ERROR;
|
---|
103 | }
|
---|
104 |
|
---|
105 | if((cta_res[1] == 0x03) && (cta_res[2] == 0xe2))
|
---|
106 | {
|
---|
107 | switch(cta_res[3 + dre_v])
|
---|
108 | {
|
---|
109 | case 0xe1:
|
---|
110 | rdr_log(reader, "checksum error: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
|
---|
111 | break;
|
---|
112 |
|
---|
113 | case 0xe2:
|
---|
114 | rdr_log(reader, "wrong cmd len: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
|
---|
115 | break;
|
---|
116 |
|
---|
117 | case 0xe3:
|
---|
118 | rdr_log(reader, "illegal command: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
|
---|
119 | break;
|
---|
120 |
|
---|
121 | case 0xe4:
|
---|
122 | rdr_log(reader, "wrong adress type: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
|
---|
123 | break;
|
---|
124 |
|
---|
125 | case 0xe5:
|
---|
126 | rdr_log(reader, "wrong CMD param: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
|
---|
127 | break;
|
---|
128 |
|
---|
129 | case 0xe6:
|
---|
130 | rdr_log(reader, "wrong UA: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
|
---|
131 | break;
|
---|
132 |
|
---|
133 | case 0xe7:
|
---|
134 | rdr_log(reader, "wrong group: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
|
---|
135 | break;
|
---|
136 |
|
---|
137 | case 0xe8:
|
---|
138 | rdr_log(reader, "wrong key num: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
|
---|
139 | break;
|
---|
140 |
|
---|
141 | case 0xeb:
|
---|
142 | rdr_log(reader, "No key or subscribe: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
|
---|
143 | break;
|
---|
144 |
|
---|
145 | case 0xec:
|
---|
146 | rdr_log(reader, "wrong signature: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
|
---|
147 | break;
|
---|
148 |
|
---|
149 | case 0xed:
|
---|
150 | rdr_log(reader, "wrong provider: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
|
---|
151 | break;
|
---|
152 |
|
---|
153 | case 0xef:
|
---|
154 | rdr_log(reader, "wrong GEO code: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
|
---|
155 | break;
|
---|
156 |
|
---|
157 | default:
|
---|
158 | rdr_log_dbg(reader, D_READER, "unknown error: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
|
---|
159 | break;
|
---|
160 | }
|
---|
161 | return ERROR; // error
|
---|
162 | }
|
---|
163 |
|
---|
164 | int32_t length_excl_leader = *p_cta_lr;
|
---|
165 |
|
---|
166 | if((cta_res[*p_cta_lr - 2] == 0x90) && (cta_res[*p_cta_lr - 1] == 0x00))
|
---|
167 | { length_excl_leader -= 2; }
|
---|
168 |
|
---|
169 | checksum = ~xor(cta_res + 2, length_excl_leader - 3);
|
---|
170 |
|
---|
171 | if(cta_res[length_excl_leader - 1] != checksum)
|
---|
172 | {
|
---|
173 | rdr_log(reader, "checksum does not match, expected %02x received %02x:%s", checksum,
|
---|
174 | cta_res[length_excl_leader - 1], cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
|
---|
175 | return ERROR; // error
|
---|
176 | }
|
---|
177 | return OK;
|
---|
178 | }
|
---|
179 |
|
---|
180 | #define dre_script(cmd, len, cmd_type, crypted, keynum) \
|
---|
181 | { \
|
---|
182 | dre_command(reader, cmd, len, cta_res, &cta_lr, crypted, keynum, crypted, cmd_type); \
|
---|
183 | }
|
---|
184 |
|
---|
185 | #define dre_cmd(cmd) \
|
---|
186 | { \
|
---|
187 | dre_command(reader, cmd, sizeof(cmd), cta_res, &cta_lr, 0, 0, 0, 0); \
|
---|
188 | }
|
---|
189 |
|
---|
190 | #define dre_cmd_c(cmd,crypted,keynum) \
|
---|
191 | { \
|
---|
192 | dre_command(reader, cmd, sizeof(cmd),cta_res,&cta_lr, crypted, keynum, 1, 0); \
|
---|
193 | }
|
---|
194 |
|
---|
195 | static int32_t dre_set_provider_info(struct s_reader *reader)
|
---|
196 | {
|
---|
197 | def_resp;
|
---|
198 | int32_t i;
|
---|
199 | int subscr_cmd_len = 4;
|
---|
200 | uint8_t subscr[4]; // = { 0x59, 0x14 }; // subscriptions
|
---|
201 | uint8_t dates[] = { 0x5b, 0x00, 0x14 }; // validity dates
|
---|
202 | uint8_t subscr_len = 0, n = 0;
|
---|
203 | struct dre_data *csystem_data = reader->csystem_data;
|
---|
204 |
|
---|
205 | cs_clear_entitlement(reader);
|
---|
206 |
|
---|
207 | switch(csystem_data->provider)
|
---|
208 | {
|
---|
209 | case 0x02:
|
---|
210 | case 0x03:
|
---|
211 | subscr[0] = 0x84;
|
---|
212 | subscr[1] = 0;
|
---|
213 | subscr[2] = 0x5F;
|
---|
214 | subscr[3] = csystem_data->provider;
|
---|
215 | dates[0] = 0x85;
|
---|
216 | subscr_len = 0x5F;
|
---|
217 | break;
|
---|
218 |
|
---|
219 | case 0x18:
|
---|
220 | case 0x19:
|
---|
221 | case 0x1A:
|
---|
222 | subscr[0] = 0x94;
|
---|
223 | subscr[1] = 0;
|
---|
224 | subscr[2] = 0x5F;
|
---|
225 | subscr[3] = csystem_data->provider;
|
---|
226 | dates[0] = 0x95;
|
---|
227 | subscr_len = 0x5F;
|
---|
228 | break;
|
---|
229 |
|
---|
230 | default:
|
---|
231 | subscr[0] = 0x59;
|
---|
232 | subscr[1] = csystem_data->provider;
|
---|
233 | subscr_len = 0x20;
|
---|
234 | subscr_cmd_len = 2;
|
---|
235 | }
|
---|
236 |
|
---|
237 | chk_subscr:
|
---|
238 |
|
---|
239 | if((dre_script(subscr, subscr_cmd_len, 0, 0, 0))) // ask subscription packages, returns error on 0x11 card
|
---|
240 | {
|
---|
241 | uint8_t pbm[subscr_len];
|
---|
242 | char tmp_dbg[subscr_len*2+1];
|
---|
243 | memcpy(pbm, cta_res + 3, cta_lr - 6);
|
---|
244 | rdr_log_dbg(reader, D_READER, "pbm: %s", cs_hexdump(0, pbm, subscr_len, tmp_dbg, sizeof(tmp_dbg)));
|
---|
245 |
|
---|
246 | for(i = 0; i < subscr_len; i++)
|
---|
247 | {
|
---|
248 | if(pbm[i] != 0xff)
|
---|
249 | {
|
---|
250 | dates[1] = i;
|
---|
251 | dates[2] = csystem_data->provider;
|
---|
252 | dre_cmd(dates); // ask for validity dates
|
---|
253 |
|
---|
254 | time_t start;
|
---|
255 | time_t end;
|
---|
256 | start = (cta_res[3] << 24) | (cta_res[4] << 16) | (cta_res[5] << 8) | cta_res[6];
|
---|
257 | end = (cta_res[7] << 24) | (cta_res[8] << 16) | (cta_res[9] << 8) | cta_res[10];
|
---|
258 |
|
---|
259 | struct tm temp;
|
---|
260 |
|
---|
261 | localtime_r(&start, &temp);
|
---|
262 | int32_t startyear = temp.tm_year + 1900;
|
---|
263 | int32_t startmonth = temp.tm_mon + 1;
|
---|
264 | int32_t startday = temp.tm_mday;
|
---|
265 | localtime_r(&end, &temp);
|
---|
266 | int32_t endyear = temp.tm_year + 1900;
|
---|
267 | int32_t endmonth = temp.tm_mon + 1;
|
---|
268 | int32_t endday = temp.tm_mday;
|
---|
269 | rdr_log(reader, "active package %i valid from %04i/%02i/%02i to %04i/%02i/%02i",
|
---|
270 | i + n, startyear, startmonth, startday, endyear, endmonth, endday);
|
---|
271 | cs_add_entitlement(reader, reader->caid, b2ll(4, reader->prid[0]), 0, i + n, start, end, 5, 1);
|
---|
272 | }
|
---|
273 | }
|
---|
274 | }
|
---|
275 |
|
---|
276 | if(subscr_len == 0x5F) // read second part subscription packages, for DRE3 and DRE4
|
---|
277 | {
|
---|
278 | subscr[1] = 0x5F;
|
---|
279 | subscr[2] = 0x21;
|
---|
280 | subscr_len = 0x21;
|
---|
281 | n = 0x5F;
|
---|
282 | goto chk_subscr;
|
---|
283 | }
|
---|
284 |
|
---|
285 | return OK;
|
---|
286 | }
|
---|
287 |
|
---|
288 | static void dre_read_ee(struct s_reader *reader, const char *path, uint8_t provid)
|
---|
289 | {
|
---|
290 | def_resp;
|
---|
291 | int i, n;
|
---|
292 | uint8_t *ee = malloc(2048);
|
---|
293 | if(ee == NULL) return;
|
---|
294 |
|
---|
295 | uint8_t drecmd43[] = { 0x80, 0x00, 0x00, 0x00, 0x05, 0x59, 0x03, 0x43, 0x11, 0xAD };
|
---|
296 | uint8_t drecmd45[] = { 0x45, 0x11 };
|
---|
297 |
|
---|
298 | drecmd43[8] = drecmd45[1] = provid;
|
---|
299 | drecmd43[9] = ~xor(&drecmd43[7], 2);
|
---|
300 |
|
---|
301 | for(i = 0; i < 8; i++)
|
---|
302 | {
|
---|
303 | for(n = 0; n < 8; n++)
|
---|
304 | {
|
---|
305 | reader_cmd2icc(reader, drecmd43, 10, cta_res, &cta_lr);
|
---|
306 |
|
---|
307 | dre_cmd_c(drecmd45, n, i * 32);
|
---|
308 |
|
---|
309 | if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
|
---|
310 | {
|
---|
311 | free(ee);
|
---|
312 | rdr_log(reader, "ERROR read ee.bin from card");
|
---|
313 | return;
|
---|
314 | }
|
---|
315 |
|
---|
316 | memcpy(&ee[((n * 8) + i) * 32] ,&cta_res[2] ,32);
|
---|
317 |
|
---|
318 | }
|
---|
319 | }
|
---|
320 |
|
---|
321 | FILE *pFile = fopen(path, "wb");
|
---|
322 |
|
---|
323 | if(pFile == NULL)
|
---|
324 | {
|
---|
325 | free(ee);
|
---|
326 | return ;
|
---|
327 | }
|
---|
328 |
|
---|
329 | fwrite(ee, 2048, 1, pFile);
|
---|
330 | fclose(pFile);
|
---|
331 | free(ee);
|
---|
332 | rdr_log(reader, "ee.bin saved to %s", path);
|
---|
333 | }
|
---|
334 | /*
|
---|
335 | static void cmd_test(struct s_reader *reader)
|
---|
336 | {
|
---|
337 | def_resp;
|
---|
338 | int i;
|
---|
339 | uint8_t drecmd[] = { 0x00, 0x02 };
|
---|
340 | char tmp[64];
|
---|
341 |
|
---|
342 | for(i = 0; i <= 0xFF; i++)
|
---|
343 | {
|
---|
344 | if(i == 0x45) continue;
|
---|
345 | drecmd[0] = i;
|
---|
346 | dre_cmd(drecmd);
|
---|
347 | if(cta_res[2] == 0xE2)
|
---|
348 | {
|
---|
349 | if(cta_res[3] != 0xE3) rdr_log(reader, "cmd %02X error %02X",i ,cta_res[3]);
|
---|
350 | }
|
---|
351 | else
|
---|
352 | {
|
---|
353 | rdr_log(reader, "cmd %02X answer %s",i ,cs_hexdump(0, cta_res, cta_res[1]+2, tmp, sizeof(tmp)));
|
---|
354 | }
|
---|
355 | }
|
---|
356 |
|
---|
357 | uint8_t drecmd[64];
|
---|
358 |
|
---|
359 | //memset(drecmd, 0, 64);
|
---|
360 | //drecmd[0] = 0x71;
|
---|
361 | for(i = 2; i <= 64; i++)
|
---|
362 | {
|
---|
363 | memset(drecmd, 0, 64);
|
---|
364 | drecmd[i-1] = 0x02;
|
---|
365 | drecmd[0] = 0x71;
|
---|
366 |
|
---|
367 | dre_script(drecmd, i, 0, 0, 0);
|
---|
368 |
|
---|
369 | if(cta_res[2] == 0xE2)
|
---|
370 | {
|
---|
371 | if((cta_res[3] != 0xE2) & (cta_res[3] != 0xED)) rdr_log(reader, "Len %02X error %02X",i ,cta_res[3]);
|
---|
372 | 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)));
|
---|
373 | }
|
---|
374 | else
|
---|
375 | {
|
---|
376 | rdr_log(reader, "Len %02X answer %s",i ,cs_hexdump(0, cta_res, cta_res[1]+2, tmp, sizeof(tmp)));
|
---|
377 | }
|
---|
378 | }
|
---|
379 | }
|
---|
380 | */
|
---|
381 | static int32_t dre_card_init(struct s_reader *reader, ATR *newatr)
|
---|
382 | {
|
---|
383 | get_atr;
|
---|
384 | def_resp;
|
---|
385 | uint8_t ua[] = { 0x43, 0x15 }; // get serial number (UA)
|
---|
386 | uint8_t providers[] = { 0x49, 0x15 }; // get providers
|
---|
387 | uint8_t cmd56[] = { 0x56, 0x00 };
|
---|
388 | int32_t i;
|
---|
389 | char *card;
|
---|
390 | char tmp[9];
|
---|
391 |
|
---|
392 | if((atr[0] != 0x3b) || (atr[1] != 0x15) || (atr[2] != 0x11) || (atr[3] != 0x12) || (
|
---|
393 | ((atr[4] != 0x01) || (atr[5] != 0x01)) &&
|
---|
394 | ((atr[4] != 0xca) || (atr[5] != 0x07)) &&
|
---|
395 | ((atr[4] != 0xcb) || (atr[5] != 0x07)) &&
|
---|
396 | ((atr[4] != 0xcc) || (atr[5] != 0x07)) &&
|
---|
397 | ((atr[4] != 0xcd) || (atr[5] != 0x07))
|
---|
398 | ))
|
---|
399 | { return ERROR; }
|
---|
400 |
|
---|
401 | if(!cs_malloc(&reader->csystem_data, sizeof(struct dre_data)))
|
---|
402 | { return ERROR; }
|
---|
403 | struct dre_data *csystem_data = reader->csystem_data;
|
---|
404 |
|
---|
405 | csystem_data->provider = atr[6];
|
---|
406 | uint8_t checksum = xor(atr + 1, 6);
|
---|
407 |
|
---|
408 | if(checksum != atr[7])
|
---|
409 | { rdr_log(reader, "warning: expected ATR checksum %02x, smartcard reports %02x", checksum, atr[7]); }
|
---|
410 |
|
---|
411 | switch(atr[6])
|
---|
412 | {
|
---|
413 | case 0:
|
---|
414 | if(!(dre_cmd(cmd56))) { return ERROR; }
|
---|
415 | if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00)) { return ERROR; }
|
---|
416 |
|
---|
417 | switch(cta_res[4])
|
---|
418 | {
|
---|
419 | case 0x02:
|
---|
420 | card = "Tricolor Centr DRE3";
|
---|
421 | reader->caid = 0x4ae1;
|
---|
422 | break;
|
---|
423 |
|
---|
424 | case 0x03:
|
---|
425 | card = "Tricolor Syberia DRE3";
|
---|
426 | reader->caid = 0x4ae1;
|
---|
427 | break;
|
---|
428 |
|
---|
429 | case 0x18:
|
---|
430 | case 0x19:
|
---|
431 | card = "Tricolor Centr DRE4";
|
---|
432 | reader->caid = 0x2710;
|
---|
433 | break;
|
---|
434 |
|
---|
435 | case 0x1A:
|
---|
436 | card = "Tricolor Syberia DRE4";
|
---|
437 | reader->caid = 0x2710;
|
---|
438 | break;
|
---|
439 |
|
---|
440 | default:
|
---|
441 | return ERROR;
|
---|
442 | }
|
---|
443 | csystem_data->provider = cta_res[4];
|
---|
444 | providers[0] = 0x83;
|
---|
445 | break;
|
---|
446 |
|
---|
447 | case 0x11:
|
---|
448 | card = "Tricolor Centr DRE2";
|
---|
449 | reader->caid = 0x4ae1;
|
---|
450 | break; // 59 type card = MSP (74 type = ATMEL)
|
---|
451 |
|
---|
452 | case 0x12:
|
---|
453 | card = "Cable TV";
|
---|
454 | reader->caid = 0x4ae1; // TODO not sure about this one
|
---|
455 | break;
|
---|
456 |
|
---|
457 | case 0x14:
|
---|
458 | card = "Tricolor Syberia DRE2";
|
---|
459 | reader->caid = 0x4ae1;
|
---|
460 | break; // 59 type card
|
---|
461 |
|
---|
462 | case 0x15:
|
---|
463 | card = "Platforma HD / DW old";
|
---|
464 | reader->caid = 0x4ae1;
|
---|
465 | break; // 59 type card
|
---|
466 |
|
---|
467 | default:
|
---|
468 | return ERROR;
|
---|
469 | }
|
---|
470 |
|
---|
471 | memset(reader->prid, 0x00, 8);
|
---|
472 |
|
---|
473 | if(atr[6] > 0)
|
---|
474 | {
|
---|
475 | reader->prid[0][3] = atr[6];
|
---|
476 | }
|
---|
477 | else
|
---|
478 | {
|
---|
479 | reader->prid[0][3] = csystem_data->provider;
|
---|
480 | }
|
---|
481 |
|
---|
482 | uint8_t cmd54[] = { 0x54, 0x14 }; // geocode
|
---|
483 | cmd54[1] = csystem_data->provider;
|
---|
484 | uint8_t geocode = 0;
|
---|
485 |
|
---|
486 | if((dre_cmd(cmd54))) // error would not be fatal, like on 0x11 cards
|
---|
487 | { geocode = cta_res[3]; }
|
---|
488 |
|
---|
489 | providers[1] = csystem_data->provider;
|
---|
490 | if(!(dre_cmd(providers)))
|
---|
491 | { return ERROR; } // fatal error
|
---|
492 |
|
---|
493 | if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
|
---|
494 | { return ERROR; }
|
---|
495 |
|
---|
496 | uint8_t provname[128];
|
---|
497 |
|
---|
498 | for(i = 0; ((i < cta_res[2] - 6) && (i < 128)); i++)
|
---|
499 | {
|
---|
500 | provname[i] = cta_res[6 + i];
|
---|
501 | if(provname[i] == 0x00)
|
---|
502 | { break; }
|
---|
503 | }
|
---|
504 |
|
---|
505 | int32_t major_version = cta_res[3];
|
---|
506 | int32_t minor_version = cta_res[4];
|
---|
507 |
|
---|
508 | ua[1] = csystem_data->provider;
|
---|
509 | dre_cmd(ua); // error would not be fatal
|
---|
510 |
|
---|
511 | int32_t hexlength = cta_res[1] - 2; // discard first and last byte, last byte is always checksum, first is answer code
|
---|
512 |
|
---|
513 | if(reader->force_ua)
|
---|
514 | {
|
---|
515 | rdr_log(reader, "WARNING!!! used UA from force_ua %08X", reader->force_ua);
|
---|
516 | memcpy(cta_res + 3, &reader->force_ua, 4);
|
---|
517 | }
|
---|
518 |
|
---|
519 | reader->hexserial[0] = 0;
|
---|
520 | reader->hexserial[1] = 0;
|
---|
521 | memcpy(reader->hexserial + 2, cta_res + 3, hexlength);
|
---|
522 |
|
---|
523 | int32_t low_dre_id, dre_chksum;
|
---|
524 | uint8_t buf[32];
|
---|
525 |
|
---|
526 | if(major_version < 0x3)
|
---|
527 | {
|
---|
528 | low_dre_id = ((cta_res[4] << 16) | (cta_res[5] << 8) | cta_res[6]) - 48608;
|
---|
529 | dre_chksum = 0;
|
---|
530 | snprintf((char *)buf, sizeof(buf), "%i%i%08i", csystem_data->provider - 16, major_version + 1, low_dre_id);
|
---|
531 |
|
---|
532 | for(i = 0; i < 32; i++)
|
---|
533 | {
|
---|
534 | if(buf[i] == 0x00)
|
---|
535 | { break; }
|
---|
536 | dre_chksum += buf[i] - 48;
|
---|
537 | }
|
---|
538 |
|
---|
539 | if(major_version < 2)
|
---|
540 | {
|
---|
541 | reader->caid = 0x4ae0;
|
---|
542 | card = csystem_data->provider == 0x11 ? "Tricolor Centr DRE1" : "Tricolor Syberia DRE1";
|
---|
543 | }
|
---|
544 |
|
---|
545 | rdr_log(reader, "type: DRE Crypt, caid: %04X, serial: {%s}, dre id: %i%i%i%08i, geocode %i, card: %s v%i.%i",
|
---|
546 | reader->caid, cs_hexdump(0, reader->hexserial + 2, 4, tmp, sizeof(tmp)), dre_chksum,
|
---|
547 | csystem_data->provider - 16, major_version + 1, low_dre_id, geocode, card, major_version, minor_version);
|
---|
548 | }
|
---|
549 | else
|
---|
550 | {
|
---|
551 | low_dre_id = ((cta_res[4] << 16) | (cta_res[5] << 8) | cta_res[6]);
|
---|
552 | dre_chksum = 0;
|
---|
553 | snprintf((char *)buf, sizeof(buf), "%i%i%08i", csystem_data->provider, major_version, low_dre_id);
|
---|
554 |
|
---|
555 | for(i = 0; i < 32; i++)
|
---|
556 | {
|
---|
557 | if(buf[i] == 0x00)
|
---|
558 | { break; }
|
---|
559 | dre_chksum += buf[i] - 48;
|
---|
560 | }
|
---|
561 | rdr_log(reader, "type: DRE Crypt, caid: %04X, serial: {%s}, dre id: %i%03i%i%08i, geocode %i, card: %s v%i.%i",
|
---|
562 | reader->caid, cs_hexdump(0, reader->hexserial + 2, 4, tmp, sizeof(tmp)), dre_chksum, csystem_data->provider,
|
---|
563 | major_version, low_dre_id, geocode, card, major_version, minor_version);
|
---|
564 | }
|
---|
565 |
|
---|
566 | rdr_log(reader, "Provider name:%s.", provname);
|
---|
567 |
|
---|
568 |
|
---|
569 | memset(reader->sa, 0, sizeof(reader->sa));
|
---|
570 | 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...
|
---|
571 |
|
---|
572 | rdr_log_sensitive(reader, "SA = %02X%02X%02X%02X, UA = {%s}", reader->sa[0][0], reader->sa[0][1], reader->sa[0][2],
|
---|
573 | reader->sa[0][3], cs_hexdump(0, reader->hexserial + 2, 4, tmp, sizeof(tmp)));
|
---|
574 |
|
---|
575 | reader->nprov = 1;
|
---|
576 |
|
---|
577 | //cmd_test(reader);
|
---|
578 |
|
---|
579 | // exec user script, wicardd format
|
---|
580 | if(reader->userscript != NULL)
|
---|
581 | {
|
---|
582 | uint8_t *usercmd = NULL;
|
---|
583 | int cmd_len;
|
---|
584 | int n;
|
---|
585 | char *tempbuf = malloc(2048);
|
---|
586 | trim2(reader->userscript);
|
---|
587 | FILE *pFile = fopen(reader->userscript, "rt");
|
---|
588 |
|
---|
589 | if(pFile != NULL)
|
---|
590 | {
|
---|
591 | uint8_t ignoreProvid = 0;
|
---|
592 | uint8_t crypted = 0;
|
---|
593 | uint8_t cryptkey = 0;
|
---|
594 | do
|
---|
595 | {
|
---|
596 | tempbuf[0] = '\0';
|
---|
597 | if(usercmd != NULL) free(usercmd);
|
---|
598 |
|
---|
599 | if(fgets(tempbuf, 2048, pFile) == NULL) continue;
|
---|
600 |
|
---|
601 | if(strlen(tempbuf) < 10) continue;
|
---|
602 |
|
---|
603 | trim2(tempbuf);
|
---|
604 |
|
---|
605 | ignoreProvid = 0;
|
---|
606 | crypted = 0;
|
---|
607 | cryptkey = 0;
|
---|
608 |
|
---|
609 | if(tempbuf[0] == '8' && tempbuf[1] == '6' && csystem_data->provider == 0x11) ignoreProvid = 1;
|
---|
610 | else if(strncmp(tempbuf ,"REG2" ,4) == 0)
|
---|
611 | {
|
---|
612 | dre_read_ee(reader, &tempbuf[4] ,csystem_data->provider);
|
---|
613 | continue;
|
---|
614 | }
|
---|
615 | else if(strncmp(tempbuf ,"CR" ,2) == 0)
|
---|
616 | {
|
---|
617 | crypted = 1;
|
---|
618 | cryptkey = ((tempbuf[2] - (tempbuf[2] > 0x39 ? 0x37:0x30)) << 4) + ((tempbuf[3] - (tempbuf[3] > 0x39 ? 0x37:0x30)) & 0xF);
|
---|
619 | }
|
---|
620 | else if(tempbuf[0] != '5' && tempbuf[1] != '9') continue;
|
---|
621 |
|
---|
622 | strtoupper(tempbuf);
|
---|
623 |
|
---|
624 | cmd_len = strlen(tempbuf) / 2 - 3 + ignoreProvid - (crypted * 2);
|
---|
625 | usercmd = malloc(cmd_len);
|
---|
626 |
|
---|
627 | for(i = 0, n = 4 + (crypted * 4); i < cmd_len; i++, n += 2)
|
---|
628 | {
|
---|
629 | usercmd[i] = ((tempbuf[n] - (tempbuf[n] > 0x39 ? 0x37 : 0x30)) << 4) + ((tempbuf[n + 1] - (tempbuf[n + 1] > 0x39 ? 0x37 : 0x30)) & 0xF);
|
---|
630 | }
|
---|
631 |
|
---|
632 | /*if(usercmd[cmd_len-1] != csystem_data->provider && !ignoreProvid)
|
---|
633 | {
|
---|
634 | rdr_log(reader, "Skip script: current provid %02X , script provid %02X", csystem_data->provider, usercmd[cmd_len-1]);
|
---|
635 | continue;
|
---|
636 | }
|
---|
637 | */
|
---|
638 | rdr_log(reader, "User script: %s", tempbuf);
|
---|
639 |
|
---|
640 | /*ret =*/
|
---|
641 |
|
---|
642 | rdr_log(reader, "Script %s", (dre_script(usercmd, cmd_len, ignoreProvid, crypted, cryptkey)) ? "done" : "error");
|
---|
643 | }
|
---|
644 | while(!feof(pFile));
|
---|
645 | }
|
---|
646 | else
|
---|
647 | {
|
---|
648 | rdr_log(reader, "Can't open script file (%s)", reader->userscript);
|
---|
649 | }
|
---|
650 |
|
---|
651 | //if(usercmd != NULL) free(usercmd);
|
---|
652 | if(tempbuf != NULL) free(tempbuf);
|
---|
653 | }
|
---|
654 |
|
---|
655 | if(csystem_data->provider == 0x11)
|
---|
656 | {
|
---|
657 | memset(reader->prid[1], 0x00, 8);
|
---|
658 | reader->prid[1][3] = 0xFE;
|
---|
659 | reader->nprov = 2;
|
---|
660 | }
|
---|
661 |
|
---|
662 | if(!dre_set_provider_info(reader))
|
---|
663 | { return ERROR; } // fatal error
|
---|
664 |
|
---|
665 |
|
---|
666 | rdr_log(reader, "ready for requests");
|
---|
667 | return OK;
|
---|
668 | }
|
---|
669 |
|
---|
670 | static void DREover(struct s_reader *reader, const uint8_t *ECMdata, uint8_t *DW)
|
---|
671 | {
|
---|
672 | uint32_t key_schedule[32];
|
---|
673 |
|
---|
674 | if(reader->des_key_length < 128)
|
---|
675 | {
|
---|
676 | rdr_log(reader, "error: deskey is missing or too short");
|
---|
677 | return;
|
---|
678 | }
|
---|
679 |
|
---|
680 | if(ECMdata[2] >= (43 + 4) && ECMdata[40] == 0x3A && ECMdata[41] == 0x4B)
|
---|
681 | {
|
---|
682 | des_set_key(&reader->des_key[(ECMdata[42] & 0x0F) * 8], key_schedule);
|
---|
683 |
|
---|
684 | des(DW, key_schedule, 0); // even DW post-process
|
---|
685 | des(DW + 8, key_schedule, 0); // odd DW post-process
|
---|
686 | };
|
---|
687 | };
|
---|
688 |
|
---|
689 | static int32_t dre_do_ecm(struct s_reader *reader, const ECM_REQUEST *er, struct s_ecm_answer *ea)
|
---|
690 | {
|
---|
691 | def_resp;
|
---|
692 | uint16_t overcryptId;
|
---|
693 | uint8_t tmp[16];
|
---|
694 | char tmp_dbg[256];
|
---|
695 | struct dre_data *csystem_data = reader->csystem_data;
|
---|
696 | if(reader->caid == 0x4ae0)
|
---|
697 | {
|
---|
698 | uint8_t ecmcmd41[] = { 0x41,
|
---|
699 | 0x58, 0x1f, 0x00, // fixed part, dont change
|
---|
700 | 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // 0x01 - 0x08: next key
|
---|
701 | 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, // 0x11 - 0x18: current key
|
---|
702 | 0x3b, 0x59, 0x11 }; // 0x3b = keynumber, can be a value 56 ;; 0x59 number of package = 58+1 - Pay Package ;; 0x11 = provider
|
---|
703 |
|
---|
704 | ecmcmd41[22] = csystem_data->provider;
|
---|
705 | memcpy(ecmcmd41 + 4, er->ecm + 8, 16);
|
---|
706 | ecmcmd41[20] = er->ecm[6]; // keynumber
|
---|
707 | ecmcmd41[21] = 0x58 + er->ecm[25]; // package number
|
---|
708 | rdr_log_dbg(reader, D_READER, "unused ECM info front:%s", cs_hexdump(0, er->ecm, 8, tmp_dbg, sizeof(tmp_dbg)));
|
---|
709 | 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)));
|
---|
710 |
|
---|
711 | if((dre_cmd(ecmcmd41))) // ecm request
|
---|
712 | {
|
---|
713 | if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
|
---|
714 | { return ERROR; } // exit if response is not 90 00
|
---|
715 | memcpy(ea->cw, cta_res + 11, 8);
|
---|
716 | memcpy(ea->cw + 8, cta_res + 3, 8);
|
---|
717 |
|
---|
718 | return OK;
|
---|
719 | }
|
---|
720 | }
|
---|
721 | else if(reader->caid == 0x4ae1)
|
---|
722 | {
|
---|
723 | if(csystem_data->provider == 0x11 || csystem_data->provider == 0x14)
|
---|
724 | {
|
---|
725 | uint8_t ecmcmd51[] = { 0x51, 0x02, 0x56, 0x05, 0x00, 0x4A, 0xE3, // fixed header?
|
---|
726 | 0x9C, 0xDA, // first three nibbles count up, fourth nibble counts down; all ECMs sent twice
|
---|
727 | 0xC1, 0x71, 0x21, 0x06, 0xF0, 0x14, 0xA7, 0x0E, // next key?
|
---|
728 | 0x89, 0xDA, 0xC9, 0xD7, 0xFD, 0xB9, 0x06, 0xFD, // current key?
|
---|
729 | 0xD5, 0x1E, 0x2A, 0xA3, 0xB5, 0xA0, 0x82, 0x11, // key or signature?
|
---|
730 | 0x14 }; // provider
|
---|
731 |
|
---|
732 | memcpy(ecmcmd51 + 1, er->ecm + 5, 0x21);
|
---|
733 | rdr_log_dbg(reader, D_READER, "unused ECM info front:%s", cs_hexdump(0, er->ecm, 5, tmp_dbg, sizeof(tmp_dbg)));
|
---|
734 | rdr_log_dbg(reader, D_READER, "unused ECM info back:%s", cs_hexdump(0, er->ecm + 37, 4, tmp_dbg, sizeof(tmp_dbg)));
|
---|
735 | ecmcmd51[33] = csystem_data->provider; // no part of sig
|
---|
736 |
|
---|
737 | if((dre_cmd(ecmcmd51))) // ecm request
|
---|
738 | {
|
---|
739 | if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
|
---|
740 | { return ERROR; } // exit if response is not 90 00
|
---|
741 |
|
---|
742 | if(er->ecm[2] >= 46 && er->ecm[43] == 1 && csystem_data->provider == 0x11)
|
---|
743 | {
|
---|
744 | memcpy(tmp, cta_res + 11, 8);
|
---|
745 | memcpy(tmp + 8, cta_res + 3, 8);
|
---|
746 | overcryptId = b2i(2, &er->ecm[44]);
|
---|
747 | rdr_log_dbg(reader, D_READER, "ICG ID: %04X", overcryptId);
|
---|
748 |
|
---|
749 | Drecrypt2OverCW(overcryptId,tmp);
|
---|
750 |
|
---|
751 | if(isValidDCW(tmp))
|
---|
752 | {
|
---|
753 | memcpy(ea->cw, tmp, 16);
|
---|
754 | return OK;
|
---|
755 | }
|
---|
756 | return ERROR;
|
---|
757 | }
|
---|
758 |
|
---|
759 | DREover(reader, er->ecm, cta_res + 3);
|
---|
760 |
|
---|
761 | if(isValidDCW(cta_res + 3))
|
---|
762 | {
|
---|
763 | memcpy(ea->cw, cta_res + 11, 8);
|
---|
764 | memcpy(ea->cw + 8, cta_res + 3, 8);
|
---|
765 | return OK;
|
---|
766 | }
|
---|
767 | }
|
---|
768 | }
|
---|
769 | else if((csystem_data->provider == 0x02 || csystem_data->provider == 0x03) && er->ecm[3] == 3)
|
---|
770 | {
|
---|
771 | // DRE 3
|
---|
772 |
|
---|
773 | if (er->ecm[4] == 2)
|
---|
774 | {
|
---|
775 | memcpy(ea->cw, &er->ecm[42], 8);
|
---|
776 | memcpy(&ea->cw[8], &er->ecm[34], 8);
|
---|
777 | return OK;
|
---|
778 | }
|
---|
779 |
|
---|
780 | uint8_t cmdlen;
|
---|
781 | uint8_t crypted = er->ecm[8] & 1;
|
---|
782 | uint8_t cryptkey = (er->ecm[8] & 6) >> 1;
|
---|
783 |
|
---|
784 | if (crypted == 0)
|
---|
785 | {
|
---|
786 | cmdlen = 50;
|
---|
787 | }
|
---|
788 | else
|
---|
789 | {
|
---|
790 | cmdlen = 57;
|
---|
791 | }
|
---|
792 |
|
---|
793 | uint8_t ecmcmd[cmdlen];
|
---|
794 |
|
---|
795 | memcpy(ecmcmd, &er->ecm[17], cmdlen - 1);
|
---|
796 | ecmcmd[cmdlen - 1] = csystem_data->provider;
|
---|
797 |
|
---|
798 | dre_cmd_c(ecmcmd, crypted, cryptkey);
|
---|
799 |
|
---|
800 | if(cta_res[2] == 0xD2 && isValidDCW(cta_res + 3))
|
---|
801 | {
|
---|
802 | memcpy(ea->cw, cta_res + 11, 8);
|
---|
803 | memcpy(ea->cw + 8, cta_res + 3, 8);
|
---|
804 | return OK;
|
---|
805 | }
|
---|
806 | }
|
---|
807 | }
|
---|
808 | else if(reader->caid == 0x2710 && er->ecm[3] == 4)
|
---|
809 | {
|
---|
810 | // DRE 4
|
---|
811 |
|
---|
812 | if (er->ecm[4] == 4)
|
---|
813 | {
|
---|
814 | memcpy(ea->cw, &er->ecm[22], 8);
|
---|
815 | memcpy(&ea->cw[8], &er->ecm[14], 8);
|
---|
816 | return OK;
|
---|
817 | }
|
---|
818 |
|
---|
819 | uint8_t cmdlen;
|
---|
820 | uint8_t crypted = er->ecm[8] & 1;
|
---|
821 | uint8_t cryptkey = (er->ecm[8] & 6) >> 1;
|
---|
822 |
|
---|
823 | if (crypted == 0)
|
---|
824 | {
|
---|
825 | cmdlen = 58;
|
---|
826 | }
|
---|
827 | else
|
---|
828 | {
|
---|
829 | cmdlen = 65;
|
---|
830 | }
|
---|
831 |
|
---|
832 | uint8_t ecmcmd[cmdlen];
|
---|
833 |
|
---|
834 | memcpy(ecmcmd, &er->ecm[9], cmdlen - 1);
|
---|
835 | ecmcmd[cmdlen - 1] = csystem_data->provider;
|
---|
836 |
|
---|
837 | dre_cmd_c(ecmcmd, crypted, cryptkey);
|
---|
838 |
|
---|
839 | if(cta_res[2] == 0xD2 && isValidDCW(cta_res + 3))
|
---|
840 | {
|
---|
841 | memcpy(ea->cw, cta_res + 11, 8);
|
---|
842 | memcpy(ea->cw + 8, cta_res + 3, 8);
|
---|
843 | return OK;
|
---|
844 | }
|
---|
845 | }
|
---|
846 | return ERROR;
|
---|
847 | }
|
---|
848 |
|
---|
849 | static int32_t dre_do_emm(struct s_reader *reader, EMM_PACKET *ep)
|
---|
850 | {
|
---|
851 | def_resp;
|
---|
852 | struct dre_data *csystem_data = reader->csystem_data;
|
---|
853 |
|
---|
854 | if(reader->caid == 0x4ae1)
|
---|
855 | {
|
---|
856 | if(reader->caid != b2i(2, ep->caid)) return ERROR;
|
---|
857 |
|
---|
858 | if(ep->type == UNIQUE && ep->emm[39] == 0x3d)
|
---|
859 | {
|
---|
860 | /* For new package activation. */
|
---|
861 | uint8_t emmcmd58[26];
|
---|
862 | emmcmd58[0] = 0x58;
|
---|
863 | memcpy(&emmcmd58[1], &ep->emm[40], 24);
|
---|
864 | emmcmd58[25] = csystem_data->provider;
|
---|
865 |
|
---|
866 | if((dre_cmd(emmcmd58)))
|
---|
867 | if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
|
---|
868 | { return ERROR; }
|
---|
869 | }
|
---|
870 | else if(ep->emm[0] == 0x86 && ep->emm[4] == 0x02 /*&& csystem_data->provider != 0x11*/)
|
---|
871 | {
|
---|
872 | uint8_t emmcmd52[0x3a];
|
---|
873 | emmcmd52[0] = 0x52;
|
---|
874 | int32_t i;
|
---|
875 | for(i = 0; i < 2; i++)
|
---|
876 | {
|
---|
877 | memcpy(emmcmd52 + 1, ep->emm + 5 + 32 + i * 56, 56);
|
---|
878 |
|
---|
879 | // check for shared address
|
---|
880 | if(ep->emm[3] != reader->sa[0][0])
|
---|
881 | { return OK; } // ignore, wrong address
|
---|
882 |
|
---|
883 | emmcmd52[0x39] = csystem_data->provider;
|
---|
884 |
|
---|
885 | if((dre_cmd(emmcmd52)))
|
---|
886 | if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
|
---|
887 | { return ERROR; } // exit if response is not 90 00
|
---|
888 | }
|
---|
889 | }
|
---|
890 | else if(ep->emm[0] == 0x86 && ep->emm[4] == 0x4D && csystem_data->provider == 0x11)
|
---|
891 | {
|
---|
892 | uint8_t emmcmd52[0x3a];
|
---|
893 |
|
---|
894 | emmcmd52[0] = 0x52;
|
---|
895 | emmcmd52[1] = 0x01;
|
---|
896 | emmcmd52[2] = ep->emm[5];
|
---|
897 | emmcmd52[3] = 0x01;
|
---|
898 | emmcmd52[4] = ep->emm[3];
|
---|
899 | emmcmd52[5] = 0;
|
---|
900 | emmcmd52[6] = 0;
|
---|
901 | emmcmd52[7] = 0;
|
---|
902 | emmcmd52[9] = 0x01;
|
---|
903 | emmcmd52[10] = 0x01;
|
---|
904 | emmcmd52[11] = 0;
|
---|
905 | memcpy(emmcmd52 + 13, ep->emm + 0x5C, 4);
|
---|
906 | int32_t i;
|
---|
907 |
|
---|
908 | for(i = 0; i < 2; i++)
|
---|
909 | {
|
---|
910 | emmcmd52[8] = ep->emm[0x61 + i * 0x29];
|
---|
911 | if(i == 0) emmcmd52[12] = ep->emm[0x60] == 0x56 ? 0x56 : 0x3B;
|
---|
912 | else emmcmd52[12] = ep->emm[0x60] == 0x56 ? 0x3B : 0x56;
|
---|
913 | memcpy(emmcmd52 + 0x11, ep->emm + 0x62 + i * 0x29, 40);
|
---|
914 |
|
---|
915 | // check for shared address
|
---|
916 | if(ep->emm[3] != reader->sa[0][0])
|
---|
917 | { return OK; } // ignore, wrong address
|
---|
918 |
|
---|
919 | emmcmd52[0x39] = csystem_data->provider;
|
---|
920 |
|
---|
921 | if((dre_cmd(emmcmd52)))
|
---|
922 | if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
|
---|
923 | { return ERROR; } // exit if response is not 90 00
|
---|
924 | }
|
---|
925 | }
|
---|
926 | else if (ep->emm[0] == 0x8c && (csystem_data->provider == 0x02 || csystem_data->provider == 0x03)) // dre3 group emm
|
---|
927 | {
|
---|
928 | if(ep->emm[3] != reader->sa[0][0])
|
---|
929 | { return OK; } // ignore, wrong address
|
---|
930 |
|
---|
931 | uint8_t crypted = ep->emm[10];
|
---|
932 |
|
---|
933 | if ((crypted & 1) == 1)
|
---|
934 | {
|
---|
935 | uint8_t emmcmd[0x49];
|
---|
936 |
|
---|
937 | memcpy(emmcmd, &ep->emm[0x13], 0x48);
|
---|
938 |
|
---|
939 | emmcmd[0x48] = csystem_data->provider;
|
---|
940 |
|
---|
941 | dre_cmd_c(emmcmd, crypted & 1, (crypted & 6) >> 1);
|
---|
942 |
|
---|
943 | if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
|
---|
944 | { return ERROR; } //exit if response is not 90 00
|
---|
945 |
|
---|
946 | memcpy(emmcmd, &ep->emm[0x5B], 0x48);
|
---|
947 |
|
---|
948 | emmcmd[0x48] = csystem_data->provider;
|
---|
949 |
|
---|
950 | dre_cmd_c(emmcmd, crypted & 1, (crypted & 6) >> 1);
|
---|
951 |
|
---|
952 | if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
|
---|
953 | { return ERROR; } //exit if response is not 90 00
|
---|
954 |
|
---|
955 | return OK;
|
---|
956 | }
|
---|
957 | else
|
---|
958 | {
|
---|
959 | uint8_t emmcmd[0x42];
|
---|
960 |
|
---|
961 | memcpy(emmcmd, &ep->emm[0x13], 0x41);
|
---|
962 |
|
---|
963 | emmcmd[0x41] = csystem_data->provider;
|
---|
964 |
|
---|
965 | dre_cmd_c(emmcmd, crypted & 1, (crypted & 6) >> 1);
|
---|
966 |
|
---|
967 | if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
|
---|
968 | { return ERROR; } // exit if response is not 90 00
|
---|
969 |
|
---|
970 | memcpy(emmcmd, &ep->emm[0x5B], 0x41);
|
---|
971 |
|
---|
972 | emmcmd[0x41] = csystem_data->provider;
|
---|
973 |
|
---|
974 | dre_cmd_c(emmcmd, crypted & 1, (crypted & 6) >> 1);
|
---|
975 |
|
---|
976 | if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
|
---|
977 | { return ERROR; } // exit if response is not 90 00
|
---|
978 |
|
---|
979 | return OK;
|
---|
980 | }
|
---|
981 | }
|
---|
982 | else if(ep->type == GLOBAL && ep->emm[0] == 0x91)
|
---|
983 | {
|
---|
984 | Drecrypt2OverEMM(ep->emm);
|
---|
985 | return OK;
|
---|
986 | }
|
---|
987 | else return OK;
|
---|
988 | }
|
---|
989 | else if(reader->caid == 0x2710)
|
---|
990 | {
|
---|
991 | // DRE 4
|
---|
992 | if(ep->type == UNIQUE)
|
---|
993 | {
|
---|
994 | uint16_t cmdlen;
|
---|
995 | uint8_t class, hlbUA, KEYindex;
|
---|
996 | int i, keycount;
|
---|
997 | uint8_t CMDtype = ep->emm[7];
|
---|
998 | uint16_t EMMlen = ep->emm[2] | ((ep->emm[1] & 0xF) << 8);
|
---|
999 | uint8_t cryptflag = ep->emm[10];
|
---|
1000 | uint8_t crypted = cryptflag & 1;
|
---|
1001 | uint8_t cryptkey = (cryptflag & 6) >> 1;
|
---|
1002 |
|
---|
1003 | if (CMDtype == 0x61)
|
---|
1004 | {
|
---|
1005 | uint8_t emmcmd91[19];
|
---|
1006 |
|
---|
1007 | emmcmd91[0] = 0x91;
|
---|
1008 | emmcmd91[1] = ep->emm[19];
|
---|
1009 | emmcmd91[2] = ep->emm[8];
|
---|
1010 | emmcmd91[3] = ep->emm[20];
|
---|
1011 | if(reader->force_ua) emmcmd91[3] += 2;
|
---|
1012 | memcpy(&emmcmd91[4], &reader->hexserial[2], 4);
|
---|
1013 | emmcmd91[8] = 0xF0;
|
---|
1014 | emmcmd91[17] = ep->emm[22];
|
---|
1015 | emmcmd91[18] = csystem_data->provider;
|
---|
1016 |
|
---|
1017 | if ((EMMlen - 24) > 16)
|
---|
1018 | {
|
---|
1019 | hlbUA = reader->hexserial[5] & 0xF;
|
---|
1020 |
|
---|
1021 | uint16_t keypos = cryptflag == 2 ? 17 : 9;
|
---|
1022 | keycount = (EMMlen - 24) / keypos;
|
---|
1023 |
|
---|
1024 | for(i = 0; i <= keycount ;i++)
|
---|
1025 | {
|
---|
1026 | if (i == keycount) return OK;
|
---|
1027 | if (hlbUA == (ep->emm[23 + (keypos * i)] & 0xF) ) break;
|
---|
1028 | }
|
---|
1029 |
|
---|
1030 | keypos = 24 + (keypos * i);
|
---|
1031 |
|
---|
1032 | memcpy(&emmcmd91[9], &ep->emm[keypos], 8);
|
---|
1033 |
|
---|
1034 | if((dre_cmd(emmcmd91)))
|
---|
1035 | if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00) || (cta_res[2] != 0xA2))
|
---|
1036 | return ERROR; // exit if response is not 90 00
|
---|
1037 |
|
---|
1038 | if (cryptflag == 2)
|
---|
1039 | {
|
---|
1040 | if (emmcmd91[17] == 0x56) KEYindex = 0x3B;
|
---|
1041 | else KEYindex = 0x56;
|
---|
1042 |
|
---|
1043 | keypos += 8;
|
---|
1044 | memcpy(&emmcmd91[9], &ep->emm[keypos], 8);
|
---|
1045 | emmcmd91[17] = KEYindex;
|
---|
1046 |
|
---|
1047 | dre_cmd(emmcmd91);
|
---|
1048 |
|
---|
1049 | if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00) || (cta_res[2] != 0xA2))
|
---|
1050 | { return ERROR; } // exit if response is not 90 00
|
---|
1051 |
|
---|
1052 | return OK;
|
---|
1053 | }
|
---|
1054 | }
|
---|
1055 | return ERROR;
|
---|
1056 | }
|
---|
1057 | else if (CMDtype == 0x62)
|
---|
1058 | {
|
---|
1059 | if (!memcmp(&reader->hexserial[2], &ep->emm[3], 4))
|
---|
1060 | {
|
---|
1061 | if (crypted)
|
---|
1062 | {
|
---|
1063 | cmdlen = 49;
|
---|
1064 | }
|
---|
1065 | else
|
---|
1066 | {
|
---|
1067 | cmdlen = 42;
|
---|
1068 | }
|
---|
1069 |
|
---|
1070 | uint8_t emmcmd92[cmdlen];
|
---|
1071 |
|
---|
1072 | memcpy(emmcmd92, &ep->emm[19], cmdlen - 1);
|
---|
1073 | emmcmd92[cmdlen - 1] = csystem_data->provider;
|
---|
1074 |
|
---|
1075 | if (crypted)
|
---|
1076 | {
|
---|
1077 | dre_cmd_c(emmcmd92, crypted, cryptkey);
|
---|
1078 | }
|
---|
1079 | else
|
---|
1080 | {
|
---|
1081 | dre_cmd(emmcmd92);
|
---|
1082 | }
|
---|
1083 |
|
---|
1084 | if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
|
---|
1085 | { return ERROR; } // exit if response is not 90 00
|
---|
1086 |
|
---|
1087 | class = ep->emm[8];
|
---|
1088 |
|
---|
1089 | uint8_t emmcmd95[3];
|
---|
1090 |
|
---|
1091 | emmcmd95[0] = 0x95;
|
---|
1092 | emmcmd95[1] = class;
|
---|
1093 | emmcmd95[2] = csystem_data->provider;
|
---|
1094 |
|
---|
1095 | dre_cmd(emmcmd95);
|
---|
1096 |
|
---|
1097 | uint8_t emmcmd91[19];
|
---|
1098 |
|
---|
1099 | emmcmd91[0] = 0x91;
|
---|
1100 | emmcmd91[1] = ep->emm[102];
|
---|
1101 | emmcmd91[2] = ep->emm[8];
|
---|
1102 | emmcmd91[3] = ep->emm[103];
|
---|
1103 | if(reader->force_ua) emmcmd91[3] += 2;
|
---|
1104 | memcpy(&emmcmd91[4], &reader->hexserial[2], 4);
|
---|
1105 | emmcmd91[8] = ep->emm[104];
|
---|
1106 | memcpy(&emmcmd91[9], &ep->emm[72], 8);
|
---|
1107 | emmcmd91[17] = ep->emm[105];
|
---|
1108 | emmcmd91[18] = csystem_data->provider;
|
---|
1109 |
|
---|
1110 | dre_cmd(emmcmd91);
|
---|
1111 |
|
---|
1112 | if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00) || (cta_res[2] != 0xA2) )
|
---|
1113 | { return ERROR; } // exit if response is not 90 00
|
---|
1114 |
|
---|
1115 | if (emmcmd91[17] == 0x56) KEYindex = 0x3B;
|
---|
1116 | else KEYindex = 0x56;
|
---|
1117 |
|
---|
1118 | memcpy(&emmcmd91[9], &ep->emm[86], 8);
|
---|
1119 | emmcmd91[17] = KEYindex;
|
---|
1120 |
|
---|
1121 | dre_cmd(emmcmd91);
|
---|
1122 |
|
---|
1123 | if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
|
---|
1124 | { return ERROR; } // exit if response is not 90 00
|
---|
1125 | }
|
---|
1126 | return OK;
|
---|
1127 | }
|
---|
1128 | else
|
---|
1129 | {
|
---|
1130 | if (memcmp(&reader->hexserial[2], &ep->emm[3], 4)) return OK;
|
---|
1131 |
|
---|
1132 | if (CMDtype == 0x63)
|
---|
1133 | {
|
---|
1134 | uint8_t emmcmdA5[7];
|
---|
1135 |
|
---|
1136 | emmcmdA5[0] = 0xA5;
|
---|
1137 | emmcmdA5[1] = 0;
|
---|
1138 | memcpy(&emmcmdA5[2], &reader->hexserial[2], 4);
|
---|
1139 | emmcmdA5[6] = csystem_data->provider;
|
---|
1140 |
|
---|
1141 | dre_cmd(emmcmdA5);
|
---|
1142 |
|
---|
1143 | if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
|
---|
1144 | { return ERROR; } //exit if response is not 90 00
|
---|
1145 | }
|
---|
1146 |
|
---|
1147 | if (crypted) cmdlen = EMMlen - 19;
|
---|
1148 | else cmdlen = ep->emm[11] + 1;
|
---|
1149 |
|
---|
1150 | uint8_t emmcmd[cmdlen];
|
---|
1151 |
|
---|
1152 | memcpy(emmcmd, &ep->emm[19], cmdlen - 1);
|
---|
1153 | emmcmd[cmdlen - 1] = csystem_data->provider;
|
---|
1154 |
|
---|
1155 | if(emmcmd[0] == 0x45)
|
---|
1156 | {
|
---|
1157 | cs_log("TRICOLOR Send KILL command for your card");
|
---|
1158 | return ERROR;
|
---|
1159 | }
|
---|
1160 |
|
---|
1161 | dre_cmd_c(emmcmd, crypted, cryptkey);
|
---|
1162 |
|
---|
1163 | if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
|
---|
1164 | { return ERROR; } //exit if response is not 90 00
|
---|
1165 | }
|
---|
1166 | return OK;
|
---|
1167 | }
|
---|
1168 | return ERROR;
|
---|
1169 | }
|
---|
1170 | else if(reader->caid != 0x2710 && reader->caid != 0x4AE1)
|
---|
1171 | {
|
---|
1172 | uint8_t emmcmd42[] =
|
---|
1173 | {
|
---|
1174 | 0x42, 0x85, 0x58, 0x01, 0xC8, 0x00, 0x00, 0x00, 0x05, 0xB8, 0x0C, 0xBD, 0x7B, 0x07, 0x04, 0xC8,
|
---|
1175 | 0x77, 0x31, 0x95, 0xF2, 0x30, 0xB7, 0xE9, 0xEE, 0x0F, 0x81, 0x39, 0x1C, 0x1F, 0xA9, 0x11, 0x3E,
|
---|
1176 | 0xE5, 0x0E, 0x8E, 0x50, 0xA4, 0x31, 0xBB, 0x01, 0x00, 0xD6, 0xAF, 0x69, 0x60, 0x04, 0x70, 0x3A,
|
---|
1177 | 0x91,
|
---|
1178 | 0x56, 0x58, 0x11
|
---|
1179 | };
|
---|
1180 | int32_t i;
|
---|
1181 |
|
---|
1182 | switch(ep->type)
|
---|
1183 | {
|
---|
1184 | case UNIQUE:
|
---|
1185 | for(i = 0; i < 2; i++)
|
---|
1186 | {
|
---|
1187 | memcpy(emmcmd42 + 1, ep->emm + 42 + i * 49, 48);
|
---|
1188 | emmcmd42[49] = ep->emm[i * 49 + 41]; // keynr
|
---|
1189 | emmcmd42[50] = 0x58 + ep->emm[40]; // package nr
|
---|
1190 | emmcmd42[51] = csystem_data->provider;
|
---|
1191 | if((dre_cmd(emmcmd42)))
|
---|
1192 | {
|
---|
1193 | if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
|
---|
1194 | { return ERROR; } // exit if response is not 90 00
|
---|
1195 | }
|
---|
1196 | }
|
---|
1197 | break;
|
---|
1198 |
|
---|
1199 | case SHARED:
|
---|
1200 | default:
|
---|
1201 | memcpy(emmcmd42 + 1, ep->emm + 6, 48);
|
---|
1202 | emmcmd42[51] = csystem_data->provider;
|
---|
1203 | //emmcmd42[50] = ecmcmd42[2]; // TODO package nr could also be fixed 0x58
|
---|
1204 | emmcmd42[50] = 0x58;
|
---|
1205 | emmcmd42[49] = ep->emm[5]; // keynr
|
---|
1206 |
|
---|
1207 | /* response:
|
---|
1208 | 59 05 A2 02 05 01 5B
|
---|
1209 | 90 00 */
|
---|
1210 |
|
---|
1211 | if((dre_cmd(emmcmd42))) // first emm request
|
---|
1212 | {
|
---|
1213 | if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
|
---|
1214 | { return ERROR; } // exit if response is not 90 00
|
---|
1215 |
|
---|
1216 | memcpy(emmcmd42 + 1, ep->emm + 55, 7); // TODO OR next two lines?
|
---|
1217 | //memcpy (emmcmd42 + 1, ep->emm + 55, 7); // FIXME either I cant count or my EMM log contains errors
|
---|
1218 | //memcpy (emmcmd42 + 8, ep->emm + 67, 41);
|
---|
1219 | emmcmd42[51] = csystem_data->provider;
|
---|
1220 | //emmcmd42[50] = ecmcmd42[2]; // TODO package nr could also be fixed 0x58
|
---|
1221 | emmcmd42[50] = 0x58;
|
---|
1222 | emmcmd42[49] = ep->emm[54]; // keynr
|
---|
1223 |
|
---|
1224 | if((dre_cmd(emmcmd42))) // second emm request
|
---|
1225 | {
|
---|
1226 | if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
|
---|
1227 | { return ERROR; } // exit if response is not 90 00
|
---|
1228 | }
|
---|
1229 | }
|
---|
1230 | }
|
---|
1231 | return OK;
|
---|
1232 | }
|
---|
1233 | return ERROR;
|
---|
1234 | }
|
---|
1235 |
|
---|
1236 | static int32_t dre_card_info(struct s_reader *UNUSED(rdr))
|
---|
1237 | {
|
---|
1238 | return OK;
|
---|
1239 | }
|
---|
1240 |
|
---|
1241 | const struct s_cardsystem reader_dre =
|
---|
1242 | {
|
---|
1243 | .desc = "dre",
|
---|
1244 | .caids = (uint16_t[]){ 0x4AE0, 0x4AE1, 0x7BE0, 0x7BE1, 0x2710, 0 },
|
---|
1245 | .do_emm = dre_do_emm,
|
---|
1246 | .do_ecm = dre_do_ecm,
|
---|
1247 | .card_info = dre_card_info,
|
---|
1248 | .card_init = dre_card_init,
|
---|
1249 | .get_emm_type = dre_common_get_emm_type,
|
---|
1250 | .get_emm_filter = dre_common_get_emm_filter,
|
---|
1251 | };
|
---|
1252 |
|
---|
1253 | #endif
|
---|