source: trunk/reader-videoguard2.c@ 1717

Last change on this file since 1717 was 1717, checked in by merek, 11 years ago

Merge from UMP r1790 - dingo35: Keep improvements of old postprocess routine

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