source: trunk/reader-videoguard2.c @ 473

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

Optimization of write_card routines + related bugfix in viaccess_do_emm

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