source: trunk/reader-dre.c@ 2032

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

Add dre_get_emm_filter, make dre_get_emm_type write sa to ep->hexserial

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