source: trunk/reader-viaccess.c @ 5375

Last change on this file since 5375 was 5368, checked in by _network, 8 years ago

viaccess: small fix for cccam emm workaround (#1838)

File size: 32.8 KB
Line 
1#include "globals.h"
2#include "reader-common.h"
3
4struct via_date {
5  uint16_t day_s   : 5;
6  uint16_t month_s : 4;
7  uint16_t year_s  : 7;
8
9  uint16_t day_e   : 5;
10  uint16_t month_e : 4;
11  uint16_t year_e  : 7;
12};
13
14static void parse_via_date(const uchar *buf, struct via_date *vd, int32_t fend)
15{
16  uint16_t 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, int32_t l)
33{
34  int32_t 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      int32_t 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 int32_t chk_prov(struct s_reader * reader, uchar *id, uchar keynr)
120{
121  int32_t 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 int32_t 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 int32_t viaccess_card_init(struct s_reader * reader, ATR newatr)
163{
164    get_atr;
165    def_resp;
166    int32_t 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[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=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, 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    snprintf((char *)buf+strlen((char *)buf), sizeof(buf)-strlen((char *)buf), ",%06X", 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    if (cfg.ulparent)
251        unlock_parental(reader);
252
253    cs_log("[viaccess-reader] ready for requests");
254    return OK;
255}
256
257bool check_crc( uchar *data )
258{
259 int32_t valid = 0;
260
261     uchar sum1=data[0] + data[1] + data[2] ;
262     uchar sum2=data[4] + data[5] + data[6] ;
263     uchar sum3=data[8] + data[9] + data[10] ;
264     uchar sum4=data[12] + data[13] + data[14] ;
265     
266     if ( ( sum1 == data[3] ) && ( sum2 == data[7] ) && ( sum3 == data[11] )&& ( sum4 == data[15] ) )
267        valid = 1;
268
269  return valid;
270}
271
272static int32_t viaccess_do_ecm(struct s_reader * reader, ECM_REQUEST *er)
273{
274  def_resp;
275  static const unsigned char insa4[] = { 0xca,0xa4,0x04,0x00,0x03 }; // set provider id
276  unsigned char ins88[] = { 0xca,0x88,0x00,0x00,0x00 }; // set ecm
277  unsigned char insf8[] = { 0xca,0xf8,0x00,0x00,0x00 }; // set geographic info
278  static const unsigned char insc0[] = { 0xca,0xc0,0x00,0x00,0x12 }; // read dcw
279
280  uchar *ecm88Data=er->ecm+4; //XXX what is the 4th byte for ??
281  int32_t ecm88Len=SCT_LEN(er->ecm)-4;
282  uint32_t provid=0;
283  int32_t rc=0;
284  int32_t hasD2 = 0;
285  int32_t curEcm88len=0;
286  int32_t nanoLen=0;
287  uchar *nextEcm;
288  uchar DE04[256];
289  int32_t D2KeyID=0;
290  int32_t curnumber_ecm=0;
291  //nanoD2 d2 02 0d 02 -> D2 nano, len 2
292  // 0d -> post AES decrypt CW
293  // 0b -> pre AES decrypt CW
294  int32_t nanoD2 = 0; //   0x0b = 1  0x0d = 2
295
296  memset(DE04, 0, sizeof(DE04)); //fix dorcel de04 bug
297
298  nextEcm=ecm88Data;
299 
300  while (ecm88Len && !rc) {
301   
302    if(ecm88Data[0] ==0x00 &&  ecm88Data[1] == 0x00) {
303        // nano 0x00  and len 0x00 aren't valid ... something is obviously wrong with this ecm.
304        cs_log("[viaccess-reader] ECM: Invalid ECM structure. Rejecting");
305        return ERROR;
306    }
307   
308    // 80 33 nano 80 (ecm) + len (33)
309    if(ecm88Data[0]==0x80) { // nano 80, give ecm len
310        curEcm88len=ecm88Data[1];
311        nextEcm=ecm88Data+curEcm88len+2;
312        ecm88Data += 2;
313        ecm88Len -= 2;
314    }
315
316    if(!curEcm88len) { //there was no nano 80 -> simple ecm
317        curEcm88len=ecm88Len;
318    }
319   
320    // d2 02 0d 02 -> D2 nano, len 2,  select the AES key to be used
321    if(ecm88Data[0]==0xd2) {
322        // test if need post or pre AES decrypt
323        if(ecm88Data[2]==0x0b)
324        {
325            nanoD2 = 1;
326            cs_debug_mask(D_READER, "[viaccess-reader] ECM: nano D2 0x0b");
327        }
328        if(ecm88Data[2]==0x0d)
329        {
330            nanoD2 = 2;
331            cs_debug_mask(D_READER, "[viaccess-reader] ECM: nano D2 0x0d");
332        }
333        // use the d2 arguments to get the key # to be used
334        int32_t len = ecm88Data[1] + 2;
335        D2KeyID=ecm88Data[3];
336        ecm88Data += len;
337        ecm88Len -= len;
338        curEcm88len -=len;
339        hasD2 = 1;
340    }
341    else
342        hasD2 = 0;
343
344
345    // 40 07 03 0b 00  -> nano 40, len =7  ident 030B00 (tntsat), key #0  <== we're pointing here
346    // 09 -> use key #9
347    // 05 67 00
348    if ((ecm88Data[0]==0x90 || ecm88Data[0]==0x40) && (ecm88Data[1]==0x03 || ecm88Data[1]==0x07 ) )
349    {
350        uchar ident[3], keynr;
351        uchar *ecmf8Data=0;
352        int32_t ecmf8Len=0;
353
354        nanoLen=ecm88Data[1] + 2;
355        keynr=ecm88Data[4]&0x0F;       
356
357        // 40 07 03 0b 00  -> nano 40, len =7  ident 030B00 (tntsat), key #0  <== we're pointing here
358        // 09 -> use key #9
359        if(nanoLen>5) {
360            curnumber_ecm =(ecm88Data[6]<<8) | (ecm88Data[7]);
361            cs_debug_mask(D_READER, "checking if the ecm number (%x) match the card one (%x)",curnumber_ecm,reader->last_geo.number_ecm);
362            // if we have an ecm number we check it.
363            // we can't assume that if the nano len is 5 or more we have an ecm number
364            // as some card don't support this
365            if( reader->last_geo.number_ecm > 0 ) {
366                if (reader->last_geo.number_ecm == curnumber_ecm && 
367                        !( ecm88Data[nanoLen-1] == 0x01 && (ecm88Data[2] == 0x03 && ecm88Data[3] == 0x0B && ecm88Data[4] == 0x00 ) )) {
368                    keynr=ecm88Data[5];
369                    cs_debug_mask(D_READER, "keyToUse = %02x, ECM ending with %02x",ecm88Data[5], ecm88Data[nanoLen-1]);
370                } else {
371                    if( ecm88Data[nanoLen-1] == 0x01 && (ecm88Data[2] == 0x03 && ecm88Data[3] == 0x0B && ecm88Data[4] == 0x00 ) )
372                    {
373                        cs_debug_mask(D_READER, "Skip ECM ending with = %02x for ecm number (%x) for provider %02x%02x%02x",ecm88Data[nanoLen-1], curnumber_ecm, ecm88Data[2], ecm88Data[3], ecm88Data[4]);
374                    }
375                    cs_debug_mask(D_READER, "Skip ECM ending with = %02x for ecm number (%x)",ecm88Data[nanoLen-1], curnumber_ecm);
376                    ecm88Data=nextEcm;
377                    ecm88Len-=curEcm88len;
378                    continue; //loop to next ecm
379                }
380            }
381            else { // long ecm but we don't have an ecm number so we have to try them all.
382                keynr=ecm88Data[5];
383                cs_debug_mask(D_READER, "keyToUse = %02x",ecm88Data[5]);
384            }
385        }
386
387        memcpy (ident, &ecm88Data[2], sizeof(ident));
388        provid = b2i(3, ident);
389        ident[2]&=0xF0;
390
391        if(hasD2 && reader->aes_list) {
392            // check that we have the AES key to decode the CW
393            // if not there is no need to send the ecm to the card
394            if(!aes_present(reader->aes_list, 0x500, (uint32_t) (provid & 0xFFFFF0) , D2KeyID))
395                return ERROR;
396        }
397
398
399        if (!chk_prov(reader, ident, keynr))
400        {
401          cs_debug_mask(D_READER, "[viaccess-reader] ECM: provider or key not found on card");
402          snprintf( er->msglog, MSGLOGSIZE, "provider(%02x%02x%02x) or key(%d) not found on card", ident[0],ident[1],ident[2], keynr );
403          return ERROR;
404        }
405       
406        ecm88Data+=nanoLen;
407        ecm88Len-=nanoLen;
408        curEcm88len-=nanoLen;
409
410        // DE04
411        if (ecm88Data[0]==0xDE && ecm88Data[1]==0x04)
412        {
413            memcpy (DE04, &ecm88Data[0], 6);
414            ecm88Data+=6;
415        }
416        //
417
418        if( reader->last_geo.provid != provid ) 
419        {
420          reader->last_geo.provid = provid;
421          reader->last_geo.geo_len = 0;
422          reader->last_geo.geo[0]  = 0;
423          write_cmd(insa4, ident); // set provider
424        }
425       
426        //Nano D2 0x0b Pre AES decrypt CW       
427        if ( hasD2 && nanoD2 == 1) 
428        {
429            uchar *ecm88DataCW = ecm88Data;
430            int32_t cwStart = 0;
431            //int32_t cwStartRes = 0;
432            int32_t exit = 0;
433            // find CW start
434            while(cwStart < curEcm88len -1 && !exit)
435            {
436                if(ecm88Data[cwStart] == 0xEA && ecm88Data[cwStart+1] == 0x10)
437                {
438                    ecm88DataCW = ecm88DataCW + cwStart + 2;
439                    exit = 1;
440                }
441                cwStart++;
442            } 
443            // use AES from list to decrypt CW
444            cs_debug_mask(D_READER, "Decoding CW : using AES key id %d for provider %06x",D2KeyID, (provid & 0xFFFFF0));
445            if (aes_decrypt_from_list(reader->aes_list,0x500, (uint32_t) (provid & 0xFFFFF0), D2KeyID, &ecm88DataCW[0], 16) == 0)
446                snprintf( er->msglog, MSGLOGSIZE, "AES Decrypt : key id %d not found for CAID %04X , provider %06x", D2KeyID, 0x500, (provid & 0xFFFFF0) );
447        }
448
449        while(ecm88Len>0 && ecm88Data[0]<0xA0)
450        {
451          int32_t nanoLen=ecm88Data[1]+2;
452          if (!ecmf8Data)
453            ecmf8Data=(uchar *)ecm88Data;
454          ecmf8Len+=nanoLen;
455          ecm88Len-=nanoLen;
456          curEcm88len-=nanoLen;
457          ecm88Data+=nanoLen;
458        }
459        if(ecmf8Len)
460        {
461          if( reader->last_geo.geo_len!=ecmf8Len || 
462             memcmp(reader->last_geo.geo, ecmf8Data, reader->last_geo.geo_len))
463          {
464            memcpy(reader->last_geo.geo, ecmf8Data, ecmf8Len);
465            reader->last_geo.geo_len= ecmf8Len;
466            insf8[3]=keynr;
467            insf8[4]=ecmf8Len;
468            write_cmd(insf8, ecmf8Data);
469          }
470        }
471        ins88[2]=ecmf8Len?1:0;
472        ins88[3]=keynr;
473        ins88[4]= curEcm88len;
474        //
475        // we should check the nano to make sure the ecm is valid
476        // we should look for at least 1 E3 nano, 1 EA nano and the F0 signature nano
477        //
478        // DE04
479        if (DE04[0]==0xDE)
480        {
481            memcpy(DE04+6, (uchar *)ecm88Data, curEcm88len-6);
482            write_cmd(ins88, DE04); // request dcw
483        }
484        else
485        {
486            write_cmd(ins88, (uchar *)ecm88Data); // request dcw
487        }
488        //
489        write_cmd(insc0, NULL); // read dcw
490        switch(cta_res[0])
491        {
492          case 0xe8: // even
493            if(cta_res[1]==8) { memcpy(er->cw,cta_res+2,8); rc=1; }
494            break;
495          case 0xe9: // odd
496            if(cta_res[1]==8) { memcpy(er->cw+8,cta_res+2,8); rc=1; }
497            break;
498          case 0xea: // complete
499            if(cta_res[1]==16) { memcpy(er->cw,cta_res+2,16); rc=1; }
500            break;
501          default :
502            ecm88Data=nextEcm;
503            ecm88Len-=curEcm88len;
504            cs_debug_mask(D_READER, "[viaccess-reader] ECM: key to use is not the current one, trying next ECM");
505            snprintf( er->msglog, MSGLOGSIZE, "key to use is not the current one, trying next ECM" );
506        }
507    }
508    else {
509        ecm88Data=nextEcm;
510        ecm88Len-=curEcm88len;
511        cs_debug_mask(D_READER, "[viaccess-reader] ECM: Unknown ECM type");
512        snprintf( er->msglog, MSGLOGSIZE, "Unknown ECM type" );
513    }
514  }
515
516  if ( hasD2 && !check_crc(er->cw) && nanoD2 == 2) {
517    cs_debug_mask(D_READER, "Decoding CW : using AES key id %d for provider %06x",D2KeyID, (provid & 0xFFFFF0));
518    rc=aes_decrypt_from_list(reader->aes_list,0x500, (uint32_t) (provid & 0xFFFFF0), D2KeyID,er->cw, 16);
519    if( rc == 0 )
520        snprintf( er->msglog, MSGLOGSIZE, "AES Decrypt : key id %d not found for CAID %04X , provider %06x", D2KeyID, 0x500, (provid & 0xFFFFF0) );
521  }
522
523  return(rc?OK:ERROR);
524}
525
526static int32_t viaccess_get_emm_type(EMM_PACKET *ep, struct s_reader * rdr)
527{
528    uint32_t provid=0;
529    cs_debug_mask(D_EMM, "Entered viaccess_get_emm_type ep->emm[0]=%02x",ep->emm[0]);
530
531    if (ep->emm[3] == 0x90 && ep->emm[4] == 0x03) {
532        provid = ep->emm[5] << 16 | ep->emm[6] << 8 | (ep->emm[7] & 0xFE);
533        i2b_buf(4, provid, ep->provid);
534    }
535
536    switch (ep->emm[0]) {
537        case 0x88:
538            ep->type=UNIQUE;
539            memset(ep->hexserial, 0, 8);
540            memcpy(ep->hexserial, ep->emm + 4, 4);
541            cs_debug_mask(D_EMM, "VIACCESS EMM: UNIQUE");
542            return(!memcmp(rdr->hexserial + 1, ep->hexserial, 4));
543
544        case 0x8A:
545        case 0x8B:
546            ep->type=GLOBAL;
547            cs_debug_mask(D_EMM, "VIACCESS EMM: GLOBAL");
548            return TRUE;
549
550        case 0x8C:
551        case 0x8D:
552            ep->type=SHARED;
553            cs_debug_mask(D_EMM, "VIACCESS EMM: SHARED (part)");
554            return FALSE;
555
556        case 0x8E:
557            ep->type=SHARED;
558            memset(ep->hexserial, 0, 8);
559            memcpy(ep->hexserial, ep->emm + 3, 3);
560            cs_debug_mask(D_EMM, "VIACCESS EMM: SHARED");
561
562            //check for provider as serial (cccam only?)
563            int8_t i;
564            for (i=0;i<rdr->nprov;i++) {
565                if (!memcmp(&rdr->prid[i][1], ep->hexserial, 3))
566                    return TRUE;
567            }
568            return(!memcmp(&rdr->sa[0][0], ep->hexserial, 3));
569
570        default:
571            ep->type = UNKNOWN;
572            cs_debug_mask(D_EMM, "VIACCESS EMM: UNKNOWN");
573            return TRUE;
574    }   
575}
576
577static void viaccess_get_emm_filter(struct s_reader * rdr, uchar *filter)
578{
579    int32_t idx = 2;
580
581    filter[0]=0xFF;
582    filter[1]=0;
583
584    filter[idx++]=EMM_GLOBAL;
585    filter[idx++]=0;
586    filter[idx+0]     = 0x8D;
587    filter[idx+0+16]  = 0xFE;
588    //filter[idx+6]     = 0xA0; // FIXME: dummy, flood client with EMM's
589    //filter[idx+6+16]  = 0xF0;
590    filter[1]++;
591    idx += 32;
592
593    filter[idx++]=EMM_SHARED;
594    filter[idx++]=0;
595    filter[idx+0]    = 0x8E;
596    filter[idx+0+16] = 0xFF;
597    memcpy(filter+idx+1, &rdr->sa[0][0], 3);
598    memset(filter+idx+1+16, 0xFF, 3);
599    filter[1]++;
600    idx += 32;
601
602    filter[idx++]=EMM_UNIQUE;
603    filter[idx++]=0;
604    filter[idx+0]    = 0x88;
605    filter[idx+0+16] = 0xFF;
606    memcpy(filter+idx+1, rdr->hexserial + 1, 4);
607    memset(filter+idx+1+16, 0xFF, 4);
608    filter[1]++;
609    idx += 32;
610
611    return;
612}
613
614static int32_t viaccess_do_emm(struct s_reader * reader, EMM_PACKET *ep)
615{
616  def_resp;
617  static const unsigned char insa4[] = { 0xca,0xa4,0x04,0x00,0x03 }; // set provider id
618  unsigned char insf0[] = { 0xca,0xf0,0x00,0x01,0x22 }; // set adf
619  unsigned char insf4[] = { 0xca,0xf4,0x00,0x01,0x00 }; // set adf, encrypted
620  unsigned char ins18[] = { 0xca,0x18,0x01,0x01,0x00 }; // set subscription
621  unsigned char ins1c[] = { 0xca,0x1c,0x01,0x01,0x00 }; // set subscription, encrypted
622  static const unsigned char insc8[] = { 0xca,0xc8,0x00,0x00,0x02 }; // read extended status
623  // static const unsigned char insc8Data[] = { 0x00,0x00 }; // data for read extended status
624
625    int32_t emmdatastart=7;
626
627    if (ep->emm[1] == 0x01) { // emm from cccam
628        emmdatastart=10;
629        ep->emm[1] = 0x70; // (& 0x0f) of this byte is length, so 0x01 would increase the length by 256
630        ep->emm[2] -= 3; // last 3 bytes are garbage
631        if (ep->type == SHARED) {
632            // build missing 0x90 nano from provider at serial position
633            memcpy(ep->emm+7, ep->emm+3, 3);
634            ep->emm[5] = 0x90;
635            ep->emm[6] = 0x03;
636            ep->emm[9] |= 0x01;
637            emmdatastart = 5;
638        }
639    }
640
641  if (ep->type == UNIQUE) emmdatastart++;
642  int32_t emmLen=SCT_LEN(ep->emm)-emmdatastart;
643  int32_t rc=0;
644
645  ///cs_dump(ep->emm, emmLen+emmdatastart, "RECEIVED EMM VIACCESS");
646
647  int32_t emmUpToEnd;
648  uchar *emmParsed = ep->emm+emmdatastart;
649  int32_t provider_ok = 0;
650  uint32_t emm_provid;
651  uchar keynr = 0;
652  int32_t ins18Len = 0;
653  uchar ins18Data[512];
654  uchar insData[512];
655  uchar *nano81Data = 0;
656  uchar *nano91Data = 0;
657  uchar *nano92Data = 0;
658  uchar *nano9EData = 0;
659  uchar *nanoF0Data = 0;
660
661  for (emmUpToEnd=emmLen; (emmParsed[1] != 0) && (emmUpToEnd > 0); emmUpToEnd -= (2 + emmParsed[1]), emmParsed += (2 + emmParsed[1])) {
662    ///cs_dump (emmParsed, emmParsed[1] + 2, "NANO");
663
664    if (emmParsed[0]==0x90 && emmParsed[1]==0x03) {
665        /* identification of the service operator */
666       
667        uchar soid[3], ident[3], i;
668       
669        for (i=0; i<3; i++) {
670            soid[i]=ident[i]=emmParsed[2+i];
671        }
672        ident[2]&=0xF0;
673        emm_provid=b2i(3, ident);
674        keynr=soid[2]&0x0F;
675        if (chk_prov(reader, ident, keynr)) {
676            provider_ok = 1;
677        } else {
678            cs_debug_mask(D_READER, "[viaccess-reader] EMM: provider or key not found on card (%x, %x)", ident, keynr);
679            cs_log("[viaccess-reader] EMM: provider or key not found on card (%x, %x)", ident, keynr);
680            return ERROR;
681        }
682       
683        // check if the provider changes. If yes, set the new one. If not, don't .. card will return an error if we do.
684        if( reader->last_geo.provid != emm_provid ) {
685            write_cmd(insa4, ident);             
686            if( cta_res[cta_lr-2]!=0x90 || cta_res[cta_lr-1]!=0x00 ) {
687                cs_dump(insa4, 5, "set provider cmd:");
688                cs_dump(soid, 3, "set provider data:");
689                cs_log("[viaccess-reader] update error: %02X %02X", cta_res[cta_lr-2], cta_res[cta_lr-1]);
690                return ERROR;
691            }
692        }
693        // as we are maybe changing the used provider, clear the cache, so the next ecm will re-select the correct one
694        reader->last_geo.provid = 0;
695        reader->last_geo.geo_len = 0;
696        reader->last_geo.geo[0]  = 0;
697       
698    } 
699    else if (emmParsed[0]==0x9e && emmParsed[1]==0x20) {
700      /* adf */
701
702      if (!nano91Data) {
703        /* adf is not crypted, so test it */
704
705        uchar custwp;
706        uchar *afd;
707
708        custwp=reader->sa[0][3];
709        afd=(uchar*)emmParsed+2;
710
711        if( afd[31-custwp/8] & (1 << (custwp & 7)) )
712          cs_debug_mask(D_READER, "[viaccess-reader] emm for our card %08X", b2i(4, &reader->sa[0][0]));
713        else
714          return SKIPPED;
715      }
716
717      // memorize
718      nano9EData = emmParsed;
719
720    } else if (emmParsed[0]==0x81) {
721      nano81Data = emmParsed;
722    } else if (emmParsed[0]==0x91 && emmParsed[1]==0x08) {
723      nano91Data = emmParsed;
724    } else if (emmParsed[0]==0x92 && emmParsed[1]==0x08) {
725      nano92Data = emmParsed;
726    } else if (emmParsed[0]==0xF0 && emmParsed[1]==0x08) {
727      nanoF0Data = emmParsed;
728    } else {
729      /* other nanos */
730      show_subs(reader, emmParsed);
731   
732      memcpy(ins18Data+ins18Len, emmParsed, emmParsed[1] + 2);
733      ins18Len += emmParsed [1] + 2;
734    }
735  }
736
737  if (!provider_ok) {
738    cs_debug_mask(D_READER, "[viaccess-reader] provider not found in emm, continue anyway");
739    // force key to 1...
740    keynr = 1;
741    ///return ERROR;
742  }
743
744  if (!nanoF0Data) {
745    cs_dump(ep->emm, ep->l, "can't find 0xf0 in emm...");
746    return ERROR; // error
747  }
748
749  if (nano9EData) {
750    if (!nano91Data) {
751      // set adf
752      insf0[3] = keynr;  // key
753      insf0[4] = nano9EData[1] + 2;
754      write_cmd(insf0, nano9EData); 
755      if( cta_res[cta_lr-2]!=0x90 || cta_res[cta_lr-1]!=0x00 ) {
756        cs_dump(insf0, 5, "set adf cmd:");
757        cs_dump(nano9EData, insf0[4] , "set adf data:");
758        cs_log("[viaccess-reader] update error: %02X %02X", cta_res[cta_lr-2], cta_res[cta_lr-1]);
759        return ERROR;
760      }
761    } else {
762      // set adf crypte
763      insf4[3] = keynr;  // key
764      insf4[4] = nano91Data[1] + 2 + nano9EData[1] + 2;
765      memcpy (insData, nano91Data, nano91Data[1] + 2);
766      memcpy (insData + nano91Data[1] + 2, nano9EData, nano9EData[1] + 2);
767      write_cmd(insf4, insData); 
768      if(( cta_res[cta_lr-2]!=0x90 && cta_res[cta_lr-2]!=0x91) || cta_res[cta_lr-1]!=0x00 ) {
769        cs_dump(insf4, 5, "set adf encrypted cmd:");
770        cs_dump(insData, insf4[4], "set adf encrypted data:");
771        cs_log("[viaccess-reader] update error: %02X %02X", cta_res[cta_lr-2], cta_res[cta_lr-1]);
772        return ERROR;
773      }
774    }
775  }
776
777  if (!nano92Data) {
778    // send subscription
779    ins18[2] = nano9EData ? 0x01: 0x00; // found 9E nano ?
780    ins18[3] = keynr;  // key
781    ins18[4] = ins18Len + nanoF0Data[1] + 2;
782    memcpy (insData, ins18Data, ins18Len);
783    memcpy (insData + ins18Len, nanoF0Data, nanoF0Data[1] + 2);
784    write_cmd(ins18, insData);
785    if( (cta_res[cta_lr-2]==0x90 || cta_res[cta_lr-2]==0x91) && cta_res[cta_lr-1]==0x00 ) {
786      cs_debug_mask(D_READER, "[viaccess-reader] update successfully written");
787      rc=1; // written
788    } else {
789      cs_dump(ins18, 5, "set subscription cmd:");
790      cs_dump(insData, ins18[4], "set subscription data:");
791      cs_log("[viaccess-reader] update error: %02X %02X", cta_res[cta_lr-2], cta_res[cta_lr-1]);
792    }
793   
794  } else {
795    // send subscription encrypted
796
797    if (!nano81Data) {
798      cs_dump(ep->emm, ep->l, "0x92 found, but can't find 0x81 in emm...");
799      return ERROR; // error
800    }
801
802    ins1c[2] = nano9EData ? 0x01: 0x00; // found 9E nano ?
803    if (ep->type == UNIQUE) ins1c[2] = 0x02;
804    ins1c[3] = keynr;  // key
805    ins1c[4] = nano92Data[1] + 2 + nano81Data[1] + 2 + nanoF0Data[1] + 2;
806    memcpy (insData, nano92Data, nano92Data[1] + 2);
807    memcpy (insData + nano92Data[1] + 2, nano81Data, nano81Data[1] + 2);
808    memcpy (insData + nano92Data[1] + 2 + nano81Data[1] + 2, nanoF0Data, nanoF0Data[1] + 2);
809    write_cmd(ins1c, insData); 
810   
811    if( (cta_res[cta_lr-2]==0x90 && cta_res[cta_lr-1]==0x00) ) {
812        cs_log("[viaccess-reader] update successfully written");
813        rc=1; // written
814    } 
815    else {
816        if( cta_res[cta_lr-2]&0x1 )
817            cs_log("[viaccess-reader] update not written. Data already exists or unknown address");
818   
819        //if( cta_res[cta_lr-2]&0x8 ) {
820            write_cmd(insc8, NULL);
821            if( (cta_res[cta_lr-2]==0x90 && cta_res[cta_lr-1]==0x00) ) {
822                cs_log("[viaccess-reader] extended status  %02X %02X", cta_res[0], cta_res[1]);
823            }
824        //}
825      return ERROR;
826    }
827
828  }
829
830  /*
831  Sub Main()
832    Sc.Write("CA A4 04 00 03")
833    RX
834    Sc.Write("02 07 11")
835    RX
836    Sc.Write("CA F0 00 01 22")
837    RX
838    Sc.Write("9E 20")
839    Sc.Write("10 10 08 8A 80 00 04 00 10 10 26 E8 54 80 1E 80")
840    Sc.Write("00 01 00 00 00 00 00 50 00 00 80 02 22 00 08 50")
841    RX
842    Sc.Write("CA 18 01 01 11")
843    RX
844    Sc.Write("A9 05 34 DE 34 FF 80")
845    Sc.Write("F0 08 1A 3E AF B5 2B EE E3 3B")
846    RX
847
848    End Sub
849*/
850  return rc;
851}
852
853static int32_t viaccess_card_info(struct s_reader * reader)
854{
855  def_resp;
856  int32_t i, l, scls, show_cls;
857  uchar insac[] = { 0xca, 0xac, 0x00, 0x00, 0x00 }; // select data
858  uchar insb8[] = { 0xca, 0xb8, 0x00, 0x00, 0x00 }; // read selected data
859  uchar insa4[] = { 0xca, 0xa4, 0x00, 0x00, 0x00 }; // select issuer
860  uchar insc0[] = { 0xca, 0xc0, 0x00, 0x00, 0x00 }; // read data item
861  static const uchar ins24[] = { 0xca, 0x24, 0x00, 0x00, 0x09 }; // set pin
862
863  static const uchar cls[] = { 0x00, 0x21, 0xff, 0x9f};
864  static const uchar pin[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04};
865
866  show_cls=reader->show_cls;
867  reader->last_geo.provid  = 0;
868  reader->last_geo.geo_len = 0;
869  reader->last_geo.geo[0]  = 0;
870
871  cs_log("[viaccess-reader] card detected"); 
872 
873  // set pin
874  write_cmd(ins24, pin);
875
876  insac[2]=0xa4; write_cmd(insac, NULL); // request unique id
877  insb8[4]=0x07; write_cmd(insb8, NULL); // read unique id
878  cs_log("[viaccess-reader] serial: %llu", b2ll(5, cta_res+2));
879
880  scls=0;
881  insa4[2]=0x00; write_cmd(insa4, NULL); // select issuer 0
882  for (i=1; (cta_res[cta_lr-2]==0x90) && (cta_res[cta_lr-1]==0); i++)
883  {
884    uint32_t l_provid, l_sa;
885    uchar l_name[64];
886    insc0[4]=0x1a; write_cmd(insc0, NULL); // show provider properties
887    cta_res[2]&=0xF0;
888    l_provid=b2i(3, cta_res);
889
890    insac[2]=0xa5; write_cmd(insac, NULL); // request sa
891    insb8[4]=0x06; write_cmd(insb8, NULL); // read sa
892    l_sa=b2i(4, cta_res+2);
893
894    insac[2]=0xa7; write_cmd(insac, NULL); // request name
895    insb8[4]=0x02; write_cmd(insb8, NULL); // read name nano + len
896    l=cta_res[1];
897    insb8[4]=l; write_cmd(insb8, NULL); // read name
898    cta_res[l]=0;
899    trim((char *)cta_res);
900    if (cta_res[0])
901      snprintf((char *)l_name, sizeof(l_name), ", name: %s", cta_res);
902    else
903      l_name[0]=0;
904
905    // read GEO
906    insac[2]=0xa6; write_cmd(insac, NULL); // request GEO
907    insb8[4]=0x02; write_cmd(insb8, NULL); // read GEO nano + len
908    l=cta_res[1];
909    insb8[4]=l; write_cmd(insb8, NULL); // read geo
910    cs_ri_log(reader, "provider: %d, id: %06X%s, sa: %08X, geo: %s",
911           i, l_provid, l_name, l_sa, (l<4) ? "empty" : cs_hexdump(1, cta_res, l));
912
913    // read classes subscription
914    insac[2]=0xa9; insac[4]=4;
915    write_cmd(insac, cls); // request class subs
916    scls=0;
917    while( (cta_res[cta_lr-2]==0x90) && (cta_res[cta_lr-1]==0) )
918    {
919      insb8[4]=0x02; write_cmd(insb8, NULL); // read class subs nano + len
920      if( (cta_res[cta_lr-2]==0x90) && (cta_res[cta_lr-1]==0) )
921      {
922        int32_t fshow;
923        l=cta_res[1];
924        //fshow=(client[cs_idx].dbglvl==D_DUMP)?1:(scls < show_cls)?1:0;
925        fshow=(scls<show_cls);
926        insb8[4]=l; write_cmd(insb8, NULL); // read class subs
927        if( (cta_res[cta_lr-2]==0x90) && (fshow) && 
928            (cta_res[cta_lr-1]==0x00 || cta_res[cta_lr-1]==0x08) )
929        {
930          show_class(reader, NULL, cta_res, cta_lr-2);
931          scls++;
932        }
933      }
934    }
935
936    insac[4]=0;
937    insa4[2]=0x02; 
938    write_cmd(insa4, NULL); // select next provider
939  }
940  //return ERROR;
941  return OK;
942}
943
944#ifdef HAVE_DVBAPI
945void dvbapi_sort_nanos(unsigned char *dest, const unsigned char *src, int32_t len);
946
947int32_t viaccess_reassemble_emm(uchar *buffer, uint32_t *len) {
948    static uchar emm_global[512];
949    static int32_t emm_global_len = 0;
950
951    int32_t pos=0, i;
952    uint32_t k;
953
954    // Viaccess
955    if (*len>500) return 0;
956
957    switch(buffer[0]) {
958        case 0x8c:
959        case 0x8d:
960            // emm-s part 1
961            if (!memcmp(emm_global, buffer, *len))
962                return 0;
963
964            // copy first part of the emm-s
965            memcpy(emm_global, buffer, *len);
966            emm_global_len=*len;
967            //cs_ddump_mask(D_READER, buffer, len, "viaccess global emm:");
968            return 0;
969                   
970        case 0x8e:
971            // emm-s part 2
972            if (!emm_global_len) return 0;
973
974            //extract nanos from emm-gh and emm-s
975            uchar emmbuf[512];
976
977            cs_debug_mask(D_DVBAPI, "viaccess_reassemble_emm: start extracting nanos");
978            //extract from emm-gh
979            for (i=3; i<emm_global_len; i+=emm_global[i+1]+2) {
980                //copy nano (length determined by i+1)
981                memcpy(emmbuf+pos, emm_global+i, emm_global[i+1]+2);
982                pos+=emm_global[i+1]+2;
983            }
984           
985            if (buffer[2]==0x2c) { 
986                //add 9E 20 nano + first 32 bytes of emm content
987                memcpy(emmbuf+pos, "\x9E\x20", 2);
988                memcpy(emmbuf+pos+2, buffer+7, 32);
989                pos+=34;
990
991                //add F0 08 nano + 8 subsequent bytes of emm content
992                memcpy(emmbuf+pos, "\xF0\x08", 2);
993                memcpy(emmbuf+pos+2, buffer+39, 8);
994                pos+=10;
995            } else {
996                //extract from variable emm-s
997                for (k=7; k<(*len); k+=buffer[k+1]+2) {
998                    //copy nano (length determined by k+1)
999                    memcpy(emmbuf+pos, buffer+k, buffer[k+1]+2);
1000                    pos+=buffer[k+1]+2;
1001                }
1002            }
1003
1004            cs_ddump_mask(D_DVBAPI, buffer, *len, "viaccess_reassemble_emm: %s emm-s", (buffer[2]==0x2c) ? "fixed" : "variable");
1005
1006            dvbapi_sort_nanos(buffer+7, emmbuf, pos);
1007            pos+=7;
1008
1009            //calculate emm length and set it on position 2
1010            buffer[2]=pos-3;
1011
1012            cs_ddump_mask(D_DVBAPI, emm_global, emm_global_len, "viaccess_reassemble_emm: emm-gh");
1013            cs_ddump_mask(D_DVBAPI, buffer, pos, "viaccess_reassemble_emm: assembled emm");
1014
1015            *len=pos;
1016            break;
1017    }
1018    return 1;
1019}
1020#endif
1021
1022void reader_viaccess(struct s_cardsystem *ph) 
1023{
1024    ph->do_emm=viaccess_do_emm;
1025    ph->do_ecm=viaccess_do_ecm;
1026    ph->card_info=viaccess_card_info;
1027    ph->card_init=viaccess_card_init;
1028    ph->get_emm_type=viaccess_get_emm_type;
1029    ph->get_emm_filter=viaccess_get_emm_filter;
1030    ph->caids[0]=0x05;
1031    ph->desc="viaccess";
1032}
Note: See TracBrowser for help on using the repository browser.