source: trunk/reader-videoguard2.c @ 495

Last change on this file since 495 was 495, checked in by dingo35, 10 years ago

Sky Italia fix, many thanks to Sifteam and Pynkyz

File size: 24.9 KB
Line 
1#include "globals.h"
2#include "reader-common.h"
3
4#include <termios.h>
5#include <unistd.h>
6#ifdef OS_LINUX
7#include <linux/serial.h>
8#endif
9
10#define MAX_ATR_LEN 33         // max. ATR length
11#define MAX_HIST    15         // max. number of historical characters
12
13//////  ====================================================================================
14
15int aes_active=0;
16AES_KEY dkey, ekey;
17
18static void cAES_SetKey(const unsigned char *key)
19{
20  AES_set_decrypt_key(key,128,&dkey);
21  AES_set_encrypt_key(key,128,&ekey);
22  aes_active=1;
23}
24
25static int cAES_Encrypt(const unsigned char *data, int len, unsigned char *crypt)
26{
27  if(aes_active) {
28    len=(len+15)&(~15); // pad up to a multiple of 16
29    int i;
30    for(i=0; i<len; i+=16) AES_encrypt(data+i,crypt+i,(const AES_KEY *)&ekey);
31    return len;
32    }
33  return -1;
34}
35
36//////  ====================================================================================
37
38// SIFTEAM funzione per cambio endianness
39static void swap_lb (unsigned char *buff, int len)
40{
41
42#if __BYTE_ORDER != __BIG_ENDIAN
43  return;
44
45#endif /*  */
46  int i;
47  unsigned short *tmp;
48  for (i = 0; i < len / 2; i++) {
49    tmp = (unsigned short *) buff + i;
50    *tmp = ((*tmp << 8) & 0xff00) | ((*tmp >> 8) & 0x00ff);
51  }
52} 
53
54static inline void __xxor(unsigned char *data, int len, const unsigned char *v1, const unsigned char *v2)
55{
56  switch(len) { // looks ugly, but the compiler can optimize it very well ;)
57    case 16:
58      *((unsigned int *)data+3) = *((unsigned int *)v1+3) ^ *((unsigned int *)v2+3);
59      *((unsigned int *)data+2) = *((unsigned int *)v1+2) ^ *((unsigned int *)v2+2);
60    case 8:
61      *((unsigned int *)data+1) = *((unsigned int *)v1+1) ^ *((unsigned int *)v2+1);
62    case 4:
63      *((unsigned int *)data+0) = *((unsigned int *)v1+0) ^ *((unsigned int *)v2+0);
64      break;
65    default:
66      while(len--) *data++ = *v1++ ^ *v2++;
67      break;
68    }
69}
70#define xor16(v1,v2,d) __xxor((d),16,(v1),(v2))
71#define val_by2on3(x)  ((0xaaab*(x))>>16) //fixed point *2/3
72
73unsigned short cardkeys[3][32];
74unsigned char stateD3A[16];
75
76static void cCamCryptVG2_LongMult(unsigned short *pData, unsigned short *pLen, unsigned int mult, unsigned int carry);
77static void cCamCryptVG2_PartialMod(unsigned short val, unsigned int count, unsigned short *outkey, const unsigned short *inkey);
78static void cCamCryptVG2_RotateRightAndHash(unsigned char *p);
79static void cCamCryptVG2_Reorder16A(unsigned char *dest, const unsigned char *src);
80static void cCamCryptVG2_ReorderAndEncrypt(unsigned char *p);
81static void cCamCryptVG2_Process_D0(const unsigned char *ins, unsigned char *data, const unsigned char *status);
82static void cCamCryptVG2_Process_D1(const unsigned char *ins, unsigned char *data, const unsigned char *status);
83static void cCamCryptVG2_Decrypt_D3(unsigned char *ins, unsigned char *data, const unsigned char *status);
84static void cCamCryptVG2_PostProcess_Decrypt(unsigned char *buff, int len, unsigned char *cw1, unsigned char *cw2);
85static void cCamCryptVG2_SetSeed(unsigned char *Key1, unsigned char *Key2);
86static void cCamCryptVG2_GetCamKey(unsigned char *buff);
87
88static void cCamCryptVG2_SetSeed(unsigned char *Key1, unsigned char *Key2)
89{
90  swap_lb (Key1, 64);
91  swap_lb (Key2, 64);
92  memcpy(cardkeys[1],Key1,sizeof(cardkeys[1]));
93  memcpy(cardkeys[2],Key2,sizeof(cardkeys[2]));
94  swap_lb (Key1, 64);
95  swap_lb (Key2, 64);
96}
97
98static void cCamCryptVG2_GetCamKey(unsigned char *buff)
99{
100  unsigned short *tb2=(unsigned short *)buff, c=1;
101  memset(tb2,0,64);
102  tb2[0]=1;
103  int i;
104  for(i=0; i<32; i++) cCamCryptVG2_LongMult(tb2,&c,cardkeys[1][i],0);
105  swap_lb (buff, 64);
106}
107
108static void cCamCryptVG2_PostProcess_Decrypt(unsigned char *buff, int len, unsigned char *cw1, unsigned char *cw2)
109{
110  switch(buff[0]) {
111    case 0xD0:
112      cCamCryptVG2_Process_D0(buff,buff+5,buff+buff[4]+5);
113      break;
114    case 0xD1:
115      cCamCryptVG2_Process_D1(buff,buff+5,buff+buff[4]+5);
116      break;
117    case 0xD3:
118      cCamCryptVG2_Decrypt_D3(buff,buff+5,buff+buff[4]+5);
119      if(buff[1]==0x54) {
120        memcpy(cw1,buff+5,8);
121        int ind;
122        for(ind=14; ind<len+5;) {
123          if(buff[ind]==0x25) {
124            memcpy(cw2,buff+5+ind+2,8);
125            break;
126            }
127          if(buff[ind+1]==0) break;
128          ind+=buff[ind+1];
129          }
130        }
131      break;
132    }
133}
134
135static void cCamCryptVG2_Process_D0(const unsigned char *ins, unsigned char *data, const unsigned char *status)
136{
137  switch(ins[1]) {
138    case 0xb4:
139      swap_lb (data, 64);
140      memcpy(cardkeys[0],data,sizeof(cardkeys[0]));
141      break;
142    case 0xbc: 
143      {
144      swap_lb (data, 64);
145      unsigned short *idata=(unsigned short *)data;
146      const unsigned short *key1=(const unsigned short *)cardkeys[1];
147      unsigned short key2[32];
148      memcpy(key2,cardkeys[2],sizeof(key2));
149      int count2;
150      for(count2=0; count2<32; count2++) {
151        unsigned int rem=0, div=key1[count2];
152        int i;
153        for(i=31; i>=0; i--) {
154          unsigned int x=idata[i] | (rem<<16);
155          rem=(x%div)&0xffff;
156          }
157        unsigned int carry=1, t=val_by2on3(div) | 1;
158        while(t) {
159          if(t&1) carry=((carry*rem)%div)&0xffff;
160          rem=((rem*rem)%div)&0xffff;
161          t>>=1;
162          }
163        cCamCryptVG2_PartialMod(carry,count2,key2,key1);
164        }
165      unsigned short idatacount=0;
166      int i;
167      for(i=31; i>=0; i--) cCamCryptVG2_LongMult(idata,&idatacount,key1[i],key2[i]);
168      swap_lb (data, 64);
169      unsigned char stateD1[16];
170      cCamCryptVG2_Reorder16A(stateD1,data);
171      cAES_SetKey(stateD1);
172      break;
173      }
174  }
175}
176
177static void cCamCryptVG2_Process_D1(const unsigned char *ins, unsigned char *data, const unsigned char *status)
178{
179  unsigned char iter[16], tmp[16];
180  memset(iter,0,sizeof(iter));
181  memcpy(iter,ins,5);
182  xor16(iter,stateD3A,iter);
183  memcpy(stateD3A,iter,sizeof(iter));
184
185  int datalen=status-data;
186  int datalen1=datalen;
187  if(datalen<0) datalen1+=15;
188  int blocklen=datalen1>>4;
189  int i;
190  int iblock;
191  for(i=0,iblock=0; i<blocklen+2; i++,iblock+=16) {
192    unsigned char in[16];
193    int docalc=1;
194    if(blocklen==i && (docalc=datalen&0xf)) {
195      memset(in,0,sizeof(in));
196      memcpy(in,&data[iblock],datalen-(datalen1&~0xf));
197      }
198    else if(blocklen+1==i) {
199      memset(in,0,sizeof(in));
200      memcpy(&in[5],status,2);
201      }
202    else
203      memcpy(in,&data[iblock],sizeof(in));
204
205    if(docalc) {
206      xor16(iter,in,tmp);
207      cCamCryptVG2_ReorderAndEncrypt(tmp);
208      xor16(tmp,stateD3A,iter);
209      }
210    }
211  memcpy(stateD3A,tmp,16);
212}
213
214static void cCamCryptVG2_Decrypt_D3(unsigned char *ins, unsigned char *data, const unsigned char *status)
215{
216  if(ins[4]>16) ins[4]-=16;
217  if(ins[1]==0xbe) memset(stateD3A,0,sizeof(stateD3A));
218
219  unsigned char tmp[16];
220  memset(tmp,0,sizeof(tmp));
221  memcpy(tmp,ins,5);
222  xor16(tmp,stateD3A,stateD3A);
223
224  int len1=ins[4];
225  int blocklen=len1>>4;
226  if(ins[1]!=0xbe) blocklen++;
227
228  unsigned char iter[16], states[16][16];
229  memset(iter,0,sizeof(iter));
230  int blockindex;
231  for(blockindex=0; blockindex<blocklen; blockindex++) {
232    iter[0]+=blockindex;
233    xor16(iter,stateD3A,iter);
234    cCamCryptVG2_ReorderAndEncrypt(iter);
235    xor16(iter,&data[blockindex*16],states[blockindex]);
236    if(blockindex==(len1>>4)) {
237      int c=len1-(blockindex*16);
238      if(c<16) memset(&states[blockindex][c],0,16-c);
239      }
240    xor16(states[blockindex],stateD3A,stateD3A);
241    cCamCryptVG2_RotateRightAndHash(stateD3A);
242    }
243  memset(tmp,0,sizeof(tmp));
244  memcpy(tmp+5,status,2);
245  xor16(tmp,stateD3A,stateD3A);
246  cCamCryptVG2_ReorderAndEncrypt(stateD3A);
247
248  memcpy(stateD3A,status-16,sizeof(stateD3A));
249  cCamCryptVG2_ReorderAndEncrypt(stateD3A);
250
251  memcpy(data,states[0],len1);
252  if(ins[1]==0xbe) {
253    cCamCryptVG2_Reorder16A(tmp,states[0]);
254    cAES_SetKey(tmp);
255    }
256}
257
258static void cCamCryptVG2_ReorderAndEncrypt(unsigned char *p)
259{
260  unsigned char tmp[16];
261  cCamCryptVG2_Reorder16A(tmp,p);
262  cAES_Encrypt(tmp,16,tmp);
263  cCamCryptVG2_Reorder16A(p,tmp);
264}
265
266// reorder AAAABBBBCCCCDDDD to ABCDABCDABCDABCD
267
268static void cCamCryptVG2_Reorder16A(unsigned char *dest, const unsigned char *src)
269{
270  int i;
271  int j;
272  int k;
273  for(i=0,k=0; i<4; i++)
274    for(j=i; j<16; j+=4,k++)
275      dest[k]=src[j];
276}
277
278static void cCamCryptVG2_LongMult(unsigned short *pData, unsigned short *pLen, unsigned int mult, unsigned int carry)
279{
280  int i;
281  for(i=0; i<*pLen; i++) {
282    carry+=pData[i]*mult;
283    pData[i]=(unsigned short)carry;
284    carry>>=16;
285    }
286  if(carry) pData[(*pLen)++]=carry;
287}
288
289static void cCamCryptVG2_PartialMod(unsigned short val, unsigned int count, unsigned short *outkey, const unsigned short *inkey)
290{
291  if(count) {
292    unsigned int mod=inkey[count];
293    unsigned short mult=(inkey[count]-outkey[count-1])&0xffff;
294    unsigned int i;
295    unsigned int ib1;
296    for(i=0,ib1=count-2; i<count-1; i++,ib1--) {
297      unsigned int t=(inkey[ib1]*mult)%mod;
298      mult=t-outkey[ib1];
299      if(mult>t) mult+=mod;
300      }
301    mult+=val;
302    if((val>mult) || (mod<mult)) mult-=mod;
303    outkey[count]=(outkey[count]*mult)%mod;
304    }
305  else 
306    outkey[0]=val;
307}
308
309static const unsigned char table1[256] = {
310  0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5, 0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76,
311  0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0, 0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0,
312  0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc, 0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15,
313  0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a, 0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75,
314  0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0, 0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84,
315  0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b, 0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf,
316  0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85, 0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8,
317  0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5, 0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2,
318  0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17, 0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73,
319  0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88, 0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb,
320  0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c, 0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79,
321  0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9, 0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08,
322  0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6, 0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a,
323  0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e, 0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e,
324  0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94, 0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf,
325  0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68, 0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16,
326  };
327
328static void cCamCryptVG2_RotateRightAndHash(unsigned char *p)
329{
330  unsigned char t1=p[15];
331  int i;
332  for(i=0; i<16; i++) {
333    unsigned char t2=t1;
334    t1=p[i]; p[i]=table1[(t1>>1)|((t2&1)<<7)];
335    }
336}
337
338//////  ====================================================================================
339
340static unsigned char CW1[8], CW2[8];
341
342extern uchar cta_cmd[], cta_res[];
343extern ushort cta_lr;
344
345extern int io_serial_need_dummy_char;
346
347struct CmdTabEntry {
348  unsigned char cla;
349  unsigned char cmd;
350  unsigned char len;
351  unsigned char mode;
352};
353
354struct CmdTab {
355  unsigned char index;
356  unsigned char size;
357  unsigned char Nentries;
358  unsigned char dummy;
359  struct CmdTabEntry e[1];
360};
361
362struct CmdTab *cmd_table=NULL;
363void memorize_cmd_table (const unsigned char *mem, int size){
364  cmd_table=(struct CmdTab *)malloc(sizeof(unsigned char) * size);
365  memcpy(cmd_table,mem,size);
366}
367
368int cmd_table_get_info(const unsigned char *cmd, unsigned char *rlen, unsigned char *rmode)
369{
370  struct CmdTabEntry *pcte=cmd_table->e;
371  int i;
372  for(i=0; i<cmd_table->Nentries; i++,pcte++)
373    if(cmd[1]==pcte->cmd) {
374      *rlen=pcte->len;
375      *rmode=pcte->mode;
376      return 1;
377      }
378  return 0;
379}
380
381static int status_ok(const unsigned char *status){
382    //cs_log("check status %02x%02x", status[0],status[1]);
383    return (status[0] == 0x90 || status[0] == 0x91)
384           && (status[1] == 0x00 || status[1] == 0x01
385               || status[1] == 0x20 || status[1] == 0x21
386               || status[1] == 0x80 || status[1] == 0x81
387               || status[1] == 0xa0 || status[1] == 0xa1);
388}
389
390#define write_cmd(cmd, data) (card_write(cmd, data) == 0)
391#define read_cmd(cmd, data) (card_write(cmd, NULL) == 0)
392
393static int read_cmd_len(const unsigned char *cmd) 
394{ 
395  unsigned char cmd2[5]; 
396  memcpy(cmd2,cmd,5); 
397  cmd2[3]=0x80; 
398  cmd2[4]=1; 
399  if(!read_cmd(cmd2,NULL) || cta_res[1] != 0x90 || cta_res[2] != 0x00) { 
400    cs_log("failed to read %02x%02x cmd length (%02x %02x)",cmd[1],cmd[2],cta_res[1],cta_res[2]); 
401    return -1;
402    } 
403  return cta_res[0];   
404}
405
406static int do_cmd(const unsigned char *ins, const unsigned char *txbuff, unsigned char *rxbuff)
407{
408  unsigned char ins2[5];
409  memcpy(ins2,ins,5);
410  unsigned char len=0, mode=0;
411  if(cmd_table_get_info(ins2,&len,&mode)) {
412    if(len==0xFF && mode==2) {
413      if(ins2[4]==0) ins2[4]=len=read_cmd_len(ins2);
414      }
415    else if(mode!=0) ins2[4]=len;
416    }
417  if(ins2[0]==0xd3) ins2[4]=len+16;
418  len=ins2[4];
419
420  unsigned char tmp[264];
421  if(!rxbuff) rxbuff=tmp;
422  if(mode>1) {
423    if(!read_cmd(ins2,NULL) || !status_ok(cta_res+len)) return -1;
424    memcpy(rxbuff,ins2,5);
425    memcpy(rxbuff+5,cta_res,len);
426    memcpy(rxbuff+5+len,cta_res+len,2);
427    }
428  else {
429    if(!write_cmd(ins2,txbuff) || !status_ok(cta_res)) return -2;
430    memcpy(rxbuff,ins2,5);
431    memcpy(rxbuff+5,txbuff,len);
432    memcpy(rxbuff+5+len,cta_res,2);
433    }
434
435  cCamCryptVG2_PostProcess_Decrypt(rxbuff,len,CW1,CW2);
436
437  // Log decrypted INS54
438  if (rxbuff[1] == 0x54) {
439    cs_dump (rxbuff, 5, "Decrypted INS54:");
440    cs_dump (rxbuff + 5, rxbuff[4], "");
441  }
442
443  return len;
444}
445
446#define BASEYEAR 1997
447static void rev_date_calc(const unsigned char *Date, int *year, int *mon, int *day, int *hh, int *mm, int *ss)
448{
449  *year=(Date[0]/12)+BASEYEAR;
450  *mon=(Date[0]%12)+1;
451  *day=Date[1];
452  *hh=Date[2]/8;
453  *mm=(0x100*(Date[2]-*hh*8)+Date[3])/32;
454  *ss=(Date[3]-*mm*32)*2;
455}
456
457static void read_tiers(void)
458{
459  static const unsigned char ins2a[5] = { 0xd0,0x2a,0x00,0x00,0x00 };
460  int l;
461  l=do_cmd(ins2a,NULL,NULL);
462  if(l<0 || !status_ok(cta_res+l)) return;
463  static unsigned char ins76[5] = { 0xd0,0x76,0x00,0x00,0x00 };
464  ins76[3]=0x7f; ins76[4]=2;
465  if(!read_cmd(ins76,NULL) || !status_ok(cta_res+2)) return;
466  ins76[3]=0; ins76[4]=0;
467  int num=cta_res[1];
468  int i;
469  for(i=0; i<num; i++) {
470    ins76[2]=i;
471    l=do_cmd(ins76,NULL,NULL);
472    if(l<0 || !status_ok(cta_res+l)) return;
473    if(cta_res[2]==0 && cta_res[3]==0) break;
474    int y,m,d,H,M,S;
475    rev_date_calc(&cta_res[4],&y,&m,&d,&H,&M,&S);
476    cs_log("Tier: %02x%02x, expiry date: %04d/%02d/%02d-%02d:%02d:%02d",cta_res[2],cta_res[3],y,m,d,H,M,S);
477    }
478}
479
480int videoguard_card_init(uchar *atr, int atrsize)
481{
482  /* known atrs */
483  unsigned char atr_bskyb[] = { 0x3F, 0x7F, 0x13, 0x25, 0x03, 0x33, 0xB0, 0x06, 0x69, 0xFF, 0x4A, 0x50, 0xD0, 0x00, 0x00, 0x53, 0x59, 0x00, 0x00, 0x00 };
484  unsigned char atr_bskyb_new[] = { 0x3F, 0xFD, 0x13, 0x25, 0x02, 0x50, 0x00, 0x0F, 0x33, 0xB0, 0x0F, 0x69, 0xFF, 0x4A, 0x50, 0xD0, 0x00, 0x00, 0x53, 0x59, 0x02 };
485  unsigned char atr_skyitalia[] = { 0x3F, 0xFF, 0x13, 0x25, 0x03, 0x10, 0x80, 0x33, 0xB0, 0x0E, 0x69, 0xFF, 0x4A, 0x50, 0x70, 0x00, 0x00, 0x49, 0x54, 0x02, 0x00, 0x00 };
486  unsigned char atr_skyitalia93b[] = { 0x3F, 0xFD, 0x13, 0x25, 0x02, 0x50, 0x80, 0x0F, 0x33, 0xB0, 0x13, 0x69, 0xFF, 0x4A, 0x50, 0xD0, 0x80, 0x00, 0x49, 0x54, 0x03 };
487  unsigned char atr_directv[] = { 0x3F, 0x78, 0x13, 0x25, 0x03, 0x40, 0xB0, 0x20, 0xFF, 0xFF, 0x4A, 0x50, 0x00 };
488  unsigned char atr_yes[] = { 0x3F, 0xFF, 0x13, 0x25, 0x03, 0x10, 0x80, 0x33, 0xB0, 0x11, 0x69, 0xFF, 0x4A, 0x50, 0x50, 0x00, 0x00, 0x47, 0x54, 0x01, 0x00, 0x00 };
489  unsigned char atr_viasat_new[] = { 0x3F, 0x7D, 0x11, 0x25, 0x02, 0x41, 0xB0, 0x03, 0x69, 0xFF, 0x4A, 0x50, 0xF0, 0x80, 0x00, 0x56, 0x54, 0x03};
490
491    if ((atrsize == sizeof (atr_bskyb)) && (memcmp (atr, atr_bskyb, atrsize) == 0))
492    {
493        cs_log("Type: Videoguard BSkyB");
494        /* BSkyB seems to need one additionnal byte in the serial communication... */
495        io_serial_need_dummy_char = 1;
496    }
497    else if ((atrsize == sizeof (atr_bskyb_new)) && (memcmp (atr, atr_bskyb_new, atrsize) == 0))
498    {
499        cs_log("Type: Videoguard BSkyB - New");
500    }
501    else if ((atrsize == sizeof (atr_skyitalia)) && (memcmp (atr, atr_skyitalia, atrsize) == 0))
502    {
503        cs_log("Type: Videoguard Sky Italia");
504    }
505    else if ((atrsize == sizeof (atr_directv)) && (memcmp (atr, atr_directv, atrsize) == 0))
506    {
507        cs_log("Type: Videoguard DirecTV");
508    }
509    else if ((atrsize == sizeof (atr_yes)) && (memcmp (atr, atr_yes, atrsize) == 0))
510    {
511        cs_log("Type: Videoguard YES DBS Israel");
512    }
513    else if ((atrsize == sizeof (atr_viasat_new)) && (memcmp (atr, atr_viasat_new, atrsize) == 0))
514    {
515        cs_log("Type: Videoguard Viasat new (093E)");
516    }
517    else if ((atrsize == sizeof (atr_skyitalia93b)) && (memcmp (atr, atr_skyitalia93b, atrsize) == 0))
518    {
519        cs_log("Type: Videoguard Sky Italia new (093B)");
520    }
521    else
522    {
523        /* not a known videoguard */
524        return (0);
525    }
526
527#ifdef OS_LINUX
528if (reader[ridx].typ != R_INTERN) {
529  int bconst=B38400;
530  int baud=64516;
531  int fd=open(reader[ridx].device,O_RDWR|O_NONBLOCK|O_NOCTTY);
532
533  struct termios tio;
534  memset(&tio,0,sizeof(tio));
535  tio.c_cflag = (CS8 | CREAD | HUPCL | CLOCAL);
536  tio.c_cflag |= CSTOPB;
537  tio.c_iflag = (INPCK | BRKINT);
538  tio.c_cc[VMIN] = 1;
539  cfsetispeed(&tio,bconst);
540  cfsetospeed(&tio,bconst);
541  tio.c_cflag |= (PARENB | PARODD);
542
543  struct serial_struct s;
544  if(ioctl(fd,TIOCGSERIAL,&s)<0) {
545    cs_log("%s: get serial failed: %s",reader[ridx].device,strerror(errno));
546    return 0;
547    }
548  if(!tcsetattr(fd,TCSANOW,&tio)) {
549      if (reader[ridx].custom_speed) {
550        s.custom_divisor=(s.baud_base+(baud/2))/baud;
551        s.flags=(s.flags&~ASYNC_SPD_MASK) | ASYNC_SPD_CUST;
552        cs_log ("%s: custom: baud_base=%d baud=%d divisor=%d -> effective baudrate %d (%+.2f%% off)",
553                reader[ridx].device,s.baud_base,baud,s.custom_divisor,s.baud_base/s.custom_divisor,
554                (float)(s.baud_base/s.custom_divisor-baud)/(float)baud);
555      } else {
556        s.flags &= ~ASYNC_SPD_CUST;
557        cs_log ("%s: baud=%d", reader[ridx].device, 38400);
558        }
559      if(ioctl(fd,TIOCSSERIAL,&s)<0) {
560        cs_log ("%s: set serial failed: %s",reader[ridx].device,strerror(errno));
561        return 0;
562        }
563      }
564  else {
565    cs_log ("%s: tcsetattr failed: %s",reader[ridx].device,strerror(errno));
566    return 0;
567    }
568}
569#endif
570
571  unsigned char ins7401[5] = { 0xD0,0x74,0x01,0x00,0x00 };
572  int l;
573  if((l=read_cmd_len(ins7401))<0) return 0;
574  ins7401[4]=l;
575  if(!read_cmd(ins7401,NULL) || !status_ok(cta_res+l)) {
576    cs_log ("failed to read cmd list");
577    return 0;
578    }
579  memorize_cmd_table (cta_res,l);
580
581  unsigned char buff[256];
582
583  unsigned char ins7416[5] = { 0xD0,0x74,0x16,0x00,0x00 };
584  if(do_cmd(ins7416, NULL, NULL)<0) {
585    cs_log ("cmd 7416 failed");
586    return 0;
587    }
588
589  unsigned char ins36[5] = { 0xD0,0x36,0x00,0x00,0x00 };
590  unsigned char boxID [4];
591
592  if (reader[ridx].boxid > 0) {
593    /* the boxid is specified in the config */
594    int i;
595    for (i=0; i < 4; i++) {
596        boxID[i] = (reader[ridx].boxid >> (8 * (3 - i))) % 0x100;
597    }
598  } else {
599    /* we can try to get the boxid from the card */
600    int boxidOK=0;
601    l=do_cmd(ins36, NULL, buff);
602    if(l>=0) {
603      int i;
604      for(i=0; i<l ;i++) {
605        if(buff[i+1]==0xF3 && (buff[i]==0x00 || buff[i]==0x0A)) {
606          memcpy(&boxID,&buff[i+2],sizeof(boxID));
607          boxidOK=1;
608          break;
609          }
610        }
611      }
612
613    if(!boxidOK) {
614      cs_log ("no boxID available");
615      return 0;
616      }
617  }
618
619  unsigned char ins4C[5] = { 0xD0,0x4C,0x00,0x00,0x09 };
620  unsigned char payload4C[9] = { 0,0,0,0, 3,0,0,0,4 };
621  memcpy(payload4C,boxID,4);
622  if(!write_cmd(ins4C,payload4C) || !status_ok(cta_res+l)) {
623    cs_log("sending boxid failed");
624    return 0;
625    }
626
627  short int SWIRDstatus = cta_res[1];
628  unsigned char ins58[5] = { 0xD0,0x58,0x00,0x00,0x00 };
629  l=do_cmd(ins58, NULL, buff);
630  if(l<0) {
631    cs_log("cmd ins58 failed");
632    return 0;
633    }
634  memset(reader[ridx].hexserial, 0, 4);
635  memcpy(reader[ridx].hexserial+4, cta_res+3, 4);
636  reader[ridx].caid[0] = cta_res[24]*0x100+cta_res[25];
637
638  /* we have one provider, 0x0000 */
639  reader[ridx].nprov = 1;
640  memset(reader[ridx].prid, 0x00, sizeof(reader[ridx].prid));
641
642  /*
643  cs_log ("INS58 : Fuse byte=0x%02X, IRDStatus=0x%02X", cta_res[2],SWIRDstatus);
644  if (SWIRDstatus==4)  {
645  // If swMarriage=4, not married then exchange for BC Key
646  cs_log ("Card not married, exchange for BC Keys");
647   */
648
649  unsigned char seed1[] = {
650    0xb9, 0xd5, 0xef, 0xd5, 0xf5, 0xd5, 0xfb, 0xd5, 0x31, 0xd6, 0x43, 0xd6, 0x55, 0xd6, 0x61, 0xd6,
651    0x85, 0xd6, 0x9d, 0xd6, 0xaf, 0xd6, 0xc7, 0xd6, 0xd9, 0xd6, 0x09, 0xd7, 0x15, 0xd7, 0x21, 0xd7,
652    0x27, 0xd7, 0x3f, 0xd7, 0x45, 0xd7, 0xb1, 0xd7, 0xbd, 0xd7, 0xdb, 0xd7, 0x11, 0xd8, 0x23, 0xd8,
653    0x29, 0xd8, 0x2f, 0xd8, 0x4d, 0xd8, 0x8f, 0xd8, 0xa1, 0xd8, 0xad, 0xd8, 0xbf, 0xd8, 0xd7, 0xd8
654    };
655  unsigned char seed2[] = {
656    0x01, 0x00, 0xcf, 0x13, 0xe0, 0x60, 0x54, 0xac, 0xab, 0x99, 0xe6, 0x0c, 0x9f, 0x5b, 0x91, 0xb9,
657    0x72, 0x72, 0x4d, 0x5b, 0x5f, 0xd3, 0xb7, 0x5b, 0x01, 0x4d, 0xef, 0x9e, 0x6b, 0x8a, 0xb9, 0xd1,
658    0xc9, 0x9f, 0xa1, 0x2a, 0x8d, 0x86, 0xb6, 0xd6, 0x39, 0xb4, 0x64, 0x65, 0x13, 0x77, 0xa1, 0x0a,
659    0x0c, 0xcf, 0xb4, 0x2b, 0x3a, 0x2f, 0xd2, 0x09, 0x92, 0x15, 0x40, 0x47, 0x66, 0x5c, 0xda, 0xc9
660    };
661  cCamCryptVG2_SetSeed(seed1,seed2);
662
663  unsigned char insB4[5] = { 0xD0,0xB4,0x00,0x00,0x40 };
664  unsigned char tbuff[64];
665  cCamCryptVG2_GetCamKey(tbuff);
666  l=do_cmd(insB4, tbuff, NULL);
667  if(l<0 || !status_ok(cta_res)) {
668    cs_log ("cmd D0B4 failed (%02X%02X)", cta_res[0], cta_res[1]);
669    return 0;
670    }
671
672  unsigned char insBC[5] = { 0xD0,0xBC,0x00,0x00,0x00 };
673  l=do_cmd(insBC, NULL, NULL);
674  if(l<0) {
675    cs_log("cmd D0BC failed");
676    return 0;
677    }
678
679  unsigned char insBE[5] = { 0xD3,0xBE,0x00,0x00,0x00 };
680  l=do_cmd(insBE, NULL, NULL);
681  if(l<0) {
682    cs_log("cmd D3BE failed");
683    return 0;
684    }
685
686  unsigned char ins58a[5] = { 0xD1,0x58,0x00,0x00,0x00 };
687  l=do_cmd(ins58a, NULL, NULL);
688  if(l<0) {
689    cs_log("cmd D158 failed");
690    return 0;
691    }
692
693  unsigned char ins4Ca[5] = { 0xD1,0x4C,0x00,0x00,0x00 };
694  l=do_cmd(ins4Ca,payload4C, NULL);
695  if(l<0 || !status_ok(cta_res)) {
696    cs_log("cmd D14Ca failed");
697    return 0;
698    }
699
700  cs_log("type: Videoguard, caid: %04X, serial: %02X%02X%02X%02X, BoxID: %02X%02X%02X%02X",
701         reader[ridx].caid[0],
702         reader[ridx].hexserial[4],reader[ridx].hexserial[5],reader[ridx].hexserial[6],reader[ridx].hexserial[7],
703         boxID[0],boxID[1],boxID[2],boxID[3]);
704
705  ///read_tiers();
706
707  cs_log("ready for requests");
708
709  return(1);
710}
711
712int videoguard_do_ecm(ECM_REQUEST *er)
713{
714  static unsigned char ins40[5] = { 0xD1,0x40,0x00,0x80,0xFF };
715  static const unsigned char ins54[5] = { 0xD3,0x54,0x00,0x00,0x00};
716  int posECMpart2=er->ecm[6]+7;
717  int lenECMpart2=er->ecm[posECMpart2]+1;
718  unsigned char tbuff[264];
719  tbuff[0]=0;
720  memcpy(&tbuff[1],&(er->ecm[posECMpart2+1]),lenECMpart2-1);
721  ins40[4]=lenECMpart2;
722  int l;
723  l = do_cmd(ins40,tbuff,NULL);
724  if(l>0 && status_ok(cta_res)) {
725    l = do_cmd(ins54,NULL,NULL);
726    if(l>0 && status_ok(cta_res+l)) {
727      if(er->ecm[0]&1) {
728        memcpy(er->cw+8,CW1,8);
729      } else {
730        memcpy(er->cw+0,CW1,8);
731        }
732      return 1;
733      }
734    }
735  return 0;
736}
737
738static unsigned int num_addr(const unsigned char *data)
739{
740  return ((data[3]&0x30)>>4)+1;
741}
742
743static int addr_mode(const unsigned char *data)
744{
745  switch(data[3]&0xC0) {
746    case 0x40: return 3;
747    case 0x80: return 2;
748    default:   return 0;
749    }
750}
751
752static const unsigned char * payload_addr(const unsigned char *data, const unsigned char *a)
753{
754  int s;
755  int l;
756  const unsigned char *ptr = NULL;
757
758  switch(addr_mode(data)) {
759    case 2: s=3; break;
760    case 3: s=4; break;
761    default: return NULL;
762    }
763
764  int position=-1;
765  for(l=0;l<num_addr(data);l++) {
766    if(!memcmp(&data[l*4+4],a+4,s)) {
767      position=l;
768      break;
769      }
770    }
771
772  /* skip header, the list of address, and the separator (the two 00 00) */
773  ptr = data+4+4*num_addr(data)+2;
774
775  /* skip optional 00 */
776  if (*ptr == 0x00) ptr++;
777
778  /* skip the 1st bitmap len */
779  ptr++;
780
781  /* check */
782  if (*ptr != 0x02) return NULL;
783
784  /* skip the 1st timestamp 02 00 or 02 06 xx aabbccdd yy */
785  ptr += 2 + ptr[1];
786
787  for(l=0;l<position;l++) {
788
789    /* skip the payload of the previous SA */
790    ptr += 1 + ptr [0];
791
792    /* skip optional 00 */
793    if (*ptr == 0x00) ptr++;
794
795    /* skip the bitmap len */
796    ptr++;
797
798    /* check */
799    if (*ptr != 0x02) return NULL;
800
801    /* skip the timestamp 02 00 or 02 06 xx aabbccdd yy */
802    ptr += 2 + ptr[1];
803    }
804
805  return ptr;
806}
807
808int videoguard_do_emm(EMM_PACKET *ep)
809{
810  unsigned char ins42[5] = { 0xD1,0x42,0x00,0x00,0xFF };
811  int rc=0;
812
813  const unsigned char *payload = payload_addr(ep->emm, reader[ridx].hexserial);
814  if (payload) {
815    ins42[4]=*payload;
816    int l = do_cmd(ins42,payload+1,NULL);
817    if(l>0 && status_ok(cta_res)) {
818      rc=1;
819      }
820
821    cs_log("EMM request return code : %02X%02X", cta_res[0], cta_res[1]);
822//cs_dump(ep->emm, 64, "EMM:");
823    if (status_ok (cta_res)) {
824      read_tiers();
825      }
826
827    }
828 
829  return(rc);
830}
831
832int videoguard_card_info(void)
833{
834  /* info is displayed in init, or when processing info */
835  cs_log("card detected");
836  cs_log("type: Videoguard" );
837  read_tiers ();
838  return(1);
839}
Note: See TracBrowser for help on using the repository browser.