source: trunk/reader-videoguard2.c@ 109

Last change on this file since 109 was 96, checked in by polo, 11 years ago

Add card info logging when log file reach MaxLogSize

File size: 23.6 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(const uchar *cmd, const 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,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_bskyb_new[] = { 0x3F, 0xFD, 0x13, 0x25, 0x02, 0x50, 0x00, 0x0F, 0x33, 0xB0, 0x0F, 0x69, 0xFF, 0x4A, 0x50, 0xD0, 0x00, 0x00, 0x53, 0x59, 0x02 };
465 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 };
466 unsigned char atr_premiere[] = { 0x3F, 0xFF, 0x11, 0x25, 0x03, 0x10, 0x80, 0x41, 0xB0, 0x07, 0x69, 0xFF, 0x4A, 0x50, 0x70, 0x00, 0x00, 0x50, 0x31, 0x01, 0x00, 0x11 };
467 unsigned char atr_directv[] = { 0x3F, 0x78, 0x13, 0x25, 0x03, 0x40, 0xB0, 0x20, 0xFF, 0xFF, 0x4A, 0x50, 0x00 };
468
469 if ((atrsize == sizeof (atr_bskyb)) && (memcmp (atr, atr_bskyb, atrsize) == 0))
470 {
471 cs_log("Type: Videoguard BSkyB");
472 /* BSkyB seems to need one additionnal byte in the serial communication... */
473 io_serial_need_dummy_char = 1;
474 }
475 else if ((atrsize == sizeof (atr_bskyb_new)) && (memcmp (atr, atr_bskyb_new, atrsize) == 0))
476 {
477 cs_log("Type: Videoguard BSkyB - New");
478 }
479 else if ((atrsize == sizeof (atr_skyitalia)) && (memcmp (atr, atr_skyitalia, atrsize) == 0))
480 {
481 cs_log("Type: Videoguard Sky Italia");
482 }
483 else if ((atrsize == sizeof (atr_premiere)) && (memcmp (atr, atr_premiere, atrsize) == 0))
484 {
485 cs_log("Type: Videoguard Premiere NDS");
486 }
487 else if ((atrsize == sizeof (atr_directv)) && (memcmp (atr, atr_directv, atrsize) == 0))
488 {
489 cs_log("Type: Videoguard DirecTV");
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]==0x00 && buff[i+1]==0xF3) {
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,2,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);
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
802 reader[ridx].online = 1;
803
804 return(1);
805}
Note: See TracBrowser for help on using the repository browser.