source: trunk/reader-videoguard2.c@ 54

Last change on this file since 54 was 54, checked in by smurzch2, 14 years ago

Preliminary support for Mac OS X.

Now, it compile, but it will not work with the serial port.
Thanks rorothetroll for this patch

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