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

Last change on this file since 5375 was 5355, checked in by Admin, 8 years ago

Correct some field lengths in WebIf, don't exit OSCam anymore when some minor config parameters are wrong.

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