source: trunk/reader-videoguard-common.c@ 4149

Last change on this file since 4149 was 4141, checked in by dingo35, 13 years ago

all: simplify debug system, add D_DVBAPI = -d128, eliminate cs_ptyp which complicates stuff unnecc

File size: 35.4 KB
Line 
1//
2// Common videoguard functions.
3//
4#include "globals.h"
5#include "reader-common.h"
6#include "reader-videoguard-common.h"
7
8void set_known_card_info(struct s_reader * reader, const unsigned char * atr, const unsigned int *atr_size)
9{
10 /* Set to sensible default values */
11 reader->card_baseyear = 1997;
12 reader->card_tierstart = 0;
13 reader->card_system_version = NDSUNKNOWN;
14 reader->card_desc = "VideoGuard Unknown Card";
15
16 NDS_ATR_ENTRY nds_atr_table[]={ // {atr}, atr len, base year, tier start, nds version, description
17 /* known NDS1 atrs */
18 {{ 0x3F, 0x78, 0x13, 0x25, 0x04, 0x40, 0xB0, 0x09, 0x4A, 0x50, 0x01, 0x4E, 0x5A },
19 13, 1992, 0, NDS1, "VideoGuard Sky New Zealand (0969)"}, //160E
20 {{ 0x3F, 0x78, 0x12, 0x25, 0x01, 0x40, 0xB0, 0x14, 0x4A, 0x50, 0x01, 0x53, 0x44 },
21 13, 1997, 0, NDS1, "VideoGuard StarTV India (caid unknown)"}, //105.5E
22 /* known NDS1+ atrs */
23 {{ 0x3F, 0x7F, 0x13, 0x25, 0x04, 0x33, 0xB0, 0x02, 0x69, 0xFF, 0x4A, 0x50, 0xE0, 0x00, 0x00, 0x54,
24 0x42, 0x00, 0x00, 0x00 },
25 20, 1997, 0, NDS12, "VideoGuard China (0988)"},
26 {{ 0x3F, 0x78, 0x13, 0x25, 0x03, 0x40, 0xB0, 0x20, 0xFF, 0xFF, 0x4A, 0x50, 0x00 },
27 13, 1997, 0, NDS12, "VideoGuard DirecTV"},
28 /* known NDS2 atrs */
29 {{ 0x3F, 0xFD, 0x13, 0x25, 0x02, 0x50, 0x80, 0x0F, 0x33, 0xB0, 0x08, 0xFF, 0xFF, 0x4A, 0x50, 0x90,
30 0x00, 0x00, 0x47, 0x4C, 0x01 },
31 21, 2004, 0, NDS2, "VideoGuard Sky Brasil GL39 (0907)"},
32 {{ 0x3F, 0x7F, 0x11, 0x25, 0x03, 0x33, 0xB0, 0x09, 0x69, 0xFF, 0x4A, 0x50, 0x70, 0x00, 0x00, 0x46,
33 0x44, 0x01, 0x00, 0x00 },
34 20, 2000, 0, NDS2, "VideoGuard Foxtel Australia (090B)"}, //156E
35 {{ 0x3F, 0xFF, 0x13, 0x25, 0x03, 0x10, 0x80, 0x33, 0xB0, 0x0E, 0x69, 0xFF, 0x4A, 0x50, 0x70, 0x00,
36 0x00, 0x49, 0x54, 0x02, 0x00, 0x00 },
37 22, 1997, 0, NDS2, "VideoGuard Sky Italia (0919)"},
38 {{ 0x3F, 0xFF, 0x14, 0x25, 0x03, 0x10, 0x80, 0x41, 0xB0, 0x01, 0x69, 0xFF, 0x4A, 0x50, 0x70, 0x00,
39 0x00, 0x5A, 0x4A, 0x01, 0x00, 0x00 },
40 22, 2004, 0, NDS2, "VideoGuard Dolce Romania (092F)"},
41 {{ 0x3F, 0xFF, 0x13, 0x25, 0x03, 0x10, 0x80, 0x54, 0xB0, 0x01, 0x69, 0xFF, 0x4A, 0x50, 0x70, 0x00,
42 0x00, 0x41, 0x55, 0x01, 0x00, 0x00 },
43 22, 1997, 0, NDS2, "VideoGuard OnoCable Espana (093A)"},
44 {{ 0x3F, 0xFD, 0x13, 0x25, 0x02, 0x50, 0x80, 0x0F, 0x33, 0xB0, 0x13, 0x69, 0xFF, 0x4A, 0x50, 0xD0,
45 0x80, 0x00, 0x49, 0x54, 0x03 },
46 21, 1997, 0, NDS2, "VideoGuard Sky Italia (093B)"},
47 {{ 0x3F, 0x7D, 0x11, 0x25, 0x02, 0x41, 0xB0, 0x03, 0x69, 0xFF, 0x4A, 0x50, 0xF0, 0x80, 0x00, 0x56,
48 0x54, 0x03 },
49 18, 2000, 0, NDS2, "VideoGuard Viasat (093E)"},
50 {{ 0x3F, 0xFF, 0x13, 0x25, 0x02, 0x40, 0xB0, 0x12, 0x69, 0xFF, 0x4A, 0x50, 0x90, 0x47, 0x4C, 0x00,
51 0x00, 0x00, 0x00, 0x00 },
52 20, 2000, 0, NDS2, "VideoGuard Sky Brasil GL23 (0942)"},
53 {{ 0x3F, 0xFF, 0x13, 0x25, 0x02, 0x50, 0x80, 0x0F, 0x54, 0xB0, 0x03, 0xFF, 0xFF, 0x4A, 0x50, 0x80,
54 0x00, 0x00, 0x00, 0x00, 0x47, 0x4C, 0x05 },
55 23, 2009, 0, NDS2, "VideoGuard Sky Brasil GL54 (0943)"},
56 {{ 0x3F, 0xFD, 0x13, 0x25, 0x02, 0x50, 0x00, 0x0F, 0x33, 0xB0, 0x0F, 0x69, 0xFF, 0x4A, 0x50, 0xD0,
57 0x00, 0x00, 0x53, 0x59, 0x02 },
58 21, 1997, 0, NDS2, "VideoGuard BSkyB (0963)"},
59 {{ 0x3F, 0xFF, 0x13, 0x25, 0x03, 0x10, 0x80, 0x33, 0xB0, 0x10, 0x69, 0xFF, 0x4A, 0x50, 0x70, 0x00,
60 0x00, 0x4E, 0x5A, 0x01, 0x00, 0x00 },
61 22, 1992, 0, NDS2, "VideoGuard Sky New Zealand (096A)"}, //160E
62 {{ 0x3F, 0xFD, 0x11, 0x25, 0x02, 0x50, 0x80, 0x0F, 0x41, 0xB0, 0x03, 0x69, 0xFF, 0x4A, 0x50, 0xF0,
63 0x80, 0x00, 0x46, 0x44, 0x03 },
64 20, 2000, 0, NDS2, "VideoGuard Foxtel Australia (096C)"}, //156E
65 {{ 0x3F, 0xFF, 0x11, 0x25, 0x03, 0x10, 0x80, 0x41, 0xB0, 0x06, 0x69, 0xFF, 0x4A, 0x50, 0x70, 0x00,
66 0x00, 0x41, 0x5A, 0x01, 0x00, 0x11 },
67 22, 2004, 50, NDS2, "VideoGuard Astro Malaysia (09AC)"},
68 {{ 0x3F, 0xFF, 0x14, 0x25, 0x03, 0x10, 0x80, 0x41, 0xB0, 0x07, 0x69, 0xFF, 0x4A, 0x50, 0x70, 0x80,
69 0x00, 0x58, 0x34, 0x01, 0x00, 0x14 },
70 22, 1997, 0, NDS2, "VideoGuard Cingal Philippines (09B4)"},
71 {{ 0x3F, 0xFF, 0x14, 0x25, 0x03, 0x10, 0x80, 0x41, 0xB0, 0x02, 0x69, 0xFF, 0x4A, 0x50, 0x70, 0x80,
72 0x00, 0x58, 0x38, 0x01, 0x00, 0x14 },
73 22, 1997, 0, NDS2, "VideoGuard TopTV (09B8)"},
74 {{ 0x3F, 0xFD, 0x13, 0x25, 0x02, 0x50, 0x80, 0x0F, 0x54, 0xB0, 0x04, 0x69, 0xFF, 0x4A, 0x50, 0xD0,
75 0x80, 0x00, 0x49, 0x54, 0x03 },
76 21, 1997, 0, NDS2, "VideoGuard Sky Italia (09CD)"},
77 {{ 0x3F, 0xFF, 0x13, 0x25, 0x03, 0x10, 0x80, 0x33, 0xB0, 0x11, 0x69, 0xFF, 0x4A, 0x50, 0x50, 0x00,
78 0x00, 0x47, 0x54, 0x01, 0x00, 0x00 },
79 22, 1997, 0, NDS2, "VideoGuard YES DBS Israel"},
80 {{ 0x3F, 0x7F, 0x11, 0x25, 0x03, 0x33, 0xB0, 0x09, 0x69, 0xFF, 0x4A, 0x50, 0x70, 0x00, 0x00, 0x56,
81 0x54, 0x01, 0x00, 0x00 },
82 20, 2000, 0, NDS2, "VideoGuard Viasat Scandinavia"},
83 {{ 0x3F, 0xFF, 0x11, 0x25, 0x03, 0x10, 0x80, 0x41, 0xB0, 0x07, 0x69, 0xFF, 0x4A, 0x50, 0x70, 0x00,
84 0x00, 0x50, 0x31, 0x01, 0x00, 0x11 },
85 22, 1997, 0, NDS2, "VideoGuard Sky Germany"},
86 {{ 0x3F, 0xFF, 0x14, 0x25, 0x03, 0x10, 0x80, 0x41, 0xB0, 0x01, 0x69, 0xFF, 0x4A, 0x50, 0x70, 0x00,
87 0x00, 0x5A, 0x48, 0x01, 0x00, 0x00 },
88 22, 2004, 0, NDS2, "VideoGuard DSMART Turkey"},
89 {{ 0x3F, 0xFF, 0x14, 0x25, 0x03, 0x10, 0x80, 0x54, 0xB0, 0x01, 0x69, 0xFF, 0x4A, 0x50, 0x70, 0x00,
90 0x00, 0x4B, 0x57, 0x01, 0x00, 0x00 },
91 22, 1997, 0, NDS2, "VideoGuard Kabel BW"},
92 {{ 0x3F, 0xFF, 0x14, 0x25, 0x03, 0x10, 0x80, 0x33, 0xB0, 0x10, 0x69, 0xFF, 0x4A, 0x50, 0x70, 0x00,
93 0x00, 0x5A, 0x45, 0x01, 0x00, 0x00 },
94 22 , 2004, 0, NDS2, "VideoGuard Get Kabel Norway"},
95 // NDS Version Unknown as Yet
96 {{ 0x3F, 0x7F, 0x13, 0x25, 0x02, 0x40, 0xB0, 0x12, 0x69, 0xFF, 0x4A, 0x50, 0x90, 0x41, 0x55, 0x00,
97 0x00, 0x00, 0x00, 0x00 },
98 20, 1997, 0, NDSUNKNOWN, "VideoGuard OnoCable Espana (0915)"},
99 {{ 0x3F, 0xFF, 0x14, 0x25, 0x03, 0x10, 0x80, 0x41, 0xB0, 0x07, 0x69, 0xFF, 0x4A, 0x50, 0x70, 0x80,
100 0x00, 0x58, 0x44, 0x01, 0x00, 0x14 },
101 22, 1997, 0, NDSUNKNOWN, "VideoGuard Sky Vivacom (09BD)"}, //45E
102 {{ 0x3F, 0x7F, 0x13, 0x25, 0x05, 0x40, 0xB0, 0x11, 0x69, 0xFF, 0x4A, 0x50, 0x00, 0x00, 0x00, 0x48,
103 0x4B, 0x00, 0x01, 0x00 },
104 20, 1997, 0, NDSUNKNOWN, "VideoGuard StarTV India (caid unknown)"}, //105.5E
105 {{ 0 }, 0, 0, 0, 0, NULL}
106 };
107
108 int i=0;
109 while(nds_atr_table[i].desc) {
110 if ((*atr_size == nds_atr_table[i].atr_len)
111 && (memcmp (atr, nds_atr_table[i].atr, nds_atr_table[i].atr_len) == 0)) {
112 reader->card_baseyear=nds_atr_table[i].base_year;
113 reader->card_tierstart=nds_atr_table[i].tier_start;
114 reader->card_system_version = nds_atr_table[i].nds_version;
115 reader->card_desc = nds_atr_table[i].desc;
116 break;
117 }
118 i++;
119 }
120}
121
122static void cCamCryptVG_LongMult(unsigned short *pData, unsigned short *pLen, unsigned int mult, unsigned int carry);
123static void cCamCryptVG_PartialMod(unsigned short val, unsigned int count, unsigned short *outkey, const unsigned short *inkey);
124static void cCamCryptVG_RotateRightAndHash(unsigned char *p);
125static void cCamCryptVG_Reorder16A(unsigned char *dest, const unsigned char *src);
126static void cCamCryptVG_ReorderAndEncrypt(struct s_reader * reader, unsigned char *p);
127static void cCamCryptVG_Process_D0(struct s_reader * reader, const unsigned char *ins, unsigned char *data);
128static void cCamCryptVG_Process_D1(struct s_reader * reader, const unsigned char *ins, unsigned char *data, const unsigned char *status);
129static void cCamCryptVG_Decrypt_D3(struct s_reader * reader, unsigned char *ins, unsigned char *data, const unsigned char *status);
130static void cCamCryptVG_PostProcess_Decrypt(struct s_reader * reader, unsigned char *rxbuff);
131static int cAES_Encrypt(struct s_reader * reader, const unsigned char *data, int len, unsigned char *crypt);
132static void swap_lb (const unsigned char *buff, int len);
133
134int cw_is_valid(unsigned char *cw, int start) //returns 1 if cw_is_valid, returns 0 if cw is all zeros
135{
136 int i;
137 for (i = start; i < start+8; i++)
138 if (cw[i] != 0) { //test if cw = 00
139 return OK;
140 }
141 return ERROR;
142}
143
144void cAES_SetKey(struct s_reader * reader, const unsigned char *key)
145{
146 AES_set_encrypt_key(key,128,&(reader->ekey));
147}
148
149int cAES_Encrypt(struct s_reader * reader, const unsigned char *data, int len, unsigned char *crypt)
150{
151 len=(len+15)&(~15); // pad up to a multiple of 16
152 int i;
153 for(i=0; i<len; i+=16) AES_encrypt(data+i,crypt+i,&(reader->ekey));
154 return len;
155}
156
157static void swap_lb (const unsigned char *buff, int len)
158{
159
160#if __BYTE_ORDER != __BIG_ENDIAN
161 return;
162
163#endif /* */
164 int i;
165 unsigned short *tmp;
166 for (i = 0; i < len / 2; i++) {
167 tmp = (unsigned short *) buff + i;
168 *tmp = ((*tmp << 8) & 0xff00) | ((*tmp >> 8) & 0x00ff);
169 }
170}
171
172inline void __xxor(unsigned char *data, int len, const unsigned char *v1, const unsigned char *v2)
173{
174 switch(len) { // looks ugly, but the compiler can optimize it very well ;)
175 case 16:
176 *((unsigned int *)data+3) = *((unsigned int *)v1+3) ^ *((unsigned int *)v2+3);
177 *((unsigned int *)data+2) = *((unsigned int *)v1+2) ^ *((unsigned int *)v2+2);
178 case 8:
179 *((unsigned int *)data+1) = *((unsigned int *)v1+1) ^ *((unsigned int *)v2+1);
180 case 4:
181 *((unsigned int *)data+0) = *((unsigned int *)v1+0) ^ *((unsigned int *)v2+0);
182 break;
183 default:
184 while(len--) *data++ = *v1++ ^ *v2++;
185 break;
186 }
187}
188
189void cCamCryptVG_SetSeed(struct s_reader * reader)
190{
191#if __BYTE_ORDER != __BIG_ENDIAN
192 static const unsigned char key1[] = {
193 0xb9, 0xd5, 0xef, 0xd5, 0xf5, 0xd5, 0xfb, 0xd5, 0x31, 0xd6, 0x43, 0xd6, 0x55, 0xd6, 0x61, 0xd6,
194 0x85, 0xd6, 0x9d, 0xd6, 0xaf, 0xd6, 0xc7, 0xd6, 0xd9, 0xd6, 0x09, 0xd7, 0x15, 0xd7, 0x21, 0xd7,
195 0x27, 0xd7, 0x3f, 0xd7, 0x45, 0xd7, 0xb1, 0xd7, 0xbd, 0xd7, 0xdb, 0xd7, 0x11, 0xd8, 0x23, 0xd8,
196 0x29, 0xd8, 0x2f, 0xd8, 0x4d, 0xd8, 0x8f, 0xd8, 0xa1, 0xd8, 0xad, 0xd8, 0xbf, 0xd8, 0xd7, 0xd8
197 };
198 static const unsigned char key2[] = {
199 0x01, 0x00, 0xcf, 0x13, 0xe0, 0x60, 0x54, 0xac, 0xab, 0x99, 0xe6, 0x0c, 0x9f, 0x5b, 0x91, 0xb9,
200 0x72, 0x72, 0x4d, 0x5b, 0x5f, 0xd3, 0xb7, 0x5b, 0x01, 0x4d, 0xef, 0x9e, 0x6b, 0x8a, 0xb9, 0xd1,
201 0xc9, 0x9f, 0xa1, 0x2a, 0x8d, 0x86, 0xb6, 0xd6, 0x39, 0xb4, 0x64, 0x65, 0x13, 0x77, 0xa1, 0x0a,
202 0x0c, 0xcf, 0xb4, 0x2b, 0x3a, 0x2f, 0xd2, 0x09, 0x92, 0x15, 0x40, 0x47, 0x66, 0x5c, 0xda, 0xc9
203 };
204#else
205 static const unsigned char key1[] = {
206 0xd5, 0xb9, 0xd5, 0xef, 0xd5, 0xf5, 0xd5, 0xfb, 0xd6, 0x31, 0xd6, 0x43, 0xd6, 0x55, 0xd6, 0x61,
207 0xd6, 0x85, 0xd6, 0x9d, 0xd6, 0xaf, 0xd6, 0xc7, 0xd6, 0xd9, 0xd7, 0x09, 0xd7, 0x15, 0xd7, 0x21,
208 0xd7, 0x27, 0xd7, 0x3f, 0xd7, 0x45, 0xd7, 0xb1, 0xd7, 0xbd, 0xd7, 0xdb, 0xd8, 0x11, 0xd8, 0x23,
209 0xd8, 0x29, 0xd8, 0x2f, 0xd8, 0x4d, 0xd8, 0x8f, 0xd8, 0xa1, 0xd8, 0xad, 0xd8, 0xbf, 0xd8, 0xd7
210 };
211 static const unsigned char key2[] = {
212 0x00, 0x01, 0x13, 0xcf, 0x60, 0xe0, 0xac, 0x54, 0x99, 0xab, 0x0c, 0xe6, 0x5b, 0x9f, 0xb9, 0x91,
213 0x72, 0x72, 0x5b, 0x4d, 0xd3, 0x5f, 0x5b, 0xb7, 0x4d, 0x01, 0x9e, 0xef, 0x8a, 0x6b, 0xd1, 0xb9,
214 0x9f, 0xc9, 0x2a, 0xa1, 0x86, 0x8d, 0xd6, 0xb6, 0xb4, 0x39, 0x65, 0x64, 0x77, 0x13, 0x0a, 0xa1,
215 0xcf, 0x0c, 0x2b, 0xb4, 0x2f, 0x3a, 0x09, 0xd2, 0x15, 0x92, 0x47, 0x40, 0x5c, 0x66, 0xc9, 0xda
216 };
217#endif
218 memcpy(reader->cardkeys[1],key1,sizeof(reader->cardkeys[1]));
219 memcpy(reader->cardkeys[2],key2,sizeof(reader->cardkeys[2]));
220}
221
222void cCamCryptVG_GetCamKey(struct s_reader * reader, unsigned char *buff)
223{
224 unsigned short *tb2=(unsigned short *)buff, c=1;
225 memset(tb2,0,64);
226 tb2[0]=1;
227 int i;
228 for(i=0; i<32; i++) cCamCryptVG_LongMult(tb2,&c,reader->cardkeys[1][i],0);
229 swap_lb (buff, 64);
230}
231
232static void cCamCryptVG_PostProcess_Decrypt(struct s_reader * reader, unsigned char *rxbuff)
233{
234 switch(rxbuff[0]) {
235 case 0xD0:
236 cCamCryptVG_Process_D0(reader,rxbuff,rxbuff+5);
237 break;
238 case 0xD1:
239 cCamCryptVG_Process_D1(reader,rxbuff,rxbuff+5,rxbuff+rxbuff[4]+5);
240 break;
241 case 0xD3:
242 cCamCryptVG_Decrypt_D3(reader,rxbuff,rxbuff+5,rxbuff+rxbuff[4]+5);
243 break;
244 }
245}
246
247static void cCamCryptVG_Process_D0(struct s_reader * reader, const unsigned char *ins, unsigned char *data)
248{
249 switch(ins[1]) {
250 case 0xb4:
251 swap_lb (data, 64);
252 memcpy(reader->cardkeys[0],data,sizeof(reader->cardkeys[0]));
253 break;
254 case 0xbc:
255 {
256 swap_lb (data, 64);
257 unsigned short *idata=(unsigned short *)data;
258 const unsigned short *key1=(const unsigned short *)reader->cardkeys[1];
259 unsigned short key2[32];
260 memcpy(key2,reader->cardkeys[2],sizeof(key2));
261 int count2;
262 for(count2=0; count2<32; count2++) {
263 unsigned int rem=0, div=key1[count2];
264 int i;
265 for(i=31; i>=0; i--) {
266 unsigned int x=idata[i] | (rem<<16);
267 rem=(x%div)&0xffff;
268 }
269 unsigned int carry=1, t=val_by2on3(div) | 1;
270 while(t) {
271 if(t&1) carry=((carry*rem)%div)&0xffff;
272 rem=((rem*rem)%div)&0xffff;
273 t>>=1;
274 }
275 cCamCryptVG_PartialMod(carry,count2,key2,key1);
276 }
277 unsigned short idatacount=0;
278 int i;
279 for(i=31; i>=0; i--) cCamCryptVG_LongMult(idata,&idatacount,key1[i],key2[i]);
280 swap_lb (data, 64);
281 unsigned char stateD1[16];
282 cCamCryptVG_Reorder16A(stateD1,data);
283 cAES_SetKey(reader,stateD1);
284 break;
285 }
286 }
287}
288
289static void cCamCryptVG_Process_D1(struct s_reader * reader, const unsigned char *ins, unsigned char *data, const unsigned char *status)
290{
291 unsigned char iter[16], tmp[16];
292 memset(iter,0,sizeof(iter));
293 memcpy(iter,ins,5);
294 xor16(iter,reader->stateD3A,iter);
295 memcpy(reader->stateD3A,iter,sizeof(iter));
296
297 int datalen=status-data;
298 int datalen1=datalen;
299 if(datalen<0) datalen1+=15;
300 int blocklen=datalen1>>4;
301 int i;
302 int iblock;
303 for(i=0,iblock=0; i<blocklen+2; i++,iblock+=16) {
304 unsigned char in[16];
305 int docalc=1;
306 if(blocklen==i && (docalc=datalen&0xf)) {
307 memset(in,0,sizeof(in));
308 memcpy(in,&data[iblock],datalen-(datalen1&~0xf));
309 }
310 else if(blocklen+1==i) {
311 memset(in,0,sizeof(in));
312 memcpy(&in[5],status,2);
313 }
314 else
315 memcpy(in,&data[iblock],sizeof(in));
316
317 if(docalc) {
318 xor16(iter,in,tmp);
319 cCamCryptVG_ReorderAndEncrypt(reader,tmp);
320 xor16(tmp,reader->stateD3A,iter);
321 }
322 }
323 memcpy(reader->stateD3A,tmp,16);
324}
325
326static void cCamCryptVG_Decrypt_D3(struct s_reader * reader, unsigned char *ins, unsigned char *data, const unsigned char *status)
327{
328 if(ins[4]>16) ins[4]-=16;
329 if(ins[1]==0xbe) memset(reader->stateD3A,0,sizeof(reader->stateD3A));
330
331 unsigned char tmp[16];
332 memset(tmp,0,sizeof(tmp));
333 memcpy(tmp,ins,5);
334 xor16(tmp,reader->stateD3A,reader->stateD3A);
335
336 int len1=ins[4];
337 int blocklen=len1>>4;
338 if(ins[1]!=0xbe) blocklen++;
339
340 unsigned char iter[16], states[16][16];
341 memset(iter,0,sizeof(iter));
342 int blockindex;
343 for(blockindex=0; blockindex<blocklen; blockindex++) {
344 iter[0]+=blockindex;
345 xor16(iter,reader->stateD3A,iter);
346 cCamCryptVG_ReorderAndEncrypt(reader,iter);
347 xor16(iter,&data[blockindex*16],states[blockindex]);
348 if(blockindex==(len1>>4)) {
349 int c=len1-(blockindex*16);
350 if(c<16) memset(&states[blockindex][c],0,16-c);
351 }
352 xor16(states[blockindex],reader->stateD3A,reader->stateD3A);
353 cCamCryptVG_RotateRightAndHash(reader->stateD3A);
354 }
355 memset(tmp,0,sizeof(tmp));
356 memcpy(tmp+5,status,2);
357 xor16(tmp,reader->stateD3A,reader->stateD3A);
358 cCamCryptVG_ReorderAndEncrypt(reader,reader->stateD3A);
359
360 memcpy(reader->stateD3A,status-16,sizeof(reader->stateD3A));
361 cCamCryptVG_ReorderAndEncrypt(reader,reader->stateD3A);
362
363 memcpy(data,states[0],len1);
364 if(ins[1]==0xbe) {
365 cCamCryptVG_Reorder16A(tmp,states[0]);
366 cAES_SetKey(reader,tmp);
367 }
368}
369
370static void cCamCryptVG_ReorderAndEncrypt(struct s_reader * reader, unsigned char *p)
371{
372 unsigned char tmp[16];
373 cCamCryptVG_Reorder16A(tmp,p);
374 cAES_Encrypt(reader,tmp,16,tmp);
375 cCamCryptVG_Reorder16A(p,tmp);
376}
377
378// reorder AAAABBBBCCCCDDDD to ABCDABCDABCDABCD
379static void cCamCryptVG_Reorder16A(unsigned char *dest, const unsigned char *src)
380{
381 int i;
382 int j;
383 int k;
384 for(i=0,k=0; i<4; i++)
385 for(j=i; j<16; j+=4,k++)
386 dest[k]=src[j];
387}
388
389static void cCamCryptVG_LongMult(unsigned short *pData, unsigned short *pLen, unsigned int mult, unsigned int carry)
390{
391 int i;
392 for(i=0; i<*pLen; i++) {
393 carry+=pData[i]*mult;
394 pData[i]=(unsigned short)carry;
395 carry>>=16;
396 }
397 if(carry) pData[(*pLen)++]=carry;
398}
399
400static void cCamCryptVG_PartialMod(unsigned short val, unsigned int count, unsigned short *outkey, const unsigned short *inkey)
401{
402 if(count) {
403 unsigned int mod=inkey[count];
404 unsigned short mult=(inkey[count]-outkey[count-1])&0xffff;
405 unsigned int i;
406 unsigned int ib1;
407 for(i=0,ib1=count-2; i<count-1; i++,ib1--) {
408 unsigned int t=(inkey[ib1]*mult)%mod;
409 mult=t-outkey[ib1];
410 if(mult>t) mult+=mod;
411 }
412 mult+=val;
413 if((val>mult) || (mod<mult)) mult-=mod;
414 outkey[count]=(outkey[count]*mult)%mod;
415 }
416 else
417 outkey[0]=val;
418}
419
420static void cCamCryptVG_RotateRightAndHash(unsigned char *p)
421{
422 static const unsigned char table1[256] = {
423 0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5, 0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76,
424 0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0, 0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0,
425 0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc, 0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15,
426 0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a, 0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75,
427 0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0, 0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84,
428 0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b, 0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf,
429 0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85, 0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8,
430 0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5, 0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2,
431 0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17, 0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73,
432 0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88, 0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb,
433 0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c, 0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79,
434 0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9, 0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08,
435 0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6, 0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a,
436 0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e, 0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e,
437 0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94, 0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf,
438 0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68, 0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16,
439 };
440 unsigned char t1=p[15];
441 int i;
442 for(i=0; i<16; i++) {
443 unsigned char t2=t1;
444 t1=p[i]; p[i]=table1[(t1>>1)|((t2&1)<<7)];
445 }
446}
447
448int status_ok(const unsigned char *status)
449{
450 //cs_log("[videoguard-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
458void memorize_cmd_table (struct s_reader * reader, const unsigned char *mem, int size){
459 reader->cmd_table=(struct s_CmdTab *)malloc(sizeof(unsigned char) * size);
460 memcpy(reader->cmd_table,mem,size);
461}
462
463int cmd_table_get_info(struct s_reader * reader, const unsigned char *cmd, unsigned char *rlen, unsigned char *rmode)
464{
465 struct s_CmdTabEntry *pcte=reader->cmd_table->e;
466 int i;
467 for(i=0; i< reader->cmd_table->Nentries; i++,pcte++)
468 if(cmd[1]==pcte->cmd) {
469 *rlen=pcte->len;
470 *rmode=pcte->mode;
471 return 1;
472 }
473 return 0;
474}
475
476int cmd_exists(struct s_reader * reader, const unsigned char *cmd)
477{
478 struct s_CmdTabEntry *pcte=reader->cmd_table->e;
479 int i;
480 for(i=0; i< reader->cmd_table->Nentries; i++,pcte++)
481 if(cmd[1]==pcte->cmd) {
482 return 1;
483 }
484 return 0;
485}
486
487int read_cmd_len(struct s_reader * reader, const unsigned char *cmd)
488{
489 def_resp;
490 unsigned char cmd2[5];
491 memcpy(cmd2,cmd,5);
492 cmd2[3]=0x80;
493 cmd2[4]=1;
494 // some card reply with L 91 00 (L being the command length).
495
496 if(!write_cmd_vg(cmd2,NULL) || !status_ok(cta_res+1)) {
497 cs_debug_mask(D_READER, "[videoguard-reader] failed to read %02x%02x cmd length (%02x %02x)",cmd[1],cmd[2],cta_res[1],cta_res[2]);
498 return -1;
499 }
500 return cta_res[0];
501}
502
503int do_cmd(struct s_reader * reader, const unsigned char *ins, const unsigned char *txbuff, unsigned char *rxbuff,
504 unsigned char * cta_res)
505{
506 ushort cta_lr;
507 unsigned char ins2[5];
508 memcpy(ins2,ins,5);
509 unsigned char len=0, mode=0;
510 if(cmd_table_get_info(reader,ins2,&len,&mode)) {
511 if(len==0xFF && mode==2) {
512 if(ins2[4]==0) ins2[4]=len=read_cmd_len(reader,ins2);
513 }
514 else if(mode!=0) ins2[4]=len;
515 }
516 if(ins2[0]==0xd3) ins2[4]=len+16;
517 len=ins2[4];
518
519 unsigned char tmp[264];
520 if(!rxbuff) rxbuff=tmp;
521 if(mode>1) {
522 if(!write_cmd_vg(ins2,NULL) || !status_ok(cta_res+len)) return -1;
523 memcpy(rxbuff,ins2,5);
524 memcpy(rxbuff+5,cta_res,len);
525 memcpy(rxbuff+5+len,cta_res+len,2);
526 }
527 else {
528 if(!write_cmd_vg(ins2,(uchar *)txbuff) || !status_ok(cta_res)) return -2;
529 memcpy(rxbuff,ins2,5);
530 memcpy(rxbuff+5,txbuff,len);
531 memcpy(rxbuff+5+len,cta_res,2);
532 }
533
534 cCamCryptVG_PostProcess_Decrypt(reader,rxbuff);
535
536 return len;
537}
538
539void rev_date_calc(const unsigned char *Date, int *year, int *mon, int *day, int *hh, int *mm, int *ss, int base_year)
540{
541 *year=(Date[0]/12)+base_year;
542 *mon=(Date[0]%12)+1;
543 *day=Date[1] & 0x1f;
544 *hh=Date[2]/8;
545 *mm=(0x100*(Date[2]-*hh*8)+Date[3])/32;
546 *ss=(Date[3]-*mm*32)*2;
547}
548
549void do_post_dw_hash(unsigned char *cw, unsigned char *ecm_header_data)
550{
551 int i, ecmi, ecm_header_count;
552 unsigned char buffer[0x80];
553 unsigned char md5_digest[0x10];
554 static const unsigned short Hash3[] = {0x0123,0x4567,0x89AB,0xCDEF,0xF861,0xCB52};
555 static const unsigned char Hash4[] = {0x0B,0x04,0x07,0x08,0x05,0x09,0x0B,0x0A,0x07,0x02,0x0A,0x05,0x04,0x08,0x0D,0x0F};
556 static const unsigned short NdTabB001[0x15][0x20] = {
557 {0xEAF1, 0x0237, 0x29D0, 0xBAD2, 0xE9D3, 0x8BAE, 0x2D6D, 0xCD1B,
558 0x538D, 0xDE6B, 0xA634, 0xF81A, 0x18B5, 0x5087, 0x14EA, 0x672E,
559 0xF0FC, 0x055E, 0x62E5, 0xB78F, 0x5D09, 0x0003, 0xE4E8, 0x2DCE,
560 0x6BE0, 0xAC4E, 0xF485, 0x6967, 0xF28C, 0x97A0, 0x01EF, 0x0100},
561 {0xC539, 0xF5B9, 0x9099, 0x013A, 0xD4B9, 0x6AB5, 0xEA67, 0x7EB4,
562 0x6C30, 0x4BF0, 0xB810, 0xB0B5, 0xB76D, 0xA751, 0x1AE7, 0x14CA,
563 0x4F4F, 0x1586, 0x2608, 0x10B1, 0xE7E1, 0x48BE, 0x7DDD, 0x5ECB,
564 0xCFBF, 0x323B, 0x8B31, 0xB131, 0x0F1A, 0x664B, 0x0140, 0x0100},
565 {0x3C7D, 0xBDC4, 0xFEC7, 0x26A6, 0xB0A0, 0x6E55, 0xF710, 0xF9BF,
566 0x0023, 0xE81F, 0x41CA, 0xBE32, 0xB461, 0xE92D, 0xF1AF, 0x409F,
567 0xFC85, 0xFE5B, 0x7FCE, 0x17F5, 0x01AB, 0x4A46, 0xEB05, 0xA251,
568 0xDC6F, 0xF0C0, 0x10F0, 0x1D51, 0xEFAA, 0xE9BF, 0x0100, 0x0100},
569 {0x1819, 0x0CAA, 0x9067, 0x607A, 0x7576, 0x1CBC, 0xE51D, 0xBF77,
570 0x7EC6, 0x839E, 0xB695, 0xF096, 0xDC10, 0xCB69, 0x4654, 0x8E68,
571 0xD62D, 0x4F1A, 0x4227, 0x92AC, 0x9064, 0x6BD1, 0x1E75, 0x2747,
572 0x00DA, 0xA6A6, 0x6CF1, 0xD151, 0xBE56, 0x3E33, 0x0128, 0x0100},
573 {0x4091, 0x09ED, 0xD494, 0x6054, 0x1869, 0x71D5, 0xB572, 0x7BF1,
574 0xE925, 0xEE2D, 0xEEDE, 0xA13C, 0x6613, 0x9BAB, 0x122D, 0x7AE4,
575 0x5268, 0xE6C9, 0x50CB, 0x79A1, 0xF212, 0xA062, 0x6B48, 0x70B3,
576 0xF6B0, 0x06D5, 0xF8AB, 0xECF5, 0x6255, 0xEDD8, 0x79D2, 0x290A},
577 {0xD3CF, 0x014E, 0xACB3, 0x8F6B, 0x0F2C, 0xA5D8, 0xE8E0, 0x863D,
578 0x80D5, 0x5705, 0x658A, 0x8BC2, 0xEE46, 0xD3AE, 0x0199, 0x0100,
579 0x4A35, 0xABE4, 0xF976, 0x935A, 0xA8A5, 0xBAE9, 0x24D0, 0x71AA,
580 0xB3FE, 0x095E, 0xAB06, 0x4CD5, 0x2F0D, 0x1ACB, 0x59F3, 0x4C50},
581 {0xFD27, 0x0F8E, 0x191A, 0xEEE7, 0x2F49, 0x3A05, 0x3267, 0x4F88,
582 0x38AE, 0xFCE9, 0x9476, 0x18C6, 0xF961, 0x4EF0, 0x39D0, 0x42E6,
583 0xB747, 0xE625, 0xB68E, 0x5100, 0xF92A, 0x86FE, 0xE79B, 0xEE91,
584 0x21D5, 0x4C3C, 0x683D, 0x5AD1, 0x1B49, 0xF407, 0x0194, 0x0100},
585 {0x4BF9, 0xDC0D, 0x9478, 0x5174, 0xCB4A, 0x8A89, 0x4D6A, 0xFED8,
586 0xF123, 0xA8CD, 0xEEE7, 0xA6D1, 0xB763, 0xF5E2, 0xE085, 0x01EF,
587 0xE466, 0x9FA3, 0x2F68, 0x2190, 0x423F, 0x287F, 0x7F3F, 0x09F6,
588 0x2111, 0xA963, 0xD0BB, 0x674A, 0xBA72, 0x45F9, 0xF186, 0xB8F5},
589 {0x0010, 0xD1B9, 0xB164, 0x9E87, 0x1F49, 0x6950, 0x2DBF, 0x38D3,
590 0x2EB0, 0x3E8E, 0x91E6, 0xF688, 0x7E41, 0x566E, 0x01B0, 0x0100,
591 0x24A1, 0x73D8, 0xA0C3, 0xF71B, 0xA0A5, 0x2A06, 0xBA46, 0xFEC3,
592 0xDD4C, 0x52CC, 0xF9BC, 0x3B7E, 0x3812, 0x0666, 0xB74B, 0x40F8},
593 {0x28F2, 0x7C81, 0xFC92, 0x6FBD, 0x53D6, 0x72A3, 0xBBDF, 0xB6FC,
594 0x9CE5, 0x2331, 0xD4F6, 0xC5BB, 0xE8BB, 0x6676, 0x02D9, 0x2F0E,
595 0xD009, 0xD136, 0xCD09, 0x7551, 0x1826, 0x9D9B, 0x63EA, 0xFC63,
596 0x68CD, 0x3672, 0xCB95, 0xD28E, 0xF1CD, 0x20CA, 0x014C, 0x0100},
597 {0xE539, 0x55B7, 0x989D, 0x21C4, 0x463A, 0xE68F, 0xF8B5, 0xE5C5,
598 0x662B, 0x35BF, 0x3C50, 0x0131, 0xF4BF, 0x38B2, 0x41BC, 0xB829,
599 0x02B7, 0x6B8F, 0xA25C, 0xAFD2, 0xD84A, 0x2243, 0x53EB, 0xC6C9,
600 0x2E14, 0x181F, 0x8F96, 0xDF0E, 0x0D4C, 0x30F6, 0xFFE1, 0x9DDA},
601 {0x30B6, 0x777E, 0xDA3D, 0xAF77, 0x205E, 0xC90B, 0x856B, 0xB451,
602 0x3BCC, 0x76C2, 0x8ACF, 0xDCB1, 0xA5E5, 0xDD64, 0x0197, 0x0100,
603 0xE751, 0xB661, 0x0404, 0xDB4A, 0xE9DD, 0xA400, 0xAF26, 0x3F5E,
604 0x904B, 0xA924, 0x09E0, 0xE72B, 0x825B, 0x2C50, 0x6FD0, 0x0D52},
605 {0x2730, 0xC2BA, 0x9E44, 0x5815, 0xFC47, 0xB21D, 0x67B8, 0xF8B9,
606 0x047D, 0xB0AF, 0x9F14, 0x741B, 0x4668, 0xBE54, 0xDE16, 0xDB14,
607 0x7CB7, 0xF2B8, 0x0683, 0x762C, 0x09A0, 0x9507, 0x7F92, 0x022C,
608 0xBA6A, 0x7D52, 0x0AF4, 0x1BC3, 0xB46A, 0xC4FD, 0x01C2, 0x0100},
609 {0x7611, 0x66F3, 0xEE87, 0xEDD3, 0xC559, 0xEFD4, 0xDC59, 0xF86B,
610 0x6D1C, 0x1C85, 0x9BB1, 0x3373, 0x763F, 0x4EBE, 0x1BF3, 0x99B5,
611 0xD721, 0x978F, 0xCF5C, 0xAC51, 0x0984, 0x7462, 0x8F0C, 0x2817,
612 0x4AD9, 0xFD41, 0x6678, 0x7C85, 0xD330, 0xC9F8, 0x1D9A, 0xC622},
613 {0x5AE4, 0xE16A, 0x60F6, 0xFD45, 0x668C, 0x29D6, 0x0285, 0x6B92,
614 0x92C2, 0x21DE, 0x45E0, 0xEF3D, 0x8B0D, 0x02CD, 0x0198, 0x0100,
615 0x9E6D, 0x4D38, 0xDEF9, 0xE6F2, 0xF72E, 0xB313, 0x14F2, 0x390A,
616 0x2D67, 0xC71E, 0xCB69, 0x7F66, 0xD3CF, 0x7F8A, 0x81D9, 0x9DDE},
617 {0x85E3, 0x8F29, 0x36EB, 0xC968, 0x3696, 0x59F6, 0x7832, 0xA78B,
618 0xA1D8, 0xF5CF, 0xAB64, 0x646D, 0x7A2A, 0xBAF8, 0xAA87, 0x41C7,
619 0x5120, 0xDE78, 0x738D, 0xDC1A, 0x268D, 0x5DF8, 0xED69, 0x1C8A,
620 0xBC85, 0x3DCD, 0xAE30, 0x0F8D, 0xEC89, 0x3ABD, 0x0166, 0x0100},
621 {0xB8BD, 0x643B, 0x748E, 0xBD63, 0xEC6F, 0xE23A, 0x9493, 0xDD76,
622 0x0A62, 0x774F, 0xCD68, 0xA67A, 0x9A23, 0xC8A8, 0xBDE5, 0x9D1B,
623 0x2B86, 0x8B36, 0x5428, 0x1DFB, 0xCD1D, 0x0713, 0x29C2, 0x8E8E,
624 0x5207, 0xA13F, 0x6005, 0x4F5E, 0x52E0, 0xE7C8, 0x6D1C, 0x3E34},
625 {0x581D, 0x2BFA, 0x5E1D, 0xA891, 0x1069, 0x1DA4, 0x39A0, 0xBE45,
626 0x5B9A, 0x7333, 0x6F3E, 0x8637, 0xA550, 0xC9E9, 0x5C6C, 0x42BA,
627 0xA712, 0xC3EA, 0x3808, 0x0910, 0xAA4D, 0x5B25, 0xABCD, 0xE680,
628 0x96AD, 0x2CEC, 0x8EBB, 0xA47D, 0x1690, 0xE8FB, 0x01C8, 0x0100},
629 {0x73B9, 0x82BC, 0x9EBC, 0xB130, 0x0DA5, 0x8617, 0x9F7B, 0x9766,
630 0x205D, 0x752D, 0xB05C, 0x2A17, 0xA75C, 0x18EF, 0x8339, 0xFD34,
631 0x8DA2, 0x7970, 0xD0B4, 0x70F1, 0x3765, 0x7380, 0x7CAF, 0x570E,
632 0x6440, 0xBC44, 0x0743, 0x2D02, 0x0419, 0xA240, 0x2113, 0x1AD4},
633 {0x1EB5, 0xBBFF, 0x39B1, 0x3209, 0x705F, 0x15F4, 0xD7AD, 0x340B,
634 0xC2A6, 0x25CA, 0xF412, 0x9570, 0x0F4F, 0xE4D5, 0x1614, 0xE464,
635 0x911A, 0x0F0E, 0x07DA, 0xA929, 0x2379, 0xD988, 0x0AA6, 0x3B57,
636 0xBF63, 0x71FB, 0x72D5, 0x26CE, 0xB0AF, 0xCF45, 0x011B, 0x0100},
637 {0x9999, 0x98FE, 0xA108, 0x6588, 0xF90B, 0x4554, 0xFF38, 0x4642,
638 0x8F5F, 0x6CC3, 0x4E8E, 0xFF7E, 0x64C2, 0x50CA, 0x0E7F, 0xAD7D,
639 0x6AAB, 0x33C1, 0xE1F4, 0x6165, 0x7894, 0x83B9, 0x0A0C, 0x38AF,
640 0x5803, 0x18C0, 0xFA36, 0x592C, 0x4548, 0xABB8, 0x1527, 0xAEE9}
641 };
642
643
644 //ecm_header_data = 01 03 b0 01 01
645 if (!cw_is_valid(cw,0)) //if cw is all zero, keep it that way
646 {
647 return;
648 }
649 ecm_header_count = ecm_header_data[0];
650 for (i = 0, ecmi = 1; i < ecm_header_count; i++)
651 {
652 if (ecm_header_data[ecmi + 1] != 0xb0)
653 {
654 ecmi += ecm_header_data[ecmi] + 1;
655 }
656 else
657 {
658 switch (ecm_header_data[ecmi + 2])
659 { //b0 01
660 case 1:
661 {
662 unsigned short hk[8], i, j, m = 0;
663 for (i = 0; i < 6; i++)
664 hk[2 + i] = Hash3[i];
665 for (i = 0; i < 2; i++)
666 {
667 for (j = 0; j < 0x48; j += 2)
668 {
669 if (i)
670 {
671 hk[0] = ((hk[3] & hk[5]) | ((~hk[5]) & hk[4]));
672 }
673 else
674 {
675 hk[0] = ((hk[3] & hk[4]) | ((~hk[3]) & hk[5]));
676 }
677 if (j < 8)
678 {
679 hk[0] = (hk[0] + ((cw[j + 1] << 8) | cw[j]));
680 }
681 if (j == 8)
682 {
683 hk[0] = (hk[0] + 0x80);
684 }
685 hk[0] = (hk[0] + hk[2] + (0xFF & NdTabB001[ecm_header_data[ecmi + 3]][m >> 1] >> ((m & 1) << 3)));
686 hk[1] = hk[2];
687 hk[2] = hk[3];
688 hk[3] = hk[4];
689 hk[4] = hk[5];
690 hk[5] = hk[6];
691 hk[6] = hk[7];
692 hk[7] = hk[2] + (((hk[0] << Hash4[m & 0xF]) | (hk[0] >> (0x10 - Hash4[m & 0xF]))));
693 m = (m + 1) & 0x3F;
694 }
695 }
696 for (i = 0; i < 6; i++)
697 {
698 hk[2 + i] += Hash3[i];
699 }
700 for (i = 0; i < 7; i++)
701 {
702 cw[i] = hk[2 + (i >> 1)] >> ((i & 1) << 3);
703 }
704 cw[3] = (cw[0] + cw[1] + cw[2]) & 0xFF;
705 cw[7] = (cw[4] + cw[5] + cw[6]) & 0xFF;
706 cs_ddump_mask(D_READER, cw, 8, "Postprocessed Case 1 DW:");
707 break;
708 }
709 case 3:
710 {
711 memset(buffer, 0, sizeof(buffer));
712 memcpy(buffer, cw, 8);
713 memcpy(buffer + 8, &ecm_header_data[ecmi + 3], ecm_header_data[ecmi] - 2);
714 MD5(buffer, 8 + ecm_header_data[ecmi] - 2, md5_digest);
715 memcpy(cw, md5_digest, 8);
716 cs_ddump_mask(D_READER, cw, 8, "Postprocessed Case 3 DW:");
717 break;
718 }
719 case 2:
720 {
721 /* Method 2 left out */
722 //memcpy(DW_OUTPUT, DW_INPUT, 8);
723 break;
724 }
725 }
726 }
727 }
728}
729
730int num_addr(const unsigned char *data)
731{
732 return ((data[3] & 0x30) >> 4) + 1;
733}
734
735/*
736Example of GLOBAL EMM's
737This one has IRD-EMM + Card-EMM
73882 70 20 00 02 06 02 7D 0E 89 53 71 16 90 14 40
73901 ED 17 7D 9E 1F 28 CF 09 97 54 F1 8E 72 06 E7
74051 AF F5
741This one has only IRD-EMM
74282 70 6D 00 07 69 01 30 07 14 5E 0F FF FF 00 06
74300 0D 01 00 03 01 00 00 00 0F 00 00 00 5E 01 00
74401 0C 2E 70 E4 55 B6 D2 34 F7 44 86 9E 5C 91 14
74581 FC DF CB D0 86 65 77 DF A9 E1 6B A8 9F 9B DE
74690 92 B9 AA 6C B3 4E 87 D2 EC 92 DA FC 71 EF 27
747B3 C3 D0 17 CF 0B D6 5E 8C DB EB B3 37 55 6E 09
7487F 27 3C F1 85 29 C9 4E 0B EE DF 68 BE 00 C9 00
749*/
750const unsigned char *payload_addr(uchar emmtype, const unsigned char *data, const unsigned char *a)
751{
752 int s;
753 int l;
754 const unsigned char *ptr = NULL;
755 int position = -1;
756 int numAddrs = 0;
757 switch (emmtype) {
758 case SHARED:
759 {
760 s = 3;
761 break;
762 }
763 case UNIQUE:
764 {
765 s = 4;
766 break;
767 }
768 default:
769 {
770 s = 0;
771 }
772 }
773
774 numAddrs = num_addr(data);
775 if (s > 0) {
776 for (l = 0; l < numAddrs; l++) {
777 if (!memcmp(&data[l * 4 + 4], a + 2, s)) {
778 position = l;
779 break;
780 }
781 }
782 }
783
784 int num_filter = (position == -1) ? 0 : numAddrs;
785 /* skip header and the filter list */
786 ptr = data + 4 + 4 * num_filter;
787 if (*ptr != 0x02 && *ptr != 0x07) // some clients omit 00 00 separator */
788 {
789 ptr += 2; // skip 00 00 separator
790 if (*ptr == 0x00)
791 ptr++; // skip optional 00
792 ptr++; // skip the 1st bitmap len
793 }
794
795 /* check for IRD-EMM */
796 if (*ptr != 0x02 && *ptr != 0x07) {
797 return NULL;
798 }
799
800 /* skip IRD-EMM part, 02 00 or 02 06 xx aabbccdd yy */
801 ptr += 2 + ptr[1];
802 /* check for EMM boundaries - ptr should not exceed EMM length */
803 if ((int) (ptr - (data + 3)) >= data[2]) {
804 return NULL;
805 }
806
807 for (l = 0; l < position; l++) {
808 /* skip the payload of the previous sub-EMM */
809 ptr += 1 + ptr[0];
810 /* check for EMM boundaries - ptr should not exceed EMM length */
811 if ((int) (ptr - (data + 3)) >= data[2]) {
812 return NULL;
813 }
814
815 /* skip optional 00 */
816 if (*ptr == 0x00) {
817 ptr++;
818 }
819
820 /* skip the bitmap len */
821 ptr++;
822 /* check for IRD-EMM */
823 if (*ptr != 0x02 && *ptr != 0x07) {
824 return NULL;
825 }
826
827 /* skip IRD-EMM part, 02 00 or 02 06 xx aabbccdd yy */
828 ptr += 2 + ptr[1];
829 }
830
831 return ptr;
832}
833
834
835
836int videoguard_get_emm_type(EMM_PACKET *ep, struct s_reader * rdr)
837{
838
839/*
84082 30 ad 70 00 XX XX XX 00 XX XX XX 00 XX XX XX 00 XX XX XX 00 00
841d3 02 00 22 90 20 44 02 4a 50 1d 88 ab 02 ac 79 16 6c df a1 b1 b7 77 00 ba eb 63 b5 c9 a9 30 2b 43 e9 16 a9 d5 14 00
842d3 02 00 22 90 20 44 02 13 e3 40 bd 29 e4 90 97 c3 aa 93 db 8d f5 6b e4 92 dd 00 9b 51 03 c9 3d d0 e2 37 44 d3 bf 00
843d3 02 00 22 90 20 44 02 97 79 5d 18 96 5f 3a 67 70 55 bb b9 d2 49 31 bd 18 17 2a e9 6f eb d8 76 ec c3 c9 cc 53 39 00
844d2 02 00 21 90 1f 44 02 99 6d df 36 54 9c 7c 78 1b 21 54 d9 d4 9f c1 80 3c 46 10 76 aa 75 ef d6 82 27 2e 44 7b 00
845*/
846
847 int i, pos;
848 int serial_count = ((ep->emm[3] >> 4) & 3) + 1;
849 int serial_len = (ep->emm[3] & 0x80) ? 3 : 4;
850 uchar emmtype = (ep->emm[3] & VG_EMMTYPE_MASK) >> 6;
851
852 pos = 4 + (serial_len * serial_count) + 2;
853
854 switch(emmtype) {
855 case VG_EMMTYPE_G:
856 ep->type=GLOBAL;
857 cs_debug_mask(D_EMM, "EMM: GLOBAL");
858 return TRUE;
859
860 case VG_EMMTYPE_U:
861 cs_debug_mask(D_EMM, "EMM: UNIQUE");
862 ep->type=UNIQUE;
863 if (ep->emm[1] == 0) // detected UNIQUE EMM from cccam (there is no serial)
864 return TRUE;
865
866 for (i = 1;i <= serial_count;i++) {
867 if (!memcmp (rdr->hexserial + 2, ep->emm + (serial_len * i), serial_len)) {
868 memcpy(ep->hexserial, ep->emm + (serial_len * i), serial_len);
869 return TRUE;
870 }
871
872 pos = pos + ep->emm[pos+5] + 5;
873 }
874 return FALSE; // if UNIQUE but no serial match return FALSE
875
876 case VG_EMMTYPE_S:
877 ep->type=SHARED;
878 cs_debug_mask(D_EMM, "EMM: SHARED");
879
880 for (i = 0; i < serial_count; i++) {
881 if (!memcmp(&ep->emm[i * 4 + 4], rdr->hexserial + 2, serial_len)) {
882 memcpy(ep->hexserial, &ep->emm[i * 4 + 4], serial_len);
883 return TRUE;
884 }
885 }
886
887 return FALSE;
888
889 default:
890 if (ep->emm[pos-2] != 0x00 && ep->emm[pos-1] != 0x00 && ep->emm[pos-1] != 0x01) {
891 //remote emm without serial
892 ep->type=UNKNOWN;
893 return TRUE;
894 }
895 return FALSE;
896 }
897}
898
899void videoguard_get_emm_filter(struct s_reader * rdr, uchar *filter)
900{
901 filter[0]=0xFF;
902 filter[1]=5;
903
904 //ToDo videoguard_get_emm_filter basic construction
905 filter[2]=UNIQUE;
906 filter[3]=0;
907
908 filter[4+0] = 0x82;
909 filter[4+0+16] = 0xFF;
910 filter[4+1] = 0x40;
911 filter[4+1+16] = 0xC0;
912 memcpy(filter+4+2, rdr->hexserial+2, 4);
913 memset(filter+4+2+16, 0xFF, 4);
914
915 filter[36]=UNIQUE;
916 filter[37]=0;
917
918 filter[38+0] = 0x82;
919 filter[38+0+16] = 0xFF;
920 filter[38+1] = 0x40;
921 filter[38+1+16] = 0xC0;
922 memcpy(filter+38+6, rdr->hexserial+2, 4);
923 memset(filter+38+6+16, 0xFF, 4);
924
925 filter[70]=UNIQUE;
926 filter[71]=0;
927
928 filter[72+0] = 0x82;
929 filter[72+0+16] = 0xFF;
930 filter[72+1] = 0x40;
931 filter[72+1+16] = 0xC0;
932 memcpy(filter+72+10, rdr->hexserial+2, 4);
933 memset(filter+72+10+16, 0xFF, 4);
934
935 // fourth serial position does not fit within the 16bytes demux filter
936
937
938 filter[104]=SHARED;
939 filter[105]=0;
940
941 filter[106+0] = 0x82;
942 filter[106+0+16] = 0xFF;
943 filter[106+1] = 0x80;
944 filter[106+1+16] = 0xC0;
945 memcpy(filter+106+2, rdr->hexserial+2, 3);
946 memset(filter+106+2+16, 0xFF, 3);
947
948
949 filter[138]=GLOBAL;
950 filter[139]=0;
951
952 filter[140+0] = 0x82;
953 filter[140+0+16] = 0xFF;
954 filter[140+1] = 0x00;
955 filter[140+1+16] = 0xC0;
956
957
958 return;
959}
960
Note: See TracBrowser for help on using the repository browser.