source: trunk/reader-dre.c@ 1774

Last change on this file since 1774 was 1774, checked in by merek, 10 years ago

Merge from UMP r1836

  • Property svn:eol-style set to native
File size: 13.0 KB
Line 
1#include "globals.h"
2#include "reader-common.h"
3
4extern uchar cta_res[];
5extern ushort cta_lr;
6static uchar provider;
7static short int mode;
8
9#define OK_RESPONSE 0x61
10#define CMD_BYTE 0x59
11
12static uchar xor (uchar * cmd, int cmdlen)
13{
14 int i;
15 uchar checksum = 0x00;
16 for (i = 0; i < cmdlen; i++)
17 checksum ^= cmd[i];
18 return checksum;
19}
20
21static int dre_command (uchar * cmd, int cmdlen) //attention: inputcommand will be changed!!!! answer will be in cta_res, length cta_lr ; returning 1 = no error, return ERROR = err
22{
23 static uchar startcmd[] = { 0x80, 0xFF, 0x10, 0x01, 0x05 }; //any command starts with this,
24 //last byte is nr of bytes of the command that will be sent
25 //after the startcmd
26//response on startcmd+cmd: = { 0x61, 0x05 } //0x61 = "OK", last byte is nr. of bytes card will send
27 static uchar reqans[] = { 0x00, 0xC0, 0x00, 0x00, 0x08 }; //after command answer has to be requested,
28 //last byte must be nr. of bytes that card has reported to send
29 uchar command[256];
30 int headerlen = sizeof (startcmd);
31 startcmd[4] = cmdlen + 3; //commandlength + type + len + checksum bytes
32 memcpy (command, startcmd, headerlen);
33 command[headerlen++] = CMD_BYTE; //type
34 command[headerlen++] = cmdlen + 1; //len = command + 1 checksum byte
35 memcpy (command + headerlen, cmd, cmdlen);
36
37 uchar checksum = ~xor (cmd, cmdlen);
38 //cs_debug ("[dre-reader] Checksum: %02x", checksum);
39 cmdlen += headerlen;
40 command[cmdlen++] = checksum;
41
42 reader_cmd2icc (command, cmdlen);
43
44 if ((cta_lr != 2) || (cta_res[0] != OK_RESPONSE)) {
45 cs_log ("[dre-reader] unexpected answer from card: %s", cs_hexdump (0, cta_res, cta_lr));
46 return ERROR; //error
47 }
48
49 reqans[4] = cta_res[1]; //adapt length byte
50 reader_cmd2icc (reqans, 5);
51
52 if (cta_res[0] != CMD_BYTE) {
53 cs_log ("[dre-reader] unknown response: cta_res[0] expected to be %02x, is %02x", CMD_BYTE, cta_res[0]);
54 return ERROR;
55 }
56 if ((cta_res[1] == 0x03) && (cta_res[2] == 0xe2)) {
57 switch (cta_res[3]) {
58 case 0xe1:
59 cs_log ("[dre-reader] checksum error: %s.", cs_hexdump (0, cta_res, cta_lr));
60 break;
61 case 0xe2:
62 cs_log ("[dre-reader] wrong provider: %s.", cs_hexdump (0, cta_res, cta_lr));
63 break;
64 case 0xe3:
65 cs_log ("[dre-reader] illegal command: %s.", cs_hexdump (0, cta_res, cta_lr));
66 break;
67 case 0xec:
68 cs_log ("[dre-reader] wrong signature: %s.", cs_hexdump (0, cta_res, cta_lr));
69 break;
70 default:
71 cs_debug ("[dre-reader] unknown error: %s.", cs_hexdump (0, cta_res, cta_lr));
72 break;
73 }
74 return ERROR; //error
75 }
76 int length_excl_leader = cta_lr;
77 if ((cta_res[cta_lr - 2] == 0x90) && (cta_res[cta_lr - 1] == 0x00))
78 length_excl_leader -= 2;
79
80 checksum = ~xor (cta_res + 2, length_excl_leader - 3);
81
82 if (cta_res[length_excl_leader - 1] != checksum) {
83 cs_log ("[dre-reader] checksum does not match, expected %02x received %02x:%s", checksum,
84 cta_res[length_excl_leader - 1], cs_hexdump (0, cta_res, cta_lr));
85 return ERROR; //error
86 }
87 return OK;
88}
89
90#define dre_cmd(cmd) \
91{ \
92 dre_command(cmd, sizeof(cmd)); \
93}
94
95static int dre_set_provider_info (void)
96{
97 int i;
98 static uchar cmd59[] = { 0x59, 0x14 }; // subscriptions
99 static uchar cmd5b[] = { 0x5b, 0x00, 0x14 }; //validity dates
100
101 cmd59[1] = provider;
102 if ((dre_cmd (cmd59))) { //ask subscription packages, returns error on 0x11 card
103 uchar pbm[32];
104 memcpy (pbm, cta_res + 3, cta_lr - 6);
105 cs_debug ("[dre-reader] pbm: %s", cs_hexdump (0, pbm, 32));
106
107 if (pbm[0] == 0xff)
108 cs_ri_log ("[dre-reader] no active packages");
109 else
110 for (i = 0; i < 32; i++)
111 if (pbm[i] != 0xff) {
112 cmd5b[1] = i;
113 cmd5b[2] = provider;
114 dre_cmd (cmd5b); //ask for validity dates
115
116 time_t start;
117 time_t end;
118 start = (cta_res[3] << 24) | (cta_res[4] << 16) | (cta_res[5] << 8) | cta_res[6];
119 end = (cta_res[7] << 24) | (cta_res[8] << 16) | (cta_res[9] << 8) | cta_res[10];
120
121 struct tm *temp;
122
123 temp = localtime (&start);
124 int startyear = temp->tm_year + 1900;
125 int startmonth = temp->tm_mon + 1;
126 int startday = temp->tm_mday;
127 temp = localtime (&end);
128 int endyear = temp->tm_year + 1900;
129 int endmonth = temp->tm_mon + 1;
130 int endday = temp->tm_mday;
131 cs_ri_log ("[dre-reader] active package %i valid from %04i/%02i/%02i to %04i/%02i/%02i", i, startyear, startmonth, startday,
132 endyear, endmonth, endday);
133 }
134 }
135 return OK;
136}
137
138int dre_card_init (ATR newatr)
139{
140 get_atr;
141 static uchar ua[] = { 0x43, 0x15 }; // get serial number (UA)
142 static uchar providers[] = { 0x49, 0x15 }; // get providers
143 int i;
144 char *card;
145
146 if ((atr[0] != 0x3b) || (atr[1] != 0x15) || (atr[2] != 0x11) || (atr[3] != 0x12 || atr[4] != 0xca || atr[5] != 0x07))
147 return ERROR;
148
149 provider = atr[6];
150 uchar checksum = xor (atr + 1, 6);
151
152 if (checksum != atr[7])
153 cs_log ("[dre-reader] warning: expected ATR checksum %02x, smartcard reports %02x", checksum, atr[7]);
154
155 switch (atr[6]) {
156 case 0x11:
157 card = "Tricolor Centr";
158 reader[ridx].caid[0] = 0x4ae0;
159 mode = 41;
160 break; //59 type card = MSP (74 type = ATMEL)
161 case 0x12:
162 card = "Cable TV";
163 reader[ridx].caid[0] = 0x4ae0; //TODO not sure about this one
164 mode = 41; //TODO not sure
165 break;
166 case 0x14:
167 card = "Tricolor Syberia / Platforma HD new";
168 reader[ridx].caid[0] = 0x4ae1;
169 mode = 51;
170 break; //59 type card
171 case 0x15:
172 card = "Platforma HD / DW old";
173 reader[ridx].caid[0] = 0x4ae1;
174 mode = 51;
175 break; //59 type card
176 default:
177 card = "Unknown";
178 reader[ridx].caid[0] = 0x4ae1;
179 mode = 51;
180 break;
181 }
182
183 memset (reader[ridx].prid, 0x00, 8);
184
185 static uchar cmd30[] =
186 { 0x30, 0x81, 0x00, 0x81, 0x82, 0x03, 0x84, 0x05, 0x06, 0x87, 0x08, 0x09, 0x00, 0x81, 0x82, 0x03, 0x84, 0x05,
187 0x00
188 };
189 dre_cmd (cmd30); //unknown command, generates error on card 0x11 and 0x14
190/*
191response:
19259 03 E2 E3
193FE 48 */
194
195 static uchar cmd54[] = { 0x54, 0x14 }; // geocode
196 cmd54[1] = provider;
197 uchar geocode = 0;
198 if ((dre_cmd (cmd54))) //error would not be fatal, like on 0x11 cards
199 geocode = cta_res[3];
200
201 providers[1] = provider;
202 if (!(dre_cmd (providers)))
203 return ERROR; //fatal error
204 if ((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
205 return ERROR;
206 uchar provname[128];
207 for (i = 0; ((i < cta_res[2] - 6) && (i < 128)); i++) {
208 provname[i] = cta_res[6 + i];
209 if (provname[i] == 0x00)
210 break;
211 }
212 int major_version = cta_res[3];
213 int minor_version = cta_res[4];
214
215 ua[1] = provider;
216 dre_cmd (ua); //error would not be fatal
217
218 int hexlength = cta_res[1] - 2; //discard first and last byte, last byte is always checksum, first is answer code
219
220 reader[ridx].hexserial[0] = 0;
221 reader[ridx].hexserial[1] = 0;
222 memcpy (reader[ridx].hexserial + 2, cta_res + 3, hexlength);
223
224 int low_dre_id = ((cta_res[4] << 16) | (cta_res[5] << 8) | cta_res[6]) - 48608;
225 int dre_chksum = 0;
226 uchar buf[32];
227 sprintf ((char *)buf, "%i%i%08i", provider - 16, major_version + 1, low_dre_id);
228 for (i = 0; i < 32; i++) {
229 if (buf[i] == 0x00)
230 break;
231 dre_chksum += buf[i] - 48;
232 }
233
234 //cs_ri_log("[dre-reader] type: DRE Crypt, caid: %04X, serial: %llu, card: v%x",
235 cs_ri_log ("[dre-reader] type: DRE Crypt, caid: %04X, serial: %s, dre id: %i%i%i%08i, geocode %i, card: %s v%i.%i",
236 reader[ridx].caid[0], cs_hexdump (0, reader[ridx].hexserial + 2, 4), dre_chksum, provider - 16,
237 major_version + 1, low_dre_id, geocode, card, major_version, minor_version);
238 cs_ri_log ("[dre-reader] Provider name:%s.", provname);
239
240
241 memset (reader[ridx].sa, 0, sizeof (reader[ridx].sa));
242 memcpy (reader[ridx].sa[0], reader[ridx].hexserial + 2, 1); //copy first byte of unique address also in shared address, because we dont know what it is...
243
244 cs_ri_log ("[dre-reader] SA = %02X%02X%02X%02X, UA = %s", reader[ridx].sa[0][0], reader[ridx].sa[0][1], reader[ridx].sa[0][2],
245 reader[ridx].sa[0][3], cs_hexdump (0, reader[ridx].hexserial + 2, 4));
246
247 reader[ridx].nprov = 1;
248
249 if (!dre_set_provider_info ())
250 return ERROR; //fatal error
251
252 cs_log ("[dre-reader] ready for requests");
253 return OK;
254}
255
256int dre_do_ecm (ECM_REQUEST * er)
257{
258 if (mode == 41) {
259 static uchar ecmcmd41[] = { 0x41,
260 0x58, 0x1f, 0x00, //fixed part, dont change
261 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, //0x01 - 0x08: next key
262 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, //0x11 - 0x18: current key
263 0x3b, 0x59, 0x11 //0x3b = keynumber, can be a value 56 ;; 0x59 number of package = 58+1 - Pay Package ;; 0x11 = provider
264 };
265 ecmcmd41[22] = provider;
266 memcpy (ecmcmd41 + 4, er->ecm + 8, 16);
267 ecmcmd41[20] = er->ecm[6]; //keynumber
268 ecmcmd41[21] = 0x58 + er->ecm[25]; //package number
269 cs_debug ("[dre-reader] unused ECM info front:%s", cs_hexdump (0, er->ecm, 8));
270 cs_debug ("[dre-reader] unused ECM info back:%s", cs_hexdump (0, er->ecm + 24, er->ecm[2] + 2 - 24));
271 if ((dre_cmd (ecmcmd41))) { //ecm request
272 if ((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
273 return ERROR; //exit if response is not 90 00
274 memcpy (er->cw, cta_res + 11, 8);
275 memcpy (er->cw + 8, cta_res + 3, 8);
276
277 return OK;
278 }
279 }
280 else {
281
282 static uchar ecmcmd51[] = { 0x51, 0x02, 0x56, 0x05, 0x00, 0x4A, 0xE3, //fixed header?
283 0x9C, 0xDA, //first three nibbles count up, fourth nibble counts down; all ECMs sent twice
284 0xC1, 0x71, 0x21, 0x06, 0xF0, 0x14, 0xA7, 0x0E, //next key?
285 0x89, 0xDA, 0xC9, 0xD7, 0xFD, 0xB9, 0x06, 0xFD, //current key?
286 0xD5, 0x1E, 0x2A, 0xA3, 0xB5, 0xA0, 0x82, 0x11, //key or signature?
287 0x14 //provider
288 };
289 memcpy (ecmcmd51 + 1, er->ecm + 5, 0x21);
290 cs_debug ("[dre-reader] unused ECM info front:%s", cs_hexdump (0, er->ecm, 5));
291 cs_debug ("[dre-reader] unused ECM info back:%s", cs_hexdump (0, er->ecm + 37, 4));
292 ecmcmd51[33] = provider; //no part of sig
293 if ((dre_cmd (ecmcmd51))) { //ecm request
294 if ((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
295 return ERROR; //exit if response is not 90 00
296 memcpy (er->cw, cta_res + 11, 8);
297 memcpy (er->cw + 8, cta_res + 3, 8);
298 return OK;
299 }
300 }
301 return ERROR;
302}
303
304int dre_get_emm_type(EMM_PACKET *ep, struct s_reader * rdr)
305{
306 switch (ep->emm[0]) {
307 case 0x87:
308 ep->type = UNIQUE; //FIXME no filling of ep->hexserial
309 break;
310 case 0x89:
311 ep->type = SHARED; //FIXME no filling of ep->hexserial
312 break;
313 default:
314 ep->type = UNKNOWN;
315 }
316 return TRUE; //FIXME no checking of serial or SA
317}
318
319
320int dre_do_emm (EMM_PACKET * ep)
321{
322
323 int emm_length = ((ep->emm[1] & 0x0f) << 8) + ep->emm[2];
324
325 cs_ddump (ep->emm, emm_length + 3, "EMM:");
326 ep->type = ep->emm[0];
327
328 if (mode == 51) {
329 static uchar emmcmd52[0x3a];
330 emmcmd52[0] = 0x52;
331 int i;
332 for (i = 0; i < 2; i++) {
333 memcpy (emmcmd52 + 1, ep->emm + 5 + 32 + i * 56, 56);
334 // check for shared address
335 if(ep->emm[3]!=reader[ridx].sa[0][0])
336 return OK; // ignore, wrong address
337 emmcmd52[0x39] = provider;
338 if ((dre_cmd (emmcmd52)))
339 if ((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
340 return ERROR; //exit if response is not 90 00
341 }
342 }
343 else {
344 static uchar emmcmd42[] =
345 { 0x42, 0x85, 0x58, 0x01, 0xC8, 0x00, 0x00, 0x00, 0x05, 0xB8, 0x0C, 0xBD, 0x7B, 0x07, 0x04, 0xC8,
346 0x77, 0x31, 0x95, 0xF2, 0x30, 0xB7, 0xE9, 0xEE, 0x0F, 0x81, 0x39, 0x1C, 0x1F, 0xA9, 0x11, 0x3E,
347 0xE5, 0x0E, 0x8E, 0x50, 0xA4, 0x31, 0xBB, 0x01, 0x00, 0xD6, 0xAF, 0x69, 0x60, 0x04, 0x70, 0x3A,
348 0x91,
349 0x56, 0x58, 0x11
350 };
351 int i;
352 switch (ep->type) {
353 case UNIQUE:
354 for (i = 0; i < 2; i++) {
355 memcpy (emmcmd42 + 1, ep->emm + 42 + i*49, 48);
356 emmcmd42[49] = ep->emm[i*49 + 41]; //keynr
357 emmcmd42[50] = 0x58 + ep->emm[40]; //package nr
358 emmcmd42[51] = provider;
359 if ((dre_cmd (emmcmd42))) {
360 if ((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
361 return ERROR; //exit if response is not 90 00
362 }
363 }
364 break;
365 case SHARED:
366 default:
367 memcpy (emmcmd42 + 1, ep->emm + 6, 48);
368 emmcmd42[51] = provider;
369 //emmcmd42[50] = ecmcmd42[2]; //TODO package nr could also be fixed 0x58
370 emmcmd42[50] = 0x58;
371 emmcmd42[49] = ep->emm[5]; //keynr
372 /* response:
373 59 05 A2 02 05 01 5B
374 90 00 */
375 if ((dre_cmd (emmcmd42))) { //first emm request
376 if ((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
377 return ERROR; //exit if response is not 90 00
378
379 memcpy (emmcmd42 + 1, ep->emm + 55, 7); //TODO OR next two lines?
380 /*memcpy (emmcmd42 + 1, ep->emm + 55, 7); //FIXME either I cant count or my EMM log contains errors
381 memcpy (emmcmd42 + 8, ep->emm + 67, 41); */
382 emmcmd42[51] = provider;
383 //emmcmd42[50] = ecmcmd42[2]; //TODO package nr could also be fixed 0x58
384 emmcmd42[50] = 0x58;
385 emmcmd42[49] = ep->emm[54]; //keynr
386 if ((dre_cmd (emmcmd42))) { //second emm request
387 if ((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
388 return ERROR; //exit if response is not 90 00
389 }
390 }
391 }
392 }
393 return OK; //success
394}
395
396int dre_card_info (void)
397{
398 return OK;
399}
Note: See TracBrowser for help on using the repository browser.