source: trunk/reader-dre.c@ 1926

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

Merge UMP r1944-1969: - Adding SC8in1 support, thanks to dingo35

  • Property svn:eol-style set to native
File size: 13.1 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 (struct s_reader * reader, 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 (reader, 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 (reader, 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(reader, cmd, sizeof(cmd)); \
93}
94
95static int dre_set_provider_info (struct s_reader * reader)
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 (reader, "[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 (reader, "[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 (struct s_reader * reader, 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->caid[0] = 0x4ae0;
159 mode = 41;
160 break; //59 type card = MSP (74 type = ATMEL)
161 case 0x12:
162 card = "Cable TV";
163 reader->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->caid[0] = 0x4ae1;
169 mode = 51;
170 break; //59 type card
171 case 0x15:
172 card = "Platforma HD / DW old";
173 reader->caid[0] = 0x4ae1;
174 mode = 51;
175 break; //59 type card
176 default:
177 card = "Unknown";
178 reader->caid[0] = 0x4ae1;
179 mode = 51;
180 break;
181 }
182
183 memset (reader->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->hexserial[0] = 0;
221 reader->hexserial[1] = 0;
222 memcpy (reader->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 (reader, "[dre-reader] type: DRE Crypt, caid: %04X, serial: %s, dre id: %i%i%i%08i, geocode %i, card: %s v%i.%i",
236 reader->caid[0], cs_hexdump (0, reader->hexserial + 2, 4), dre_chksum, provider - 16,
237 major_version + 1, low_dre_id, geocode, card, major_version, minor_version);
238 cs_ri_log (reader, "[dre-reader] Provider name:%s.", provname);
239
240
241 memset (reader->sa, 0, sizeof (reader->sa));
242 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...
243
244 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],
245 reader->sa[0][3], cs_hexdump (0, reader->hexserial + 2, 4));
246
247 reader->nprov = 1;
248
249 if (!dre_set_provider_info (reader))
250 return ERROR; //fatal error
251
252 cs_log ("[dre-reader] ready for requests");
253 return OK;
254}
255
256int dre_do_ecm (struct s_reader * reader, 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 rdr=rdr;
307 switch (ep->emm[0]) {
308 case 0x87:
309 ep->type = UNIQUE; //FIXME no filling of ep->hexserial
310 break;
311 case 0x89:
312 ep->type = SHARED; //FIXME no filling of ep->hexserial
313 break;
314 default:
315 ep->type = UNKNOWN;
316 }
317 return TRUE; //FIXME no checking of serial or SA
318}
319
320
321int dre_do_emm (struct s_reader * reader, EMM_PACKET * ep)
322{
323
324 int emm_length = ((ep->emm[1] & 0x0f) << 8) + ep->emm[2];
325
326 cs_ddump (ep->emm, emm_length + 3, "EMM:");
327 ep->type = ep->emm[0];
328
329 if (mode == 51) {
330 static uchar emmcmd52[0x3a];
331 emmcmd52[0] = 0x52;
332 int i;
333 for (i = 0; i < 2; i++) {
334 memcpy (emmcmd52 + 1, ep->emm + 5 + 32 + i * 56, 56);
335 // check for shared address
336 if(ep->emm[3]!=reader->sa[0][0])
337 return OK; // ignore, wrong address
338 emmcmd52[0x39] = provider;
339 if ((dre_cmd (emmcmd52)))
340 if ((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
341 return ERROR; //exit if response is not 90 00
342 }
343 }
344 else {
345 static uchar emmcmd42[] =
346 { 0x42, 0x85, 0x58, 0x01, 0xC8, 0x00, 0x00, 0x00, 0x05, 0xB8, 0x0C, 0xBD, 0x7B, 0x07, 0x04, 0xC8,
347 0x77, 0x31, 0x95, 0xF2, 0x30, 0xB7, 0xE9, 0xEE, 0x0F, 0x81, 0x39, 0x1C, 0x1F, 0xA9, 0x11, 0x3E,
348 0xE5, 0x0E, 0x8E, 0x50, 0xA4, 0x31, 0xBB, 0x01, 0x00, 0xD6, 0xAF, 0x69, 0x60, 0x04, 0x70, 0x3A,
349 0x91,
350 0x56, 0x58, 0x11
351 };
352 int i;
353 switch (ep->type) {
354 case UNIQUE:
355 for (i = 0; i < 2; i++) {
356 memcpy (emmcmd42 + 1, ep->emm + 42 + i*49, 48);
357 emmcmd42[49] = ep->emm[i*49 + 41]; //keynr
358 emmcmd42[50] = 0x58 + ep->emm[40]; //package nr
359 emmcmd42[51] = provider;
360 if ((dre_cmd (emmcmd42))) {
361 if ((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
362 return ERROR; //exit if response is not 90 00
363 }
364 }
365 break;
366 case SHARED:
367 default:
368 memcpy (emmcmd42 + 1, ep->emm + 6, 48);
369 emmcmd42[51] = provider;
370 //emmcmd42[50] = ecmcmd42[2]; //TODO package nr could also be fixed 0x58
371 emmcmd42[50] = 0x58;
372 emmcmd42[49] = ep->emm[5]; //keynr
373 /* response:
374 59 05 A2 02 05 01 5B
375 90 00 */
376 if ((dre_cmd (emmcmd42))) { //first emm request
377 if ((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
378 return ERROR; //exit if response is not 90 00
379
380 memcpy (emmcmd42 + 1, ep->emm + 55, 7); //TODO OR next two lines?
381 /*memcpy (emmcmd42 + 1, ep->emm + 55, 7); //FIXME either I cant count or my EMM log contains errors
382 memcpy (emmcmd42 + 8, ep->emm + 67, 41); */
383 emmcmd42[51] = provider;
384 //emmcmd42[50] = ecmcmd42[2]; //TODO package nr could also be fixed 0x58
385 emmcmd42[50] = 0x58;
386 emmcmd42[49] = ep->emm[54]; //keynr
387 if ((dre_cmd (emmcmd42))) { //second emm request
388 if ((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
389 return ERROR; //exit if response is not 90 00
390 }
391 }
392 }
393 }
394 return OK; //success
395}
396
397int dre_card_info (void)
398{
399 return OK;
400}
Note: See TracBrowser for help on using the repository browser.