2 #include "reader-common.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 ////// ====================================================================================
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
);
23 static int cAES_Encrypt(const unsigned char *data
, int len
, unsigned char *crypt
)
26 len
=(len
+15)&(~15); // pad up to a multiple of 16
28 for(i
=0; i
<len
; i
+=16) AES_encrypt(data
+i
,crypt
+i
,(const AES_KEY
*)&ekey
);
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 ;)
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);
43 *((unsigned int *)data
+1) = *((unsigned int *)v1
+1) ^ *((unsigned int *)v2
+1);
45 *((unsigned int *)data
+0) = *((unsigned int *)v1
+0) ^ *((unsigned int *)v2
+0);
48 while(len
--) *data
++ = *v1
++ ^ *v2
++;
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;
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
)
89 cCamCryptVG2_Process_D0(buff
,buff
+5,buff
+buff
[4]+5);
92 cCamCryptVG2_Process_D1(buff
,buff
+5,buff
+buff
[4]+5);
95 cCamCryptVG2_Decrypt_D3(buff
,buff
+5,buff
+buff
[4]+5);
99 for(ind
=14; ind
<len
+5;) {
100 if(buff
[ind
]==0x25) {
101 memcpy(cw2
,buff
+5+ind
+2,8);
104 if(buff
[ind
+1]==0) break;
112 static void cCamCryptVG2_Process_D0(const unsigned char *ins
, unsigned char *data
, const unsigned char *status
)
116 memcpy(cardkeys
[0],data
,sizeof(cardkeys
[0]));
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
));
125 for(count2
=0; count2
<32; count2
++) {
126 unsigned int rem
=0, div
=key1
[count2
];
128 for(i
=31; i
>=0; i
--) {
129 unsigned int x
=idata
[i
] | (rem
<<16);
132 unsigned int carry
=1, t
=val_by2on3(div
) | 1;
134 if(t
&1) carry
=((carry
*rem
)%div
)&0xffff;
135 rem
=((rem
*rem
)%div
)&0xffff;
138 cCamCryptVG2_PartialMod(carry
,count2
,key2
,key1
);
140 unsigned short idatacount
=0;
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
);
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
));
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;
165 for(i
=0,iblock
=0; i
<blocklen
+2; i
++,iblock
+=16) {
166 unsigned char in
[16];
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);
176 memcpy(in
,&data
[iblock
],sizeof(in
));
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
));
193 xor16(tmp
,stateD3A
,stateD3A
);
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
));
202 for(blockindex
=0; blockindex
<blocklen
; 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
);
224 cCamCryptVG2_Reorder16A(tmp
,states
[0]);
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
)
244 for(i
=0,k
=0; i
<4; i
++)
245 for(j
=i
; j
<16; j
+=4,k
++)
249 static void cCamCryptVG2_LongMult(unsigned short *pData
, unsigned short *pLen
, unsigned int mult
, unsigned int carry
)
252 for(i
=0; i
<*pLen
; i
++) {
253 carry
+=pData
[i
]*mult
;
254 pData
[i
]=(unsigned short)carry
;
257 if(carry
) pData
[(*pLen
)++]=carry
;
260 static void cCamCryptVG2_PartialMod(unsigned short val
, unsigned int count
, unsigned short *outkey
, const unsigned short *inkey
)
263 unsigned int mod
=inkey
[count
];
264 unsigned short mult
=(inkey
[count
]-outkey
[count
-1])&0xffff;
267 for(i
=0,ib1
=count
-2; i
<count
-1; i
++,ib1
--) {
268 unsigned int t
=(inkey
[ib1
]*mult
)%mod
;
270 if(mult
>t
) mult
+=mod
;
273 if((val
>mult
) || (mod
<mult
)) mult
-=mod
;
274 outkey
[count
]=(outkey
[count
]*mult
)%mod
;
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];
303 for(i
=0; i
<16; i
++) {
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
;
328 unsigned char Nentries
;
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
;
343 for(i
=0; i
<cmd_table
->Nentries
; i
++,pcte
++)
344 if(cmd
[1]==pcte
->cmd
) {
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
)
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
);
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];
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]);
390 static int do_cmd(const unsigned char *ins
, const unsigned char *txbuff
, unsigned char *rxbuff
)
392 unsigned char ins2
[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;
404 unsigned char tmp
[264];
405 if(!rxbuff
) rxbuff
=tmp
;
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);
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
);
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
;
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 };
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;
447 for(i
=0; i
<num
; 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;
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
)
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");
471 /* not a known videoguard */
477 int fd
=open(reader
[ridx
].device
,O_RDWR
|O_NONBLOCK
|O_NOCTTY
);
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
);
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
));
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
);
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
));
511 cs_log ("%s: tcsetattr failed: %s",reader
[ridx
].device
,strerror(errno
));
515 unsigned char ins7401
[5] = { 0xD0,0x74,0x01,0x00,0x00 };
517 if((l
=read_cmd_len(ins7401
))<0) return 0;
519 if(!read_cmd(ins7401
,NULL
) || !status_ok(cta_res
+l
)) {
520 cs_log ("failed to read cmd list");
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");
533 unsigned char ins36
[5] = { 0xD0,0x36,0x00,0x00,0x00 };
535 unsigned char boxID
[4];
537 l
=do_cmd(ins36
, NULL
, buff
);
541 if(buff
[i
]==0x00 && buff
[i
+1]==0xF3) {
542 memcpy(&boxID
,&buff
[i
+2],sizeof(boxID
));
550 cs_log ("no boxID available");
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");
562 unsigned char ins58
[5] = { 0xD0,0x58,0x00,0x00,0x00 };
563 l
=do_cmd(ins58
, NULL
, buff
);
565 cs_log("cmd ins58 failed");
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]);
600 unsigned char insBC
[5] = { 0xD0,0xBC,0x00,0x00,0x00 };
601 l
=do_cmd(insBC
, NULL
, NULL
);
603 cs_log("cmd D0BC failed");
607 unsigned char insBE
[5] = { 0xD3,0xBE,0x00,0x00,0x00 };
608 l
=do_cmd(insBE
, NULL
, NULL
);
610 cs_log("cmd D3BE failed");
614 unsigned char ins58a
[5] = { 0xD1,0x58,0x00,0x00,0x00 };
615 l
=do_cmd(ins58a
, NULL
, NULL
);
617 cs_log("cmd D158 failed");
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");
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]);
635 cs_log("ready for requests");
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];
648 memcpy(&tbuff
[1],&(er
->ecm
[posECMpart2
+1]),lenECMpart2
);
649 ins40
[4]=lenECMpart2
;
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
)) {
656 memcpy(er
->cw
+8,CW1
,8);
658 memcpy(er
->cw
+0,CW1
,8);
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) {
680 static const unsigned char * payload_addr(const unsigned char *data
, const unsigned char *a
)
684 const unsigned char *ptr
= NULL
;
686 switch(addr_mode(data
)) {
689 default: return NULL
;
693 for(l
=0;l
<num_addr(data
);l
++) {
694 if(!memcmp(&data
[l
*4+4],a
+4,s
)) {
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 */
710 if (*ptr
!= 0x02) return NULL
;
712 /* skip the 1st timestamp 02 00 or 02 06 xx aabbccdd yy */
715 for(l
=0;l
<position
;l
++) {
717 /* skip the payload of the previous SA */
720 /* skip optional 00 */
721 if (*ptr
== 0x00) ptr
++;
723 /* skip the bitmap len */
727 if (*ptr
!= 0x02) return NULL
;
729 /* skip the timestamp 02 00 or 02 06 xx aabbccdd yy */
736 int videoguard_do_emm(EMM_PACKET
*ep
)
738 unsigned char ins42
[5] = { 0xD1,0x42,0x00,0x00,0xFF };
741 const unsigned char *payload
= payload_addr(ep
->emm
, reader
[ridx
].hexserial
);
744 int l
= do_cmd(ins42
,payload
+1,NULL
);
745 if(l
>0 && status_ok(cta_res
)) {
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
)) {
760 int videoguard_card_info(void)
762 /* info is displayed in init, or when processing info */