source: trunk/reader-viaccess.c@ 4149

Last change on this file since 4149 was 4141, checked in by dingo35, 13 years ago

all: simplify debug system, add D_DVBAPI = -d128, eliminate cs_ptyp which complicates stuff unnecc

File size: 31.4 KB
Line 
1#include "globals.h"
2#include "reader-common.h"
3
4struct via_date {
5 ushort day_s : 5;
6 ushort month_s : 4;
7 ushort year_s : 7;
8
9 ushort day_e : 5;
10 ushort month_e : 4;
11 ushort year_e : 7;
12};
13
14static void parse_via_date(const uchar *buf, struct via_date *vd, int fend)
15{
16 ushort date;
17
18 date = (buf[0]<<8) | buf[1];
19 vd->day_s = date & 0x1f;
20 vd->month_s = (date>>5) & 0x0f;
21 vd->year_s = (date>>9) & 0x7f;
22
23 if( fend )
24 {
25 date = (buf[2]<<8) | buf[3];
26 vd->day_e = date & 0x1f;
27 vd->month_e = (date>>5) & 0x0f;
28 vd->year_e = (date>>9) & 0x7f;
29 }
30}
31
32static void show_class(struct s_reader * reader, const char *p, const uchar *b, int l)
33{
34 int i, j;
35
36 // b -> via date (4 bytes)
37 b+=4;
38 l-=4;
39
40 j=l-1;
41 for (; j>=0; j--)
42 for (i=0; i<8; i++)
43 if (b[j] & (1 << (i&7)))
44 {
45 uchar cls;
46 struct via_date vd;
47 parse_via_date(b-4, &vd, 1);
48 cls=(l-(j+1))*8+i;
49 if (p)
50 cs_log("%sclass: %02X, expiry date: %04d/%02d/%02d - %04d/%02d/%02d", p, cls,
51 vd.year_s+1980, vd.month_s, vd.day_s,
52 vd.year_e+1980, vd.month_e, vd.day_e);
53 else
54 cs_ri_log(reader, "class: %02X, expiry date: %04d/%02d/%02d - %04d/%02d/%02d", cls,
55 vd.year_s+1980, vd.month_s, vd.day_s,
56 vd.year_e+1980, vd.month_e, vd.day_e);
57 }
58}
59
60static void show_subs(struct s_reader * reader, const uchar *emm)
61{
62 // emm -> A9, A6, B6
63
64 switch( emm[0] )
65 {
66 case 0xA9:
67 show_class(reader, "nano A9: ", emm+2, emm[1]);
68 break;
69/*
70 {
71 int i, j, byts;
72 const uchar *oemm;
73
74 oemm = emm;
75 byts = emm[1]-4;
76 emm+=6;
77
78 j=byts-1;
79 for( ; j>=0; j-- )
80 for( i=0; i<8; i++ )
81 if( emm[j] & (1 << (i&7)) )
82 {
83 uchar cls;
84 struct via_date vd;
85 parse_via_date(emm-4, &vd, 1);
86 cls=(byts-(j+1))*8+i;
87 cs_log("%sclass %02X: expiry date: %02d/%02d/%04d - %02d/%02d/%04d",
88 fnano?"nano A9: ":"", cls,
89 vd.day_s, vd.month_s, vd.year_s+1980,
90 vd.day_e, vd.month_e, vd.year_e+1980);
91 }
92 break;
93 }
94*/
95 case 0xA6:
96 {
97 char szGeo[256];
98
99 memset(szGeo, 0, 256);
100 strncpy(szGeo, (char *)emm+2, emm[1]);
101 cs_log("[viaccess-reader] nano A6: geo %s", szGeo);
102 break;
103 }
104 case 0xB6:
105 {
106 uchar m; // modexp
107 struct via_date vd;
108
109 m=emm[emm[1]+1];
110 parse_via_date(emm+2, &vd, 0);
111 cs_log("[viaccess-reader] nano B6: modexp %d%d%d%d%d%d: %02d/%02d/%04d", (m&0x20)?1:0,
112 (m&0x10)?1:0,(m&0x08)?1:0,(m&0x04)?1:0,(m&0x02)?1:0,(m&0x01)?1:0,
113 vd.day_s, vd.month_s, vd.year_s+1980);
114 break;
115 }
116 }
117}
118
119static int chk_prov(struct s_reader * reader, uchar *id, uchar keynr)
120{
121 int i, j, rc;
122 for (rc=i=0; (!rc) && (i<reader->nprov); i++)
123 if(!memcmp(&reader->prid[i][1], id, 3))
124 for (j=0; (!rc) && (j<16); j++)
125 if (reader->availkeys[i][j]==keynr)
126 rc=1;
127 return(rc);
128}
129
130static int unlock_parental(struct s_reader * reader)
131{
132 /* disabling parental lock. assuming pin "0000" if no pin code is provided in the config */
133
134 static const uchar inDPL[] = {0xca, 0x24, 0x02, 0x00, 0x09};
135 uchar cmDPL[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F};
136 def_resp;
137
138 if (strcmp(reader->pincode, "none")) {
139 cs_log("[viaccess-reader] Using PIN %s",reader->pincode);
140 // the pin need to be coded in bcd, so we need to convert from ascii to bcd, so '1234' -> 0x12 0x34
141 cmDPL[6]=((reader->pincode[0]-0x30)<<4) | ((reader->pincode[1]-0x30) & 0x0f);
142 cmDPL[7]=((reader->pincode[2]-0x30)<<4) | ((reader->pincode[3]-0x30) & 0x0f);
143 }
144 else {
145 cs_log("[viaccess-reader] Using PIN 0000!");
146 }
147 write_cmd(inDPL,cmDPL);
148 if( !(cta_res[cta_lr-2]==0x90 && cta_res[cta_lr-1]==0) ) {
149 if (strcmp(reader->pincode, "none")) {
150 cs_log("[viaccess-reader] Can't disable parental lock. Wrong PIN? OSCam used %s!",reader->pincode);
151 }
152 else {
153 cs_log("[viaccess-reader] Can't disable parental lock. Wrong PIN? OSCam used 0000!");
154 }
155 }
156 else
157 cs_log("[viaccess-reader] Parental lock disabled");
158
159 return 0;
160}
161
162static int viaccess_card_init(struct s_reader * reader, ATR newatr)
163{
164 get_atr;
165 def_resp;
166 int i;
167 uchar buf[256];
168 uchar insac[] = { 0xca, 0xac, 0x00, 0x00, 0x00 }; // select data
169 uchar insb8[] = { 0xca, 0xb8, 0x00, 0x00, 0x00 }; // read selected data
170 uchar insa4[] = { 0xca, 0xa4, 0x00, 0x00, 0x00 }; // select issuer
171 uchar insc0[] = { 0xca, 0xc0, 0x00, 0x00, 0x00 }; // read data item
172 static const uchar insFAC[] = { 0x87, 0x02, 0x00, 0x00, 0x03 }; // init FAC
173 static const uchar FacDat[] = { 0x00, 0x00, 0x28 };
174 static unsigned char ins8702_data[] = { 0x00, 0x00, 0x11};
175 static unsigned char ins8704[] = { 0x87, 0x04, 0x00, 0x00, 0x07 };
176 static unsigned char ins8706[] = { 0x87, 0x06, 0x00, 0x00, 0x04 };
177
178
179 if ((atr[0]!=0x3f) || (atr[1]!=0x77) || ((atr[2]!=0x18) && (atr[2]!=0x11) && (atr[2]!=0x19)) || (atr[9]!=0x68))
180 return ERROR;
181
182 write_cmd(insFAC, FacDat);
183 if( !(cta_res[cta_lr-2]==0x90 && cta_res[cta_lr-1]==0) )
184 return ERROR;
185
186 memset(&reader->last_geo, 0, sizeof(reader->last_geo));
187 write_cmd(insFAC, ins8702_data);
188 if ((cta_res[cta_lr-2]==0x90) && (cta_res[cta_lr-1]==0x00)) {
189 write_cmd(ins8704, NULL);
190 if ((cta_res[cta_lr-2]==0x90) && (cta_res[cta_lr-1]==0x00)) {
191 write_cmd(ins8706, NULL);
192 if ((cta_res[cta_lr-2]==0x90) && (cta_res[cta_lr-1]==0x00)) {
193 reader->last_geo.number_ecm =(cta_res[2]<<8) | (cta_res[3]);
194 cs_log("[viaccess-reader] using ecm #%x for long viaccess ecm",reader->last_geo.number_ecm);
195 }
196 }
197 }
198
199
200// switch((atr[atrsize-4]<<8)|atr[atrsize-3])
201// {
202// case 0x6268: ver="2.3"; break;
203// case 0x6668: ver="2.4(?)"; break;
204// case 0xa268:
205// default: ver="unknown"; break;
206// }
207
208 reader->caid[0]=0x500;
209 memset(reader->prid, 0xff, sizeof(reader->prid));
210 insac[2]=0xa4; write_cmd(insac, NULL); // request unique id
211 insb8[4]=0x07; write_cmd(insb8, NULL); // read unique id
212 memcpy(reader->hexserial, cta_res+2, 5);
213// cs_log("[viaccess-reader] type: Viaccess, ver: %s serial: %llu", ver, b2ll(5, cta_res+2));
214 cs_ri_log(reader, "type: Viaccess (%sstandard atr), caid: %04X, serial: %llu",
215 atr[9]==0x68?"":"non-",reader->caid[0], b2ll(5, cta_res+2));
216
217 i=0;
218 insa4[2]=0x00; write_cmd(insa4, NULL); // select issuer 0
219 buf[0]=0;
220 while((cta_res[cta_lr-2]==0x90) && (cta_res[cta_lr-1]==0))
221 {
222 insc0[4]=0x1a; write_cmd(insc0, NULL); // show provider properties
223 cta_res[2]&=0xF0;
224 reader->prid[i][0]=0;
225 memcpy(&reader->prid[i][1], cta_res, 3);
226 memcpy(&reader->availkeys[i][0], cta_res+10, 16);
227 sprintf((char *)buf+strlen((char *)buf), ",%06lX", b2i(3, &reader->prid[i][1]));
228//cs_log("[viaccess-reader] buf: %s", buf);
229
230 insac[2]=0xa5; write_cmd(insac, NULL); // request sa
231 insb8[4]=0x06; write_cmd(insb8, NULL); // read sa
232 memcpy(&reader->sa[i][0], cta_res+2, 4);
233
234/*
235 insac[2]=0xa7; write_cmd(insac, NULL); // request name
236 insb8[4]=0x02; write_cmd(insb8, NULL); // read name nano + len
237 l=cta_res[1];
238 insb8[4]=l; write_cmd(insb8, NULL); // read name
239 cta_res[l]=0;
240cs_log("[viaccess-reader] name: %s", cta_res);
241*/
242
243 insa4[2]=0x02;
244 write_cmd(insa4, NULL); // select next issuer
245 i++;
246 }
247 reader->nprov=i;
248 cs_ri_log(reader, "providers: %d (%s)", reader->nprov, buf+1);
249
250 /* init the maybe existing aes key */
251 aes_set_key((char *)reader->aes_key);
252
253 if (cfg->ulparent)
254 unlock_parental(reader);
255
256 cs_log("[viaccess-reader] ready for requests");
257 return OK;
258}
259
260bool check_crc( uchar *data )
261{
262 int valid = 0;
263
264 uchar sum1=data[0] + data[1] + data[2] ;
265 uchar sum2=data[4] + data[5] + data[6] ;
266 uchar sum3=data[8] + data[9] + data[10] ;
267 uchar sum4=data[12] + data[13] + data[14] ;
268
269 if ( ( sum1 == data[3] ) && ( sum2 == data[7] ) && ( sum3 == data[11] )&& ( sum4 == data[15] ) )
270 valid = 1;
271
272 return valid;
273}
274
275static int viaccess_do_ecm(struct s_reader * reader, ECM_REQUEST *er)
276{
277 def_resp;
278 static const unsigned char insa4[] = { 0xca,0xa4,0x04,0x00,0x03 }; // set provider id
279 unsigned char ins88[] = { 0xca,0x88,0x00,0x00,0x00 }; // set ecm
280 unsigned char insf8[] = { 0xca,0xf8,0x00,0x00,0x00 }; // set geographic info
281 static const unsigned char insc0[] = { 0xca,0xc0,0x00,0x00,0x12 }; // read dcw
282
283 uchar *ecm88Data=er->ecm+4; //XXX what is the 4th byte for ??
284 int ecm88Len=SCT_LEN(er->ecm)-4;
285 ulong provid=0;
286 int rc=0;
287 int hasD2 = 0;
288 int curEcm88len=0;
289 int nanoLen=0;
290 uchar *nextEcm;
291 uchar DE04[256];
292 int D2KeyID=0;
293 int curnumber_ecm=0;
294 //nanoD2 d2 02 0d 02 -> D2 nano, len 2
295 // 0d -> post AES decrypt CW
296 // 0b -> pre AES decrypt CW
297 int nanoD2 = 0; // 0x0b = 1 0x0d = 2
298
299 memset(DE04, 0, sizeof(DE04)); //fix dorcel de04 bug
300
301 nextEcm=ecm88Data;
302
303 while (ecm88Len && !rc) {
304
305 if(ecm88Data[0] ==0x00 && ecm88Data[1] == 0x00) {
306 // nano 0x00 and len 0x00 aren't valid ... something is obviously wrong with this ecm.
307 cs_log("[viaccess-reader] ECM: Invalid ECM structure. Rejecting");
308 return ERROR;
309 }
310
311 // 80 33 nano 80 (ecm) + len (33)
312 if(ecm88Data[0]==0x80) { // nano 80, give ecm len
313 curEcm88len=ecm88Data[1];
314 nextEcm=ecm88Data+curEcm88len+2;
315 ecm88Data += 2;
316 ecm88Len -= 2;
317 }
318
319 if(!curEcm88len) { //there was no nano 80 -> simple ecm
320 curEcm88len=ecm88Len;
321 }
322
323 // d2 02 0d 02 -> D2 nano, len 2, select the AES key to be used
324 if(ecm88Data[0]==0xd2) {
325 // test if need post or pre AES decrypt
326 if(ecm88Data[2]==0x0b)
327 {
328 nanoD2 = 1;
329 cs_debug_mask(D_READER, "[viaccess-reader] ECM: nano D2 0x0b");
330 }
331 if(ecm88Data[2]==0x0d)
332 {
333 nanoD2 = 2;
334 cs_debug_mask(D_READER, "[viaccess-reader] ECM: nano D2 0x0d");
335 }
336 // use the d2 arguments to get the key # to be used
337 int len = ecm88Data[1] + 2;
338 D2KeyID=ecm88Data[3];
339 ecm88Data += len;
340 ecm88Len -= len;
341 curEcm88len -=len;
342 hasD2 = 1;
343 }
344 else
345 hasD2 = 0;
346
347
348 // 40 07 03 0b 00 -> nano 40, len =7 ident 030B00 (tntsat), key #0 <== we're pointing here
349 // 09 -> use key #9
350 // 05 67 00
351 if ((ecm88Data[0]==0x90 || ecm88Data[0]==0x40) && (ecm88Data[1]==0x03 || ecm88Data[1]==0x07 ) )
352 {
353 uchar ident[3], keynr;
354 uchar *ecmf8Data=0;
355 int ecmf8Len=0;
356
357 nanoLen=ecm88Data[1] + 2;
358 keynr=ecm88Data[4]&0x0F;
359
360 // 40 07 03 0b 00 -> nano 40, len =7 ident 030B00 (tntsat), key #0 <== we're pointing here
361 // 09 -> use key #9
362 if(nanoLen>5) {
363 curnumber_ecm =(ecm88Data[6]<<8) | (ecm88Data[7]);
364 cs_debug_mask(D_READER, "checking if the ecm number (%x) match the card one (%x)",curnumber_ecm,reader->last_geo.number_ecm);
365 // if we have an ecm number we check it.
366 // we can't assume that if the nano len is 5 or more we have an ecm number
367 // as some card don't support this
368 if( reader->last_geo.number_ecm > 0 ) {
369 if(reader->last_geo.number_ecm ==curnumber_ecm ) {
370 keynr=ecm88Data[5];
371 cs_debug_mask(D_READER, "keyToUse = %02x",ecm88Data[5]);
372 }
373 else
374 {
375 ecm88Data=nextEcm;
376 ecm88Len-=curEcm88len;
377 continue; //loop to next ecm
378 }
379 }
380 else { // long ecm but we don't have an ecm number so we have to try them all.
381 keynr=ecm88Data[5];
382 cs_debug_mask(D_READER, "keyToUse = %02x",ecm88Data[5]);
383 }
384 }
385
386 memcpy (ident, &ecm88Data[2], sizeof(ident));
387 provid = b2i(3, ident);
388 ident[2]&=0xF0;
389
390 if(hasD2 && reader->aes_list) {
391 // check that we have the AES key to decode the CW
392 // if not there is no need to send the ecm to the card
393 if(!aes_present(reader->aes_list, 0x500, (uint32) (provid & 0xFFFFF0) , D2KeyID))
394 return ERROR;
395 }
396
397
398 if (!chk_prov(reader, ident, keynr))
399 {
400 cs_debug_mask(D_READER, "[viaccess-reader] ECM: provider or key not found on card");
401 snprintf( er->msglog, MSGLOGSIZE, "provider(%02x%02x%02x) or key(%d) not found on card", ident[0],ident[1],ident[2], keynr );
402 return ERROR;
403 }
404
405 ecm88Data+=nanoLen;
406 ecm88Len-=nanoLen;
407 curEcm88len-=nanoLen;
408
409 // DE04
410 if (ecm88Data[0]==0xDE && ecm88Data[1]==0x04)
411 {
412 memcpy (DE04, &ecm88Data[0], 6);
413 ecm88Data+=6;
414 }
415 //
416
417 if( reader->last_geo.provid != provid )
418 {
419 reader->last_geo.provid = provid;
420 reader->last_geo.geo_len = 0;
421 reader->last_geo.geo[0] = 0;
422 write_cmd(insa4, ident); // set provider
423 }
424
425 //Nano D2 0x0b Pre AES decrypt CW
426 if ( hasD2 && nanoD2 == 1)
427 {
428 uchar *ecm88DataCW = ecm88Data;
429 int cwStart = 0;
430 //int cwStartRes = 0;
431 int exit = 0;
432 // find CW start
433 while(cwStart < curEcm88len -1 && !exit)
434 {
435 if(ecm88Data[cwStart] == 0xEA && ecm88Data[cwStart+1] == 0x10)
436 {
437 ecm88DataCW = ecm88DataCW + cwStart + 2;
438 exit = 1;
439 }
440 cwStart++;
441 }
442 // use AES from list to decrypt CW
443 if(reader->aes_list)
444 {
445 cs_debug_mask(D_READER, "Decoding CW : using AES key id %d for provider %06x",D2KeyID, (provid & 0xFFFFF0));
446 rc=aes_decrypt_from_list(reader->aes_list,0x500, (uint32) (provid & 0xFFFFF0), D2KeyID, &ecm88DataCW[0], 16);
447 if( rc == 0 )
448 snprintf( er->msglog, MSGLOGSIZE, "AES Decrypt : key id %d not found for CAID %04X , provider %06lx", D2KeyID, 0x500, (provid & 0xFFFFF0) );
449 }
450 else
451 {
452 aes_decrypt(&ecm88DataCW[0], 16);
453 }
454 }
455
456 while(ecm88Len>0 && ecm88Data[0]<0xA0)
457 {
458 int nanoLen=ecm88Data[1]+2;
459 if (!ecmf8Data)
460 ecmf8Data=(uchar *)ecm88Data;
461 ecmf8Len+=nanoLen;
462 ecm88Len-=nanoLen;
463 curEcm88len-=nanoLen;
464 ecm88Data+=nanoLen;
465 }
466 if(ecmf8Len)
467 {
468 if( reader->last_geo.geo_len!=ecmf8Len ||
469 memcmp(reader->last_geo.geo, ecmf8Data, reader->last_geo.geo_len))
470 {
471 memcpy(reader->last_geo.geo, ecmf8Data, ecmf8Len);
472 reader->last_geo.geo_len= ecmf8Len;
473 insf8[3]=keynr;
474 insf8[4]=ecmf8Len;
475 write_cmd(insf8, ecmf8Data);
476 }
477 }
478 ins88[2]=ecmf8Len?1:0;
479 ins88[3]=keynr;
480 ins88[4]= curEcm88len;
481 //
482 // we should check the nano to make sure the ecm is valid
483 // we should look for at least 1 E3 nano, 1 EA nano and the F0 signature nano
484 //
485 // DE04
486 if (DE04[0]==0xDE)
487 {
488 memcpy(DE04+6, (uchar *)ecm88Data, curEcm88len-6);
489 write_cmd(ins88, DE04); // request dcw
490 }
491 else
492 {
493 write_cmd(ins88, (uchar *)ecm88Data); // request dcw
494 }
495 //
496 write_cmd(insc0, NULL); // read dcw
497 switch(cta_res[0])
498 {
499 case 0xe8: // even
500 if(cta_res[1]==8) { memcpy(er->cw,cta_res+2,8); rc=1; }
501 break;
502 case 0xe9: // odd
503 if(cta_res[1]==8) { memcpy(er->cw+8,cta_res+2,8); rc=1; }
504 break;
505 case 0xea: // complete
506 if(cta_res[1]==16) { memcpy(er->cw,cta_res+2,16); rc=1; }
507 break;
508 default :
509 ecm88Data=nextEcm;
510 ecm88Len-=curEcm88len;
511 cs_debug_mask(D_READER, "[viaccess-reader] ECM: key to use is not the current one, trying next ECM");
512 snprintf( er->msglog, MSGLOGSIZE, "key to use is not the current one, trying next ECM" );
513 }
514 }
515 else {
516 ecm88Data=nextEcm;
517 ecm88Len-=curEcm88len;
518 cs_debug_mask(D_READER, "[viaccess-reader] ECM: Unknown ECM type");
519 snprintf( er->msglog, MSGLOGSIZE, "Unknown ECM type" );
520 }
521 }
522
523 if ( hasD2 && !check_crc(er->cw) && nanoD2 == 2) {
524 if(reader->aes_list) {
525 cs_debug_mask(D_READER, "Decoding CW : using AES key id %d for provider %06x",D2KeyID, (provid & 0xFFFFF0));
526 rc=aes_decrypt_from_list(reader->aes_list,0x500, (uint32) (provid & 0xFFFFF0), D2KeyID,er->cw, 16);
527 if( rc == 0 )
528 snprintf( er->msglog, MSGLOGSIZE, "AES Decrypt : key id %d not found for CAID %04X , provider %06lx", D2KeyID, 0x500, (provid & 0xFFFFF0) );
529 }
530 else
531 aes_decrypt(er->cw, 16);
532 }
533
534 return(rc?OK:ERROR);
535}
536
537static int viaccess_get_emm_type(EMM_PACKET *ep, struct s_reader * rdr)
538{
539 ulong provid=0;
540 cs_debug_mask(D_EMM, "Entered viaccess_get_emm_type ep->emm[0]=%02x",ep->emm[0]);
541
542 if (ep->emm[3] == 0x90 && ep->emm[4] == 0x03) {
543 provid = ep->emm[5] << 16 | ep->emm[6] << 8 | (ep->emm[7] & 0xFE);
544 memcpy(ep->provid, i2b(4, provid), 4);
545 }
546
547 switch (ep->emm[0]) {
548 case 0x88:
549 ep->type=UNIQUE;
550 memset(ep->hexserial, 0, 8);
551 memcpy(ep->hexserial, ep->emm + 4, 4);
552 cs_debug_mask(D_EMM, "VIACCESS EMM: UNIQUE");
553 return(!memcmp(rdr->hexserial + 1, ep->hexserial, 4));
554
555 case 0x8A:
556 case 0x8B:
557 ep->type=GLOBAL;
558 cs_debug_mask(D_EMM, "VIACCESS EMM: GLOBAL");
559 return TRUE;
560
561 case 0x8C:
562 case 0x8D:
563 ep->type=SHARED;
564 cs_debug_mask(D_EMM, "VIACCESS EMM: SHARED (part)");
565 return FALSE;
566
567 case 0x8E:
568 ep->type=SHARED;
569 memset(ep->hexserial, 0, 8);
570 memcpy(ep->hexserial, ep->emm + 3, 3);
571 cs_debug_mask(D_EMM, "VIACCESS EMM: SHARED");
572 return(!memcmp(&rdr->sa[0][0], ep->hexserial, 3));
573
574 default:
575 ep->type = UNKNOWN;
576 cs_debug_mask(D_EMM, "VIACCESS EMM: UNKNOWN");
577 return TRUE;
578 }
579}
580
581static void viaccess_get_emm_filter(struct s_reader * rdr, uchar *filter)
582{
583 filter[0]=0xFF;
584 filter[1]=3;
585
586 filter[2]=GLOBAL;
587 filter[3]=0;
588
589 filter[4+0] = 0x8D;
590 filter[4+0+16] = 0xFE;
591 //filter[4+6] = 0xA0; // FIXME: dummy, flood client with EMM's
592 //filter[4+6+16] = 0xF0;
593
594
595 filter[36]=SHARED;
596 filter[37]=0;
597
598 filter[38+0] = 0x8E;
599 filter[38+0+16] = 0xFF;
600 memcpy(filter+38+1, &rdr->sa[0][0], 3);
601 memset(filter+38+1+16, 0xFF, 3);
602
603
604 filter[70]=UNIQUE;
605 filter[71]=0;
606
607 filter[72+0] = 0x88;
608 filter[72+0+16] = 0xFF;
609 memcpy(filter+72+1, rdr->hexserial + 1, 4);
610 memset(filter+72+1+16, 0xFF, 4);
611
612 return;
613}
614
615static int viaccess_do_emm(struct s_reader * reader, EMM_PACKET *ep)
616{
617 def_resp;
618 static const unsigned char insa4[] = { 0xca,0xa4,0x04,0x00,0x03 }; // set provider id
619 unsigned char insf0[] = { 0xca,0xf0,0x00,0x01,0x22 }; // set adf
620 unsigned char insf4[] = { 0xca,0xf4,0x00,0x01,0x00 }; // set adf, encrypted
621 unsigned char ins18[] = { 0xca,0x18,0x01,0x01,0x00 }; // set subscription
622 unsigned char ins1c[] = { 0xca,0x1c,0x01,0x01,0x00 }; // set subscription, encrypted
623 static const unsigned char insc8[] = { 0xca,0xc8,0x00,0x00,0x02 }; // read extended status
624 // static const unsigned char insc8Data[] = { 0x00,0x00 }; // data for read extended status
625
626 int emmdatastart=7;
627 if (ep->type == UNIQUE) emmdatastart++;
628 int emmLen=SCT_LEN(ep->emm)-emmdatastart;
629 int rc=0;
630
631 ///cs_dump(ep->emm, emmLen+emmdatastart, "RECEIVED EMM VIACCESS");
632
633 int emmUpToEnd;
634 uchar *emmParsed = ep->emm+emmdatastart;
635 int provider_ok = 0;
636 unsigned int emm_provid;
637 uchar keynr = 0;
638 int ins18Len = 0;
639 uchar ins18Data[512];
640 uchar insData[512];
641 uchar *nano81Data = 0;
642 uchar *nano91Data = 0;
643 uchar *nano92Data = 0;
644 uchar *nano9EData = 0;
645 uchar *nanoF0Data = 0;
646
647 for (emmUpToEnd=emmLen; (emmParsed[1] != 0) && (emmUpToEnd > 0); emmUpToEnd -= (2 + emmParsed[1]), emmParsed += (2 + emmParsed[1])) {
648 ///cs_dump (emmParsed, emmParsed[1] + 2, "NANO");
649
650 if (emmParsed[0]==0x90 && emmParsed[1]==0x03) {
651 /* identification of the service operator */
652
653 uchar soid[3], ident[3], i;
654
655 for (i=0; i<3; i++) {
656 soid[i]=ident[i]=emmParsed[2+i];
657 }
658 ident[2]&=0xF0;
659 emm_provid=b2i(3, ident);
660 keynr=soid[2]&0x0F;
661 if (chk_prov(reader, ident, keynr)) {
662 provider_ok = 1;
663 } else {
664 cs_debug_mask(D_READER, "[viaccess-reader] EMM: provider or key not found on card (%x, %x)", ident, keynr);
665 cs_log("[viaccess-reader] EMM: provider or key not found on card (%x, %x)", ident, keynr);
666 return ERROR;
667 }
668
669 // check if the provider changes. If yes, set the new one. If not, don't .. card will return an error if we do.
670 if( reader->last_geo.provid != emm_provid ) {
671 write_cmd(insa4, ident);
672 if( cta_res[cta_lr-2]!=0x90 || cta_res[cta_lr-1]!=0x00 ) {
673 cs_dump(insa4, 5, "set provider cmd:");
674 cs_dump(soid, 3, "set provider data:");
675 cs_log("[viaccess-reader] update error: %02X %02X", cta_res[cta_lr-2], cta_res[cta_lr-1]);
676 return ERROR;
677 }
678 }
679 // as we are maybe changing the used provider, clear the cache, so the next ecm will re-select the correct one
680 reader->last_geo.provid = 0;
681 reader->last_geo.geo_len = 0;
682 reader->last_geo.geo[0] = 0;
683
684 }
685 else if (emmParsed[0]==0x9e && emmParsed[1]==0x20) {
686 /* adf */
687
688 if (!nano91Data) {
689 /* adf is not crypted, so test it */
690
691 uchar custwp;
692 uchar *afd;
693
694 custwp=reader->sa[0][3];
695 afd=(uchar*)emmParsed+2;
696
697 if( afd[31-custwp/8] & (1 << (custwp & 7)) )
698 cs_debug_mask(D_READER, "[viaccess-reader] emm for our card %08X", b2i(4, &reader->sa[0][0]));
699 else
700 return SKIPPED;
701 }
702
703 // memorize
704 nano9EData = emmParsed;
705
706 } else if (emmParsed[0]==0x81) {
707 nano81Data = emmParsed;
708 } else if (emmParsed[0]==0x91 && emmParsed[1]==0x08) {
709 nano91Data = emmParsed;
710 } else if (emmParsed[0]==0x92 && emmParsed[1]==0x08) {
711 nano92Data = emmParsed;
712 } else if (emmParsed[0]==0xF0 && emmParsed[1]==0x08) {
713 nanoF0Data = emmParsed;
714 } else if (emmParsed[0]==0x1D && emmParsed[0]==0x01 && emmParsed[0]==0x01) {
715 /* from cccam... skip it... */
716 } else {
717 /* other nanos */
718 show_subs(reader, emmParsed);
719
720 memcpy(ins18Data+ins18Len, emmParsed, emmParsed[1] + 2);
721 ins18Len += emmParsed [1] + 2;
722 }
723 }
724
725 if (!provider_ok) {
726 cs_debug_mask(D_READER, "[viaccess-reader] provider not found in emm, continue anyway");
727 // force key to 1...
728 keynr = 1;
729 ///return ERROR;
730 }
731
732 if (!nanoF0Data) {
733 cs_dump(ep->emm, ep->l, "can't find 0xf0 in emm...");
734 return ERROR; // error
735 }
736
737 if (nano9EData) {
738 if (!nano91Data) {
739 // set adf
740 insf0[3] = keynr; // key
741 insf0[4] = nano9EData[1] + 2;
742 write_cmd(insf0, nano9EData);
743 if( cta_res[cta_lr-2]!=0x90 || cta_res[cta_lr-1]!=0x00 ) {
744 cs_dump(insf0, 5, "set adf cmd:");
745 cs_dump(nano9EData, insf0[4] , "set adf data:");
746 cs_log("[viaccess-reader] update error: %02X %02X", cta_res[cta_lr-2], cta_res[cta_lr-1]);
747 return ERROR;
748 }
749 } else {
750 // set adf crypte
751 insf4[3] = keynr; // key
752 insf4[4] = nano91Data[1] + 2 + nano9EData[1] + 2;
753 memcpy (insData, nano91Data, nano91Data[1] + 2);
754 memcpy (insData + nano91Data[1] + 2, nano9EData, nano9EData[1] + 2);
755 write_cmd(insf4, insData);
756 if(( cta_res[cta_lr-2]!=0x90 && cta_res[cta_lr-2]!=0x91) || cta_res[cta_lr-1]!=0x00 ) {
757 cs_dump(insf4, 5, "set adf encrypted cmd:");
758 cs_dump(insData, insf4[4], "set adf encrypted data:");
759 cs_log("[viaccess-reader] update error: %02X %02X", cta_res[cta_lr-2], cta_res[cta_lr-1]);
760 return ERROR;
761 }
762 }
763 }
764
765 if (!nano92Data) {
766 // send subscription
767 ins18[2] = nano9EData ? 0x01: 0x00; // found 9E nano ?
768 ins18[3] = keynr; // key
769 ins18[4] = ins18Len + nanoF0Data[1] + 2;
770 memcpy (insData, ins18Data, ins18Len);
771 memcpy (insData + ins18Len, nanoF0Data, nanoF0Data[1] + 2);
772 write_cmd(ins18, insData);
773 if( (cta_res[cta_lr-2]==0x90 || cta_res[cta_lr-2]==0x91) && cta_res[cta_lr-1]==0x00 ) {
774 cs_debug_mask(D_READER, "[viaccess-reader] update successfully written");
775 rc=1; // written
776 } else {
777 cs_dump(ins18, 5, "set subscription cmd:");
778 cs_dump(insData, ins18[4], "set subscription data:");
779 cs_log("[viaccess-reader] update error: %02X %02X", cta_res[cta_lr-2], cta_res[cta_lr-1]);
780 }
781
782 } else {
783 // send subscription encrypted
784
785 if (!nano81Data) {
786 cs_dump(ep->emm, ep->l, "0x92 found, but can't find 0x81 in emm...");
787 return ERROR; // error
788 }
789
790 ins1c[2] = nano9EData ? 0x01: 0x00; // found 9E nano ?
791 if (ep->type == UNIQUE) ins1c[2] = 0x02;
792 ins1c[3] = keynr; // key
793 ins1c[4] = nano92Data[1] + 2 + nano81Data[1] + 2 + nanoF0Data[1] + 2;
794 memcpy (insData, nano92Data, nano92Data[1] + 2);
795 memcpy (insData + nano92Data[1] + 2, nano81Data, nano81Data[1] + 2);
796 memcpy (insData + nano92Data[1] + 2 + nano81Data[1] + 2, nanoF0Data, nanoF0Data[1] + 2);
797 write_cmd(ins1c, insData);
798
799 if( (cta_res[cta_lr-2]==0x90 && cta_res[cta_lr-1]==0x00) ) {
800 cs_log("[viaccess-reader] update successfully written");
801 rc=1; // written
802 }
803 else {
804 if( cta_res[cta_lr-2]&0x1 )
805 cs_log("[viaccess-reader] update not written. Data already exists or unknown address");
806
807 //if( cta_res[cta_lr-2]&0x8 ) {
808 write_cmd(insc8, NULL);
809 if( (cta_res[cta_lr-2]==0x90 && cta_res[cta_lr-1]==0x00) ) {
810 cs_log("[viaccess-reader] extended status %02X %02X", cta_res[0], cta_res[1]);
811 }
812 //}
813 return ERROR;
814 }
815
816 }
817
818 /*
819 Sub Main()
820 Sc.Write("CA A4 04 00 03")
821 RX
822 Sc.Write("02 07 11")
823 RX
824 Sc.Write("CA F0 00 01 22")
825 RX
826 Sc.Write("9E 20")
827 Sc.Write("10 10 08 8A 80 00 04 00 10 10 26 E8 54 80 1E 80")
828 Sc.Write("00 01 00 00 00 00 00 50 00 00 80 02 22 00 08 50")
829 RX
830 Sc.Write("CA 18 01 01 11")
831 RX
832 Sc.Write("A9 05 34 DE 34 FF 80")
833 Sc.Write("F0 08 1A 3E AF B5 2B EE E3 3B")
834 RX
835
836 End Sub
837*/
838 return rc;
839}
840
841static int viaccess_card_info(struct s_reader * reader)
842{
843 def_resp;
844 int i, l, scls, show_cls;
845 uchar insac[] = { 0xca, 0xac, 0x00, 0x00, 0x00 }; // select data
846 uchar insb8[] = { 0xca, 0xb8, 0x00, 0x00, 0x00 }; // read selected data
847 uchar insa4[] = { 0xca, 0xa4, 0x00, 0x00, 0x00 }; // select issuer
848 uchar insc0[] = { 0xca, 0xc0, 0x00, 0x00, 0x00 }; // read data item
849 static const uchar ins24[] = { 0xca, 0x24, 0x00, 0x00, 0x09 }; // set pin
850
851 static const uchar cls[] = { 0x00, 0x21, 0xff, 0x9f};
852 static const uchar pin[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04};
853
854 show_cls=reader->show_cls;
855 reader->last_geo.provid = 0;
856 reader->last_geo.geo_len = 0;
857 reader->last_geo.geo[0] = 0;
858
859 cs_log("[viaccess-reader] card detected");
860
861 // set pin
862 write_cmd(ins24, pin);
863
864 insac[2]=0xa4; write_cmd(insac, NULL); // request unique id
865 insb8[4]=0x07; write_cmd(insb8, NULL); // read unique id
866 cs_log("[viaccess-reader] serial: %llu", b2ll(5, cta_res+2));
867
868 scls=0;
869 insa4[2]=0x00; write_cmd(insa4, NULL); // select issuer 0
870 for (i=1; (cta_res[cta_lr-2]==0x90) && (cta_res[cta_lr-1]==0); i++)
871 {
872 ulong l_provid, l_sa;
873 uchar l_name[64];
874 insc0[4]=0x1a; write_cmd(insc0, NULL); // show provider properties
875 cta_res[2]&=0xF0;
876 l_provid=b2i(3, cta_res);
877
878 insac[2]=0xa5; write_cmd(insac, NULL); // request sa
879 insb8[4]=0x06; write_cmd(insb8, NULL); // read sa
880 l_sa=b2i(4, cta_res+2);
881
882 insac[2]=0xa7; write_cmd(insac, NULL); // request name
883 insb8[4]=0x02; write_cmd(insb8, NULL); // read name nano + len
884 l=cta_res[1];
885 insb8[4]=l; write_cmd(insb8, NULL); // read name
886 cta_res[l]=0;
887 trim((char *)cta_res);
888 if (cta_res[0])
889 snprintf((char *)l_name, sizeof(l_name), ", name: %s", cta_res);
890 else
891 l_name[0]=0;
892
893 // read GEO
894 insac[2]=0xa6; write_cmd(insac, NULL); // request GEO
895 insb8[4]=0x02; write_cmd(insb8, NULL); // read GEO nano + len
896 l=cta_res[1];
897 insb8[4]=l; write_cmd(insb8, NULL); // read geo
898 cs_ri_log(reader, "provider: %d, id: %06X%s, sa: %08X, geo: %s",
899 i, l_provid, l_name, l_sa, (l<4) ? "empty" : cs_hexdump(1, cta_res, l));
900
901 // read classes subscription
902 insac[2]=0xa9; insac[4]=4;
903 write_cmd(insac, cls); // request class subs
904 scls=0;
905 while( (cta_res[cta_lr-2]==0x90) && (cta_res[cta_lr-1]==0) )
906 {
907 insb8[4]=0x02; write_cmd(insb8, NULL); // read class subs nano + len
908 if( (cta_res[cta_lr-2]==0x90) && (cta_res[cta_lr-1]==0) )
909 {
910 int fshow;
911 l=cta_res[1];
912 //fshow=(client[cs_idx].dbglvl==D_DUMP)?1:(scls < show_cls)?1:0;
913 fshow=(scls<show_cls);
914 insb8[4]=l; write_cmd(insb8, NULL); // read class subs
915 if( (cta_res[cta_lr-2]==0x90) && (fshow) &&
916 (cta_res[cta_lr-1]==0x00 || cta_res[cta_lr-1]==0x08) )
917 {
918 show_class(reader, NULL, cta_res, cta_lr-2);
919 scls++;
920 }
921 }
922 }
923
924 insac[4]=0;
925 insa4[2]=0x02;
926 write_cmd(insa4, NULL); // select next provider
927 }
928 //return ERROR;
929 return OK;
930}
931
932#ifdef HAVE_DVBAPI
933int viaccess_reassemble_emm(uchar *buffer, uint *len) {
934 static uchar emm_global[512];
935 static int emm_global_len = 0;
936
937 int pos, emm_len = 0, k;
938 uchar emmbuf[512];
939
940 // Viaccess
941 if (*len>500) return 0;
942
943 switch(buffer[0]) {
944 case 0x8c:
945 case 0x8d:
946 // emm-s part 1
947 if (!memcmp(emm_global, buffer, *len))
948 return 0;
949
950 //cs_log("viaccess global emm_provid: %06X provid: %06X", emm_provid, provider);
951
952 // copy first part of the emm-s
953 memcpy(emm_global, buffer, *len);
954 emm_global_len=*len;
955 //cs_ddump_mask(D_READER, buffer, len, "viaccess global emm:");
956 return 0;
957
958 case 0x8e:
959 // emm-s part 2
960 if (!emm_global_len) return 0;
961
962 if (buffer[6]!=0x00) return 0;
963
964 memcpy(emmbuf, buffer, 7);
965 pos=7;
966
967 for (k=3; k<emm_global[2]+2 && k<emm_global_len; k += emm_global[k+1]+2) {
968 if (emm_global[k]!=0x90) continue;
969 memcpy(emmbuf+pos, emm_global+k, emm_global[k+1]+2);
970 pos += emm_global[k+1]+2;
971 }
972
973 memcpy(emmbuf+pos, "\x9E\x20", 2);
974 memcpy(emmbuf+pos+2, buffer+7, 32);
975 pos+=34;
976
977 int found=0;
978 for (k=8; k<emm_global[2]+2 && k<emm_global_len; k += emm_global[k+1]+2) {
979 if (emm_global[k] == 0xA1 || emm_global[k] == 0xA8 || emm_global[k] == 0xA9 || emm_global[k] == 0xB6) {
980 memcpy(emmbuf+pos, emm_global+k, emm_global[k+1]+2);
981 pos += emm_global[k+1]+2;
982 found=1;
983 }
984 }
985 if (found==0) return 0;
986
987 memcpy(emmbuf+pos, "\xF0\x08", 2);
988 memcpy(emmbuf+pos+2, buffer+39, 8);
989 pos+=10;
990
991 emm_len=pos;
992 emmbuf[2]=emm_len-3;
993 cs_ddump_mask(D_READER, buffer, *len, "original emm:");
994 memcpy(buffer, emmbuf, emm_len);
995 *len=emm_len;
996 break;
997 }
998 return 1;
999}
1000#endif
1001
1002void reader_viaccess(struct s_cardsystem *ph)
1003{
1004 ph->do_emm=viaccess_do_emm;
1005 ph->do_ecm=viaccess_do_ecm;
1006 ph->card_info=viaccess_card_info;
1007 ph->card_init=viaccess_card_init;
1008 ph->get_emm_type=viaccess_get_emm_type;
1009 ph->get_emm_filter=viaccess_get_emm_filter;
1010 ph->caids[0]=0x05;
1011 ph->desc="viaccess";
1012}
Note: See TracBrowser for help on using the repository browser.