source: trunk/reader-dre.c@ 1125

Last change on this file since 1125 was 1125, checked in by C.H.A.D.o, 11 years ago

Remove unused parameters

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