source: trunk/reader-videoguard2.c@ 1714

Last change on this file since 1714 was 1714, checked in by landlord, 11 years ago

Simplify Sky IT post processing, thanks to furb3t

File size: 30.9 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;
17int BASEYEAR = 1997;
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
36static int cw_is_valid(unsigned char *cw) //returns 1 if cw_is_valid, returns 0 if cw is all zeros
37{
38 int i;
39 for (i = 0; i < 8; i++)
40 if (cw[i] != 0) {//test if cw = 00
41 return OK;
42 }
43 return ERROR;
44}
45
46unsigned short Nd$TabB001[0x4][0x20]= {
47 { 0xEAF1,0x0237,0x29D0,0xBAD2,0xE9D3,0x8BAE,0x2D6D,0xCD1B,
48 0x538D,0xDE6B,0xA634,0xF81A,0x18B5,0x5087,0x14EA,0x672E,
49 0xF0FC,0x055E,0x62E5,0xB78F,0x5D09,0x0003,0xE4E8,0x2DCE,
50 0x6BE0,0xAC4E,0xF485,0x6967,0xF28C,0x97A0,0x01EF,0x0100, },
51 { 0xC539,0xF5B9,0x9099,0x013A,0xD4B9,0x6AB5,0xEA67,0x7EB4,
52 0x6C30,0x4BF0,0xB810,0xB0B5,0xB76D,0xA751,0x1AE7,0x14CA,
53 0x4F4F,0x1586,0x2608,0x10B1,0xE7E1,0x48BE,0x7DDD,0x5ECB,
54 0xCFBF,0x323B,0x8B31,0xB131,0x0F1A,0x664B,0x0140,0x0100, },
55 { 0x3C7D,0xBDC4,0xFEC7,0x26A6,0xB0A0,0x6E55,0xF710,0xF9BF,
56 0x0023,0xE81F,0x41CA,0xBE32,0xB461,0xE92D,0xF1AF,0x409F,
57 0xFC85,0xFE5B,0x7FCE,0x17F5,0x01AB,0x4A46,0xEB05,0xA251,
58 0xDC6F,0xF0C0,0x10F0,0x1D51,0xEFAA,0xE9BF,0x0100,0x0100, },
59 { 0x1819,0x0CAA,0x9067,0x607A,0x7576,0x1CBC,0xE51D,0xBF77,
60 0x7EC6,0x839E,0xB695,0xF096,0xDC10,0xCB69,0x4654,0x8E68,
61 0xD62D,0x4F1A,0x4227,0x92AC,0x9064,0x6BD1,0x1E75,0x2747,
62 0x00DA,0xA6A6,0x6CF1,0xD151,0xBE56,0x3E33,0x0128,0x0100, },
63};
64
65unsigned short Hash3[] = {0x0123,0x4567,0x89AB,0xCDEF,0xF861,0xCB52};
66unsigned char Hash4[] = {0x0B,0x04,0x07,0x08,0x05,0x09,0x0B,0x0A,0x07,0x02,0x0A,0x05,0x04,0x08,0x0D,0x0F};
67
68static void postprocess_cw(unsigned char *cw, int nTableIdx)
69{
70 unsigned short hk[8],i,j,m=0;
71 for (i = 0; i < 6; i++) hk[2+i]=Hash3[i];
72 for (i = 0; i < 2; i++) {
73 for (j = 0; j < 0x48; j+=2) {
74 if (i)
75 hk[0]=((hk[3] & hk[5]) | ((~hk[5]) & hk[4]));
76 else
77 hk[0]=((hk[3] & hk[4]) | ((~hk[3]) & hk[5]));
78 if (j<8)
79 hk[0]=(hk[0]+((cw[j +1]<<8) | cw[j]));
80 if(j==8) hk[0]=(hk[0]+0x80);
81 hk[0]=(hk[0]+hk[2] + (0xFF & Nd$TabB001[nTableIdx][m>>1] >> ((m&1)<<3))) ;
82 hk[1] = hk[2];
83 hk[2] = hk[3];
84 hk[3] = hk[4];
85 hk[4] = hk[5];
86 hk[5] = hk[6];
87 hk[6] = hk[7];
88 hk[7] = hk[2]+
89 (((hk[0] << Hash4[m&0xF]) | (hk[0] >> (0x10 - Hash4[m&0xF]))));
90 m=(m+1)&0x3F;
91 }
92 }
93 for (i = 0; i < 6; i++)
94 hk[2+i]+=Hash3[i];
95 for (i = 0; i < 7; i++)
96 cw[i]=hk[2+(i>>1)]>>((i&1)<<3);
97 cw[3] = (cw[0] + cw[1] + cw[2]) & 0xFF;
98 cw[7] = (cw[4] + cw[5] + cw[6]) & 0xFF;
99}
100
101
102static void swap_lb (unsigned char *buff, int len)
103{
104
105#if __BYTE_ORDER != __BIG_ENDIAN
106 return;
107
108#endif /* */
109 int i;
110 unsigned short *tmp;
111 for (i = 0; i < len / 2; i++) {
112 tmp = (unsigned short *) buff + i;
113 *tmp = ((*tmp << 8) & 0xff00) | ((*tmp >> 8) & 0x00ff);
114 }
115}
116
117static inline void __xxor(unsigned char *data, int len, const unsigned char *v1, const unsigned char *v2)
118{
119 switch(len) { // looks ugly, but the compiler can optimize it very well ;)
120 case 16:
121 *((unsigned int *)data+3) = *((unsigned int *)v1+3) ^ *((unsigned int *)v2+3);
122 *((unsigned int *)data+2) = *((unsigned int *)v1+2) ^ *((unsigned int *)v2+2);
123 case 8:
124 *((unsigned int *)data+1) = *((unsigned int *)v1+1) ^ *((unsigned int *)v2+1);
125 case 4:
126 *((unsigned int *)data+0) = *((unsigned int *)v1+0) ^ *((unsigned int *)v2+0);
127 break;
128 default:
129 while(len--) *data++ = *v1++ ^ *v2++;
130 break;
131 }
132}
133#define xor16(v1,v2,d) __xxor((d),16,(v1),(v2))
134#define val_by2on3(x) ((0xaaab*(x))>>16) //fixed point *2/3
135
136unsigned short cardkeys[3][32];
137unsigned char stateD3A[16];
138
139static void cCamCryptVG2_LongMult(unsigned short *pData, unsigned short *pLen, unsigned int mult, unsigned int carry);
140static void cCamCryptVG2_PartialMod(unsigned short val, unsigned int count, unsigned short *outkey, const unsigned short *inkey);
141static void cCamCryptVG2_RotateRightAndHash(unsigned char *p);
142static void cCamCryptVG2_Reorder16A(unsigned char *dest, const unsigned char *src);
143static void cCamCryptVG2_ReorderAndEncrypt(unsigned char *p);
144static void cCamCryptVG2_Process_D0(const unsigned char *ins, unsigned char *data);
145static void cCamCryptVG2_Process_D1(const unsigned char *ins, unsigned char *data, const unsigned char *status);
146static void cCamCryptVG2_Decrypt_D3(unsigned char *ins, unsigned char *data, const unsigned char *status);
147static void cCamCryptVG2_PostProcess_Decrypt(unsigned char *buff, int len, unsigned char *cw1, unsigned char *cw2);
148static void cCamCryptVG2_SetSeed(unsigned char *Key1, unsigned char *Key2);
149static void cCamCryptVG2_GetCamKey(unsigned char *buff);
150
151static void cCamCryptVG2_SetSeed(unsigned char *Key1, unsigned char *Key2)
152{
153 swap_lb (Key1, 64);
154 swap_lb (Key2, 64);
155 memcpy(cardkeys[1],Key1,sizeof(cardkeys[1]));
156 memcpy(cardkeys[2],Key2,sizeof(cardkeys[2]));
157 swap_lb (Key1, 64);
158 swap_lb (Key2, 64);
159}
160
161static void cCamCryptVG2_GetCamKey(unsigned char *buff)
162{
163 unsigned short *tb2=(unsigned short *)buff, c=1;
164 memset(tb2,0,64);
165 tb2[0]=1;
166 int i;
167 for(i=0; i<32; i++) cCamCryptVG2_LongMult(tb2,&c,cardkeys[1][i],0);
168 swap_lb (buff, 64);
169}
170
171static void cCamCryptVG2_PostProcess_Decrypt(unsigned char *buff, int len, unsigned char *cw1, unsigned char *cw2)
172{
173 switch(buff[0]) {
174 case 0xD0:
175 cCamCryptVG2_Process_D0(buff,buff+5);
176 break;
177 case 0xD1:
178 cCamCryptVG2_Process_D1(buff,buff+5,buff+buff[4]+5);
179 break;
180 case 0xD3:
181 cCamCryptVG2_Decrypt_D3(buff,buff+5,buff+buff[4]+5);
182 if(buff[1]==0x54) {
183 memcpy(cw1,buff+5,8);
184 memset(cw2,0,8); //set to 0 so client will know it is not valid if not overwritten with valid cw
185 int ind;
186 for(ind=13; ind<len+13-8; ind++) {
187 if(buff[ind]==0x25) {
188 //memcpy(cw2,buff+5+ind+2,8);
189 memcpy(cw2,buff+ind+3,8); //tested on viasat 093E, sky uk 0963, sky it 919 //don't care whether cw is 0 or not
190 break;
191 }
192/* if(buff[ind+1]==0) break;
193 ind+=buff[ind+1];*/
194 }
195 }
196 break;
197 }
198}
199
200static void cCamCryptVG2_Process_D0(const unsigned char *ins, unsigned char *data)
201{
202 switch(ins[1]) {
203 case 0xb4:
204 swap_lb (data, 64);
205 memcpy(cardkeys[0],data,sizeof(cardkeys[0]));
206 break;
207 case 0xbc:
208 {
209 swap_lb (data, 64);
210 unsigned short *idata=(unsigned short *)data;
211 const unsigned short *key1=(const unsigned short *)cardkeys[1];
212 unsigned short key2[32];
213 memcpy(key2,cardkeys[2],sizeof(key2));
214 int count2;
215 for(count2=0; count2<32; count2++) {
216 unsigned int rem=0, div=key1[count2];
217 int i;
218 for(i=31; i>=0; i--) {
219 unsigned int x=idata[i] | (rem<<16);
220 rem=(x%div)&0xffff;
221 }
222 unsigned int carry=1, t=val_by2on3(div) | 1;
223 while(t) {
224 if(t&1) carry=((carry*rem)%div)&0xffff;
225 rem=((rem*rem)%div)&0xffff;
226 t>>=1;
227 }
228 cCamCryptVG2_PartialMod(carry,count2,key2,key1);
229 }
230 unsigned short idatacount=0;
231 int i;
232 for(i=31; i>=0; i--) cCamCryptVG2_LongMult(idata,&idatacount,key1[i],key2[i]);
233 swap_lb (data, 64);
234 unsigned char stateD1[16];
235 cCamCryptVG2_Reorder16A(stateD1,data);
236 cAES_SetKey(stateD1);
237 break;
238 }
239 }
240}
241
242static void cCamCryptVG2_Process_D1(const unsigned char *ins, unsigned char *data, const unsigned char *status)
243{
244 unsigned char iter[16], tmp[16];
245 memset(iter,0,sizeof(iter));
246 memcpy(iter,ins,5);
247 xor16(iter,stateD3A,iter);
248 memcpy(stateD3A,iter,sizeof(iter));
249
250 int datalen=status-data;
251 int datalen1=datalen;
252 if(datalen<0) datalen1+=15;
253 int blocklen=datalen1>>4;
254 int i;
255 int iblock;
256 for(i=0,iblock=0; i<blocklen+2; i++,iblock+=16) {
257 unsigned char in[16];
258 int docalc=1;
259 if(blocklen==i && (docalc=datalen&0xf)) {
260 memset(in,0,sizeof(in));
261 memcpy(in,&data[iblock],datalen-(datalen1&~0xf));
262 }
263 else if(blocklen+1==i) {
264 memset(in,0,sizeof(in));
265 memcpy(&in[5],status,2);
266 }
267 else
268 memcpy(in,&data[iblock],sizeof(in));
269
270 if(docalc) {
271 xor16(iter,in,tmp);
272 cCamCryptVG2_ReorderAndEncrypt(tmp);
273 xor16(tmp,stateD3A,iter);
274 }
275 }
276 memcpy(stateD3A,tmp,16);
277}
278
279static void cCamCryptVG2_Decrypt_D3(unsigned char *ins, unsigned char *data, const unsigned char *status)
280{
281 if(ins[4]>16) ins[4]-=16;
282 if(ins[1]==0xbe) memset(stateD3A,0,sizeof(stateD3A));
283
284 unsigned char tmp[16];
285 memset(tmp,0,sizeof(tmp));
286 memcpy(tmp,ins,5);
287 xor16(tmp,stateD3A,stateD3A);
288
289 int len1=ins[4];
290 int blocklen=len1>>4;
291 if(ins[1]!=0xbe) blocklen++;
292
293 unsigned char iter[16], states[16][16];
294 memset(iter,0,sizeof(iter));
295 int blockindex;
296 for(blockindex=0; blockindex<blocklen; blockindex++) {
297 iter[0]+=blockindex;
298 xor16(iter,stateD3A,iter);
299 cCamCryptVG2_ReorderAndEncrypt(iter);
300 xor16(iter,&data[blockindex*16],states[blockindex]);
301 if(blockindex==(len1>>4)) {
302 int c=len1-(blockindex*16);
303 if(c<16) memset(&states[blockindex][c],0,16-c);
304 }
305 xor16(states[blockindex],stateD3A,stateD3A);
306 cCamCryptVG2_RotateRightAndHash(stateD3A);
307 }
308 memset(tmp,0,sizeof(tmp));
309 memcpy(tmp+5,status,2);
310 xor16(tmp,stateD3A,stateD3A);
311 cCamCryptVG2_ReorderAndEncrypt(stateD3A);
312
313 memcpy(stateD3A,status-16,sizeof(stateD3A));
314 cCamCryptVG2_ReorderAndEncrypt(stateD3A);
315
316 memcpy(data,states[0],len1);
317 if(ins[1]==0xbe) {
318 cCamCryptVG2_Reorder16A(tmp,states[0]);
319 cAES_SetKey(tmp);
320 }
321}
322
323static void cCamCryptVG2_ReorderAndEncrypt(unsigned char *p)
324{
325 unsigned char tmp[16];
326 cCamCryptVG2_Reorder16A(tmp,p);
327 cAES_Encrypt(tmp,16,tmp);
328 cCamCryptVG2_Reorder16A(p,tmp);
329}
330
331// reorder AAAABBBBCCCCDDDD to ABCDABCDABCDABCD
332
333static void cCamCryptVG2_Reorder16A(unsigned char *dest, const unsigned char *src)
334{
335 int i;
336 int j;
337 int k;
338 for(i=0,k=0; i<4; i++)
339 for(j=i; j<16; j+=4,k++)
340 dest[k]=src[j];
341}
342
343static void cCamCryptVG2_LongMult(unsigned short *pData, unsigned short *pLen, unsigned int mult, unsigned int carry)
344{
345 int i;
346 for(i=0; i<*pLen; i++) {
347 carry+=pData[i]*mult;
348 pData[i]=(unsigned short)carry;
349 carry>>=16;
350 }
351 if(carry) pData[(*pLen)++]=carry;
352}
353
354static void cCamCryptVG2_PartialMod(unsigned short val, unsigned int count, unsigned short *outkey, const unsigned short *inkey)
355{
356 if(count) {
357 unsigned int mod=inkey[count];
358 unsigned short mult=(inkey[count]-outkey[count-1])&0xffff;
359 unsigned int i;
360 unsigned int ib1;
361 for(i=0,ib1=count-2; i<count-1; i++,ib1--) {
362 unsigned int t=(inkey[ib1]*mult)%mod;
363 mult=t-outkey[ib1];
364 if(mult>t) mult+=mod;
365 }
366 mult+=val;
367 if((val>mult) || (mod<mult)) mult-=mod;
368 outkey[count]=(outkey[count]*mult)%mod;
369 }
370 else
371 outkey[0]=val;
372}
373
374static const unsigned char table1[256] = {
375 0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5, 0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76,
376 0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0, 0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0,
377 0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc, 0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15,
378 0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a, 0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75,
379 0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0, 0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84,
380 0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b, 0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf,
381 0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85, 0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8,
382 0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5, 0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2,
383 0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17, 0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73,
384 0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88, 0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb,
385 0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c, 0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79,
386 0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9, 0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08,
387 0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6, 0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a,
388 0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e, 0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e,
389 0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94, 0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf,
390 0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68, 0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16,
391 };
392
393static void cCamCryptVG2_RotateRightAndHash(unsigned char *p)
394{
395 unsigned char t1=p[15];
396 int i;
397 for(i=0; i<16; i++) {
398 unsigned char t2=t1;
399 t1=p[i]; p[i]=table1[(t1>>1)|((t2&1)<<7)];
400 }
401}
402
403////// ====================================================================================
404
405unsigned char CW1[8], CW2[8];
406
407extern uchar cta_res[];
408extern ushort cta_lr;
409
410extern int io_serial_need_dummy_char;
411
412struct CmdTabEntry {
413 unsigned char cla;
414 unsigned char cmd;
415 unsigned char len;
416 unsigned char mode;
417};
418
419struct CmdTab {
420 unsigned char index;
421 unsigned char size;
422 unsigned char Nentries;
423 unsigned char dummy;
424 struct CmdTabEntry e[1];
425};
426
427struct CmdTab *cmd_table=NULL;
428static void memorize_cmd_table (const unsigned char *mem, int size){
429 cmd_table=(struct CmdTab *)malloc(sizeof(unsigned char) * size);
430 memcpy(cmd_table,mem,size);
431}
432
433static int cmd_table_get_info(const unsigned char *cmd, unsigned char *rlen, unsigned char *rmode)
434{
435 struct CmdTabEntry *pcte=cmd_table->e;
436 int i;
437 for(i=0; i<cmd_table->Nentries; i++,pcte++)
438 if(cmd[1]==pcte->cmd) {
439 *rlen=pcte->len;
440 *rmode=pcte->mode;
441 return 1;
442 }
443 return 0;
444}
445
446static int status_ok(const unsigned char *status){
447 //cs_log("[videoguard2-reader] check status %02x%02x", status[0],status[1]);
448 return (status[0] == 0x90 || status[0] == 0x91)
449 && (status[1] == 0x00 || status[1] == 0x01
450 || status[1] == 0x20 || status[1] == 0x21
451 || status[1] == 0x80 || status[1] == 0x81
452 || status[1] == 0xa0 || status[1] == 0xa1);
453}
454
455#define write_cmd(cmd, data) (card_write(cmd, data) == 0)
456#define read_cmd(cmd, data) (card_write(cmd, NULL) == 0)
457
458static int read_cmd_len(const unsigned char *cmd)
459{
460 unsigned char cmd2[5];
461 memcpy(cmd2,cmd,5);
462 cmd2[3]=0x80;
463 cmd2[4]=1;
464 if(!read_cmd(cmd2,NULL) || cta_res[1] != 0x90 || cta_res[2] != 0x00) {
465 cs_debug("[videoguard2-reader] failed to read %02x%02x cmd length (%02x %02x)",cmd[1],cmd[2],cta_res[1],cta_res[2]);
466 return -1;
467 }
468 return cta_res[0];
469}
470
471static int do_cmd(const unsigned char *ins, const unsigned char *txbuff, unsigned char *rxbuff)
472{
473 unsigned char ins2[5];
474 memcpy(ins2,ins,5);
475 unsigned char len=0, mode=0;
476 if(cmd_table_get_info(ins2,&len,&mode)) {
477 if(len==0xFF && mode==2) {
478 if(ins2[4]==0) ins2[4]=len=read_cmd_len(ins2);
479 }
480 else if(mode!=0) ins2[4]=len;
481 }
482 if(ins2[0]==0xd3) ins2[4]=len+16;
483 len=ins2[4];
484
485 unsigned char tmp[264];
486 if(!rxbuff) rxbuff=tmp;
487 if(mode>1) {
488 if(!read_cmd(ins2,NULL) || !status_ok(cta_res+len)) return -1;
489 memcpy(rxbuff,ins2,5);
490 memcpy(rxbuff+5,cta_res,len);
491 memcpy(rxbuff+5+len,cta_res+len,2);
492 }
493 else {
494 if(!write_cmd(ins2,(uchar *)txbuff) || !status_ok(cta_res)) return -2;
495 memcpy(rxbuff,ins2,5);
496 memcpy(rxbuff+5,txbuff,len);
497 memcpy(rxbuff+5+len,cta_res,2);
498 }
499
500 cCamCryptVG2_PostProcess_Decrypt(rxbuff,len,CW1,CW2);
501
502 // Log decrypted INS54
503 ///if (rxbuff[1] == 0x54) {
504 /// cs_dump (rxbuff, 5, "Decrypted INS54:");
505 /// cs_dump (rxbuff + 5, rxbuff[4], "");
506 ///}
507
508 return len;
509}
510
511static void rev_date_calc(const unsigned char *Date, int *year, int *mon, int *day, int *hh, int *mm, int *ss)
512{
513 *year=(Date[0]/12)+BASEYEAR;
514 *mon=(Date[0]%12)+1;
515 *day=Date[1];
516 *hh=Date[2]/8;
517 *mm=(0x100*(Date[2]-*hh*8)+Date[3])/32;
518 *ss=(Date[3]-*mm*32)*2;
519}
520
521typedef struct{
522 unsigned short id;
523 char name[32];
524} tier_t;
525
526static tier_t skyit_tiers[] =
527{
528 { 0x0320, "Promo" },
529 { 0x000B, "Service" },
530 { 0x0219, "Mondo HD" },
531 { 0x021A, "Cinema HD" },
532 { 0x021B, "Cinema" },
533 { 0x0222, "Sport HD" },
534 { 0x0224, "Sky Play IT" },
535 { 0x0226, "Mondo" },
536 { 0x0228, "Sport" },
537 { 0x0229, "Disney Channel" },
538 { 0x022A, "Inter Channel" },
539 { 0x022B, "Milan Channel" },
540 { 0x022C, "Roma Channel" },
541 { 0x022D, "Classica" },
542 { 0x022E, "Music & News" },
543 { 0x022F, "Caccia e Pesca" },
544 { 0x023D, "Juventus Channel" },
545 { 0x023E, "Moto TV" },
546 { 0x026B, "Calcio HD" },
547 { 0x0275, "Promo" },
548 { 0x0295, "Calcio" },
549 { 0x0296, "Serie B" },
550 { 0x02FE, "PPV" }
551};
552
553static char *get_tier_name(unsigned short tier_id){
554 static char *empty = "";
555 unsigned int i;
556
557 switch (reader[ridx].caid[0])
558 {
559 case 0x919:
560 case 0x93b:
561 for (i = 0; i < sizeof(skyit_tiers) / sizeof(tier_t); ++i)
562 if (skyit_tiers[i].id == tier_id)
563 return skyit_tiers[i].name;
564 break;
565 }
566 return empty;
567}
568
569static void read_tiers(void)
570{
571 static const unsigned char ins2a[5] = { 0xd0,0x2a,0x00,0x00,0x00 };
572 int l;
573 l=do_cmd(ins2a,NULL,NULL);
574 if(l<0 || !status_ok(cta_res+l)) return;
575 static unsigned char ins76[5] = { 0xd0,0x76,0x00,0x00,0x00 };
576 ins76[3]=0x7f; ins76[4]=2;
577 if(!read_cmd(ins76,NULL) || !status_ok(cta_res+2)) return;
578 ins76[3]=0; ins76[4]=0;
579 int num=cta_res[1];
580 int i;
581 reader[ridx].init_history_pos = 0; //reset for re-read
582 memset(reader[ridx].init_history, 0, sizeof(reader[ridx].init_history));
583 for(i=0; i<num; i++) {
584 ins76[2]=i;
585 l=do_cmd(ins76,NULL,NULL);
586 if(l<0 || !status_ok(cta_res+l)) return;
587 if(cta_res[2]==0 && cta_res[3]==0) break;
588 int y,m,d,H,M,S;
589 rev_date_calc(&cta_res[4],&y,&m,&d,&H,&M,&S);
590 unsigned short tier_id = (cta_res[2] << 8) | cta_res[3];
591 char *tier_name = get_tier_name(tier_id);
592 cs_ri_log("[videoguard2-reader] tier: %04x, expiry date: %04d/%02d/%02d-%02d:%02d:%02d %s",tier_id,y,m,d,H,M,S,tier_name);
593 }
594}
595
596int videoguard_card_init(ATR newatr)
597{
598 get_hist;
599 if ((hist_size < 7) || (hist[1] != 0xB0) || (hist[4] != 0xFF) || (hist[5] != 0x4A) || (hist[6] != 0x50))
600 return ERROR;
601 get_atr;
602 /* known atrs */
603 unsigned char atr_bskyb[] = { 0x3F, 0x7F, 0x13, 0x25, 0x03, 0x33, 0xB0, 0x06, 0x69, 0xFF, 0x4A, 0x50, 0xD0, 0x00, 0x00, 0x53, 0x59, 0x00, 0x00, 0x00 };
604 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 };
605 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 };
606 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 };
607 unsigned char atr_directv[] = { 0x3F, 0x78, 0x13, 0x25, 0x03, 0x40, 0xB0, 0x20, 0xFF, 0xFF, 0x4A, 0x50, 0x00 };
608 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 };
609 unsigned char atr_viasat_new[] = { 0x3F, 0x7D, 0x11, 0x25, 0x02, 0x41, 0xB0, 0x03, 0x69, 0xFF, 0x4A, 0x50, 0xF0, 0x80, 0x00, 0x56, 0x54, 0x03};
610 unsigned char atr_viasat_scandinavia[] = { 0x3F, 0x7F, 0x11, 0x25, 0x03, 0x33, 0xB0, 0x09, 0x69, 0xFF, 0x4A, 0x50, 0x70, 0x00, 0x00, 0x56, 0x54, 0x01, 0x00, 0x00 };
611 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 };
612 unsigned char atr_kbw[] = { 0x3F, 0xFF, 0x14, 0x25, 0x03, 0x10, 0x80, 0x54, 0xB0, 0x01, 0x69, 0xFF, 0x4A, 0x50, 0x70, 0x00, 0x00, 0x4B, 0x57, 0x01, 0x00, 0x00};
613 unsigned char atr_get[] = { 0x3F, 0xFF, 0x14, 0x25, 0x03, 0x10, 0x80, 0x33, 0xB0, 0x10, 0x69, 0xFF, 0x4A, 0x50, 0x70, 0x00, 0x00, 0x5A, 0x45, 0x01, 0x00, 0x00};
614 unsigned char atr_foxtel_90b[] = { 0x3F, 0x7F, 0x11, 0x25, 0x03, 0x33, 0xB0, 0x09, 0x69, 0xFF, 0x4A, 0x50, 0x70, 0x00, 0x00, 0x46, 0x44, 0x01, 0x00, 0x00};
615
616 if ((atr_size == sizeof (atr_bskyb)) && (memcmp (atr, atr_bskyb, atr_size) == 0))
617 {
618 cs_ri_log("[videoguard2-reader] type: VideoGuard BSkyB");
619 /* BSkyB seems to need one additionnal byte in the serial communication... */
620 io_serial_need_dummy_char = 1;
621 BASEYEAR = 2000;
622 }
623 else if ((atr_size == sizeof (atr_bskyb_new)) && (memcmp (atr, atr_bskyb_new, atr_size) == 0))
624 {
625 cs_ri_log("[videoguard2-reader] type: VideoGuard BSkyB - New");
626 }
627 else if ((atr_size == sizeof (atr_skyitalia)) && (memcmp (atr, atr_skyitalia, atr_size) == 0))
628 {
629 cs_ri_log("[videoguard2-reader] type: VideoGuard Sky Italia");
630 }
631 else if ((atr_size == sizeof (atr_directv)) && (memcmp (atr, atr_directv, atr_size) == 0))
632 {
633 cs_ri_log("[videoguard2-reader] type: VideoGuard DirecTV");
634 }
635 else if ((atr_size == sizeof (atr_yes)) && (memcmp (atr, atr_yes, atr_size) == 0))
636 {
637 cs_ri_log("[videoguard2-reader] type: VideoGuard YES DBS Israel");
638 }
639 else if ((atr_size == sizeof (atr_viasat_new)) && (memcmp (atr, atr_viasat_new, atr_size) == 0))
640 {
641 cs_ri_log("[videoguard2-reader] type: VideoGuard Viasat new (093E)");
642 BASEYEAR = 2000;
643 }
644 else if ((atr_size == sizeof (atr_viasat_scandinavia)) && (memcmp (atr, atr_viasat_scandinavia, atr_size) == 0))
645 {
646 cs_ri_log("[videoguard2-reader] type: VideoGuard Viasat Scandinavia");
647 BASEYEAR = 2000;
648 }
649 else if ((atr_size == sizeof (atr_skyitalia93b)) && (memcmp (atr, atr_skyitalia93b, atr_size) == 0))
650 {
651 cs_ri_log("[videoguard2-reader] type: VideoGuard Sky Italia new (093B)");
652 }
653 else if ((atr_size == sizeof (atr_premiere)) && (memcmp (atr, atr_premiere, atr_size) == 0))
654 {
655 cs_ri_log("[videoguard2-reader] type: VideoGuard Sky Germany");
656 }
657 else if ((atr_size == sizeof (atr_kbw)) && (memcmp (atr, atr_kbw, atr_size) == 0))
658 {
659 cs_ri_log("[videoguard2-reader] type: VideoGuard Kabel BW");
660 }
661 else if ((atr_size == sizeof (atr_get)) && (memcmp (atr, atr_get, atr_size) == 0))
662 {
663 cs_ri_log("[videoguard2-reader] type: VideoGuard Get Kabel Norway");
664 BASEYEAR = 2004;
665 }
666 else if ((atr_size == sizeof (atr_foxtel_90b)) && (memcmp (atr, atr_foxtel_90b, atr_size) == 0))
667 {
668 cs_ri_log("[videoguard2-reader] type: VideoGuard Foxtel Australia (090b)");
669 BASEYEAR = 2000;
670 }
671/* else
672 {
673 // not a known videoguard
674 return (0);
675 }*/
676 //a non videoguard2/NDS card will fail on read_cmd_len(ins7401)
677 //this way also unknown videoguard2/NDS cards will work
678
679 unsigned char ins7401[5] = { 0xD0,0x74,0x01,0x00,0x00 };
680 int l;
681 if((l=read_cmd_len(ins7401))<0) return ERROR; //not a videoguard2/NDS card or communication error
682 ins7401[4]=l;
683 if(!read_cmd(ins7401,NULL) || !status_ok(cta_res+l)) {
684 cs_log ("[videoguard2-reader] failed to read cmd list");
685 return ERROR;
686 }
687 memorize_cmd_table (cta_res,l);
688
689 unsigned char buff[256];
690
691 unsigned char ins7416[5] = { 0xD0,0x74,0x16,0x00,0x00 };
692 if(do_cmd(ins7416, NULL, NULL)<0) {
693 cs_log ("[videoguard2-reader] cmd 7416 failed");
694 return ERROR;
695 }
696
697 unsigned char ins36[5] = { 0xD0,0x36,0x00,0x00,0x00 };
698 unsigned char boxID [4];
699
700 if (reader[ridx].boxid > 0) {
701 /* the boxid is specified in the config */
702 int i;
703 for (i=0; i < 4; i++) {
704 boxID[i] = (reader[ridx].boxid >> (8 * (3 - i))) % 0x100;
705 }
706 } else {
707 /* we can try to get the boxid from the card */
708 int boxidOK=0;
709 l=do_cmd(ins36, NULL, buff);
710 if(l>=0) {
711 int i;
712 for(i=0; i<l ;i++) {
713 if(buff[i+1]==0xF3 && (buff[i]==0x00 || buff[i]==0x0A)) {
714 memcpy(&boxID,&buff[i+2],sizeof(boxID));
715 boxidOK=1;
716 break;
717 }
718 }
719 }
720
721 if(!boxidOK) {
722 cs_log ("[videoguard2-reader] no boxID available");
723 return ERROR;
724 }
725 }
726
727 unsigned char ins4C[5] = { 0xD0,0x4C,0x00,0x00,0x09 };
728 unsigned char payload4C[9] = { 0,0,0,0, 3,0,0,0,4 };
729 memcpy(payload4C,boxID,4);
730 if(!write_cmd(ins4C,payload4C) || !status_ok(cta_res+l)) {
731 cs_log("[videoguard2-reader] sending boxid failed");
732 return ERROR;
733 }
734
735 //short int SWIRDstatus = cta_res[1];
736 unsigned char ins58[5] = { 0xD0,0x58,0x00,0x00,0x00 };
737 l=do_cmd(ins58, NULL, buff);
738 if(l<0) {
739 cs_log("[videoguard2-reader] cmd ins58 failed");
740 return ERROR;
741 }
742 memset(reader[ridx].hexserial, 0, 8);
743 memcpy(reader[ridx].hexserial+2, cta_res+3, 4);
744 reader[ridx].caid[0] = cta_res[24]*0x100+cta_res[25];
745
746 /* we have one provider, 0x0000 */
747 reader[ridx].nprov = 1;
748 memset(reader[ridx].prid, 0x00, sizeof(reader[ridx].prid));
749
750 /*
751 cs_log ("[videoguard2-reader] INS58 : Fuse byte=0x%02X, IRDStatus=0x%02X", cta_res[2],SWIRDstatus);
752 if (SWIRDstatus==4) {
753 // If swMarriage=4, not married then exchange for BC Key
754 cs_log ("[videoguard2-reader] Card not married, exchange for BC Keys");
755 */
756
757 unsigned char seed1[] = {
758 0xb9, 0xd5, 0xef, 0xd5, 0xf5, 0xd5, 0xfb, 0xd5, 0x31, 0xd6, 0x43, 0xd6, 0x55, 0xd6, 0x61, 0xd6,
759 0x85, 0xd6, 0x9d, 0xd6, 0xaf, 0xd6, 0xc7, 0xd6, 0xd9, 0xd6, 0x09, 0xd7, 0x15, 0xd7, 0x21, 0xd7,
760 0x27, 0xd7, 0x3f, 0xd7, 0x45, 0xd7, 0xb1, 0xd7, 0xbd, 0xd7, 0xdb, 0xd7, 0x11, 0xd8, 0x23, 0xd8,
761 0x29, 0xd8, 0x2f, 0xd8, 0x4d, 0xd8, 0x8f, 0xd8, 0xa1, 0xd8, 0xad, 0xd8, 0xbf, 0xd8, 0xd7, 0xd8
762 };
763 unsigned char seed2[] = {
764 0x01, 0x00, 0xcf, 0x13, 0xe0, 0x60, 0x54, 0xac, 0xab, 0x99, 0xe6, 0x0c, 0x9f, 0x5b, 0x91, 0xb9,
765 0x72, 0x72, 0x4d, 0x5b, 0x5f, 0xd3, 0xb7, 0x5b, 0x01, 0x4d, 0xef, 0x9e, 0x6b, 0x8a, 0xb9, 0xd1,
766 0xc9, 0x9f, 0xa1, 0x2a, 0x8d, 0x86, 0xb6, 0xd6, 0x39, 0xb4, 0x64, 0x65, 0x13, 0x77, 0xa1, 0x0a,
767 0x0c, 0xcf, 0xb4, 0x2b, 0x3a, 0x2f, 0xd2, 0x09, 0x92, 0x15, 0x40, 0x47, 0x66, 0x5c, 0xda, 0xc9
768 };
769 cCamCryptVG2_SetSeed(seed1,seed2);
770
771 unsigned char insB4[5] = { 0xD0,0xB4,0x00,0x00,0x40 };
772 unsigned char tbuff[64];
773 cCamCryptVG2_GetCamKey(tbuff);
774 l=do_cmd(insB4, tbuff, NULL);
775 if(l<0 || !status_ok(cta_res)) {
776 cs_log ("[videoguard2-reader] cmd D0B4 failed (%02X%02X)", cta_res[0], cta_res[1]);
777 return ERROR;
778 }
779
780 unsigned char insBC[5] = { 0xD0,0xBC,0x00,0x00,0x00 };
781 l=do_cmd(insBC, NULL, NULL);
782 if(l<0) {
783 cs_log("[videoguard2-reader] cmd D0BC failed");
784 return ERROR;
785 }
786
787 unsigned char insBE[5] = { 0xD3,0xBE,0x00,0x00,0x00 };
788 l=do_cmd(insBE, NULL, NULL);
789 if(l<0) {
790 cs_log("[videoguard2-reader] cmd D3BE failed");
791 return ERROR;
792 }
793
794 unsigned char ins58a[5] = { 0xD1,0x58,0x00,0x00,0x00 };
795 l=do_cmd(ins58a, NULL, NULL);
796 if(l<0) {
797 cs_log("[videoguard2-reader] cmd D158 failed");
798 return ERROR;
799 }
800
801 unsigned char ins4Ca[5] = { 0xD1,0x4C,0x00,0x00,0x00 };
802 l=do_cmd(ins4Ca,payload4C, NULL);
803 if(l<0 || !status_ok(cta_res)) {
804 cs_log("[videoguard2-reader] cmd D14Ca failed");
805 return ERROR;
806 }
807
808 cs_ri_log("[videoguard2-reader] type: VideoGuard, caid: %04X, serial: %02X%02X%02X%02X, BoxID: %02X%02X%02X%02X",
809 reader[ridx].caid[0],
810 reader[ridx].hexserial[2],reader[ridx].hexserial[3],reader[ridx].hexserial[4],reader[ridx].hexserial[5],
811 boxID[0],boxID[1],boxID[2],boxID[3]);
812
813 ///read_tiers();
814
815 cs_log("[videoguard2-reader] ready for requests");
816
817 return OK;
818}
819
820int videoguard_do_ecm(ECM_REQUEST *er)
821{
822 static unsigned char ins40[5] = { 0xD1,0x40,0x00,0x80,0xFF };
823 static const unsigned char ins54[5] = { 0xD3,0x54,0x00,0x00,0x00};
824 int posECMpart2=er->ecm[6]+7;
825 int lenECMpart2=er->ecm[posECMpart2]+1;
826 unsigned char tbuff[264];
827 tbuff[0]=0;
828 memcpy(&tbuff[1],&(er->ecm[posECMpart2+1]),lenECMpart2-1);
829 ins40[4]=lenECMpart2;
830 int l;
831 l = do_cmd(ins40,tbuff,NULL);
832 if(l>0 && status_ok(cta_res)) {
833 l = do_cmd(ins54,NULL,NULL);
834 if(l>0 && status_ok(cta_res+l)) {
835 if (!cw_is_valid(CW1)) //sky cards report 90 00 = ok but send cw = 00 when channel not subscribed
836 return ERROR;
837 if(er->ecm[0]&1) {
838 memcpy(er->cw+8,CW1,8);
839 memcpy(er->cw+0,CW2,8);
840 }
841 else {
842 memcpy(er->cw+0,CW1,8);
843 memcpy(er->cw+8,CW2,8);
844 }
845
846 //test for postprocessing marker
847 int posB0 = -1;
848 int i;
849 for (i = 6; i < posECMpart2; i++)
850 {
851 if (er->ecm[i] == 0xB0 && er->ecm[i+1] == 0x01 ) {
852 posB0 = i;
853 break;
854 }
855 }
856 if (posB0 != -1) {
857 postprocess_cw(er->cw+0, er->ecm[posB0+2]);
858 postprocess_cw(er->cw+8, er->ecm[posB0+2]);
859 }
860 return OK;
861 }
862 }
863 return ERROR;
864}
865
866static int num_addr(const unsigned char *data)
867{
868 return ((data[3]&0x30)>>4)+1;
869}
870
871static int addr_mode(const unsigned char *data)
872{
873 switch(data[3]&0xC0) {
874 case 0x40: return 3;
875 case 0x80: return 2;
876 default: return 0;
877 }
878}
879
880static const unsigned char * payload_addr(const unsigned char *data, const unsigned char *a)
881{
882 int s;
883 int l;
884 const unsigned char *ptr = NULL;
885
886 switch(addr_mode(data)) {
887 case 2: s=3; break;
888 case 3: case 0: s=4; break;
889 default: return NULL;
890 }
891
892 int position=-1;
893 for(l=0;l<num_addr(data);l++) {
894 if(!memcmp(&data[l*4+4],a+2,s)) {
895 position=l;
896 break;
897 }
898 }
899
900 /* skip EMM-G but not EMM from cccam */
901 if (position == -1 && data[1] != 0x00) return NULL;
902
903 int num_ua = (position == -1) ? 0 : num_addr(data);
904
905 /* skip header and the list of addresses */
906 ptr = data+4+4*num_ua;
907
908 if (*ptr != 0x02) // some clients omit 00 00 separator */
909 {
910 ptr += 2; // skip 00 00 separator
911 if (*ptr == 0x00) ptr++; // skip optional 00
912 ptr++; // skip the 1st bitmap len
913 }
914
915 /* check */
916 if (*ptr != 0x02) return NULL;
917
918 /* skip the 1st timestamp 02 00 or 02 06 xx aabbccdd yy */
919 ptr += 2 + ptr[1];
920
921 for(l=0;l<position;l++) {
922
923 /* skip the payload of the previous SA */
924 ptr += 1 + ptr [0];
925
926 /* skip optional 00 */
927 if (*ptr == 0x00) ptr++;
928
929 /* skip the bitmap len */
930 ptr++;
931
932 /* check */
933 if (*ptr != 0x02) return NULL;
934
935 /* skip the timestamp 02 00 or 02 06 xx aabbccdd yy */
936 ptr += 2 + ptr[1];
937 }
938
939 return ptr;
940}
941
942int videoguard_do_emm(EMM_PACKET *ep)
943{
944 unsigned char ins42[5] = { 0xD1,0x42,0x00,0x00,0xFF };
945 int rc=ERROR;
946
947 const unsigned char *payload = payload_addr(ep->emm, reader[ridx].hexserial);
948 while (payload) {
949 ins42[4]=*payload;
950 int l = do_cmd(ins42,payload+1,NULL);
951 if(l>0 && status_ok(cta_res)) {
952 rc=OK;
953 }
954
955 cs_log("[videoguard2-reader] EMM request return code : %02X%02X", cta_res[0], cta_res[1]);
956//cs_dump(ep->emm, 64, "EMM:");
957 if (status_ok (cta_res) && (cta_res[1] & 0x01)) {
958 read_tiers();
959 }
960
961 if (num_addr(ep->emm) == 1 && (int)(&payload[1] - &ep->emm[0]) + *payload + 1 < ep->l) {
962 payload += *payload + 1;
963 if (*payload == 0x00) ++payload;
964 ++payload;
965 if (*payload != 0x02) break;
966 payload += 2 + payload[1];
967 }
968 else
969 payload = 0;
970
971 }
972
973 return(rc);
974}
975
976int videoguard_card_info(void)
977{
978 /* info is displayed in init, or when processing info */
979 cs_log("[videoguard2-reader] card detected");
980 cs_log("[videoguard2-reader] type: VideoGuard" );
981 read_tiers ();
982 return OK;
983}
Note: See TracBrowser for help on using the repository browser.