Timeout patch
[oscam.git] / reader-videoguard2.c
blob78f140cace76d11e54862c8fac3a42d753637b41
1 #include "globals.h"
2 #include "reader-common.h"
4 #include <termios.h>
5 #include <unistd.h>
6 #include <linux/serial.h>
8 #define MAX_ATR_LEN 33 // max. ATR length
9 #define MAX_HIST 15 // max. number of historical characters
11 ////// ====================================================================================
13 int aes_active=0;
14 AES_KEY dkey, ekey;
16 static void cAES_SetKey(const unsigned char *key)
18 AES_set_decrypt_key(key,128,&dkey);
19 AES_set_encrypt_key(key,128,&ekey);
20 aes_active=1;
23 static int cAES_Encrypt(const unsigned char *data, int len, unsigned char *crypt)
25 if(aes_active) {
26 len=(len+15)&(~15); // pad up to a multiple of 16
27 int i;
28 for(i=0; i<len; i+=16) AES_encrypt(data+i,crypt+i,(const AES_KEY *)&ekey);
29 return len;
31 return -1;
34 ////// ====================================================================================
36 static inline void __xxor(unsigned char *data, int len, const unsigned char *v1, const unsigned char *v2)
38 switch(len) { // looks ugly, but the compiler can optimize it very well ;)
39 case 16:
40 *((unsigned int *)data+3) = *((unsigned int *)v1+3) ^ *((unsigned int *)v2+3);
41 *((unsigned int *)data+2) = *((unsigned int *)v1+2) ^ *((unsigned int *)v2+2);
42 case 8:
43 *((unsigned int *)data+1) = *((unsigned int *)v1+1) ^ *((unsigned int *)v2+1);
44 case 4:
45 *((unsigned int *)data+0) = *((unsigned int *)v1+0) ^ *((unsigned int *)v2+0);
46 break;
47 default:
48 while(len--) *data++ = *v1++ ^ *v2++;
49 break;
52 #define xor16(v1,v2,d) __xxor((d),16,(v1),(v2))
53 #define val_by2on3(x) ((0xaaab*(x))>>16) //fixed point *2/3
55 unsigned short cardkeys[3][32];
56 unsigned char stateD3A[16];
58 static void cCamCryptVG2_LongMult(unsigned short *pData, unsigned short *pLen, unsigned int mult, unsigned int carry);
59 static void cCamCryptVG2_PartialMod(unsigned short val, unsigned int count, unsigned short *outkey, const unsigned short *inkey);
60 static void cCamCryptVG2_RotateRightAndHash(unsigned char *p);
61 static void cCamCryptVG2_Reorder16A(unsigned char *dest, const unsigned char *src);
62 static void cCamCryptVG2_ReorderAndEncrypt(unsigned char *p);
63 static void cCamCryptVG2_Process_D0(const unsigned char *ins, unsigned char *data, const unsigned char *status);
64 static void cCamCryptVG2_Process_D1(const unsigned char *ins, unsigned char *data, const unsigned char *status);
65 static void cCamCryptVG2_Decrypt_D3(unsigned char *ins, unsigned char *data, const unsigned char *status);
66 static void cCamCryptVG2_PostProcess_Decrypt(unsigned char *buff, int len, unsigned char *cw1, unsigned char *cw2);
67 static void cCamCryptVG2_SetSeed(const unsigned char *Key1, const unsigned char *Key2);
68 static void cCamCryptVG2_GetCamKey(unsigned char *buff);
70 static void cCamCryptVG2_SetSeed(const unsigned char *Key1, const unsigned char *Key2)
72 memcpy(cardkeys[1],Key1,sizeof(cardkeys[1]));
73 memcpy(cardkeys[2],Key2,sizeof(cardkeys[2]));
76 static void cCamCryptVG2_GetCamKey(unsigned char *buff)
78 unsigned short *tb2=(unsigned short *)buff, c=1;
79 memset(tb2,0,64);
80 tb2[0]=1;
81 int i;
82 for(i=0; i<32; i++) cCamCryptVG2_LongMult(tb2,&c,cardkeys[1][i],0);
85 static void cCamCryptVG2_PostProcess_Decrypt(unsigned char *buff, int len, unsigned char *cw1, unsigned char *cw2)
87 switch(buff[0]) {
88 case 0xD0:
89 cCamCryptVG2_Process_D0(buff,buff+5,buff+buff[4]+5);
90 break;
91 case 0xD1:
92 cCamCryptVG2_Process_D1(buff,buff+5,buff+buff[4]+5);
93 break;
94 case 0xD3:
95 cCamCryptVG2_Decrypt_D3(buff,buff+5,buff+buff[4]+5);
96 if(buff[1]==0x54) {
97 memcpy(cw1,buff+5,8);
98 int ind;
99 for(ind=14; ind<len+5;) {
100 if(buff[ind]==0x25) {
101 memcpy(cw2,buff+5+ind+2,8);
102 break;
104 if(buff[ind+1]==0) break;
105 ind+=buff[ind+1];
108 break;
112 static void cCamCryptVG2_Process_D0(const unsigned char *ins, unsigned char *data, const unsigned char *status)
114 switch(ins[1]) {
115 case 0xb4:
116 memcpy(cardkeys[0],data,sizeof(cardkeys[0]));
117 break;
118 case 0xbc:
120 unsigned short *idata=(unsigned short *)data;
121 const unsigned short *key1=(const unsigned short *)cardkeys[1];
122 unsigned short key2[32];
123 memcpy(key2,cardkeys[2],sizeof(key2));
124 int count2;
125 for(count2=0; count2<32; count2++) {
126 unsigned int rem=0, div=key1[count2];
127 int i;
128 for(i=31; i>=0; i--) {
129 unsigned int x=idata[i] | (rem<<16);
130 rem=(x%div)&0xffff;
132 unsigned int carry=1, t=val_by2on3(div) | 1;
133 while(t) {
134 if(t&1) carry=((carry*rem)%div)&0xffff;
135 rem=((rem*rem)%div)&0xffff;
136 t>>=1;
138 cCamCryptVG2_PartialMod(carry,count2,key2,key1);
140 unsigned short idatacount=0;
141 int i;
142 for(i=31; i>=0; i--) cCamCryptVG2_LongMult(idata,&idatacount,key1[i],key2[i]);
143 unsigned char stateD1[16];
144 cCamCryptVG2_Reorder16A(stateD1,data);
145 cAES_SetKey(stateD1);
146 break;
151 static void cCamCryptVG2_Process_D1(const unsigned char *ins, unsigned char *data, const unsigned char *status)
153 unsigned char iter[16], tmp[16];
154 memset(iter,0,sizeof(iter));
155 memcpy(iter,ins,5);
156 xor16(iter,stateD3A,iter);
157 memcpy(stateD3A,iter,sizeof(iter));
159 int datalen=status-data;
160 int datalen1=datalen;
161 if(datalen<0) datalen1+=15;
162 int blocklen=datalen1>>4;
163 int i;
164 int iblock;
165 for(i=0,iblock=0; i<blocklen+2; i++,iblock+=16) {
166 unsigned char in[16];
167 if(blocklen==i) {
168 memset(in,0,sizeof(in));
169 memcpy(in,&data[iblock],datalen-(datalen1&~0xf));
171 else if(blocklen+1==i) {
172 memset(in,0,sizeof(in));
173 memcpy(&in[5],status,2);
175 else
176 memcpy(in,&data[iblock],sizeof(in));
178 xor16(iter,in,tmp);
179 cCamCryptVG2_ReorderAndEncrypt(tmp);
180 xor16(tmp,stateD3A,iter);
182 memcpy(stateD3A,tmp,16);
185 static void cCamCryptVG2_Decrypt_D3(unsigned char *ins, unsigned char *data, const unsigned char *status)
187 if(ins[4]>16) ins[4]-=16;
188 if(ins[1]==0xbe) memset(stateD3A,0,sizeof(stateD3A));
190 unsigned char tmp[16];
191 memset(tmp,0,sizeof(tmp));
192 memcpy(tmp,ins,5);
193 xor16(tmp,stateD3A,stateD3A);
195 int len1=ins[4];
196 int blocklen=len1>>4;
197 if(ins[1]!=0xbe) blocklen++;
199 unsigned char iter[16], states[16][16];
200 memset(iter,0,sizeof(iter));
201 int blockindex;
202 for(blockindex=0; blockindex<blocklen; blockindex++) {
203 iter[0]+=blockindex;
204 xor16(iter,stateD3A,iter);
205 cCamCryptVG2_ReorderAndEncrypt(iter);
206 xor16(iter,&data[blockindex*16],states[blockindex]);
207 if(blockindex==(len1>>4)) {
208 int c=len1-(blockindex*16);
209 if(c<16) memset(&states[blockindex][c],0,16-c);
211 xor16(states[blockindex],stateD3A,stateD3A);
212 cCamCryptVG2_RotateRightAndHash(stateD3A);
214 memset(tmp,0,sizeof(tmp));
215 memcpy(tmp+5,status,2);
216 xor16(tmp,stateD3A,stateD3A);
217 cCamCryptVG2_ReorderAndEncrypt(stateD3A);
219 memcpy(stateD3A,status-16,sizeof(stateD3A));
220 cCamCryptVG2_ReorderAndEncrypt(stateD3A);
222 memcpy(data,states[0],len1);
223 if(ins[1]==0xbe) {
224 cCamCryptVG2_Reorder16A(tmp,states[0]);
225 cAES_SetKey(tmp);
229 static void cCamCryptVG2_ReorderAndEncrypt(unsigned char *p)
231 unsigned char tmp[16];
232 cCamCryptVG2_Reorder16A(tmp,p);
233 cAES_Encrypt(tmp,16,tmp);
234 cCamCryptVG2_Reorder16A(p,tmp);
237 // reorder AAAABBBBCCCCDDDD to ABCDABCDABCDABCD
239 static void cCamCryptVG2_Reorder16A(unsigned char *dest, const unsigned char *src)
241 int i;
242 int j;
243 int k;
244 for(i=0,k=0; i<4; i++)
245 for(j=i; j<16; j+=4,k++)
246 dest[k]=src[j];
249 static void cCamCryptVG2_LongMult(unsigned short *pData, unsigned short *pLen, unsigned int mult, unsigned int carry)
251 int i;
252 for(i=0; i<*pLen; i++) {
253 carry+=pData[i]*mult;
254 pData[i]=(unsigned short)carry;
255 carry>>=16;
257 if(carry) pData[(*pLen)++]=carry;
260 static void cCamCryptVG2_PartialMod(unsigned short val, unsigned int count, unsigned short *outkey, const unsigned short *inkey)
262 if(count) {
263 unsigned int mod=inkey[count];
264 unsigned short mult=(inkey[count]-outkey[count-1])&0xffff;
265 unsigned int i;
266 unsigned int ib1;
267 for(i=0,ib1=count-2; i<count-1; i++,ib1--) {
268 unsigned int t=(inkey[ib1]*mult)%mod;
269 mult=t-outkey[ib1];
270 if(mult>t) mult+=mod;
272 mult+=val;
273 if((val>mult) || (mod<mult)) mult-=mod;
274 outkey[count]=(outkey[count]*mult)%mod;
276 else
277 outkey[0]=val;
280 static const unsigned char table1[256] = {
281 0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5, 0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76,
282 0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0, 0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0,
283 0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc, 0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15,
284 0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a, 0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75,
285 0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0, 0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84,
286 0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b, 0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf,
287 0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85, 0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8,
288 0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5, 0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2,
289 0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17, 0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73,
290 0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88, 0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb,
291 0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c, 0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79,
292 0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9, 0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08,
293 0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6, 0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a,
294 0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e, 0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e,
295 0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94, 0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf,
296 0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68, 0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16,
299 static void cCamCryptVG2_RotateRightAndHash(unsigned char *p)
301 unsigned char t1=p[15];
302 int i;
303 for(i=0; i<16; i++) {
304 unsigned char t2=t1;
305 t1=p[i]; p[i]=table1[(t1>>1)|((t2&1)<<7)];
309 ////// ====================================================================================
311 static unsigned char CW1[8], CW2[8];
313 extern uchar cta_cmd[], cta_res[];
314 extern ushort cta_lr;
316 extern int io_serial_need_dummy_char;
318 struct CmdTabEntry {
319 unsigned char cla;
320 unsigned char cmd;
321 unsigned char len;
322 unsigned char mode;
325 struct CmdTab {
326 unsigned char index;
327 unsigned char size;
328 unsigned char Nentries;
329 unsigned char dummy;
330 struct CmdTabEntry e[1];
333 struct CmdTab *cmd_table=NULL;
334 void memorize_cmd_table (const unsigned char *mem, int size){
335 cmd_table=(struct CmdTab *)malloc(sizeof(unsigned char) * size);
336 memcpy(cmd_table,mem,size);
339 int cmd_table_get_info(const unsigned char *cmd, unsigned char *rlen, unsigned char *rmode)
341 struct CmdTabEntry *pcte=cmd_table->e;
342 int i;
343 for(i=0; i<cmd_table->Nentries; i++,pcte++)
344 if(cmd[1]==pcte->cmd) {
345 *rlen=pcte->len;
346 *rmode=pcte->mode;
347 return 1;
349 return 0;
352 #define CMD_LEN 5
354 static int status_ok(const unsigned char *status){
355 //cs_log("check status %02x%02x", status[0],status[1]);
356 return (status[0] == 0x90 || status[0] == 0x91)
357 && (status[1] == 0x00 || status[1] == 0x01
358 || status[1] == 0x20 || status[1] == 0x21
359 || status[1] == 0x80 || status[1] == 0x81
360 || status[1] == 0xa0 || status[1] == 0xa1);
363 static int card_write(uchar *cmd, uchar *data, int wflag)
365 int l;
366 uchar buf[256];
367 memcpy(buf, cmd, CMD_LEN);
368 l=wflag ? cmd[4] : 0;
369 if (l && data) memcpy(buf+CMD_LEN, data, l);
370 l=reader_cmd2icc(buf, CMD_LEN+l);
371 return(l);
374 #define write_cmd(cmd, data) (card_write(cmd, data, 1) == 0)
375 #define read_cmd(cmd, data) (card_write(cmd, data, 0) == 0)
377 static int read_cmd_len(const unsigned char *cmd)
379 unsigned char cmd2[5];
380 memcpy(cmd2,cmd,5);
381 cmd2[3]=0x80;
382 cmd2[4]=1;
383 if(!read_cmd(cmd2,NULL) || cta_res[1] != 0x90 || cta_res[2] != 0x00) {
384 cs_log("failed to read %02x%02x cmd length (%02x %02x)",cmd[1],cmd[2],cta_res[1],cta_res[2]);
385 return -1;
387 return cta_res[0];
390 static int do_cmd(const unsigned char *ins, const unsigned char *txbuff, unsigned char *rxbuff)
392 unsigned char ins2[5];
393 memcpy(ins2,ins,5);
394 unsigned char len=0, mode=0;
395 if(cmd_table_get_info(ins2,&len,&mode)) {
396 if(len==0xFF && mode==2) {
397 if(ins2[4]==0) ins2[4]=len=read_cmd_len(ins2);
399 else if(mode!=0) ins2[4]=len;
401 if(ins2[0]==0xd3) ins2[4]=len+16;
402 len=ins2[4];
404 unsigned char tmp[264];
405 if(!rxbuff) rxbuff=tmp;
406 if(mode>1) {
407 if(!read_cmd(ins2,NULL) || !status_ok(cta_res+len)) return -1;
408 memcpy(rxbuff,ins2,5);
409 memcpy(rxbuff+5,cta_res,len);
410 memcpy(rxbuff+5+len,cta_res+len,2);
412 else {
413 if(!write_cmd(ins2,(unsigned char *)txbuff) || !status_ok(cta_res)) return -2;
414 memcpy(rxbuff,ins2,5);
415 memcpy(rxbuff+5,txbuff,len);
416 memcpy(rxbuff+5+len,cta_res,2);
419 cCamCryptVG2_PostProcess_Decrypt(rxbuff,len,CW1,CW2);
421 return len;
424 #define BASEYEAR 1997
425 static void rev_date_calc(const unsigned char *Date, int *year, int *mon, int *day, int *hh, int *mm, int *ss)
427 *year=(Date[0]/12)+BASEYEAR;
428 *mon=(Date[0]%12)+1;
429 *day=Date[1];
430 *hh=Date[2]/8;
431 *mm=(0x100*(Date[2]-*hh*8)+Date[3])/32;
432 *ss=(Date[3]-*mm*32)*2;
435 static void read_tiers(void)
437 static const unsigned char ins2a[5] = { 0xd0,0x2a,0x00,0x00,0x00 };
438 int l;
439 l=do_cmd(ins2a,NULL,NULL);
440 if(l<0 || !status_ok(cta_res+l)) return;
441 static unsigned char ins76[5] = { 0xd0,0x76,0x00,0x00,0x00 };
442 ins76[3]=0x7f; ins76[4]=2;
443 if(!read_cmd(ins76,NULL) || !status_ok(cta_res+2)) return;
444 ins76[3]=0; ins76[4]=0;
445 int num=cta_res[1];
446 int i;
447 for(i=0; i<num; i++) {
448 ins76[2]=i;
449 l=do_cmd(ins76,NULL,NULL);
450 if(l<0 || !status_ok(cta_res+l)) return;
451 if(cta_res[2]==0 && cta_res[3]==0) break;
452 int y,m,d,H,M,S;
453 rev_date_calc(&cta_res[4],&y,&m,&d,&H,&M,&S);
454 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);
458 int videoguard_card_init(uchar *atr, int atrsize)
460 /* known atrs */
461 unsigned char atr_bskyb[] = { 0x3F, 0x7F, 0x13, 0x25, 0x03, 0x33, 0xB0, 0x06, 0x69, 0xFF, 0x4A, 0x50, 0xD0, 0x00, 0x00, 0x53, 0x59, 0x00, 0x00, 0x00 };
462 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 };
464 if ((atrsize == sizeof (atr_bskyb)) && (memcmp (atr, atr_bskyb, atrsize) == 0)) {
465 cs_log("Type: Videoguard BSkyB");
466 /* BSkyB seems to need one additionnal byte in the serial communication... */
467 io_serial_need_dummy_char = 1;
468 } else if ((atrsize == sizeof (atr_skyitalia)) && (memcmp (atr, atr_skyitalia, atrsize) == 0)) {
469 cs_log("Type: Videoguard Sky Italia");
470 } else {
471 /* not a known videoguard */
472 return (0);
475 int bconst=B38400;
476 int baud=64516;
477 int fd=open(reader[ridx].device,O_RDWR|O_NONBLOCK|O_NOCTTY);
479 struct termios tio;
480 memset(&tio,0,sizeof(tio));
481 tio.c_cflag = (CS8 | CREAD | HUPCL | CLOCAL);
482 tio.c_cflag |= CSTOPB;
483 tio.c_iflag = (INPCK | BRKINT);
484 tio.c_cc[VMIN] = 1;
485 cfsetispeed(&tio,bconst);
486 cfsetospeed(&tio,bconst);
487 tio.c_cflag |= (PARENB | PARODD);
489 struct serial_struct s;
490 if(ioctl(fd,TIOCGSERIAL,&s)<0) {
491 cs_log("%s: get serial failed: %s",reader[ridx].device,strerror(errno));
492 return 0;
494 if(!tcsetattr(fd,TCSANOW,&tio)) {
495 if (reader[ridx].custom_speed) {
496 s.custom_divisor=(s.baud_base+(baud/2))/baud;
497 s.flags=(s.flags&~ASYNC_SPD_MASK) | ASYNC_SPD_CUST;
498 cs_log ("%s: custom: baud_base=%d baud=%d divisor=%d -> effective baudrate %d (%+.2f%% off)",
499 reader[ridx].device,s.baud_base,baud,s.custom_divisor,s.baud_base/s.custom_divisor,
500 (float)(s.baud_base/s.custom_divisor-baud)/(float)baud);
501 } else {
502 s.flags &= ~ASYNC_SPD_CUST;
503 cs_log ("%s: baud=%d", reader[ridx].device, 38400);
505 if(ioctl(fd,TIOCSSERIAL,&s)<0) {
506 cs_log ("%s: set serial failed: %s",reader[ridx].device,strerror(errno));
507 return 0;
510 else {
511 cs_log ("%s: tcsetattr failed: %s",reader[ridx].device,strerror(errno));
512 return 0;
515 unsigned char ins7401[5] = { 0xD0,0x74,0x01,0x00,0x00 };
516 int l;
517 if((l=read_cmd_len(ins7401))<0) return 0;
518 ins7401[4]=l;
519 if(!read_cmd(ins7401,NULL) || !status_ok(cta_res+l)) {
520 cs_log ("failed to read cmd list");
521 return 0;
523 memorize_cmd_table (cta_res,l);
525 unsigned char buff[256];
527 unsigned char ins7416[5] = { 0xD0,0x74,0x16,0x00,0x00 };
528 if(do_cmd(ins7416, NULL, NULL)<0) {
529 cs_log ("cmd 7416 failed");
530 return 0;
533 unsigned char ins36[5] = { 0xD0,0x36,0x00,0x00,0x00 };
534 int boxidOK=0;
535 unsigned char boxID [4];
537 l=do_cmd(ins36, NULL, buff);
538 if(l>=0) {
539 int i;
540 for(i=0; i<l ;i++) {
541 if(buff[i]==0x00 && buff[i+1]==0xF3) {
542 memcpy(&boxID,&buff[i+2],sizeof(boxID));
543 boxidOK=1;
544 break;
549 if(!boxidOK) {
550 cs_log ("no boxID available");
551 return 0;
554 unsigned char ins4C[5] = { 0xD0,0x4C,0x00,0x00,0x09 };
555 unsigned char payload4C[9] = { 0,0,0,0, 3,0,0,2,4 };
556 memcpy(payload4C,boxID,4);
557 if(!write_cmd(ins4C,payload4C) || !status_ok(cta_res+l)) {
558 cs_log("sending boxid failed");
559 return 0;
562 unsigned char ins58[5] = { 0xD0,0x58,0x00,0x00,0x00 };
563 l=do_cmd(ins58, NULL, buff);
564 if(l<0) {
565 cs_log("cmd ins58 failed");
566 return 0;
568 memset(reader[ridx].hexserial, 0, 4);
569 memcpy(reader[ridx].hexserial+4, cta_res+3, 4);
570 reader[ridx].caid[0] = cta_res[24]*0x100+cta_res[25];
572 /* we have one provider, 0x0000 */
573 reader[ridx].nprov = 1;
574 memset(reader[ridx].prid, 0x00, sizeof(reader[ridx].prid));
577 const unsigned char seed1[] = {
578 0xb9, 0xd5, 0xef, 0xd5, 0xf5, 0xd5, 0xfb, 0xd5, 0x31, 0xd6, 0x43, 0xd6, 0x55, 0xd6, 0x61, 0xd6,
579 0x85, 0xd6, 0x9d, 0xd6, 0xaf, 0xd6, 0xc7, 0xd6, 0xd9, 0xd6, 0x09, 0xd7, 0x15, 0xd7, 0x21, 0xd7,
580 0x27, 0xd7, 0x3f, 0xd7, 0x45, 0xd7, 0xb1, 0xd7, 0xbd, 0xd7, 0xdb, 0xd7, 0x11, 0xd8, 0x23, 0xd8,
581 0x29, 0xd8, 0x2f, 0xd8, 0x4d, 0xd8, 0x8f, 0xd8, 0xa1, 0xd8, 0xad, 0xd8, 0xbf, 0xd8, 0xd7, 0xd8
583 const unsigned char seed2[] = {
584 0x01, 0x00, 0xcf, 0x13, 0xe0, 0x60, 0x54, 0xac, 0xab, 0x99, 0xe6, 0x0c, 0x9f, 0x5b, 0x91, 0xb9,
585 0x72, 0x72, 0x4d, 0x5b, 0x5f, 0xd3, 0xb7, 0x5b, 0x01, 0x4d, 0xef, 0x9e, 0x6b, 0x8a, 0xb9, 0xd1,
586 0xc9, 0x9f, 0xa1, 0x2a, 0x8d, 0x86, 0xb6, 0xd6, 0x39, 0xb4, 0x64, 0x65, 0x13, 0x77, 0xa1, 0x0a,
587 0x0c, 0xcf, 0xb4, 0x2b, 0x3a, 0x2f, 0xd2, 0x09, 0x92, 0x15, 0x40, 0x47, 0x66, 0x5c, 0xda, 0xc9
589 cCamCryptVG2_SetSeed(seed1,seed2);
591 unsigned char insB4[5] = { 0xD0,0xB4,0x00,0x00,0x40 };
592 unsigned char tbuff[64];
593 cCamCryptVG2_GetCamKey(tbuff);
594 l=do_cmd(insB4, tbuff, NULL);
595 if(l<0 || !status_ok(cta_res)) {
596 cs_log ("cmd D0B4 failed (%02X%02X)", cta_res[0], cta_res[1]);
597 return 0;
600 unsigned char insBC[5] = { 0xD0,0xBC,0x00,0x00,0x00 };
601 l=do_cmd(insBC, NULL, NULL);
602 if(l<0) {
603 cs_log("cmd D0BC failed");
604 return 0;
607 unsigned char insBE[5] = { 0xD3,0xBE,0x00,0x00,0x00 };
608 l=do_cmd(insBE, NULL, NULL);
609 if(l<0) {
610 cs_log("cmd D3BE failed");
611 return 0;
614 unsigned char ins58a[5] = { 0xD1,0x58,0x00,0x00,0x00 };
615 l=do_cmd(ins58a, NULL, NULL);
616 if(l<0) {
617 cs_log("cmd D158 failed");
618 return 0;
621 unsigned char ins4Ca[5] = { 0xD1,0x4C,0x00,0x00,0x00 };
622 l=do_cmd(ins4Ca,payload4C, NULL);
623 if(l<0 || !status_ok(cta_res)) {
624 cs_log("cmd D14Ca failed");
625 return 0;
628 cs_log("type: Videoguard, caid: %04X, serial: %02X%02X%02X%02X, BoxID: %02X%02X%02X%02X",
629 reader[ridx].caid[0],
630 reader[ridx].hexserial[4],reader[ridx].hexserial[5],reader[ridx].hexserial[6],reader[ridx].hexserial[7],
631 boxID[0],boxID[1],boxID[2],boxID[3]);
633 ///read_tiers();
635 cs_log("ready for requests");
637 return(1);
640 int videoguard_do_ecm(ECM_REQUEST *er)
642 static unsigned char ins40[5] = { 0xD1,0x40,0x40,0x80,0xFF };
643 static const unsigned char ins54[5] = { 0xD3,0x54,0x00,0x00,0x00};
644 int posECMpart2=er->ecm[6]+7;
645 int lenECMpart2=er->ecm[posECMpart2]+1;
646 unsigned char tbuff[264];
647 tbuff[0]=0;
648 memcpy(&tbuff[1],&(er->ecm[posECMpart2+1]),lenECMpart2);
649 ins40[4]=lenECMpart2;
650 int l;
651 l = do_cmd(ins40,tbuff,NULL);
652 if(l>0 && status_ok(cta_res)) {
653 l = do_cmd(ins54,NULL,NULL);
654 if(l>0 && status_ok(cta_res+l)) {
655 if(er->ecm[0]&1) {
656 memcpy(er->cw+8,CW1,8);
657 } else {
658 memcpy(er->cw+0,CW1,8);
660 return 1;
663 return 0;
666 static unsigned int num_addr(const unsigned char *data)
668 return ((data[3]&0x30)>>4)+1;
671 static int addr_mode(const unsigned char *data)
673 switch(data[3]&0xC0) {
674 case 0x40: return 3;
675 case 0x80: return 2;
676 default: return 0;
680 static const unsigned char * payload_addr(const unsigned char *data, const unsigned char *a)
682 int s;
683 int l;
684 const unsigned char *ptr = NULL;
686 switch(addr_mode(data)) {
687 case 2: s=3; break;
688 case 3: s=4; break;
689 default: return NULL;
692 int position=-1;
693 for(l=0;l<num_addr(data);l++) {
694 if(!memcmp(&data[l*4+4],a+4,s)) {
695 position=l;
696 break;
700 /* skip header, the list of address, and the separator (the two 00 00) */
701 ptr = data+4+4*num_addr(data)+2;
703 /* skip optional 00 */
704 if (*ptr == 0x00) ptr++;
706 /* skip the 1st bitmap len */
707 ptr++;
709 /* check */
710 if (*ptr != 0x02) return NULL;
712 /* skip the 1st timestamp 02 00 or 02 06 xx aabbccdd yy */
713 ptr += 2 + ptr[1];
715 for(l=0;l<position;l++) {
717 /* skip the payload of the previous SA */
718 ptr += 1 + ptr [0];
720 /* skip optional 00 */
721 if (*ptr == 0x00) ptr++;
723 /* skip the bitmap len */
724 ptr++;
726 /* check */
727 if (*ptr != 0x02) return NULL;
729 /* skip the timestamp 02 00 or 02 06 xx aabbccdd yy */
730 ptr += 2 + ptr[1];
733 return ptr;
736 int videoguard_do_emm(EMM_PACKET *ep)
738 unsigned char ins42[5] = { 0xD1,0x42,0x00,0x00,0xFF };
739 int rc=0;
741 const unsigned char *payload = payload_addr(ep->emm, reader[ridx].hexserial);
742 if (payload) {
743 ins42[4]=*payload;
744 int l = do_cmd(ins42,payload+1,NULL);
745 if(l>0 && status_ok(cta_res)) {
746 rc=1;
749 cs_log("EMM request return code : %02X%02X", cta_res[0], cta_res[1]);
750 //cs_dump(ep->emm, 64, "EMM:");
751 if (status_ok (cta_res)) {
752 read_tiers();
757 return(rc);
760 int videoguard_card_info(void)
762 /* info is displayed in init, or when processing info */
763 read_tiers ();
764 return(1);