1 | #include "globals.h"
|
---|
2 | #ifdef READER_VIACCESS
|
---|
3 | #include "oscam-aes.h"
|
---|
4 | #include "oscam-time.h"
|
---|
5 | #include "oscam-emm.h"
|
---|
6 | #include "reader-common.h"
|
---|
7 | #include "cscrypt/des.h"
|
---|
8 | #include "oscam-work.h"
|
---|
9 | typedef unsigned int uint;
|
---|
10 | typedef unsigned char byte;
|
---|
11 | uint8_t N98Init = 0;
|
---|
12 | uint KeyS[132];
|
---|
13 | char SBoxInverse[] = {
|
---|
14 | 13, 3,11, 0,10, 6, 5,12, 1,14, 4, 7,15, 9, 8, 2,
|
---|
15 | 5, 8, 2,14,15, 6,12, 3,11, 4, 7, 9, 1,13,10, 0,
|
---|
16 | 12, 9,15, 4,11,14, 1, 2, 0, 3, 6,13, 5, 8,10, 7,
|
---|
17 | 0, 9,10, 7,11,14, 6,13, 3, 5,12, 2, 4, 8,15, 1,
|
---|
18 | 5, 0, 8, 3,10, 9, 7,14, 2,12,11, 6, 4,15,13, 1,
|
---|
19 | 8,15, 2, 9, 4, 1,13,14,11, 6, 5, 3, 7,12,10, 0,
|
---|
20 | 15,10, 1,13, 5, 3, 6, 0, 4, 9,14, 7, 2,12, 8,11,
|
---|
21 | 3, 0, 6,13, 9,14,15, 8, 5,12,11, 7,10, 1, 4, 2 };
|
---|
22 | uint getBit(uint number, int bt)
|
---|
23 | {
|
---|
24 | return (number >> bt ) & 1;
|
---|
25 | }
|
---|
26 | void SBitslice(uint* Iarray, int offsetin, uint* Oarray, int offsetout, int row, char* box)
|
---|
27 | {
|
---|
28 | int bi,input,l,output;
|
---|
29 | uint calcArray[4] = {0,0,0,0};
|
---|
30 | for (bi = 0; bi < 32; bi++)
|
---|
31 | {
|
---|
32 | input = 0;
|
---|
33 | for (l = 0; l < 4; l++)
|
---|
34 | input += getBit(Iarray[l+offsetin],bi) << l;
|
---|
35 | output = box[input+16*row];
|
---|
36 | for (l = 0; l < 4; l++)
|
---|
37 | calcArray[l] += getBit(output,l) << bi;
|
---|
38 | }
|
---|
39 | for (l = 0; l < 4; l++)
|
---|
40 | Oarray[l+offsetout] = calcArray[l];
|
---|
41 | }
|
---|
42 | void xorBlock(uint* data, int offset)
|
---|
43 | {
|
---|
44 | int i;
|
---|
45 | for (i = 0; i < 4; i++)
|
---|
46 | data[i] ^= KeyS[i + 4*offset];
|
---|
47 | }
|
---|
48 | uint rotr(uint val, int nbits)
|
---|
49 | {
|
---|
50 | return ((val >> nbits) + (val << (32 - nbits)));
|
---|
51 | }
|
---|
52 | void LTBitsliceInverse(uint* data)
|
---|
53 | {
|
---|
54 | uint C0 = data[0];
|
---|
55 | uint C1 = data[1];
|
---|
56 | uint C2 = data[2];
|
---|
57 | uint C3 = data[3];
|
---|
58 | C2 = rotr(C2,22);
|
---|
59 | C0 = rotr(C0,5);
|
---|
60 | C2 ^= C3 ^ (C1 << 7);
|
---|
61 | C0 ^= C1 ^ C3;
|
---|
62 | C3 = rotr(C3,7);
|
---|
63 | C3 ^= C2 ^ (C0 << 3);
|
---|
64 | C1 = rotr(C1,1);
|
---|
65 | C1 ^= C0 ^ C2;
|
---|
66 | C2 = rotr(C2,3);
|
---|
67 | C0 = rotr(C0,13);
|
---|
68 | data[0] = C0;
|
---|
69 | data[1] = C1;
|
---|
70 | data[2] = C2;
|
---|
71 | data[3] = C3;
|
---|
72 | }
|
---|
73 | void N98_decrypt(byte* data)
|
---|
74 | {
|
---|
75 | int r; // round
|
---|
76 | int i,j;
|
---|
77 | uint N98[4]; // make 32 bits words
|
---|
78 | for(i = 0; i < 4; i++)
|
---|
79 | N98[i] = data[4*i] + (data[4*i+1] << 8) + (data[4*i+2] << 16) + (data[4*i+3] << 24);
|
---|
80 | for(r = 31; r >= 0; r--) // decrypt, inverse order
|
---|
81 | {
|
---|
82 | if (r == 31) {
|
---|
83 | xorBlock(N98,32);
|
---|
84 | } else {
|
---|
85 | LTBitsliceInverse(N98); // inverse Linear Transform
|
---|
86 | }
|
---|
87 | SBitslice(N98,0,N98,0, (r & 7), SBoxInverse); // SBox inverse, bitslice mode
|
---|
88 | xorBlock(N98, r);
|
---|
89 | }
|
---|
90 | for(i = 0; i < 4; i++) // set bytes to caller's array
|
---|
91 | for(j = 0; j < 4; j++)
|
---|
92 | data[4*i+j] = (N98[i] >> 8*j) & 0xFF;
|
---|
93 | }
|
---|
94 | void MakeSubKeys(uint* KeySch, char key98Idx)
|
---|
95 | {
|
---|
96 | int i,k;
|
---|
97 | char j;
|
---|
98 | uint w[140] = {0};
|
---|
99 | char Sbox[128];
|
---|
100 | // uint KeyS[132];
|
---|
101 | // calc SBox , inverse of SBoxInverse
|
---|
102 | for(i = 0; i < 8; i++) //row
|
---|
103 | {
|
---|
104 | for(j = 0; j < 16; j++) // search for column
|
---|
105 | {
|
---|
106 | k=0;
|
---|
107 | while (SBoxInverse[k+16*i] != j)
|
---|
108 | k = k +1;
|
---|
109 | Sbox[j+16*i] = k;
|
---|
110 | }
|
---|
111 | }
|
---|
112 | switch (key98Idx)
|
---|
113 | {
|
---|
114 | case 0x21:
|
---|
115 | w[0]=0x6341F22E; w[1]=0x002E2D10; w[2]=0x181D7704; w[3]=0x1D93A0F3; w[4]=1; w[5]=0; w[6]=0; w[7]=0;
|
---|
116 | break;
|
---|
117 | }
|
---|
118 | for(i = 0; i < 132; i++)
|
---|
119 | w[i+8] = rotr(w[i+0] ^ w[i+3] ^ w[i+5] ^ w[i+7] ^ 0x9E3779B9 ^ i, 21);
|
---|
120 | for(i = 0; i < 33; i++)
|
---|
121 | SBitslice(w,4*i+8,KeySch,4*i, ((35-i) & 7), Sbox); // SBox , bitslice mode
|
---|
122 | }
|
---|
123 | struct geo_cache
|
---|
124 | {
|
---|
125 | uint32_t provid;
|
---|
126 | uint8_t geo[256];
|
---|
127 | uint8_t geo_len;
|
---|
128 | int32_t number_ecm;
|
---|
129 | };
|
---|
130 | struct viaccess_data
|
---|
131 | {
|
---|
132 | struct geo_cache last_geo;
|
---|
133 | uint8_t availkeys[CS_MAXPROV][16];
|
---|
134 | };
|
---|
135 | struct via_date
|
---|
136 | {
|
---|
137 | uint16_t day_s : 5;
|
---|
138 | uint16_t month_s : 4;
|
---|
139 | uint16_t year_s : 7;
|
---|
140 | uint16_t day_e : 5;
|
---|
141 | uint16_t month_e : 4;
|
---|
142 | uint16_t year_e : 7;
|
---|
143 | };
|
---|
144 | static void parse_via_date(const uint8_t *buf, struct via_date *vd, int32_t fend)
|
---|
145 | {
|
---|
146 | uint16_t date;
|
---|
147 | date = (buf[0] << 8) | buf[1];
|
---|
148 | vd->day_s = date & 0x1f;
|
---|
149 | vd->month_s = (date >> 5) & 0x0f;
|
---|
150 | vd->year_s = (date >> 9) & 0x7f;
|
---|
151 | if(fend)
|
---|
152 | {
|
---|
153 | date = (buf[2] << 8) | buf[3];
|
---|
154 | vd->day_e = date & 0x1f;
|
---|
155 | vd->month_e = (date >> 5) & 0x0f;
|
---|
156 | vd->year_e = (date >> 9) & 0x7f;
|
---|
157 | }
|
---|
158 | }
|
---|
159 | struct emm_rass *find_rabuf(struct s_client *client, int32_t provid, uint8_t nano, int8_t add)
|
---|
160 | {
|
---|
161 | struct emm_rass *e;
|
---|
162 | LL_ITER it;
|
---|
163 | if(!client->ra_buf)
|
---|
164 | {
|
---|
165 | client->ra_buf = ll_create("client->ra_buf");
|
---|
166 | }
|
---|
167 | it = ll_iter_create(client->ra_buf);
|
---|
168 | while((e = ll_iter_next(&it)) != NULL)
|
---|
169 | {
|
---|
170 | if(!add && e->provid == provid && e->emmlen != 0)
|
---|
171 | {
|
---|
172 | return e;
|
---|
173 | }
|
---|
174 | if(add && e->provid == provid && e->emm[0] == nano)
|
---|
175 | {
|
---|
176 | return e;
|
---|
177 | }
|
---|
178 | }
|
---|
179 | if(!add)
|
---|
180 | {
|
---|
181 | return NULL;
|
---|
182 | }
|
---|
183 | if(!cs_malloc(&e, sizeof(struct emm_rass)))
|
---|
184 | {
|
---|
185 | return NULL;
|
---|
186 | }
|
---|
187 | e->provid = provid;
|
---|
188 | ll_append(client->ra_buf, e);
|
---|
189 | return e;
|
---|
190 | }
|
---|
191 | static void show_class(struct s_reader *reader, const char *p, uint32_t provid, const uint8_t *b, int32_t l)
|
---|
192 | {
|
---|
193 | int32_t i, j;
|
---|
194 | // b -> via date (4 uint8_ts)
|
---|
195 | b += 4;
|
---|
196 | l -= 4;
|
---|
197 | j = l - 1;
|
---|
198 | for(; j >= 0; j--)
|
---|
199 | {
|
---|
200 | for(i = 0; i < 8; i++)
|
---|
201 | {
|
---|
202 | if(b[j] & (1 << (i & 7)))
|
---|
203 | {
|
---|
204 | uint8_t cls;
|
---|
205 | struct via_date vd;
|
---|
206 | parse_via_date(b - 4, &vd, 1);
|
---|
207 | cls = (l - (j + 1)) * 8 + i;
|
---|
208 | if(p) // just show class info, dont add entitlement!
|
---|
209 | {
|
---|
210 | rdr_log(reader, "%sclass: %02X, expiry date: %04d/%02d/%02d - %04d/%02d/%02d", p, cls,
|
---|
211 | vd.year_s + 1980, vd.month_s, vd.day_s,
|
---|
212 | vd.year_e + 1980, vd.month_e, vd.day_e);
|
---|
213 | }
|
---|
214 | else
|
---|
215 | {
|
---|
216 | rdr_log(reader, "class: %02X, expiry date: %04d/%02d/%02d - %04d/%02d/%02d", cls,
|
---|
217 | vd.year_s + 1980, vd.month_s, vd.day_s,
|
---|
218 | vd.year_e + 1980, vd.month_e, vd.day_e);
|
---|
219 | //convert time:
|
---|
220 | time_t start_t, end_t;
|
---|
221 | struct tm tm;
|
---|
222 | memset(&tm, 0, sizeof(tm));
|
---|
223 | tm.tm_year = vd.year_s + 80; //via year starts in 1980, tm_year starts in 1900
|
---|
224 | tm.tm_mon = vd.month_s - 1; // january is 0 in tm_mon
|
---|
225 | tm.tm_mday = vd.day_s;
|
---|
226 | start_t = cs_timegm(&tm);
|
---|
227 | tm.tm_year = vd.year_e + 80; //via year starts in 1980, tm_year starts in 1900
|
---|
228 | tm.tm_mon = vd.month_e - 1; // january is 0 in tm_mon
|
---|
229 | tm.tm_mday = vd.day_e;
|
---|
230 | end_t = cs_timegm(&tm);
|
---|
231 | cs_add_entitlement(reader, reader->caid, provid, cls, cls, start_t, end_t, 5, 1);
|
---|
232 | }
|
---|
233 | }
|
---|
234 | }
|
---|
235 | }
|
---|
236 | }
|
---|
237 | static int8_t add_find_class(struct s_reader *reader, uint32_t provid, const uint8_t *b, int32_t l, int8_t add)
|
---|
238 | {
|
---|
239 | int32_t i, j, freshdate = 0;
|
---|
240 | // b -> via date (4 uint8_ts)
|
---|
241 | b += 4;
|
---|
242 | l -= 4;
|
---|
243 | j = l - 1;
|
---|
244 | for(; j >= 0; j--)
|
---|
245 | {
|
---|
246 | for(i = 0; i < 8; i++)
|
---|
247 | {
|
---|
248 | if(b[j] & (1 << (i & 7)))
|
---|
249 | {
|
---|
250 | uint8_t cls;
|
---|
251 | cls = (l - (j + 1)) * 8 + i;
|
---|
252 | if(cs_add_entitlement(reader, reader->caid, provid, cls, cls, 0, 0, 5, 0) == NULL && !add)
|
---|
253 | {
|
---|
254 | rdr_log(reader, "provid %06X class %02X not found", provid, cls);
|
---|
255 | freshdate = 1;
|
---|
256 | }
|
---|
257 | else
|
---|
258 | {
|
---|
259 | if(!add)
|
---|
260 | {
|
---|
261 | rdr_log(reader, "provid %06X has matching class %02X", provid, cls);
|
---|
262 | }
|
---|
263 | struct via_date vd;
|
---|
264 | parse_via_date(b - 4, &vd, 1);
|
---|
265 | time_t start_t, end_t;
|
---|
266 | struct tm tm;
|
---|
267 | //convert time:
|
---|
268 | memset(&tm, 0, sizeof(tm));
|
---|
269 | tm.tm_year = vd.year_s + 80; // via year starts in 1980, tm_year starts in 1900
|
---|
270 | tm.tm_mon = vd.month_s - 1; // january is 0 in tm_mon
|
---|
271 | tm.tm_mday = vd.day_s;
|
---|
272 | start_t = cs_timegm(&tm);
|
---|
273 | tm.tm_year = vd.year_e + 80; //via year starts in 1980, tm_year starts in 1900
|
---|
274 | tm.tm_mon = vd.month_e - 1; // january is 0 in tm_mon
|
---|
275 | tm.tm_mday = vd.day_e;
|
---|
276 | end_t = cs_timegm(&tm);
|
---|
277 |
|
---|
278 | if(cs_add_entitlement(reader, reader->caid, provid, cls, cls, start_t, end_t, 5, add) != NULL)
|
---|
279 | {
|
---|
280 | if(!add)
|
---|
281 | {
|
---|
282 | rdr_log(reader, "class %02X provid %06X has already this daterange or newer entitled", cls, provid);
|
---|
283 | }
|
---|
284 | }
|
---|
285 | else
|
---|
286 | {
|
---|
287 | freshdate = 1;
|
---|
288 | }
|
---|
289 | }
|
---|
290 | }
|
---|
291 | }
|
---|
292 | }
|
---|
293 | if(freshdate == 0)
|
---|
294 | {
|
---|
295 | return -2;
|
---|
296 | }
|
---|
297 | return 1; // emmdate is fresh!
|
---|
298 | }
|
---|
299 | static void show_subs(struct s_reader *reader, const uint8_t *emm)
|
---|
300 | {
|
---|
301 | switch(emm[0])
|
---|
302 | {
|
---|
303 | case 0xA9:
|
---|
304 | {
|
---|
305 | show_class(reader, "nano A9: ", 1, emm + 2, emm[1]);
|
---|
306 | break;
|
---|
307 | }
|
---|
308 | case 0xA6:
|
---|
309 | {
|
---|
310 | char szGeo[256];
|
---|
311 | memset(szGeo, 0, 256);
|
---|
312 | cs_strncpy(szGeo, (char *)emm + 2, emm[1]);
|
---|
313 | rdr_log(reader, "nano A6: geo %s", szGeo);
|
---|
314 | break;
|
---|
315 | }
|
---|
316 | case 0xB6:
|
---|
317 | {
|
---|
318 | uint8_t m; // modexp
|
---|
319 | struct via_date vd;
|
---|
320 | m = emm[emm[1] + 1];
|
---|
321 | parse_via_date(emm + 2, &vd, 0);
|
---|
322 | rdr_log(reader, "nano B6: modexp %d%d%d%d%d%d: %02d/%02d/%04d",
|
---|
323 | (m & 0x20) ? 1 : 0,
|
---|
324 | (m & 0x10) ? 1 : 0,
|
---|
325 | (m & 0x08) ? 1 : 0,
|
---|
326 | (m & 0x04) ? 1 : 0,
|
---|
327 | (m & 0x02) ? 1 : 0,
|
---|
328 | (m & 0x01) ? 1 : 0,
|
---|
329 | vd.day_s, vd.month_s, vd.year_s + 1980);
|
---|
330 | break;
|
---|
331 | }
|
---|
332 | }
|
---|
333 | }
|
---|
334 | static int32_t chk_prov(struct s_reader *reader, uint8_t *id, uint8_t keynr)
|
---|
335 | {
|
---|
336 | struct viaccess_data *csystem_data = reader->csystem_data;
|
---|
337 | int32_t i, j, rc;
|
---|
338 | for(rc = i = 0; (!rc) && (i < reader->nprov); i++)
|
---|
339 | {
|
---|
340 | if(!memcmp(&reader->prid[i][1], id, 3))
|
---|
341 | {
|
---|
342 | for(j = 0; (!rc) && (j < 16); j++)
|
---|
343 | {
|
---|
344 | if(csystem_data->availkeys[i][j] == keynr)
|
---|
345 | {
|
---|
346 | rc = 1;
|
---|
347 | }
|
---|
348 | }
|
---|
349 | }
|
---|
350 | }
|
---|
351 | return (rc);
|
---|
352 | }
|
---|
353 | static int32_t get_maturity(struct s_reader *reader)
|
---|
354 | {
|
---|
355 | /* retrieve maturity rating on the card */
|
---|
356 | def_resp;
|
---|
357 | uint8_t insac[] = { 0xca, 0xac, 0x00, 0x00, 0x00 }; // select data
|
---|
358 | uint8_t insb8[] = { 0xca, 0xb8, 0x00, 0x00, 0x00 }; // read selected data
|
---|
359 | insac[2] = 0x06;
|
---|
360 | write_cmd(insac, NULL); // request maturity rating
|
---|
361 | insb8[4] = 0x02;
|
---|
362 | write_cmd(insb8, NULL); // read maturity rating nano + len
|
---|
363 | insb8[4] = cta_res[1];
|
---|
364 | write_cmd(insb8, NULL); // read maturity rating
|
---|
365 | reader->maturity = cta_res[cta_lr - 3] & 0x0F;
|
---|
366 | if (reader->maturity < 0xF)
|
---|
367 | {
|
---|
368 | rdr_log(reader, "Maturity level [%X]= older than %i years", reader->maturity, reader->maturity);
|
---|
369 | }
|
---|
370 | else
|
---|
371 | {
|
---|
372 | rdr_log(reader, "Maturity level [%X]=no age limit", reader->maturity);
|
---|
373 | }
|
---|
374 | return 0;
|
---|
375 | }
|
---|
376 | static int32_t unlock_parental(struct s_reader *reader)
|
---|
377 | {
|
---|
378 | /* disabling parental lock. assuming pin "0000" if no pin code is provided in the config */
|
---|
379 | static const uint8_t inDPL[] = { 0xca, 0x24, 0x02, 0x00, 0x09 };
|
---|
380 | uint8_t cmDPL[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F };
|
---|
381 | def_resp;
|
---|
382 | if(strcmp(reader->pincode, "none"))
|
---|
383 | {
|
---|
384 | rdr_log(reader, "Using PIN %s", reader->pincode);
|
---|
385 | // the pin need to be coded in bcd, so we need to convert from ascii to bcd, so '1234' -> 0x12 0x34
|
---|
386 | cmDPL[6] = ((reader->pincode[0] - 0x30) << 4) | ((reader->pincode[1] - 0x30) & 0x0f);
|
---|
387 | cmDPL[7] = ((reader->pincode[2] - 0x30) << 4) | ((reader->pincode[3] - 0x30) & 0x0f);
|
---|
388 | }
|
---|
389 | else
|
---|
390 | {
|
---|
391 | rdr_log(reader, "Using PIN 0000!");
|
---|
392 | }
|
---|
393 | write_cmd(inDPL, cmDPL);
|
---|
394 | if(!(cta_res[cta_lr - 2] == 0x90 && cta_res[cta_lr - 1] == 0))
|
---|
395 | {
|
---|
396 | if(strcmp(reader->pincode, "none"))
|
---|
397 | {
|
---|
398 | rdr_log(reader, "Can't disable parental lock. Wrong PIN? OSCam used %s!", reader->pincode);
|
---|
399 | }
|
---|
400 | else
|
---|
401 | {
|
---|
402 | rdr_log(reader, "Can't disable parental lock. Wrong PIN? OSCam used 0000!");
|
---|
403 | }
|
---|
404 | }
|
---|
405 | else
|
---|
406 | {
|
---|
407 | rdr_log(reader, "Parental lock disabled");
|
---|
408 | get_maturity(reader);
|
---|
409 | }
|
---|
410 | return 0;
|
---|
411 | }
|
---|
412 | int32_t hdSurEncBasicCrypt_D2_0F_11(int32_t Value, int32_t XorVal)
|
---|
413 | {
|
---|
414 | int32_t i = (Value << 13) - Value + 0x1B59;
|
---|
415 | i = (i * Value) + 0x07CF;
|
---|
416 | return (i ^ XorVal);
|
---|
417 | }
|
---|
418 | int32_t hdSurEncCryptLookup_D2_0F_11(uint8_t Value, uint8_t AddrInd)
|
---|
419 | {
|
---|
420 | static const uint8_t lookup[] =
|
---|
421 | {
|
---|
422 | 0x94, 0xB2, 0xA9, 0x79, 0xC4, 0xC7, 0x0D, 0x36, 0x6F, 0x24, 0x11, 0xD1, 0xDB, 0x59, 0xD2, 0xA5,
|
---|
423 | 0xE1, 0x00, 0xD4, 0x97, 0xA3, 0x2B, 0x11, 0xFA, 0x5F, 0xF1, 0xC1, 0x44, 0xBF, 0x9B, 0x5A, 0xC8,
|
---|
424 | 0xF1, 0xE1, 0x99, 0x82, 0x0E, 0xB2, 0x01, 0x09, 0x0C, 0xC8, 0xB3, 0x3B, 0xD1, 0x80, 0x50, 0xE8,
|
---|
425 | 0xF5, 0x52, 0x4C, 0xE6, 0x82, 0xAC, 0x58, 0x40, 0xD4, 0x71, 0x87, 0x52, 0x06, 0xEA, 0xA6, 0x27,
|
---|
426 | 0xB7, 0xFE, 0x6C, 0x49, 0x47, 0x3B, 0x70, 0x6C, 0xEB, 0xCD, 0xC5, 0x0B, 0x8C, 0x31, 0x29, 0x42,
|
---|
427 | 0x4E, 0x10, 0x2B, 0x2D, 0x46, 0xEC, 0x39, 0xA3, 0x90, 0x4B, 0x25, 0x60, 0x9C, 0x62, 0xD4, 0x20,
|
---|
428 | 0xF6, 0x16, 0xA8, 0x9C, 0xE4, 0x20, 0xED, 0xC7, 0xBA, 0x5E, 0xB6, 0x4E, 0x03, 0x15, 0xA6, 0xF6,
|
---|
429 | 0x23, 0x98, 0x32, 0xC0, 0xAE, 0xA3, 0xFD, 0xD3, 0x7F, 0xF8, 0xED, 0xF0, 0x29, 0x29, 0x12, 0xB3,
|
---|
430 | 0xB7, 0x58, 0xAD, 0xA2, 0x58, 0x2C, 0x70, 0x1B, 0xA4, 0x25, 0xE8, 0xA5, 0x43, 0xF1, 0xB9, 0x8F,
|
---|
431 | 0x1E, 0x3B, 0x10, 0xDF, 0x52, 0xFE, 0x58, 0x29, 0xAD, 0x3F, 0x99, 0x4D, 0xDF, 0xD2, 0x08, 0x06,
|
---|
432 | 0xA1, 0x1C, 0x66, 0x29, 0x26, 0x80, 0x52, 0x8A, 0x5A, 0x73, 0xE7, 0xDF, 0xC1, 0xC4, 0x47, 0x82,
|
---|
433 | 0xAB, 0x5C, 0x32, 0xAE, 0x96, 0x04, 0x2B, 0xC3, 0x2D, 0x5A, 0xD2, 0xB0, 0x64, 0x88, 0x97, 0xBF,
|
---|
434 | 0x7E, 0x99, 0x60, 0xCC, 0x63, 0x76, 0x66, 0xE9, 0x9A, 0x3D, 0xBB, 0xF7, 0x7F, 0xE4, 0x7C, 0x3F,
|
---|
435 | 0xB8, 0x4D, 0x10, 0x8D, 0x2A, 0xEA, 0x3C, 0xD3, 0x03, 0x74, 0xE6, 0x46, 0xC0, 0x29, 0xAE, 0xB0,
|
---|
436 | 0x79, 0xBE, 0xCB, 0x18, 0x34, 0xBE, 0x5A, 0xE9, 0x19, 0x8F, 0xA3, 0x8F, 0xD6, 0x6A, 0x6C, 0x88,
|
---|
437 | 0x1E, 0x21, 0x08, 0x15, 0xC4, 0xE7, 0xE6, 0xBA, 0x97, 0x9C, 0x4F, 0x89, 0x9F, 0x1A, 0x67, 0x4F,
|
---|
438 | 0xC0, 0xD5, 0x72, 0x51, 0x16, 0xB4, 0xD3, 0x8A, 0x1F, 0xE3, 0x92, 0x02, 0x7F, 0x59, 0x56, 0x8F,
|
---|
439 | 0x07, 0x8D, 0xC1, 0xC2, 0x42, 0x69, 0x3C, 0xA6, 0xBF, 0x3D, 0xDF, 0x0D, 0xAA, 0x4F, 0x7E, 0x80,
|
---|
440 | 0x07, 0x11, 0xE2, 0x94, 0x19, 0x9B, 0x16, 0x26, 0x1A, 0x46, 0x09, 0x0D, 0xB5, 0xB8, 0x8E, 0x01,
|
---|
441 | 0x9C, 0xFE, 0x09, 0xB3, 0x60, 0xC2, 0xAE, 0x50, 0x3C, 0x68, 0x75, 0x4A, 0x57, 0xD8, 0x4F, 0xD7,
|
---|
442 | 0xA2, 0x76, 0x2C, 0xC1, 0xA2, 0x23, 0xBC, 0x54, 0x2A, 0xDD, 0xF3, 0xDD, 0xA7, 0x34, 0xF7, 0x5C,
|
---|
443 | 0xF4, 0x86, 0x23, 0x48, 0x7C, 0x3F, 0x05, 0x40, 0x0E, 0xB0, 0xE5, 0xEB, 0x3E, 0xDF, 0x6A, 0x83,
|
---|
444 | 0x65, 0xA0, 0xB2, 0x06, 0xD1, 0x40, 0x79, 0x0D, 0xDE, 0x95, 0x84, 0x96, 0x87, 0x6F, 0xCE, 0x48,
|
---|
445 | 0x24, 0x13, 0x0B, 0xF5, 0xC7, 0xF5, 0xA8, 0x7F, 0x2E, 0xC7, 0xE1, 0xBA, 0xAE, 0x2B, 0xF7, 0xF0,
|
---|
446 | 0x8E, 0xF7, 0x54, 0x0B, 0xF0, 0xD2, 0x41, 0x81, 0x68, 0x3B, 0x1E, 0x35, 0xAB, 0xD9, 0x2B, 0x46,
|
---|
447 | 0x57, 0xE8, 0x53, 0xDF, 0xDE, 0x10, 0xEF, 0xCB, 0x4C, 0xE0, 0x52, 0x18, 0x2C, 0x4E, 0xB9, 0x20,
|
---|
448 | 0xE9, 0x7E, 0x85, 0xDF, 0x75, 0x32, 0xE6, 0x10, 0xE9, 0x9C, 0x7B, 0x2E, 0x4C, 0xDA, 0x46, 0xE6,
|
---|
449 | 0xCC, 0x77, 0x36, 0x1D, 0x4A, 0x15, 0xF5, 0x32, 0x18, 0x6B, 0x7E, 0xAA, 0xCC, 0x97, 0xCC, 0xD1,
|
---|
450 | 0x2F, 0xE5, 0x58, 0x03, 0x35, 0x35, 0x3D, 0xA0, 0x2B, 0x13, 0x3A, 0x65, 0xFF, 0x24, 0x72, 0xCF,
|
---|
451 | 0xA7, 0x6D, 0x52, 0x55, 0xF6, 0xC2, 0x30, 0x23, 0x7D, 0x9B, 0x9E, 0xB0, 0x94, 0x02, 0xAD, 0x60,
|
---|
452 | 0x8A, 0x9F, 0xBC, 0xC8, 0xE4, 0x2B, 0x92, 0x96, 0xF5, 0xAE, 0x04, 0xA4, 0x33, 0x0C, 0x90, 0x67,
|
---|
453 | 0xF0, 0xB9, 0x1E, 0x7E, 0xBE, 0x02, 0x18, 0xB2, 0x03, 0xB6, 0x40, 0xBF, 0x05, 0xE3, 0x76, 0x98,
|
---|
454 | 0x21, 0x38, 0xC9, 0x5F, 0xD3, 0x51, 0x8B, 0x43, 0x0B, 0x1A, 0x0B, 0xF9, 0x3C, 0x21, 0x6C, 0x3D,
|
---|
455 | 0xB8, 0xA0, 0x57, 0xCA, 0x68, 0xCD, 0x1E, 0xD2, 0x2C, 0x50, 0xEE, 0xC0, 0xDF, 0x25, 0x88, 0x52,
|
---|
456 | 0x37, 0xE1, 0x44, 0xC6, 0x76, 0x3B, 0x91, 0x95, 0x86, 0x76, 0x87, 0x49, 0x21, 0x93, 0x44, 0x0A,
|
---|
457 | 0x52, 0xB9, 0x2D, 0x2B, 0xE3, 0x1D, 0xB0, 0xE4, 0x98, 0xC6, 0xEE, 0x3D, 0x96, 0x53, 0x4B, 0xFF,
|
---|
458 | 0x39, 0x00, 0xD5, 0x42, 0x7E, 0xE1, 0x4C, 0x6F, 0xD5, 0xB7, 0xE6, 0x99, 0x2A, 0x5B, 0x67, 0xEE,
|
---|
459 | 0x3E, 0xBA, 0xF7, 0xEC, 0x43, 0x2A, 0x1C, 0xB6, 0xB5, 0x04, 0x26, 0x59, 0xB1, 0x4C, 0x17, 0xCC,
|
---|
460 | 0x83, 0xB9, 0x00, 0x3E, 0x36, 0x91, 0x90, 0xF7, 0x5E, 0x38, 0xDC, 0xE4, 0x15, 0xC7, 0x67, 0xF0,
|
---|
461 | 0xCA, 0xC8, 0xD2, 0x91, 0x5D, 0x74, 0xAC, 0x97, 0x56, 0x36, 0x1A, 0x82, 0x0A, 0xAA, 0xB4, 0x4E,
|
---|
462 | 0xBF, 0x29, 0x5C, 0xBF, 0x58, 0xB3, 0x97, 0xF9, 0xEB, 0x7C, 0x85, 0xB4, 0xA5, 0x13, 0x2F, 0xD1,
|
---|
463 | 0xDE, 0x1C, 0xEC, 0x97, 0xDD, 0xE2, 0x39, 0xE4, 0xFB, 0x0A, 0x02, 0xE0, 0xC3, 0xBA, 0x39, 0x79,
|
---|
464 | 0xAA, 0x1C, 0x37, 0x75, 0x25, 0x54, 0xBE, 0x85, 0x74, 0x2C, 0xFA, 0x0C, 0xFA, 0x50, 0xF6, 0xBE,
|
---|
465 | 0x9F, 0x2A, 0x53, 0x7C, 0x27, 0x46, 0x68, 0x2D, 0x74, 0x2B, 0x46, 0xDA, 0xF5, 0x07, 0x95, 0x09,
|
---|
466 | 0x6A, 0x91, 0xB7, 0xB1, 0x34, 0x07, 0x5F, 0xEA, 0xBE, 0x0F, 0x87, 0x28, 0x68, 0x97, 0x43, 0x77,
|
---|
467 | 0xD5, 0x38, 0x2B, 0x11, 0x11, 0x4F, 0xD9, 0x75, 0x5E, 0xE1, 0x06, 0xA0, 0x3B, 0xAC, 0x32, 0xFE,
|
---|
468 | 0xBF, 0x73, 0x59, 0x5B, 0xA2, 0xA8, 0x7E, 0x10, 0x4C, 0x6E, 0x78, 0xF0, 0x4A, 0x4E, 0x95, 0xD6,
|
---|
469 | 0xDD, 0x05, 0x7A, 0xBB, 0xF1, 0xEB, 0xA8, 0xA4, 0x5D, 0x91, 0xF0, 0xED, 0xDB, 0xB8, 0x01, 0x41,
|
---|
470 | 0xF8, 0x97, 0x7F, 0xC3, 0x91, 0x53, 0xBF, 0xE9, 0xEA, 0x33, 0x1F, 0xDC, 0xA6, 0xE6, 0x8D, 0xCB,
|
---|
471 | 0x75, 0xD0, 0x69, 0xD0, 0xA4, 0x59, 0xA5, 0x02, 0xFC, 0x60, 0x0D, 0x6A, 0xA0, 0x05, 0x1A, 0x54,
|
---|
472 | 0x8A, 0xA7, 0x57, 0xA3, 0xF0, 0x90, 0x8A, 0xD5, 0x6F, 0x1E, 0x2E, 0x10, 0x9A, 0x93, 0x2B, 0x51,
|
---|
473 | 0x2C, 0xFD, 0x99, 0xE5, 0x9B, 0x5D, 0xB2, 0xA7, 0x37, 0x99, 0x26, 0x35, 0xCA, 0xDD, 0x22, 0x19,
|
---|
474 | 0x59, 0x2A, 0xB0, 0x99, 0x23, 0xDF, 0xA7, 0xA9, 0x85, 0x12, 0xCF, 0xBF, 0xFC, 0x74, 0x80, 0x87,
|
---|
475 | 0xE1, 0x97, 0xD0, 0xF9, 0xEF, 0x5F, 0x1B, 0x45, 0xF7, 0x76, 0xDB, 0x66, 0x39, 0x05, 0x43, 0x06,
|
---|
476 | 0xA9, 0x9F, 0x2E, 0x14, 0x9F, 0x1C, 0x0C, 0x1F, 0xD5, 0xD9, 0xA4, 0x8D, 0x18, 0x6F, 0x08, 0x53,
|
---|
477 | 0x0B, 0x92, 0x9A, 0x0C, 0xEA, 0x4C, 0xE4, 0x1D, 0x9E, 0x9A, 0x51, 0xB8, 0x7E, 0x2D, 0xE7, 0x3C,
|
---|
478 | 0xFF, 0x84, 0x5C, 0xBF, 0x8F, 0x8C, 0x89, 0x09, 0x1B, 0x7E, 0x4B, 0xE7, 0x85, 0xEC, 0x04, 0xB5,
|
---|
479 | 0x20, 0x18, 0x1E, 0x55, 0xD5, 0x5B, 0xAC, 0xC6, 0x25, 0x5A, 0xA1, 0x81, 0xC1, 0x31, 0x9C, 0xF5,
|
---|
480 | 0xB5, 0x54, 0x07, 0x65, 0x0A, 0x5B, 0x90, 0x06, 0x4F, 0x84, 0xB2, 0x7F, 0xD1, 0xAD, 0x16, 0x81,
|
---|
481 | 0x25, 0xAF, 0xAF, 0xE2, 0x03, 0xA9, 0x1F, 0x13, 0x02, 0x5D, 0x54, 0x89, 0xCD, 0x44, 0x51, 0xEB,
|
---|
482 | 0xA4, 0x2B, 0xBD, 0x47, 0xB0, 0xB6, 0x27, 0x1D, 0x9B, 0x14, 0x6F, 0xBF, 0xCD, 0x59, 0xBC, 0x0A,
|
---|
483 | 0x37, 0xA8, 0x74, 0x7D, 0x16, 0x90, 0x28, 0xD5, 0x94, 0xC3, 0xE4, 0x23, 0xC4, 0x98, 0x91, 0xCE,
|
---|
484 | 0x55, 0xBD, 0x21, 0x3B, 0x84, 0xBD, 0x44, 0x3C, 0xF9, 0xCD, 0x37, 0x43, 0x4A, 0xC6, 0x8C, 0x23,
|
---|
485 | 0x04, 0x28, 0x63, 0x7A, 0x03, 0x85, 0xD2, 0x46, 0x93, 0xCA, 0xFE, 0xC3, 0x83, 0x0B, 0x13, 0xCC,
|
---|
486 | 0x5D, 0xCB, 0xBA, 0xCA, 0x68, 0xAB, 0x05, 0xF7, 0xEC, 0x4A, 0x9C, 0x0F, 0xD5, 0xC4, 0x5A, 0xA5,
|
---|
487 | 0xA0, 0x04, 0x41, 0x6A, 0xF6, 0xEF, 0x16, 0x9B, 0x69, 0x38, 0xF6, 0x2D, 0xAA, 0xEB, 0x2D, 0xE2,
|
---|
488 | 0x82, 0xA2, 0x9F, 0x6F, 0xBD, 0x2A, 0xE3, 0x66, 0x6B, 0x21, 0xDA, 0x56, 0xAD, 0x82, 0x2B, 0x93,
|
---|
489 | 0xF3, 0x25, 0xEA, 0xFC, 0xFD, 0xFD, 0x1B, 0xA9, 0xFC, 0xB8, 0xC6, 0x98, 0x45, 0xF2, 0x70, 0x03,
|
---|
490 | 0x4A, 0x9C, 0x60, 0x82, 0x65, 0xB6, 0x68, 0x4C, 0xE7, 0x41, 0x10, 0x9D, 0x59, 0x40, 0x03, 0x02,
|
---|
491 | 0x07, 0x12, 0x33, 0xAF, 0x79, 0xE1, 0xC4, 0xEB, 0xB8, 0xCE, 0x6A, 0x90, 0x72, 0x61, 0x5D, 0x56,
|
---|
492 | 0xC7, 0x59, 0x31, 0xCB, 0x45, 0x2D, 0x42, 0x9F, 0x10, 0x1D, 0x09, 0x63, 0x59, 0x8C, 0x6C, 0xDB,
|
---|
493 | 0x11, 0xCF, 0xA1, 0xDF, 0x5F, 0x4D, 0xDF, 0xB4, 0xC3, 0x82, 0xEE, 0x58, 0x16, 0xB4, 0x74, 0xFA,
|
---|
494 | 0xBE, 0x11, 0x9C, 0x1E, 0x98, 0x29, 0xDE, 0xE3, 0xE5, 0x9E, 0xCF, 0xD7, 0x91, 0x0A, 0xA3, 0xA4,
|
---|
495 | 0x42, 0xA1, 0x95, 0x09, 0x9E, 0x16, 0xD5, 0xA8, 0x24, 0x56, 0x5B, 0x23, 0xC8, 0x56, 0x4C, 0xCB,
|
---|
496 | 0x89, 0x18, 0x69, 0xEB, 0x0C, 0x1F, 0xC0, 0x41, 0x5C, 0x63, 0x04, 0x68, 0xB2, 0x0F, 0x3F, 0x88,
|
---|
497 | 0x36, 0xDD, 0x23, 0x4D, 0x4C, 0xC0, 0x81, 0xE3, 0xE9, 0xAD, 0xE0, 0x27, 0xD5, 0xE5, 0x46, 0xEB,
|
---|
498 | 0xFF, 0x32, 0xA2, 0xB7, 0x14, 0x64, 0x0B, 0x6D, 0x1B, 0xE5, 0xD8, 0xAE, 0x9D, 0xE8, 0x55, 0xB9,
|
---|
499 | 0x52, 0x70, 0x59, 0xB8, 0x72, 0x92, 0x69, 0x37, 0x95, 0x61, 0x0A, 0xE5, 0xF6, 0x55, 0x97, 0x1D,
|
---|
500 | 0xBF, 0xF7, 0x29, 0x77, 0x0F, 0x72, 0x80, 0xB2, 0x7E, 0x56, 0xBF, 0xFD, 0xE9, 0xF5, 0x9B, 0x62,
|
---|
501 | 0xE9, 0xBD, 0x0B, 0xC2, 0x07, 0x55, 0x31, 0x4C, 0x57, 0x3A, 0x05, 0xB9, 0x27, 0x41, 0x4A, 0xC3,
|
---|
502 | 0xEC, 0x72, 0x20, 0xB3, 0x0C, 0xF9, 0xD9, 0x3A, 0x14, 0x6A, 0x03, 0x44, 0x6A, 0xF1, 0x41, 0x55,
|
---|
503 | 0x7F, 0x81, 0xC2, 0x04, 0xA8, 0x05, 0xB9, 0x49, 0x2E, 0x43, 0xC4, 0x00, 0x87, 0x86, 0x04, 0xAC,
|
---|
504 | 0xAF, 0x73, 0x78, 0x0E, 0xA4, 0x43, 0x5B, 0x36, 0xA2, 0x8F, 0x9C, 0xF7, 0x66, 0x4A, 0x5A, 0x09,
|
---|
505 | 0x6B, 0xAA, 0x69, 0x6F, 0xB1, 0x20, 0x0D, 0x56, 0x85, 0x0A, 0x5E, 0x06, 0xBF, 0xE2, 0x32, 0xB4,
|
---|
506 | 0x5C, 0x46, 0x33, 0x0D, 0x27, 0xA3, 0x6B, 0xE1, 0xB2, 0x6A, 0x7D, 0x4A, 0xA7, 0x81, 0x0F, 0x2B,
|
---|
507 | 0x16, 0x7C, 0x51, 0xD6, 0xC0, 0x3D, 0xB9, 0xFE, 0xB4, 0x66, 0xC4, 0xB6, 0x54, 0x53, 0x67, 0xDA,
|
---|
508 | 0x70, 0x96, 0x9A, 0x0A, 0x07, 0x1A, 0x26, 0xBA, 0x85, 0x50, 0xF5, 0x27, 0x53, 0x9C, 0x3A, 0x94,
|
---|
509 | 0x0A, 0x7D, 0xDB, 0xE1, 0xC3, 0xE3, 0x6A, 0x3E, 0x9E, 0xD5, 0x13, 0x0A, 0xA3, 0xD2, 0x21, 0x75,
|
---|
510 | 0x79, 0x17, 0x26, 0xAC, 0x48, 0x5F, 0x3D, 0xE1, 0x7D, 0xA4, 0xB1, 0x56, 0x0F, 0x92, 0x2C, 0x60,
|
---|
511 | 0xE6, 0xCB, 0x87, 0x35, 0xB8, 0x75, 0xC3, 0xA2, 0x03, 0x50, 0x4B, 0xA2, 0x6E, 0x01, 0xE1, 0xDD,
|
---|
512 | 0x87, 0xA5, 0x33, 0xC6, 0x2F, 0xA2, 0x41, 0xFC, 0x72, 0x98, 0xA2, 0x69, 0x4C, 0x3F, 0xF0, 0x53,
|
---|
513 | 0xF5, 0x41, 0x2B, 0x23, 0x24, 0x3B, 0xCE, 0x9D, 0x39, 0x31, 0x17, 0x08, 0xE1, 0x3F, 0x5F, 0xFB,
|
---|
514 | 0x00, 0xFA, 0xF1, 0xE3, 0xE1, 0x7B, 0x0C, 0xDF, 0x8D, 0xA2, 0xC4, 0xCD, 0x62, 0x3D, 0xAE, 0xC7,
|
---|
515 | 0x48, 0x09, 0x1C, 0x66, 0xCB, 0x0E, 0x23, 0xE8, 0x1B, 0x9F, 0x1B, 0xCB, 0xF8, 0x14, 0xC3, 0x34,
|
---|
516 | 0x91, 0x32, 0x2B, 0x39, 0x1C, 0xBA, 0x1C, 0xA0, 0x19, 0xF2, 0x57, 0x9D, 0x78, 0x00, 0x55, 0x1F,
|
---|
517 | 0x15, 0x12, 0x9A, 0xA2, 0xF2, 0xC2, 0xB7, 0x4E, 0xEA, 0x46, 0x01, 0xC2, 0xE9, 0x76, 0xBF, 0xDE,
|
---|
518 | 0xCF, 0x8B, 0xC7, 0x50, 0x80, 0xEE, 0x46, 0x91, 0x93, 0x1E, 0x5C, 0x48, 0x5D, 0xC8, 0xC8, 0x63,
|
---|
519 | 0xD1, 0x89, 0x02, 0x29, 0xE9, 0x90, 0x9F, 0x0B, 0x0A, 0x1A, 0x44, 0x17, 0xE7, 0x4E, 0xAD, 0x58,
|
---|
520 | 0x55, 0xF8, 0x38, 0xF6, 0x4F, 0xD8, 0x1C, 0x7E, 0x25, 0x9B, 0x59, 0x16, 0xBC, 0x65, 0x24, 0xC5,
|
---|
521 | 0xA7, 0x56, 0xE5, 0x20, 0x3F, 0xD9, 0x27, 0xE0, 0x32, 0x24, 0xE1, 0x7B, 0xE1, 0x32, 0xEA, 0xF4,
|
---|
522 | 0xFE, 0xD9, 0xA5, 0xFF, 0x35, 0xAE, 0xA9, 0x1B, 0x38, 0x28, 0x6A, 0xC0, 0x1A, 0x42, 0xD9, 0x5E,
|
---|
523 | 0x14, 0x2C, 0xC2, 0x2D, 0x9B, 0x94, 0x5B, 0xCF, 0x83, 0x30, 0xB9, 0x06, 0xAF, 0x4B, 0xD7, 0xF6,
|
---|
524 | 0x38, 0x7C, 0xFF, 0xB4, 0xA5, 0x1A, 0xA0, 0xE9, 0xF3, 0x01, 0xE3, 0x97, 0xC4, 0xA9, 0x57, 0xF5,
|
---|
525 | 0xB9, 0x96, 0xA7, 0xA3, 0xB8, 0x10, 0x0E, 0xFB, 0x1D, 0x39, 0x44, 0x16, 0x97, 0x94, 0x3E, 0x5F,
|
---|
526 | 0xAF, 0x0F, 0xE3, 0x99, 0xDC, 0xA0, 0xE9, 0x8D, 0x26, 0x2B, 0xD9, 0xAE, 0xEC, 0x4C, 0x4F, 0x09,
|
---|
527 | 0x86, 0x7E, 0x7B, 0xC3, 0xE3, 0xC6, 0x17, 0xAE, 0x30, 0x9C, 0x31, 0xD1, 0x84, 0x47, 0xAF, 0xCB,
|
---|
528 | 0xEA, 0x69, 0x2A, 0x08, 0x3E, 0x13, 0x00, 0xDE, 0xF6, 0x4A, 0x42, 0xD3, 0xBE, 0x33, 0xD9, 0x50,
|
---|
529 | 0x6B, 0x8D, 0x59, 0x12, 0x1A, 0xD3, 0xA7, 0x7C, 0x0A, 0xE7, 0x87, 0x47, 0xCA, 0xAA, 0x33, 0xFD,
|
---|
530 | 0xC1, 0xF6, 0x28, 0xC1, 0x62, 0xA2, 0x4C, 0x79, 0x83, 0x48, 0x86, 0x0E, 0xA4, 0x67, 0x34, 0x95,
|
---|
531 | 0xAE, 0x7D, 0xD6, 0xEE, 0x91, 0x05, 0x35, 0x91, 0xE8, 0x34, 0x39, 0xA3, 0xE5, 0xE6, 0x80, 0x53,
|
---|
532 | 0x76, 0x1F, 0x94, 0xA0, 0xF6, 0xA5, 0x41, 0x79, 0x82, 0xD3, 0xB0, 0x1F, 0xCE, 0xE1, 0x86, 0x64,
|
---|
533 | 0x65, 0x0C, 0x8D, 0xD6, 0xFA, 0xC1, 0x10, 0x6C, 0x07, 0xD5, 0xF0, 0x77, 0x65, 0xB9, 0x0C, 0xBD,
|
---|
534 | 0xAE, 0x2D, 0x62, 0x6C, 0x42, 0x7E, 0x2A, 0xBE, 0x5F, 0xC1, 0x17, 0x3B, 0x07, 0xFF, 0x5E, 0xD7,
|
---|
535 | 0x31, 0x52, 0x26, 0x2F, 0x9F, 0x12, 0xD8, 0x2E, 0xA3, 0xF5, 0xB5, 0xD2, 0xFC, 0x6E, 0x08, 0x1F,
|
---|
536 | 0xC8, 0x93, 0xA1, 0xEB, 0xF9, 0x13, 0x1D, 0x1F, 0x98, 0x5E, 0xB0, 0x0C, 0x65, 0x6C, 0xAE, 0x07,
|
---|
537 | 0x78, 0xF8, 0x12, 0xD2, 0xD1, 0x1E, 0x77, 0x5C, 0x24, 0x62, 0xE5, 0x94, 0xD6, 0x6A, 0x8E, 0xD0,
|
---|
538 | 0x72, 0x59, 0xDA, 0x48, 0x38, 0x2F, 0x31, 0x75, 0x0C, 0x52, 0xF0, 0x0C, 0x8F, 0x5C, 0xE9, 0x5E,
|
---|
539 | 0x5A, 0x94, 0xE8, 0xD2, 0x80, 0xF8, 0x4F, 0xE7, 0xAA, 0x6C, 0xBE, 0x47, 0xFB, 0xDD, 0x57, 0x0A,
|
---|
540 | 0xD8, 0x5E, 0xCC, 0x0D, 0x8F, 0x42, 0x5E, 0xDC, 0x5D, 0x95, 0x95, 0x60, 0x9B, 0x6F, 0x05, 0x5E,
|
---|
541 | 0x08, 0x45, 0x91, 0xE4, 0xB8, 0x06, 0xB1, 0xF2, 0xC0, 0xD7, 0xE3, 0x47, 0xB7, 0x38, 0x08, 0xA8,
|
---|
542 | 0x58, 0xE4, 0x55, 0xFC, 0xE2, 0x37, 0x1F, 0x38, 0xA2, 0x18, 0x9E, 0xC2, 0x0F, 0x90, 0x14, 0x20,
|
---|
543 | 0x50, 0xD1, 0xD0, 0xAB, 0x36, 0x7F, 0xAA, 0x03, 0x1C, 0xE6, 0x0A, 0xF9, 0x8E, 0x41, 0xDB, 0x32,
|
---|
544 | 0x1C, 0x68, 0xA0, 0xA0, 0xED, 0x4A, 0xF4, 0x4B, 0x09, 0xD0, 0xF0, 0x01, 0x8B, 0x17, 0x44, 0xE1,
|
---|
545 | 0xEA, 0xC5, 0x9D, 0x3B, 0x37, 0x7A, 0x68, 0xF1, 0x78, 0x46, 0xCF, 0xB6, 0x57, 0xDB, 0x4B, 0x5C,
|
---|
546 | 0x03, 0xE1, 0x9D, 0xC0, 0x37, 0x55, 0x8D, 0x03, 0xFB, 0x6A, 0x00, 0x82, 0x19, 0xD1, 0xC0, 0x76,
|
---|
547 | 0x97, 0xEE, 0xC9, 0xAD, 0x0D, 0x72, 0x0B, 0xE9, 0xA8, 0x09, 0x92, 0x03, 0xA4, 0xAA, 0x2C, 0xCF,
|
---|
548 | 0xFD, 0xDE, 0x86, 0xD0, 0x06, 0x4A, 0xAE, 0x7E, 0xC1, 0xB8, 0x2A, 0x4E, 0x9F, 0xA3, 0x5E, 0x8C,
|
---|
549 | 0x12, 0x40, 0x74, 0x38, 0xE7, 0xEA, 0xB0, 0x51, 0xC2, 0xB9, 0x6D, 0x4A, 0x50, 0xBF, 0x59, 0x9C,
|
---|
550 | 0x05, 0xB2, 0x42, 0xE2, 0x0F, 0x71, 0x44, 0xDB, 0x97, 0x0B, 0xD0, 0xDB, 0x44, 0x1F, 0x9A, 0x3B,
|
---|
551 | 0x18, 0x2A, 0x7B, 0xD9, 0x03, 0x83, 0x0B, 0xCF, 0x27, 0x20, 0x43, 0xA6, 0x42, 0xED, 0x89, 0x63,
|
---|
552 | 0xDB, 0x2D, 0x27, 0xC2, 0x3B, 0xE6, 0x0D, 0x3E, 0xB6, 0x96, 0x33, 0x70, 0xA6, 0xF3, 0xF5, 0x56,
|
---|
553 | 0xEA, 0xEB, 0xF1, 0xE7, 0xD8, 0xCB, 0x04, 0x48, 0x99, 0x4C, 0x00, 0xA4, 0x2A, 0xA5, 0x8A, 0xF1,
|
---|
554 | 0x58, 0xD5, 0x17, 0x4C, 0xC5, 0x88, 0x06, 0x8F, 0xA6, 0x67, 0xA6, 0x14, 0xC7, 0xB9, 0xE0, 0x86,
|
---|
555 | 0xAC, 0x67, 0xFD, 0xB3, 0x5B, 0x3E, 0xDF, 0x03, 0xFD, 0xC8, 0xC4, 0x4A, 0x32, 0x78, 0x6B, 0xD1,
|
---|
556 | 0xC1, 0xE2, 0x36, 0x9D, 0x0B, 0xF2, 0x54, 0x25, 0xB8, 0xB7, 0xB2, 0x10, 0x7A, 0xA6, 0x79, 0x52,
|
---|
557 | 0xC2, 0xEE, 0x98, 0xA5, 0x3D, 0xF0, 0x07, 0x8D, 0x25, 0xC3, 0xAC, 0xFD, 0xCF, 0x83, 0x98, 0x80,
|
---|
558 | 0x56, 0x95, 0xC4, 0x14, 0xA2, 0xA5, 0x93, 0xFE, 0x24, 0x59, 0x44, 0x73, 0xDF, 0xD6, 0x47, 0xDA,
|
---|
559 | 0x22, 0x3A, 0x82, 0xC5, 0xD1, 0x59, 0x40, 0x9D, 0x0C, 0x1A, 0xB7, 0x79, 0x45, 0x9A, 0xF8, 0x6D,
|
---|
560 | 0x5A, 0x5C, 0xC2, 0x80, 0xFC, 0xAA, 0x8A, 0xA4, 0xFE, 0x68, 0x61, 0x7D, 0xFE, 0x2C, 0x36, 0xE3,
|
---|
561 | 0xE0, 0x59, 0x28, 0x40, 0x79, 0xAD, 0x2D, 0x28, 0x12, 0x30, 0xFC, 0x56, 0x2E, 0x1D, 0xEC, 0x48,
|
---|
562 | 0x3A, 0xF0, 0xC5, 0x6C, 0x31, 0xE0, 0x2E, 0xB3, 0x91, 0x70, 0xB9, 0x9E, 0xBD, 0xE7, 0x96, 0x58,
|
---|
563 | 0xCB, 0xBC, 0x1C, 0xE4, 0xC7, 0x78, 0xC7, 0x1E, 0x39, 0xDB, 0xB8, 0x77, 0x50, 0xB7, 0x65, 0x20,
|
---|
564 | 0x04, 0x16, 0x8B, 0xFC, 0x66, 0xC4, 0x6D, 0x05, 0x8C, 0x3C, 0xB6, 0x32, 0x2F, 0xDE, 0xC3, 0x6F,
|
---|
565 | 0xFC, 0x82, 0x06, 0x02, 0x87, 0x47, 0xFD, 0xD8, 0xDA, 0x75, 0xE0, 0x4E, 0x8C, 0x40, 0x00, 0xB2,
|
---|
566 | 0x9B, 0x35, 0x78, 0xA4, 0x61, 0x64, 0x96, 0x62, 0x37, 0xF6, 0x3E, 0x39, 0xFA, 0x14, 0x5B, 0xC4,
|
---|
567 | 0x70, 0x17, 0xDC, 0x0C, 0x9E, 0x31, 0x82, 0x2C, 0x63, 0xCC, 0x8A, 0x43, 0x7C, 0x69, 0x12, 0x05,
|
---|
568 | 0x18, 0xA3, 0x62, 0xCC, 0xA2, 0x13, 0x96, 0x25, 0xA6, 0x1B, 0xF2, 0x10, 0xC8, 0x73, 0x4F, 0xCB,
|
---|
569 | 0x80, 0xCA, 0xAF, 0x73, 0xC9, 0x78, 0xB1, 0xAE, 0x87, 0xB8, 0xDF, 0x50, 0xD3, 0x55, 0x1E, 0x3A,
|
---|
570 | 0x81, 0xF6, 0x84, 0xD6, 0x57, 0x36, 0xCF, 0x38, 0xB7, 0xBC, 0xBC, 0x1E, 0x48, 0x62, 0x9F, 0x0F,
|
---|
571 | 0x0C, 0xE5, 0xF0, 0x63, 0x33, 0xE6, 0x59, 0x6B, 0x1E, 0xE6, 0x1C, 0x8A, 0xF9, 0xDD, 0x6B, 0xA3,
|
---|
572 | 0xDC, 0x02, 0x4A, 0x2F, 0x8C, 0x6A, 0x8D, 0x16, 0x7E, 0x2F, 0xF1, 0x75, 0xD5, 0x15, 0x93, 0x07,
|
---|
573 | 0x27, 0xD9, 0x6F, 0x1A, 0x5D, 0x43, 0xF3, 0x47, 0xC4, 0xED, 0xAD, 0x05, 0x9F, 0xEC, 0x8F, 0xD0,
|
---|
574 | 0xBE, 0xB5, 0x58, 0xF4, 0xF6, 0xBE, 0x08, 0x73, 0x96, 0x19, 0x05, 0x25, 0xEC, 0x3D, 0x26, 0xF4,
|
---|
575 | 0x93, 0xDB, 0x9F, 0x56, 0x48, 0x4C, 0xBC, 0xD0, 0x02, 0x59, 0xD1, 0x40, 0x4C, 0xA6, 0x06, 0x41,
|
---|
576 | 0xE8, 0x7D, 0x47, 0xAE, 0x3A, 0x9E, 0x1A, 0x71, 0x52, 0xD4, 0x67, 0xC1, 0x14, 0x7E, 0x40, 0x6F,
|
---|
577 | 0x1C, 0x75, 0x30, 0x7B, 0x70, 0x3A, 0xE0, 0x37, 0xB7, 0x41, 0x7F, 0xCB, 0x4A, 0xBA, 0xA7, 0xCE,
|
---|
578 | 0x56, 0x54, 0xC5, 0x46, 0x65, 0x6F, 0xB4, 0xB6, 0xF0, 0x57, 0xCE, 0x2E, 0x4F, 0xA9, 0xF0, 0x14,
|
---|
579 | 0x50, 0xC3, 0x30, 0xC5, 0xBA, 0xE1, 0x5E, 0xD6, 0xDC, 0xC5, 0x78, 0x55, 0x32, 0xAA, 0xCB, 0x29,
|
---|
580 | 0x35, 0x81, 0x46, 0x5E, 0x92, 0xE7, 0xDE, 0xCC, 0x92, 0x29, 0x86, 0xE0, 0x8F, 0x91, 0x3C, 0x74,
|
---|
581 | 0x97, 0x79, 0x63, 0x97, 0x4A, 0xCC, 0x88, 0xB5, 0xA3, 0x7A, 0xF0, 0xF0, 0x33, 0x87, 0xCD, 0xBD
|
---|
582 | };
|
---|
583 | uint8_t b = Value ^ hdSurEncBasicCrypt_D2_0F_11(Value, lookup[(((AddrInd * 2) + 0) * 256) + Value]);
|
---|
584 | return (Value ^ hdSurEncBasicCrypt_D2_0F_11(b, lookup[(((AddrInd * 2) + 1) * 256) + b]));
|
---|
585 | }
|
---|
586 | void hdSurEncPhase1_D2_0F_11(uint8_t *CWs)
|
---|
587 | {
|
---|
588 | static const uint8_t lookup1[] =
|
---|
589 | {
|
---|
590 | 0x16, 0x71, 0xCA, 0x14, 0xC4, 0xF4, 0xA3, 0x5A, 0x9D, 0x5F, 0x85, 0x8B, 0xA6, 0x77, 0xFD, 0x3C,
|
---|
591 | 0x5F, 0x13, 0x2A, 0x5F, 0x61, 0x36, 0xE4, 0xDC, 0x0D, 0x82, 0x92, 0xC5, 0x25, 0xE1, 0x7A, 0x1C,
|
---|
592 | 0x29, 0x19, 0x94, 0x2F, 0xC5, 0xD2, 0xDC, 0xBA, 0x86, 0x60, 0x64, 0x60, 0x86, 0x92, 0xA3, 0x4E,
|
---|
593 | 0x3D, 0x9B, 0xCC, 0x16, 0xBB, 0xBA, 0xD2, 0xF0, 0x6A, 0xD3, 0x2F, 0x07, 0x75, 0xBD, 0x28, 0xDB
|
---|
594 | };
|
---|
595 | static const int8_t lookup2[] = { 1, -1, -1, 1, -1, 2, 1, -2, -1, 1, 2, -2, 1, -2, -2, 4 };
|
---|
596 | static const int8_t CAddrIndex[] = { 0, 1, 3, 4 };
|
---|
597 | int32_t i, j, i1, i2, i3;
|
---|
598 | for(i = 3; i >= 0; --i)
|
---|
599 | {
|
---|
600 | for(j = 0; j <= 15; ++j)
|
---|
601 | {
|
---|
602 | CWs[j] = CWs[j] ^ hdSurEncBasicCrypt_D2_0F_11(j , lookup1 [(16 * i) + j]);
|
---|
603 | }
|
---|
604 | uint8_t Buffer[16];
|
---|
605 | uint32_t k;
|
---|
606 | for(i1 = 0; i1 <= 3; ++i1)
|
---|
607 | {
|
---|
608 | for(i2 = 0; i2 <= 3; ++i2)
|
---|
609 | {
|
---|
610 | k = 0;
|
---|
611 | for(i3 = 0; i3 <= 3; ++i3)
|
---|
612 | {
|
---|
613 | k = k + (CWs[(i2 * 4) + i3] * lookup2[(i3 * 4) + i1]);
|
---|
614 | Buffer[(i2 * 4) + i1] = (uint8_t)k;
|
---|
615 | }
|
---|
616 | }
|
---|
617 | }
|
---|
618 | memcpy(CWs, Buffer, 16);
|
---|
619 | // CW positions are mixed around here
|
---|
620 | uint8_t a4[4];
|
---|
621 | for(i1 = 1; i1 <= 3; ++i1)
|
---|
622 | {
|
---|
623 | for(i2 = 0; i2 <= 3; ++i2)
|
---|
624 | {
|
---|
625 | a4[i2] = i1 + (i2 * 4);
|
---|
626 | }
|
---|
627 | for(i2 = 0; i2 <= i1 - 1; ++i2) // the given code in Func1_3 seems to be wrong here(3 instead of i1-1)!
|
---|
628 | {
|
---|
629 | uint8_t tmp = CWs[a4[0]];
|
---|
630 | for(i3 = 1; i3 <= 3; ++i3)
|
---|
631 | {
|
---|
632 | CWs[a4[i3 - 1]] = CWs[a4[i3]];
|
---|
633 | }
|
---|
634 | CWs[a4[3]] = tmp;
|
---|
635 | }
|
---|
636 | }
|
---|
637 | for(i1 = 0; i1 <= 15; ++i1)
|
---|
638 | {
|
---|
639 | CWs[i1] = hdSurEncCryptLookup_D2_0F_11(CWs[i1], CAddrIndex[i1 & 3]);
|
---|
640 | }
|
---|
641 | }
|
---|
642 | }
|
---|
643 | void hdSurEncPhase2_D2_0F_11_sub(uint8_t *CWa, uint8_t *CWb, uint8_t AddrInd)
|
---|
644 | {
|
---|
645 | uint8_t Buffer[8];
|
---|
646 | uint8_t tmp, i;
|
---|
647 | for(i = 0; i <= 7; ++i)
|
---|
648 | {
|
---|
649 | Buffer[i] = hdSurEncCryptLookup_D2_0F_11(CWb[i], AddrInd);
|
---|
650 | }
|
---|
651 | // some bitshifting
|
---|
652 | tmp = Buffer[7];
|
---|
653 | for(i = 7; i >= 1; --i)
|
---|
654 | {
|
---|
655 | Buffer[i] = ((Buffer[1] >> 4) & 0xFF) | ((Buffer[i - 1] << 4) & 0xFF);
|
---|
656 | }
|
---|
657 | Buffer[0] = ((Buffer[0] >> 4) & 0xFF) | ((tmp << 4) & 0xFF);
|
---|
658 | // saving the result
|
---|
659 | for(i = 0; i <= 7; ++i)
|
---|
660 | {
|
---|
661 | CWa[i] = CWa[i] ^ Buffer[i];
|
---|
662 | }
|
---|
663 | }
|
---|
664 | void hdSurEncPhase2_D2_0F_11(uint8_t *CWs)
|
---|
665 | {
|
---|
666 | hdSurEncPhase2_D2_0F_11_sub(CWs, CWs + 8, 0);
|
---|
667 | hdSurEncPhase2_D2_0F_11_sub(CWs + 8, CWs, 1);
|
---|
668 | hdSurEncPhase2_D2_0F_11_sub(CWs, CWs + 8, 2);
|
---|
669 | hdSurEncPhase2_D2_0F_11_sub(CWs + 8, CWs, 3);
|
---|
670 | hdSurEncPhase2_D2_0F_11_sub(CWs, CWs + 8, 4);
|
---|
671 | }
|
---|
672 | void CommonMain_1_D2_13_15(const uint8_t *datain, uint8_t *dataout)
|
---|
673 | {
|
---|
674 | const uint8_t Tab3[88] = {
|
---|
675 | 0x1B, 0x12, 0x12, 0x0C, 0x12, 0x0C, 0x0C, 0x08, 0x09, 0x09, 0x06, 0x06, 0x06, 0x06, 0x04, 0x04,
|
---|
676 | 0x08, 0x04, 0x04, 0x02, 0x04, 0x02, 0x02, 0x01, 0x09, 0x06, 0x09, 0x06, 0x06, 0x04, 0x06, 0x04,
|
---|
677 | 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x02, 0x04, 0x04, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01,
|
---|
678 | 0x09, 0x06, 0x06, 0x04, 0x09, 0x06, 0x06, 0x04, 0x03, 0x03, 0x02, 0x02, 0x03, 0x03, 0x02, 0x02,
|
---|
679 | 0x04, 0x02, 0x04, 0x02, 0x02, 0x01, 0x02, 0x01, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02,
|
---|
680 | 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 };
|
---|
681 | int i1,i2;
|
---|
682 | unsigned long bb;
|
---|
683 | for (i1 = 0; i1 < 11; i1++)
|
---|
684 | {
|
---|
685 | bb = 0;
|
---|
686 | for (i2 = 0; i2 < 8; i2++)
|
---|
687 | {
|
---|
688 | bb += (Tab3[(i1 * 8) + i2] * datain[i2]);
|
---|
689 | }
|
---|
690 | dataout[i1] = (bb & 0xFF);
|
---|
691 | }
|
---|
692 | }
|
---|
693 | unsigned short CommonMain_2_D2_13_15(const uint8_t *data, const unsigned long num)
|
---|
694 | {
|
---|
695 | unsigned long bb1, bb2;
|
---|
696 | bb1 = num >> 3;
|
---|
697 | bb2 = (data[bb1] << 24) + (data[bb1 + 1] << 16) + (data[bb1 + 2] << 8);
|
---|
698 | return ((bb2 >> (21 - (num & 7))) & 0x7FF);
|
---|
699 | }
|
---|
700 | void CommonMain_3_D2_13_15(uint8_t *data0, uint8_t *data1, int nbrloop)
|
---|
701 | {
|
---|
702 | int i;
|
---|
703 | unsigned long bb1, bb2;
|
---|
704 | bb1 = 0;
|
---|
705 | bb2 = 0;
|
---|
706 | for (i = nbrloop - 1; i >= 0; i--)
|
---|
707 | {
|
---|
708 | bb1 += (data0[i] * 2) + data1[i];
|
---|
709 | bb2 += data0[i] + data1[i];
|
---|
710 | data0[i] = (bb1 & 0xFF);
|
---|
711 | data1[i] = (bb2 & 0xFF);
|
---|
712 | bb1 >>= 8;
|
---|
713 | bb2 >>= 8;
|
---|
714 | }
|
---|
715 | }
|
---|
716 | void CommonMain_D2_13_15(const uint8_t *datain, uint8_t *dataout, int loopval)
|
---|
717 | {
|
---|
718 | const uint8_t Tab0_Comp[0x800] = {
|
---|
719 | 0x54,0x75,0x01,0x0C,0x7C,0xE2,0xC3,0xC2,0x5E,0x13,0x26,0xCA,0xB2,0xCD,0xB8,0x3D,
|
---|
720 | 0x02,0x2C,0xE4,0x19,0x41,0x3D,0xE4,0x0F,0xEC,0xF1,0x45,0x83,0xE2,0xE2,0x72,0xF9,
|
---|
721 | 0xCD,0x75,0x1E,0x41,0xCC,0x0C,0x1F,0x39,0x87,0x9B,0x46,0xFF,0x68,0x1F,0x00,0xD8,
|
---|
722 | 0x41,0x82,0xCA,0xC6,0xEF,0x87,0x90,0xA2,0x7E,0xD9,0xDE,0xC8,0x25,0xEA,0xC9,0x75,
|
---|
723 | 0x6E,0x18,0x81,0xD8,0x5A,0xA6,0x74,0x05,0xAF,0xAE,0xE0,0x4F,0x85,0xAD,0x94,0xF6,
|
---|
724 | 0x45,0xF4,0xF5,0x55,0xA8,0xEB,0xEC,0xDB,0x6C,0xFF,0x2F,0xC2,0xC3,0x7D,0x93,0xE6,
|
---|
725 | 0xF5,0x31,0x96,0xB7,0x9A,0xDB,0xE5,0x76,0x66,0xFB,0xDD,0xBC,0x19,0x18,0x42,0xC6,
|
---|
726 | 0x36,0xCD,0x46,0x33,0xEA,0xF1,0x4C,0xC0,0x72,0x07,0xCD,0x61,0xCE,0x0E,0x08,0x01,
|
---|
727 | 0xA3,0xFA,0x84,0x21,0xF2,0x43,0x37,0x1C,0xDE,0x25,0x8A,0x1A,0xF4,0xBB,0x40,0xF3,
|
---|
728 | 0x53,0xFE,0x17,0x60,0x91,0x6D,0x7B,0x6D,0x5F,0x1C,0x15,0x73,0xCC,0x6E,0x73,0x46,
|
---|
729 | 0x27,0x73,0xA3,0x10,0x16,0x32,0xB3,0x39,0x45,0xA6,0x55,0xE7,0x91,0x32,0x24,0xC8,
|
---|
730 | 0xAE,0xAF,0x1B,0x28,0x69,0x22,0x2F,0xE9,0x77,0x72,0xBF,0x4B,0x8B,0x07,0x82,0x31,
|
---|
731 | 0xB0,0x95,0x10,0x78,0x9F,0xC5,0xF3,0x73,0xE1,0xF8,0x36,0x84,0xFE,0x1B,0x92,0xB2,
|
---|
732 | 0xE6,0xA5,0xCE,0xDA,0x56,0x48,0x52,0x77,0x9D,0x9D,0x8E,0x37,0x4B,0xC8,0x35,0x7E,
|
---|
733 | 0xB9,0x5D,0xA4,0xAE,0x3F,0xD0,0xAA,0x60,0xA8,0x4C,0x85,0x49,0xF6,0x0C,0x27,0xE8,
|
---|
734 | 0x94,0x84,0xA0,0xAA,0x06,0x4D,0xAC,0x58,0x8B,0x61,0x29,0x3D,0x68,0x25,0xD3,0xD3,
|
---|
735 | 0x8E,0xA1,0xE0,0x71,0xBF,0x21,0x0C,0xC7,0x18,0x19,0xF1,0x25,0x98,0x5F,0x79,0x5E,
|
---|
736 | 0x51,0xBA,0x8C,0x2F,0x52,0x43,0xF3,0x5A,0xE3,0x58,0x97,0x64,0x23,0xE0,0x44,0x4F,
|
---|
737 | 0x30,0x2A,0xE0,0x16,0x8D,0x4D,0xD1,0x1F,0x7B,0xC9,0xC5,0x74,0x11,0x23,0x5D,0x95,
|
---|
738 | 0xAC,0x7F,0x2E,0x30,0xBE,0x2D,0xE3,0xB5,0xC6,0xA7,0x69,0x99,0x1F,0x18,0x3C,0x96,
|
---|
739 | 0x30,0x45,0x99,0x71,0x28,0x08,0x3C,0xF7,0x37,0x4F,0x6A,0xD6,0xAE,0x9B,0x57,0xC1,
|
---|
740 | 0xCC,0x2C,0xE2,0x0F,0x7D,0x66,0xF4,0x36,0x0C,0x3B,0x35,0xF6,0x28,0x03,0xA3,0x7A,
|
---|
741 | 0x83,0x15,0xF5,0x61,0x5E,0xE8,0xB7,0xD8,0x54,0x33,0x93,0x63,0x80,0x40,0x43,0xD0,
|
---|
742 | 0x9C,0xAA,0x3A,0x98,0x50,0xD2,0xB8,0x80,0x5D,0x16,0xDF,0x1C,0x03,0xAA,0x87,0xC7,
|
---|
743 | 0x63,0xA5,0x8D,0xA9,0x2E,0xFB,0x4F,0x7C,0x2B,0xF5,0xF9,0x57,0xB5,0x90,0xD8,0x75,
|
---|
744 | 0xAB,0x81,0x4C,0x1B,0xAF,0x6C,0x0E,0xCB,0xB1,0x4F,0xD3,0xE3,0x69,0x18,0x8C,0x7A,
|
---|
745 | 0x3C,0xE1,0x11,0x86,0x47,0x78,0x11,0xA0,0xD4,0x28,0xC3,0x0D,0xAC,0xC6,0x17,0xA1,
|
---|
746 | 0x32,0x9F,0x8F,0x42,0xD9,0x3F,0x66,0xD7,0x2D,0x87,0x7B,0x65,0xD3,0xD6,0x90,0x83,
|
---|
747 | 0xA2,0x75,0xE8,0x98,0x90,0x9D,0xDE,0x81,0x9E,0x3D,0xE4,0xA9,0xE4,0x0B,0xBC,0xBA,
|
---|
748 | 0x96,0xDD,0x05,0xCA,0xAE,0x78,0x69,0x24,0xDB,0xA7,0x3E,0x7A,0x3B,0xB4,0xC4,0x59,
|
---|
749 | 0x61,0xD2,0xF2,0xE3,0x99,0x8F,0x8F,0x8A,0x82,0x33,0xB8,0x17,0x5E,0x7A,0x32,0x41,
|
---|
750 | 0x10,0x8D,0xC2,0xEF,0xAA,0xF8,0x5A,0xF7,0xD2,0x1D,0xC0,0xCB,0x5E,0xB7,0x8A,0x78,
|
---|
751 | 0x49,0x42,0xEB,0x19,0x1B,0x61,0xA0,0x77,0x5A,0xF4,0x6D,0x55,0xDA,0xEB,0xCE,0x4E,
|
---|
752 | 0xB8,0xE6,0x32,0xD7,0x51,0x3F,0x73,0x14,0x34,0x6E,0x38,0xD6,0xA7,0x28,0x87,0x4A,
|
---|
753 | 0x59,0xCA,0x1C,0x80,0xB5,0x8C,0x9D,0x94,0xCB,0xFE,0x29,0x41,0xE5,0x69,0xCF,0xFD,
|
---|
754 | 0x0B,0xE1,0x7C,0xA1,0x70,0x12,0x76,0x43,0xDA,0xB9,0xD4,0xC3,0x31,0xBC,0x94,0x77,
|
---|
755 | 0x04,0xB4,0x1C,0xAA,0xEC,0x6F,0xA5,0x12,0x9D,0x6F,0x34,0x65,0x77,0xA0,0xD2,0x6F,
|
---|
756 | 0x60,0xC6,0x47,0xC2,0xDF,0x6A,0x10,0x53,0xD4,0xBA,0xF3,0xB7,0x38,0x79,0x63,0xC9,
|
---|
757 | 0xD4,0x77,0xBC,0x54,0xE9,0x79,0x42,0xD5,0xE0,0x71,0xE7,0x9E,0x5A,0x62,0x0C,0xAD,
|
---|
758 | 0x01,0x09,0xA8,0x9F,0x8E,0x67,0x4A,0x30,0xA4,0xB1,0x08,0xFC,0x0A,0xEA,0x7A,0x1D,
|
---|
759 | 0x4C,0x4A,0x21,0xDE,0x00,0xD7,0x41,0x98,0x6B,0x38,0x50,0x3E,0x1F,0x25,0x06,0xE3,
|
---|
760 | 0x6C,0xA3,0x84,0x5B,0xC1,0xED,0x47,0xDD,0xB3,0x83,0x46,0x72,0x69,0xCE,0x72,0x04,
|
---|
761 | 0x43,0x67,0x3A,0x19,0xD9,0x0A,0xF7,0x43,0x88,0xCA,0xC7,0x31,0x34,0x21,0x4E,0x4C,
|
---|
762 | 0xE8,0xD1,0x70,0x00,0xBD,0xB1,0xB6,0x76,0x6F,0x5B,0xF9,0xF5,0xF4,0x19,0x20,0x21,
|
---|
763 | 0xC1,0xF0,0x11,0x36,0x66,0xAB,0x15,0xBD,0x69,0x92,0xC6,0x46,0xDE,0xDC,0xE9,0x9A,
|
---|
764 | 0xF8,0x6C,0x15,0x29,0x15,0xA6,0x35,0x3E,0x08,0xE5,0x90,0x62,0x9F,0x86,0x56,0x83,
|
---|
765 | 0x5D,0x60,0x0D,0x22,0x77,0xA7,0x60,0x9B,0x26,0x80,0x16,0x67,0xB4,0x46,0xBF,0x74,
|
---|
766 | 0x55,0x92,0x5B,0x34,0xFF,0xC8,0x28,0x37,0xFF,0x14,0x62,0xFA,0xBD,0x03,0x78,0x04,
|
---|
767 | 0x1B,0x65,0x7F,0x99,0x05,0x27,0x14,0xC0,0x06,0x4D,0x4B,0x0E,0x98,0x34,0x6A,0xB3,
|
---|
768 | 0xA1,0xFE,0xBC,0x45,0x7D,0x52,0x50,0x0E,0x2C,0xFB,0x91,0xF5,0xFB,0x2A,0xB7,0xD9,
|
---|
769 | 0xB8,0xB8,0x54,0x31,0x81,0x03,0x93,0x2C,0xE1,0x5C,0xB9,0x2C,0xE8,0x38,0xC0,0xA7,
|
---|
770 | 0x58,0x18,0x92,0xC5,0x8B,0xEF,0x1E,0x33,0xA4,0xBA,0x86,0x2B,0xE9,0xEE,0xB1,0xDF,
|
---|
771 | 0xAB,0xB8,0x48,0xDA,0x84,0xF1,0x68,0x05,0x4E,0xDE,0xB5,0x9E,0x88,0x12,0xC9,0x60,
|
---|
772 | 0x50,0x58,0x56,0x9D,0x26,0x84,0xB6,0x1A,0xE6,0x4B,0x40,0x94,0x6D,0xE9,0x1D,0x0D,
|
---|
773 | 0x8A,0xF9,0x2A,0xB5,0xBC,0xDB,0x06,0x8F,0x13,0x7E,0x1D,0x1C,0xC7,0xFD,0x8F,0x78,
|
---|
774 | 0x55,0x3F,0x16,0x84,0x48,0xDA,0x1A,0xD1,0x93,0x95,0x20,0x58,0x92,0x39,0xF6,0x73,
|
---|
775 | 0x4E,0x9E,0x7B,0x70,0xFC,0x1E,0x5B,0x20,0x48,0x96,0xB3,0x7C,0x50,0x09,0x5B,0x61,
|
---|
776 | 0x57,0x97,0x36,0x04,0x29,0x2C,0x32,0x8E,0x93,0x4A,0x45,0xFA,0xD5,0x24,0x14,0x1A,
|
---|
777 | 0x28,0x9C,0x1A,0x71,0xAE,0x85,0x4B,0x26,0x79,0x99,0x65,0xD0,0x07,0x98,0xED,0xC9,
|
---|
778 | 0x1B,0x39,0x57,0x5B,0xDB,0x3D,0x87,0x69,0x66,0x9B,0x03,0x23,0x54,0x6B,0x4B,0xAC,
|
---|
779 | 0x6E,0x7A,0x25,0x1E,0xB6,0x97,0xCF,0x1D,0x07,0xCB,0x2A,0x3E,0x85,0x02,0x93,0x31,
|
---|
780 | 0x12,0x27,0xF0,0xA6,0x6D,0x0F,0x9A,0xB6,0xFC,0x22,0x79,0x6C,0x77,0xFD,0x3F,0xDC,
|
---|
781 | 0x19,0xD0,0xDF,0xBD,0x9E,0xE0,0xBE,0x20,0x13,0xA3,0x0A,0x0B,0x22,0xF2,0xC8,0x6B,
|
---|
782 | 0xA1,0xDD,0x6C,0x67,0xB3,0xFD,0x71,0xC2,0x7B,0x08,0x3B,0xF1,0x37,0xB5,0x0F,0x86,
|
---|
783 | 0xFA,0xA9,0xE9,0x42,0xD1,0xE8,0xCD,0x05,0xEF,0xD3,0xCC,0x0B,0x70,0x51,0x5B,0x97,
|
---|
784 | 0x06,0xC4,0x9D,0x88,0x11,0x3E,0x99,0x9F,0xBE,0x76,0x8C,0x8D,0xE6,0xBA,0xDA,0x48,
|
---|
785 | 0xD0,0x04,0x86,0x4F,0xA9,0xC6,0xB0,0xED,0xA4,0x94,0x46,0x96,0x27,0xEE,0x9F,0xBD,
|
---|
786 | 0xDA,0x9B,0x3D,0x11,0x80,0xD3,0x7B,0x5A,0x48,0x94,0xE5,0xCC,0x48,0xEA,0xE4,0x18,
|
---|
787 | 0xDF,0x51,0xB3,0x02,0x57,0x20,0x4B,0x0F,0x07,0xFF,0x41,0x33,0x0F,0x6B,0x2E,0xAA,
|
---|
788 | 0xDE,0xB2,0x56,0xF7,0xFB,0xA2,0x48,0x3C,0x97,0x1A,0x64,0x2C,0xD1,0x74,0x40,0xCF,
|
---|
789 | 0x65,0x7F,0x14,0x08,0x59,0xC4,0x35,0xD3,0x8A,0x0F,0xFD,0x71,0x7A,0x71,0xAC,0x2D,
|
---|
790 | 0xF3,0xFD,0x7B,0x12,0x5F,0xC0,0xBC,0x4E,0x96,0x12,0xF2,0x8E,0x41,0x84,0x01,0x0F,
|
---|
791 | 0xED,0x7B,0xC1,0xB9,0x39,0x03,0x35,0x40,0x49,0x53,0xB8,0xB4,0x6B,0xA6,0xE7,0x0A,
|
---|
792 | 0x14,0xBB,0x29,0x16,0xEC,0x2A,0x3A,0xD6,0x09,0xBB,0x5C,0x20,0xF8,0x09,0xFD,0x86,
|
---|
793 | 0xC4,0x25,0x09,0x85,0x0B,0xD5,0xD8,0x51,0xB1,0xA2,0xCB,0xDC,0xC4,0xDD,0x34,0xDF,
|
---|
794 | 0xE2,0x85,0xA9,0xCC,0x4E,0x66,0x51,0xFA,0x9C,0x4D,0xB7,0x1E,0x3E,0x49,0x34,0x9C,
|
---|
795 | 0x21,0x66,0x07,0x44,0xB2,0xEC,0x73,0xC5,0xBB,0x27,0x9A,0xA5,0x91,0x5A,0xB9,0x9F,
|
---|
796 | 0xBE,0xC8,0xA2,0x27,0x89,0x21,0xA7,0xEE,0x50,0x4D,0x43,0x50,0x67,0xC2,0x3B,0x7C,
|
---|
797 | 0x20,0x0B,0x95,0x40,0xBE,0xEA,0xB5,0xD9,0x82,0xD7,0x9C,0xB5,0x21,0xAD,0xA6,0xF9,
|
---|
798 | 0x70,0xEA,0xCD,0x04,0xDD,0x58,0x91,0x89,0xB2,0xA9,0xF9,0xB4,0x12,0xA2,0x63,0x89,
|
---|
799 | 0x40,0x8E,0xEA,0x62,0xEE,0x0B,0x01,0x82,0x6F,0xB3,0x5E,0x5C,0x36,0xBE,0xF4,0x97,
|
---|
800 | 0x2C,0xCF,0x96,0x7C,0x0D,0xAD,0x62,0xCE,0xD4,0x38,0xC5,0x32,0x02,0x24,0x57,0x27,
|
---|
801 | 0xE0,0xCF,0x56,0xA5,0x72,0x6D,0x90,0x89,0x2D,0x4C,0x34,0xF6,0x1D,0xDD,0x88,0x5E,
|
---|
802 | 0x7A,0x23,0xE3,0x6F,0x42,0xA3,0xD9,0x58,0x7E,0xE3,0x52,0x74,0x57,0x63,0xB7,0xB2,
|
---|
803 | 0xC1,0xA3,0x30,0x92,0x2E,0xB0,0x91,0x01,0x13,0x36,0x9A,0x6A,0xA7,0x5B,0x3C,0x07,
|
---|
804 | 0xFB,0xD8,0x1E,0x7E,0xCF,0x49,0xAB,0x3F,0xCA,0xCE,0x74,0x40,0x54,0x8D,0x83,0x61,
|
---|
805 | 0xCA,0xC3,0x76,0x59,0x5C,0x9F,0x49,0x8A,0x7D,0xD1,0x17,0x9C,0xA4,0xDB,0xB9,0x16,
|
---|
806 | 0x4D,0x64,0xF7,0xC7,0xF0,0x24,0xE7,0x00,0xB6,0x98,0xD5,0x8B,0x54,0xCB,0x1E,0x8B,
|
---|
807 | 0xA2,0x2B,0x7D,0x50,0x51,0x8A,0xF0,0xEF,0x47,0xAE,0xD0,0xD6,0xA0,0x42,0x8A,0xD8,
|
---|
808 | 0x22,0xAF,0x02,0x99,0x4A,0xE0,0x8D,0x8D,0xBF,0x11,0x05,0xA4,0xC4,0x9D,0xB3,0x89,
|
---|
809 | 0xB4,0x4C,0xC9,0xF7,0x4D,0xC5,0x2A,0x35,0x95,0x30,0xF3,0x0E,0x2F,0xEC,0x6E,0x3A,
|
---|
810 | 0x8B,0x05,0x76,0xED,0x1A,0x7C,0xC0,0xE7,0x22,0xCB,0x59,0xFF,0xE6,0x37,0x78,0x44,
|
---|
811 | 0xD4,0xEE,0xAD,0xD7,0xBD,0x2E,0xB7,0x6A,0xA4,0x4E,0x0E,0xFB,0xB0,0xF5,0xCB,0x87,
|
---|
812 | 0xCF,0xC3,0x18,0x64,0x6F,0x26,0x5C,0xD7,0x16,0xC8,0x7F,0xAB,0x29,0xC4,0xBA,0xFF,
|
---|
813 | 0xCD,0x1C,0xE4,0x3A,0xF2,0xEB,0x6A,0x38,0xE4,0x65,0xC2,0x33,0x03,0x26,0x7D,0x9B,
|
---|
814 | 0x7E,0x1D,0x83,0x00,0x04,0x2D,0x2B,0x5F,0xFE,0x39,0x7E,0xF1,0x3C,0xA2,0x8C,0x52,
|
---|
815 | 0x95,0xBF,0x46,0x81,0x24,0x44,0xF8,0x10,0xC3,0x87,0x8E,0x64,0x80,0x17,0x44,0xE2,
|
---|
816 | 0x8B,0xD1,0x3C,0x4A,0xE2,0x1F,0xA9,0xDE,0x75,0x13,0xFC,0x2E,0x86,0x0A,0x5C,0x5F,
|
---|
817 | 0x92,0x2B,0x92,0x2D,0x2A,0xEC,0xD2,0x5C,0x82,0x6B,0x76,0x1E,0xED,0xE6,0x56,0xF7,
|
---|
818 | 0xD2,0xDB,0x96,0x68,0x02,0x68,0x99,0x49,0xEE,0x88,0x66,0xCE,0x5D,0x08,0x88,0xA8,
|
---|
819 | 0xB9,0x24,0xB0,0xB4,0xDC,0xA6,0xC9,0xD8,0x68,0x80,0xBF,0x6B,0x32,0x57,0x7F,0x91,
|
---|
820 | 0x0E,0x37,0x59,0xF6,0x76,0xD2,0xC5,0x0B,0xF3,0x23,0xBF,0x38,0x52,0x0D,0x97,0x81,
|
---|
821 | 0x17,0xBB,0x9A,0xC2,0x55,0x44,0x72,0xCE,0xEE,0xFA,0xBB,0xDA,0xAB,0xB0,0x09,0xEA,
|
---|
822 | 0xDB,0xBF,0x45,0x95,0x07,0x88,0xD4,0xD2,0x0D,0x2E,0x15,0x31,0xBE,0x6A,0xF4,0xEF,
|
---|
823 | 0xA3,0x7D,0x22,0x81,0x3B,0xA8,0x83,0xF9,0x42,0xE5,0x9B,0x79,0x01,0xF5,0xDC,0x19,
|
---|
824 | 0x64,0xEB,0x47,0x67,0xAF,0xA4,0xB2,0xAE,0xF8,0xF9,0x4D,0x63,0xAD,0x54,0xE1,0x02,
|
---|
825 | 0x56,0x89,0x4E,0x0A,0xE8,0x3E,0x03,0xFA,0x33,0x61,0x58,0x80,0x64,0x55,0x3C,0x8C,
|
---|
826 | 0x2A,0x3D,0x70,0x3E,0xE5,0xC1,0xA7,0x75,0xFC,0x91,0x75,0x05,0x8C,0x6E,0x3A,0x74,
|
---|
827 | 0x10,0xF1,0x30,0xE6,0xF6,0xF7,0xAB,0x6C,0xB1,0x2B,0xF0,0x2F,0x13,0x6E,0xD4,0x0A,
|
---|
828 | 0x64,0x29,0xF8,0xBB,0xA1,0xAA,0x55,0x09,0x93,0x47,0x2F,0x8C,0x7D,0xF1,0x2D,0x81,
|
---|
829 | 0xFE,0x78,0xFC,0xEE,0x3F,0xDD,0x49,0xDC,0x0D,0x52,0x5C,0x3B,0x8F,0x08,0xB0,0xDF,
|
---|
830 | 0xDC,0xFC,0xBE,0x5F,0x3B,0x53,0x82,0xE2,0xBD,0x6D,0x5D,0xF2,0x8D,0xFB,0x5A,0x1D,
|
---|
831 | 0x15,0x1B,0xE4,0xB1,0x56,0x06,0x1A,0xF8,0x9C,0xB9,0x44,0xF2,0xD9,0xF4,0xB2,0x00,
|
---|
832 | 0x9A,0x94,0x62,0x33,0x7E,0x0A,0xB0,0x0C,0xD5,0xEF,0x8E,0xA8,0xEB,0x47,0xE9,0x20,
|
---|
833 | 0xA8,0x68,0xEF,0x53,0xA0,0x59,0x1B,0xA0,0x2B,0xC5,0x2B,0x30,0xB6,0x5D,0xAB,0xB4,
|
---|
834 | 0x5F,0x86,0x71,0x95,0x89,0xFC,0xC7,0x9A,0xC3,0xED,0x82,0xA0,0x3D,0x73,0xC1,0x36,
|
---|
835 | 0x01,0x5F,0x9E,0xD7,0xE3,0xC0,0x62,0x74,0xED,0x13,0xB6,0xD6,0xD5,0x37,0x17,0xE1,
|
---|
836 | 0x39,0xC7,0x6D,0x31,0xBA,0x02,0xAF,0xD5,0xCC,0x51,0xA8,0x09,0x3F,0x00,0x4A,0x8F,
|
---|
837 | 0xA6,0x23,0x13,0x88,0xCD,0x1F,0x38,0x60,0xE7,0xE7,0x53,0xDC,0x65,0xE8,0x53,0x26,
|
---|
838 | 0xBB,0xE1,0x1F,0x65,0xF0,0xAD,0x53,0x3B,0xBD,0xAD,0x97,0xAC,0xD1,0xA5,0xD0,0xE9,
|
---|
839 | 0xEB,0xD6,0x11,0xD5,0x00,0xDF,0x72,0x9C,0xCC,0x7F,0xD3,0x67,0xA1,0x3A,0x79,0xE1,
|
---|
840 | 0x85,0x70,0xE5,0x43,0xC9,0x28,0xA5,0x2F,0x9E,0xE7,0xFE,0xEB,0x14,0x10,0x23,0xC7,
|
---|
841 | 0xAF,0xB1,0x24,0xC8,0xE5,0x44,0x6F,0x4C,0x04,0xEC,0xC1,0xF0,0x23,0x1C,0xF6,0xAC,
|
---|
842 | 0xAF,0xC4,0x0E,0x2D,0x59,0x39,0x47,0xA9,0x9E,0xD9,0x2E,0x79,0xBA,0xFE,0x4F,0x12,
|
---|
843 | 0x7F,0x63,0x7F,0x62,0x67,0x7C,0x52,0x2F,0xCA,0x8B,0x6B,0x4F,0x10,0x8F,0x14,0xC6,
|
---|
844 | 0xA1,0x9B,0x45,0x15,0x90,0x63,0x22,0x5D,0x68,0x4B,0xCF,0xFA,0x6A,0x06,0xF0,0x26,
|
---|
845 | 0xAC,0x6C,0x3A,0x89,0x25,0xF3,0x5E,0x90,0x06,0x93,0xB6,0x35,0x0D,0x85,0x60,0x98,
|
---|
846 | 0xBC,0x6E,0xF2,0xA5,0x17,0x29,0x70,0xD6,0xFF,0x0C,0xD0,0xC0,0x35,0xD7,0x4A,0xFD };
|
---|
847 | const uint8_t Tab1_Comp[11*8] = {
|
---|
848 | 0x70,0x49,0xD7,0xE3,0xDF,0x3C,0x96,0x03,0x2A,0x70,0x82,0xA6,0x5F,0xDE,0xCC,0x0C,
|
---|
849 | 0x2A,0x62,0x2A,0x3E,0xA4,0x0C,0x0A,0xAB,0x4F,0x06,0x5D,0xD4,0x14,0xAA,0xE1,0xC3,
|
---|
850 | 0x96,0xDA,0x16,0x36,0x45,0x3C,0x63,0xC2,0x97,0x71,0x87,0xAB,0xFA,0xB2,0xFC,0xD6,
|
---|
851 | 0x8F,0x85,0xC9,0x04,0x56,0xBA,0xEB,0x3F,0x42,0x9F,0xCB,0x66,0x55,0x45,0x1C,0x96,
|
---|
852 | 0xFF,0x4D,0x35,0xDF,0x88,0x0E,0xDC,0xC8,0x4E,0x3F,0x81,0x74,0xD8,0x77,0x4C,0x8E,
|
---|
853 | 0x00,0xC0,0x64,0x83,0x4E,0xBB,0xF0,0xB1 };
|
---|
854 | unsigned short buff8[8];
|
---|
855 | uint8_t buff11[11 + 1]; // +1 to avoid func2 bug
|
---|
856 | int i1, i2;
|
---|
857 | buff11[11] = 0;
|
---|
858 | CommonMain_1_D2_13_15(datain, buff11);
|
---|
859 | for (i1 = 0; i1 < 11; i1++)
|
---|
860 | {
|
---|
861 | buff11[i1] ^= Tab1_Comp[(loopval * 11) + i1];
|
---|
862 | }
|
---|
863 | for (i1 = 0; i1 < 8; i1++)
|
---|
864 | {
|
---|
865 | buff8[i1] = CommonMain_2_D2_13_15(buff11, i1 * 11);
|
---|
866 | }
|
---|
867 | for (i1 = 0; i1 < 8; i1++)
|
---|
868 | {
|
---|
869 | dataout[i1] = Tab0_Comp[buff8[i1]];
|
---|
870 | }
|
---|
871 | i1 = 1;
|
---|
872 | while (i1 < 8)
|
---|
873 | {
|
---|
874 | i2 = 0 ;
|
---|
875 | while (i2 < 8)
|
---|
876 | {
|
---|
877 | CommonMain_3_D2_13_15(&dataout[i2], &dataout[i1 + i2], i1);
|
---|
878 | i2 += (i1 * 2);
|
---|
879 | }
|
---|
880 | i1 *= 2;
|
---|
881 | }
|
---|
882 | }
|
---|
883 | void Common_D2_13_15(uint8_t *cw0, const uint8_t *cw1, int loopval)
|
---|
884 | {
|
---|
885 | int i;
|
---|
886 | uint8_t buff8[8];
|
---|
887 | CommonMain_D2_13_15(cw1, buff8, loopval);
|
---|
888 | for (i = 0; i < 8; i++)
|
---|
889 | {
|
---|
890 | cw0[i] ^= buff8[i];
|
---|
891 | }
|
---|
892 | }
|
---|
893 | void ExchangeCWs(uint8_t *cw0, uint8_t *cw1)
|
---|
894 | {
|
---|
895 | int i;
|
---|
896 | uint8_t b;
|
---|
897 | for (i = 0; i < 8; i++)
|
---|
898 | {
|
---|
899 | b = cw1[i];
|
---|
900 | cw1[i] = cw0[i];
|
---|
901 | cw0[i] = b;
|
---|
902 | }
|
---|
903 | }
|
---|
904 | void hdSurEncPhase1_D2_13_15(uint8_t *cws)
|
---|
905 | {
|
---|
906 | int i;
|
---|
907 | for (i = 0; i <= 7; i++)
|
---|
908 | {
|
---|
909 | // Possible code
|
---|
910 | if ((i & 1) == 0)
|
---|
911 | {
|
---|
912 | Common_D2_13_15((uint8_t *) &cws[0], (uint8_t *) &cws[8], i);
|
---|
913 | }
|
---|
914 | else
|
---|
915 | {
|
---|
916 | Common_D2_13_15((uint8_t *) &cws[8], (uint8_t *) &cws[0], i);
|
---|
917 | }
|
---|
918 | }
|
---|
919 | ExchangeCWs((uint8_t *) &cws[0], (uint8_t *) &cws[8]);
|
---|
920 | }
|
---|
921 | void hdSurEncPhase2_D2_13_15(uint8_t *cws)
|
---|
922 | {
|
---|
923 | int i;
|
---|
924 | for (i = 7; i >= 0; i--)
|
---|
925 | {
|
---|
926 | // Possible code
|
---|
927 | if ((i & 1) == 0)
|
---|
928 | {
|
---|
929 | Common_D2_13_15((uint8_t *) &cws[8], (uint8_t *) &cws[0], i);
|
---|
930 | }
|
---|
931 | else
|
---|
932 | {
|
---|
933 | Common_D2_13_15((uint8_t *) &cws[0], (uint8_t *) &cws[8], i);
|
---|
934 | }
|
---|
935 | }
|
---|
936 | ExchangeCWs((uint8_t *) &cws[8], (uint8_t *) &cws[0]);
|
---|
937 | }
|
---|
938 | static int32_t viaccess_card_init(struct s_reader *reader, ATR *newatr)
|
---|
939 | {
|
---|
940 | get_atr;
|
---|
941 | def_resp;
|
---|
942 | int32_t i;
|
---|
943 | uint8_t buf[256];
|
---|
944 | uint8_t insac[] = { 0xca, 0xac, 0x00, 0x00, 0x00 }; // select data
|
---|
945 | uint8_t insb8[] = { 0xca, 0xb8, 0x00, 0x00, 0x00 }; // read selected data
|
---|
946 | uint8_t insa4[] = { 0xca, 0xa4, 0x00, 0x00, 0x00 }; // select issuer
|
---|
947 | uint8_t insc0[] = { 0xca, 0xc0, 0x00, 0x00, 0x00 }; // read data item
|
---|
948 | static const uint8_t insFAC[] = { 0x87, 0x02, 0x00, 0x00, 0x03 }; // init FAC
|
---|
949 | static const uint8_t FacDat[] = { 0x00, 0x00, 0x28 };
|
---|
950 | static uint8_t ins8702_data[] = { 0x00, 0x00, 0x11};
|
---|
951 | static uint8_t ins8704[] = { 0x87, 0x04, 0x00, 0x00, 0x07 };
|
---|
952 | static uint8_t ins8706[] = { 0x87, 0x06, 0x00, 0x00, 0x04 };
|
---|
953 | if((atr[1] != 0x77) || ((atr[2] != 0x18) && (atr[2] != 0x11) && (atr[2] != 0x19)) || ((atr[9] != 0x68) && (atr[9] != 0x6C) && (atr[9] != 0x64)))
|
---|
954 | {
|
---|
955 | return ERROR;
|
---|
956 | }
|
---|
957 | write_cmd(insFAC, FacDat);
|
---|
958 | if(!(cta_res[cta_lr - 2] == 0x90 && cta_res[cta_lr - 1] == 0))
|
---|
959 | {
|
---|
960 | return ERROR;
|
---|
961 | }
|
---|
962 | if(!cs_malloc(&reader->csystem_data, sizeof(struct viaccess_data)))
|
---|
963 | {
|
---|
964 | return ERROR;
|
---|
965 | }
|
---|
966 | struct viaccess_data *csystem_data = reader->csystem_data;
|
---|
967 | write_cmd(insFAC, ins8702_data);
|
---|
968 | if((cta_res[cta_lr - 2] == 0x90) && (cta_res[cta_lr - 1] == 0x00))
|
---|
969 | {
|
---|
970 | write_cmd(ins8704, NULL);
|
---|
971 | if((cta_res[cta_lr - 2] == 0x90) && (cta_res[cta_lr - 1] == 0x00))
|
---|
972 | {
|
---|
973 | write_cmd(ins8706, NULL);
|
---|
974 | if((cta_res[cta_lr - 2] == 0x90) && (cta_res[cta_lr - 1] == 0x00))
|
---|
975 | {
|
---|
976 | csystem_data->last_geo.number_ecm = (cta_res[2] << 8) | (cta_res[3]);
|
---|
977 | rdr_log(reader, "using ecm #%x for long viaccess ecm", csystem_data->last_geo.number_ecm);
|
---|
978 | }
|
---|
979 | }
|
---|
980 | }
|
---|
981 | reader->caid = 0x500;
|
---|
982 | memset(reader->prid, 0xff, sizeof(reader->prid));
|
---|
983 | insac[2] = 0xa4;
|
---|
984 | write_cmd(insac, NULL); // request unique id
|
---|
985 | insb8[4] = 0x07;
|
---|
986 | write_cmd(insb8, NULL); // read unique id
|
---|
987 | memcpy(reader->hexserial, cta_res + 2, 5);
|
---|
988 | // rdr_log(reader, "[viaccess-reader] type: Viaccess, ver: %s serial: %llu", ver, b2ll(5, cta_res+2));
|
---|
989 | rdr_log_sensitive(reader, "type: Viaccess (%sstandard atr), caid: %04X, serial: {%llu}",
|
---|
990 | atr[9] == 0x68 ? "" : "non-", reader->caid, (unsigned long long) b2ll(5, cta_res + 2));
|
---|
991 | i = 0;
|
---|
992 | insa4[2] = 0x00;
|
---|
993 | write_cmd(insa4, NULL); // select issuer 0
|
---|
994 | buf[0] = 0;
|
---|
995 | while((cta_res[cta_lr - 2] == 0x90) && (cta_res[cta_lr - 1] == 0))
|
---|
996 | {
|
---|
997 | insc0[4] = 0x1a;
|
---|
998 | write_cmd(insc0, NULL); // show provider properties
|
---|
999 | cta_res[2] &= 0xF0;
|
---|
1000 | reader->prid[i][0] = 0;
|
---|
1001 | memcpy(&reader->prid[i][1], cta_res, 3);
|
---|
1002 | memcpy(&csystem_data->availkeys[i][0], cta_res + 10, 16);
|
---|
1003 | snprintf((char *)buf + cs_strlen((char *)buf), sizeof(buf) - cs_strlen((char *)buf), ",%06X", b2i(3, &reader->prid[i][1]));
|
---|
1004 | // rdr_log(reader, "[viaccess-reader] buf: %s", buf);
|
---|
1005 | insac[2] = 0xa5;
|
---|
1006 | write_cmd(insac, NULL); // request sa
|
---|
1007 | insb8[4] = 0x06;
|
---|
1008 | write_cmd(insb8, NULL); // read sa
|
---|
1009 | memcpy(&reader->sa[i][0], cta_res + 2, 4);
|
---|
1010 | insa4[2] = 0x02;
|
---|
1011 | write_cmd(insa4, NULL); // select next issuer
|
---|
1012 | i++;
|
---|
1013 | }
|
---|
1014 | reader->nprov = i;
|
---|
1015 | rdr_log(reader, "providers: %d (%s)", reader->nprov, buf + 1);
|
---|
1016 | get_maturity(reader);
|
---|
1017 | if(cfg.ulparent)
|
---|
1018 | {
|
---|
1019 | unlock_parental(reader);
|
---|
1020 | }
|
---|
1021 | rdr_log(reader, "ready for requests");
|
---|
1022 | return OK;
|
---|
1023 | }
|
---|
1024 | bool dcw_crc(uint8_t *dw)
|
---|
1025 | {
|
---|
1026 | int8_t i;
|
---|
1027 | for(i = 0; i < 16; i += 4) if(dw[i + 3] != ((dw[i] + dw[i + 1] + dw[i + 2]) & 0xFF)) { return 0; }
|
---|
1028 | return 1;
|
---|
1029 | }
|
---|
1030 | static int32_t viaccess_do_ecm(struct s_reader *reader, const ECM_REQUEST *er, struct s_ecm_answer *ea)
|
---|
1031 | {
|
---|
1032 | def_resp;
|
---|
1033 | static const uint8_t insa4[] = { 0xca, 0xa4, 0x04, 0x00, 0x03 }; // set provider id
|
---|
1034 | uint8_t ins88[] = { 0xca, 0x88, 0x00, 0x00, 0x00 }; // set ecm
|
---|
1035 | uint8_t insf8[] = { 0xca, 0xf8, 0x00, 0x00, 0x00 }; // set geographic info
|
---|
1036 | static const uint8_t insc0[] = { 0xca, 0xc0, 0x00, 0x00, 0x12 }; // read dcw
|
---|
1037 | struct viaccess_data *csystem_data = reader->csystem_data;
|
---|
1038 | // //XXX what is the 4th uint8_t for ??
|
---|
1039 | int32_t ecm88Len = MIN(MAX_ECM_SIZE - 4, SCT_LEN(er->ecm) - 4);
|
---|
1040 | if(ecm88Len < 1)
|
---|
1041 | {
|
---|
1042 | rdr_log(reader, "ECM: Size of ECM couldn't be correctly calculated.");
|
---|
1043 | return ERROR;
|
---|
1044 | }
|
---|
1045 | uint8_t ecmData[ecm88Len];
|
---|
1046 | memset(ecmData, 0, ecm88Len);
|
---|
1047 | memcpy(ecmData, er->ecm + 4, ecm88Len);
|
---|
1048 | uint8_t *ecm88Data = &ecmData[0];
|
---|
1049 | uint32_t provid = 0;
|
---|
1050 | int32_t rc = 0;
|
---|
1051 | int32_t hasD2 = 0;
|
---|
1052 | uint8_t hasE0 = 0;
|
---|
1053 | int32_t has98 = 0;
|
---|
1054 | int32_t curEcm88len = 0;
|
---|
1055 | int32_t nanoLen = 0;
|
---|
1056 | uint8_t *nextEcm;
|
---|
1057 | uint8_t DE04[MAX_ECM_SIZE];
|
---|
1058 | int32_t D2KeyID = 0;
|
---|
1059 | int32_t curnumber_ecm = 0;
|
---|
1060 | uint8_t SubECM = 0;
|
---|
1061 | char key98Idx = 0;
|
---|
1062 | // nanoD2 d2 02 0d 02 -> D2 nano, len 2
|
---|
1063 | // 0b, 0f, 13 -> pre AES decrypt CW
|
---|
1064 | // 0d, 11, 15 -> post AES decrypt CW
|
---|
1065 | int32_t nanoD2 = 0; // knowns D2 nanos: 0x0b ,0x0d ,0x0f ,0x11, 0x13, 0x15
|
---|
1066 | memset(DE04, 0, sizeof(DE04)); //fix dorcel de04 bug
|
---|
1067 | nextEcm = ecm88Data;
|
---|
1068 | while(ecm88Len > 0 && !rc)
|
---|
1069 | {
|
---|
1070 | if(ecm88Data[0] == 0x00 && ecm88Data[1] == 0x00)
|
---|
1071 | {
|
---|
1072 | // nano 0x00 and len 0x00 aren't valid... something is obviously wrong with this ecm.
|
---|
1073 | rdr_log(reader, "ECM: Invalid ECM structure. Rejecting");
|
---|
1074 | return ERROR;
|
---|
1075 | }
|
---|
1076 | // 80 33 nano 80 (ecm) + len (33)
|
---|
1077 | if(ecm88Data[0] == 0x80) // nano 80, give ecm len
|
---|
1078 | {
|
---|
1079 | curEcm88len = ecm88Data[1];
|
---|
1080 | nextEcm = ecm88Data + curEcm88len + 2;
|
---|
1081 | ecm88Data += 2;
|
---|
1082 | ecm88Len -= 2;
|
---|
1083 | }
|
---|
1084 | if(!curEcm88len) // there was no nano 80 -> simple ecm
|
---|
1085 | {
|
---|
1086 | curEcm88len = ecm88Len;
|
---|
1087 | }
|
---|
1088 | // d2 02 0d 02 -> D2 nano, len 2, select the AES key to be used
|
---|
1089 | if(ecm88Data[0] == 0xd2)
|
---|
1090 | {
|
---|
1091 | // test if it needs AES decrypt
|
---|
1092 | if(ecm88Data[2] == 0x0b)
|
---|
1093 | {
|
---|
1094 | nanoD2 = 0x0b;
|
---|
1095 | rdr_log_dbg(reader, D_READER, "ECM: nano D2 0x0b");
|
---|
1096 | }
|
---|
1097 | if(ecm88Data[2] == 0x0d)
|
---|
1098 | {
|
---|
1099 | nanoD2 = 0x0d;
|
---|
1100 | rdr_log_dbg(reader, D_READER, "ECM: nano D2 0x0d");
|
---|
1101 | }
|
---|
1102 | if(ecm88Data[2] == 0x0f)
|
---|
1103 | {
|
---|
1104 | nanoD2 = 0x0f;
|
---|
1105 | rdr_log_dbg(reader, D_READER, "ECM: nano D2 0x0f");
|
---|
1106 | }
|
---|
1107 | if(ecm88Data[2] == 0x11)
|
---|
1108 | {
|
---|
1109 | nanoD2 = 0x11;
|
---|
1110 | rdr_log_dbg(reader, D_READER, "ECM: nano D2 0x11");
|
---|
1111 | }
|
---|
1112 | if(ecm88Data[2] == 0x13)
|
---|
1113 | {
|
---|
1114 | nanoD2 = 0x13;
|
---|
1115 | rdr_log_dbg(reader, D_READER, "ECM: nano D2 0x13");
|
---|
1116 | }
|
---|
1117 | if(ecm88Data[2] == 0x15)
|
---|
1118 | {
|
---|
1119 | nanoD2 = 0x15;
|
---|
1120 | rdr_log_dbg(reader, D_READER, "ECM: nano D2 0x15");
|
---|
1121 | }
|
---|
1122 | // use the d2 arguments to get the key # to be used
|
---|
1123 | int32_t len = ecm88Data[1] + 2;
|
---|
1124 | D2KeyID = ecm88Data[3];
|
---|
1125 | ecm88Data += len;
|
---|
1126 | ecm88Len -= len;
|
---|
1127 | curEcm88len -= len;
|
---|
1128 | hasD2 = 1;
|
---|
1129 | }
|
---|
1130 | else
|
---|
1131 | {
|
---|
1132 | hasD2 = 0;
|
---|
1133 | }
|
---|
1134 | // 40 07 03 0b 00 -> nano 40, len =7 ident 030B00 (tntsat), key #0 <== we're pointing here
|
---|
1135 | // 09 -> use key #9
|
---|
1136 | // 05 67 00
|
---|
1137 | if((ecm88Data[0] == 0x90 || ecm88Data[0] == 0x40) && (ecm88Data[1] == 0x03 || ecm88Data[1] == 0x07))
|
---|
1138 | {
|
---|
1139 | uint8_t ident[3], keynr;
|
---|
1140 | uint8_t *ecmf8Data = 0;
|
---|
1141 | int32_t ecmf8Len = 0;
|
---|
1142 | nanoLen = ecm88Data[1] + 2;
|
---|
1143 | keynr = ecm88Data[4] & 0x0F;
|
---|
1144 | // 40 07 03 0b 00 -> nano 40, len =7 ident 030B00 (tntsat), key #0 <== we're pointing here
|
---|
1145 | // 09 -> use key #9
|
---|
1146 | if(nanoLen > 5)
|
---|
1147 | {
|
---|
1148 | curnumber_ecm = (ecm88Data[6] << 8) | (ecm88Data[7]);
|
---|
1149 | rdr_log_dbg(reader, D_READER, "checking if the ecm number (%x) match the card one (%x)", curnumber_ecm, csystem_data->last_geo.number_ecm);
|
---|
1150 | // if we have an ecm number we check it.
|
---|
1151 | // we can't assume that if the nano len is 5 or more we have an ecm number
|
---|
1152 | // as some card don't support this
|
---|
1153 | if(csystem_data->last_geo.number_ecm > 0)
|
---|
1154 | {
|
---|
1155 | if(csystem_data->last_geo.number_ecm == curnumber_ecm && !(ecm88Data[nanoLen - 1] == 0x00)) // select permut 4, accept 01 and FF
|
---|
1156 | {
|
---|
1157 | keynr = ecm88Data[5];
|
---|
1158 | rdr_log_dbg(reader, D_READER, "keyToUse = %02x, ECM ending with %02x", ecm88Data[5], ecm88Data[nanoLen - 1]);
|
---|
1159 | }
|
---|
1160 | else
|
---|
1161 | {
|
---|
1162 | // if(ecm88Data[nanoLen - 1] == 0x00) // select permut 4
|
---|
1163 | // {
|
---|
1164 | // rdr_log_dbg(reader, D_READER, "Skip ECM ending with = %02x for ecm number (%x) for provider %02x%02x%02x", ecm88Data[nanoLen - 1], curnumber_ecm, ecm88Data[2], ecm88Data[3], ecm88Data[4]);
|
---|
1165 | // }
|
---|
1166 | rdr_log_dbg(reader, D_READER, "Skip ECM ending with = %02x for ecm number (%x)", ecm88Data[nanoLen - 1], curnumber_ecm);
|
---|
1167 | ecm88Data = nextEcm;
|
---|
1168 | ecm88Len -= curEcm88len;
|
---|
1169 | continue; // loop to next ecm
|
---|
1170 | }
|
---|
1171 | }
|
---|
1172 | else // long ecm but we don't have an ecm number so we have to try them all.
|
---|
1173 | {
|
---|
1174 | keynr = ecm88Data[5];
|
---|
1175 | rdr_log_dbg(reader, D_READER, "keyToUse = %02x", ecm88Data[5]);
|
---|
1176 | }
|
---|
1177 | }
|
---|
1178 | memcpy(ident, &ecm88Data[2], sizeof(ident));
|
---|
1179 | provid = b2i(3, ident);
|
---|
1180 | ident[2] &= 0xF0;
|
---|
1181 | if(hasD2 && reader->aes_list)
|
---|
1182 | {
|
---|
1183 | // check that we have the AES key to decode the CW
|
---|
1184 | // if not there is no need to send the ecm to the card
|
---|
1185 | if(!aes_present(reader->aes_list, 0x500, (uint32_t)(provid & 0xFFFFF0) , D2KeyID))
|
---|
1186 | {
|
---|
1187 | return ERROR;
|
---|
1188 | }
|
---|
1189 | }
|
---|
1190 | if(!chk_prov(reader, ident, keynr))
|
---|
1191 | {
|
---|
1192 | rdr_log_dbg(reader, D_READER, "ECM: provider or key not found on card");
|
---|
1193 | snprintf(ea->msglog, MSGLOGSIZE, "provider(%02x%02x%02x) or key(%d) not found on card", ident[0], ident[1], ident[2], keynr);
|
---|
1194 | return ERROR;
|
---|
1195 | }
|
---|
1196 | SubECM = ecm88Data[nanoLen - 1] ; // 01 permut 4 , FF no permut
|
---|
1197 | ecm88Data += nanoLen;
|
---|
1198 | ecm88Len -= nanoLen;
|
---|
1199 | curEcm88len -= nanoLen;
|
---|
1200 | if(ecm88Data[0] == 0xDE && ecm88Data[1] == 0x04)
|
---|
1201 | {
|
---|
1202 | memcpy(DE04, &ecm88Data[0], 6);
|
---|
1203 | ecm88Data += 6;
|
---|
1204 | }
|
---|
1205 | if((ecm88Data[0] == 0xD9) && (ecm88Data[1] == 0x0A))
|
---|
1206 | {
|
---|
1207 | rdr_log_dbg(reader, D_READER,"[viaccess-reader] nano D9/0A ECM detected!");
|
---|
1208 | if((ecm88Data[12] == 0xE0) && (ecm88Data[13] == 0x02) && (ecm88Data[15] == 0x02)) // accept parental data 0F for ecm88Data[2]
|
---|
1209 | {
|
---|
1210 | rdr_log_dbg(reader, D_READER,"[viaccess-reader] nano E0 ECM detected!");
|
---|
1211 | hasE0 = 1;
|
---|
1212 | }
|
---|
1213 | if(((ecm88Data[16] ==0x98) || (ecm88Data[19] == 0x98)) && ((ecm88Data[17] == 0x08) || (ecm88Data[20] == 0x08)))
|
---|
1214 | {
|
---|
1215 | rdr_log_dbg(reader, D_READER,"[viaccess-reader] nano 98 ECM detected!");
|
---|
1216 | has98 = 1;
|
---|
1217 | key98Idx = ecm88Data[25];
|
---|
1218 | rdr_log_dbg(reader, D_READER,"[viaccess-reader] nano 98 Index : %02X",key98Idx);
|
---|
1219 | }
|
---|
1220 | }
|
---|
1221 | else
|
---|
1222 | {
|
---|
1223 | if((ecm88Data[0] == 0xE0) && (ecm88Data[1] == 0x02) && (ecm88Data[3] == 0x02)) // accept parental data 0F for ecm88Data[2]
|
---|
1224 | {
|
---|
1225 | rdr_log_dbg(reader, D_READER,"[viaccess-reader] nano E0 ECM detected!");
|
---|
1226 | hasE0 = 1;
|
---|
1227 | }
|
---|
1228 | }
|
---|
1229 | if((ecm88Data[4] == 0x98) && (ecm88Data[5] == 0x08))
|
---|
1230 | {
|
---|
1231 | rdr_log_dbg(reader, D_READER,"[viaccess-reader] nano 98 ECM detected!");
|
---|
1232 | has98 = 1;
|
---|
1233 | key98Idx = ecm88Data[0x0D];
|
---|
1234 | }
|
---|
1235 | if(csystem_data->last_geo.provid != provid)
|
---|
1236 | {
|
---|
1237 | csystem_data->last_geo.provid = provid;
|
---|
1238 | csystem_data->last_geo.geo_len = 0;
|
---|
1239 | csystem_data->last_geo.geo[0] = 0;
|
---|
1240 | write_cmd(insa4, ident); // set provider
|
---|
1241 | }
|
---|
1242 | // Nano D2 0x0b, 0x0f, 0x13 -> pre AES decrypt CW
|
---|
1243 | if(hasD2 && (nanoD2 == 0x0b|| nanoD2 == 0x0f|| nanoD2 == 0x13))
|
---|
1244 | {
|
---|
1245 | uint8_t *ecm88DataCW = ecm88Data;
|
---|
1246 | int32_t cwStart = 0;
|
---|
1247 | //int32_t cwStartRes = 0;
|
---|
1248 | int32_t must_exit = 0;
|
---|
1249 | // find CW start
|
---|
1250 | while(cwStart < curEcm88len - 1 && !must_exit)
|
---|
1251 | {
|
---|
1252 | if(ecm88Data[cwStart] == 0xEA && ecm88Data[cwStart + 1] == 0x10)
|
---|
1253 | {
|
---|
1254 | ecm88DataCW = ecm88DataCW + cwStart + 2;
|
---|
1255 | must_exit = 1;
|
---|
1256 | }
|
---|
1257 | cwStart = cwStart + ecm88Data[cwStart + 1] + 2; // parse via nanos
|
---|
1258 | // cwStart++; // error if EA 10 in nanos datas
|
---|
1259 | }
|
---|
1260 | if(nanoD2 == 0x0f)
|
---|
1261 | {
|
---|
1262 | hdSurEncPhase1_D2_0F_11(ecm88DataCW);
|
---|
1263 | hdSurEncPhase2_D2_0F_11(ecm88DataCW);
|
---|
1264 | }
|
---|
1265 | if(nanoD2 == 0x13)
|
---|
1266 | {
|
---|
1267 | hdSurEncPhase1_D2_13_15(ecm88DataCW);
|
---|
1268 | }
|
---|
1269 | // use AES from list to decrypt CW
|
---|
1270 | rdr_log_dbg(reader, D_READER, "Decoding CW : using AES key id %d for provider %06x", D2KeyID, (provid & 0xFFFFF0));
|
---|
1271 | if(aes_decrypt_from_list(reader->aes_list, 0x500, (uint32_t)(provid & 0xFFFFF0), D2KeyID, &ecm88DataCW[0], 16) == 0)
|
---|
1272 | {
|
---|
1273 | snprintf(ea->msglog, MSGLOGSIZE, "Missing AES key(%d)[aka E%X]",D2KeyID, D2KeyID);
|
---|
1274 | }
|
---|
1275 | if(nanoD2 == 0x0f)
|
---|
1276 | {
|
---|
1277 | hdSurEncPhase1_D2_0F_11(ecm88DataCW);
|
---|
1278 | }
|
---|
1279 | if(nanoD2 == 0x13)
|
---|
1280 | {
|
---|
1281 | hdSurEncPhase2_D2_13_15(ecm88DataCW);
|
---|
1282 | }
|
---|
1283 | }
|
---|
1284 | while(ecm88Len > 1 && ecm88Data[0] < 0xA0)
|
---|
1285 | {
|
---|
1286 | nanoLen = ecm88Data[1] + 2;
|
---|
1287 | if(!ecmf8Data)
|
---|
1288 | {
|
---|
1289 | ecmf8Data = (uint8_t *)ecm88Data;
|
---|
1290 | }
|
---|
1291 | ecmf8Len += nanoLen;
|
---|
1292 | ecm88Len -= nanoLen;
|
---|
1293 | curEcm88len -= nanoLen;
|
---|
1294 | ecm88Data += nanoLen;
|
---|
1295 | }
|
---|
1296 | if(ecmf8Len)
|
---|
1297 | {
|
---|
1298 | if(csystem_data->last_geo.geo_len != ecmf8Len || memcmp(csystem_data->last_geo.geo, ecmf8Data, csystem_data->last_geo.geo_len))
|
---|
1299 | {
|
---|
1300 | memcpy(csystem_data->last_geo.geo, ecmf8Data, ecmf8Len);
|
---|
1301 | csystem_data->last_geo.geo_len = ecmf8Len;
|
---|
1302 | insf8[3] = keynr;
|
---|
1303 | insf8[4] = ecmf8Len;
|
---|
1304 | write_cmd(insf8, ecmf8Data);
|
---|
1305 | }
|
---|
1306 | }
|
---|
1307 | ins88[2] = ecmf8Len ? 1 : 0;
|
---|
1308 | ins88[3] = keynr;
|
---|
1309 | ins88[4] = (curEcm88len > 0xFF) ? 0x00 : curEcm88len;
|
---|
1310 | //
|
---|
1311 | // we should check the nano to make sure the ecm is valid
|
---|
1312 | // we should look for at least 1 E3 nano, 1 EA nano and the F0 signature nano
|
---|
1313 | //
|
---|
1314 | // DE04
|
---|
1315 | if(DE04[0] == 0xDE)
|
---|
1316 | {
|
---|
1317 | uint32_t l = curEcm88len - 6;
|
---|
1318 | if(l > MAX_ECM_SIZE || curEcm88len <= 6) //don't known if this is ok...
|
---|
1319 | {
|
---|
1320 | rdr_log(reader, "ecm invalid/too long! len=%d", curEcm88len);
|
---|
1321 | return ERROR;
|
---|
1322 | }
|
---|
1323 | memcpy(DE04 + 6, (uint8_t *)ecm88Data, l);
|
---|
1324 | write_cmd(ins88, DE04); // request dcw
|
---|
1325 | }
|
---|
1326 | else
|
---|
1327 | {
|
---|
1328 | write_cmd(ins88, (uint8_t *)ecm88Data); // request dcw
|
---|
1329 | }
|
---|
1330 | write_cmd(insc0, NULL); // read dcw
|
---|
1331 | switch(cta_res[0])
|
---|
1332 | {
|
---|
1333 | case 0xe8: // even
|
---|
1334 | if(cta_res[1] == 8)
|
---|
1335 | {
|
---|
1336 | memcpy(ea->cw, cta_res + 2, 8);
|
---|
1337 | rc = 1;
|
---|
1338 | } break;
|
---|
1339 | case 0xe9: // odd
|
---|
1340 | if(cta_res[1] == 8)
|
---|
1341 | {
|
---|
1342 | memcpy(ea->cw + 8, cta_res + 2, 8);
|
---|
1343 | rc = 1;
|
---|
1344 | } break;
|
---|
1345 | case 0xea: // complete
|
---|
1346 | if(cta_res[1] == 16)
|
---|
1347 | {
|
---|
1348 | memcpy(ea->cw, cta_res + 2, 16);
|
---|
1349 | rc = 1;
|
---|
1350 | } break;
|
---|
1351 | default :
|
---|
1352 | ecm88Data = nextEcm;
|
---|
1353 | ecm88Len -= curEcm88len;
|
---|
1354 | rdr_log_dbg(reader, D_READER, "Error: card respondend %02X %02X, trying next ECM", cta_res[0], cta_res[1]);
|
---|
1355 | snprintf(ea->msglog, MSGLOGSIZE, "key to use is not the current one, trying next ECM");
|
---|
1356 | }
|
---|
1357 | }
|
---|
1358 | else
|
---|
1359 | {
|
---|
1360 | //ecm88Data=nextEcm;
|
---|
1361 | //ecm88Len-=curEcm88len;
|
---|
1362 | rdr_log_dbg(reader, D_READER, "ECM: Unknown ECM type");
|
---|
1363 | snprintf(ea->msglog, MSGLOGSIZE, "Unknown ECM type");
|
---|
1364 | return ERROR; /*Lets interupt the loop and exit, because we don't know this ECM type.*/
|
---|
1365 | }
|
---|
1366 | }
|
---|
1367 | // Nano D2 0d, 11, 15 -> post AES decrypt CW
|
---|
1368 | if(hasD2 && !dcw_crc(ea->cw) && (nanoD2 == 0x0d || nanoD2 == 0x11 || nanoD2 == 0x15))
|
---|
1369 | {
|
---|
1370 | if(nanoD2 == 0x11)
|
---|
1371 | {
|
---|
1372 | hdSurEncPhase1_D2_0F_11(ea->cw);
|
---|
1373 | hdSurEncPhase2_D2_0F_11(ea->cw);
|
---|
1374 | }
|
---|
1375 | if(nanoD2 == 0x15)
|
---|
1376 | {
|
---|
1377 | hdSurEncPhase1_D2_13_15(ea->cw);
|
---|
1378 | }
|
---|
1379 | rdr_log_dbg(reader, D_READER, "Decoding CW : using AES key id %d for provider %06x", D2KeyID, (provid & 0xFFFFF0));
|
---|
1380 | rc = aes_decrypt_from_list(reader->aes_list, 0x500, (uint32_t)(provid & 0xFFFFF0), D2KeyID, ea->cw, 16);
|
---|
1381 | if(rc == 0)
|
---|
1382 | {
|
---|
1383 | snprintf(ea->msglog, MSGLOGSIZE, "Missing AES key(%d)[aka E%X]",D2KeyID, D2KeyID);
|
---|
1384 | }
|
---|
1385 | if(nanoD2 == 0x11)
|
---|
1386 | {
|
---|
1387 | hdSurEncPhase1_D2_0F_11(ea->cw);
|
---|
1388 | }
|
---|
1389 | if(nanoD2 == 0x15)
|
---|
1390 | {
|
---|
1391 | hdSurEncPhase2_D2_13_15(ea->cw);
|
---|
1392 | }
|
---|
1393 | }
|
---|
1394 | if (has98)
|
---|
1395 | {
|
---|
1396 | if (N98Init == 0)
|
---|
1397 | {
|
---|
1398 | MakeSubKeys(KeyS, key98Idx);
|
---|
1399 | N98Init = 1;
|
---|
1400 | }
|
---|
1401 | uint8_t inp[16];
|
---|
1402 | memcpy(inp,ea->cw,16);
|
---|
1403 | N98_decrypt(inp);
|
---|
1404 | memcpy(ea->cw,inp,16);
|
---|
1405 | }
|
---|
1406 | if (hasE0)
|
---|
1407 | {
|
---|
1408 | if (reader->initCA28)
|
---|
1409 | {
|
---|
1410 | uint8_t returnedcw[16];
|
---|
1411 | memcpy(returnedcw,ea->cw,16);
|
---|
1412 | // Processing 3DES
|
---|
1413 | // Processing even cw
|
---|
1414 | des(returnedcw, reader->key_schedule1, 0); // decrypt
|
---|
1415 | des(returnedcw, reader->key_schedule2, 1); // crypt
|
---|
1416 | des(returnedcw, reader->key_schedule1, 0); // decrypt
|
---|
1417 | // Processing odd cw
|
---|
1418 | des(returnedcw + 8, reader->key_schedule1, 0); // decrypt
|
---|
1419 | des(returnedcw + 8, reader->key_schedule2, 1); // crypt
|
---|
1420 | des(returnedcw + 8, reader->key_schedule1, 0); // decrypt
|
---|
1421 | // returning value
|
---|
1422 | memcpy(ea->cw,returnedcw, 16);
|
---|
1423 | }
|
---|
1424 | else
|
---|
1425 | {
|
---|
1426 | snprintf(ea->msglog, MSGLOGSIZE, "Nano E0 detected, no valid boxkey + deskey defined: no decoding");
|
---|
1427 | }
|
---|
1428 | }
|
---|
1429 | if (SubECM == 1)
|
---|
1430 | {
|
---|
1431 | uint8_t rw[16];
|
---|
1432 | memcpy(rw, ea->cw, 16);
|
---|
1433 | memcpy(ea->cw, rw+4, 4);
|
---|
1434 | memcpy(ea->cw+4, rw, 4);
|
---|
1435 | memcpy(ea->cw+8, rw+12, 4);
|
---|
1436 | memcpy(ea->cw+12, rw+8, 4);
|
---|
1437 | }
|
---|
1438 | return (rc ? OK : ERROR);
|
---|
1439 | }
|
---|
1440 | static int32_t viaccess_get_emm_type(EMM_PACKET *ep, struct s_reader *rdr)
|
---|
1441 | {
|
---|
1442 | uint32_t provid = 0;
|
---|
1443 | rdr_log_dbg(rdr, D_EMM, "Entered viaccess_get_emm_type ep->emm[0]=%02x", ep->emm[0]);
|
---|
1444 | if(ep->emm[3] == 0x90 && ep->emm[4] == 0x03)
|
---|
1445 | {
|
---|
1446 | provid = b2i(3, ep->emm + 5);
|
---|
1447 | provid &= 0xFFFFF0;
|
---|
1448 | i2b_buf(4, provid, ep->provid);
|
---|
1449 | }
|
---|
1450 | switch(ep->emm[0])
|
---|
1451 | {
|
---|
1452 | case 0x88:
|
---|
1453 | ep->type = UNIQUE;
|
---|
1454 | memset(ep->hexserial, 0, 8);
|
---|
1455 | memcpy(ep->hexserial, ep->emm + 4, 4);
|
---|
1456 | rdr_log_dbg(rdr, D_EMM, "UNIQUE");
|
---|
1457 | if(!is_network_reader(rdr))
|
---|
1458 | {
|
---|
1459 | return (!memcmp(rdr->hexserial + 1, ep->hexserial, 4)); // local reader
|
---|
1460 | }
|
---|
1461 | else
|
---|
1462 | {
|
---|
1463 | return 1; // let server decide!
|
---|
1464 | }
|
---|
1465 | case 0x8A:
|
---|
1466 | case 0x8B:
|
---|
1467 | ep->type = GLOBAL;
|
---|
1468 | rdr_log_dbg(rdr, D_EMM, "GLOBAL");
|
---|
1469 | return 1;
|
---|
1470 | case 0x8C:
|
---|
1471 | case 0x8D:
|
---|
1472 | ep->type = SHARED;
|
---|
1473 | rdr_log_dbg(rdr, D_EMM, "SHARED (part)");
|
---|
1474 | // We need those packets to pass otherwise we would never
|
---|
1475 | // be able to complete EMM reassembly
|
---|
1476 | return 1;
|
---|
1477 | case 0x8E:
|
---|
1478 | ep->type = SHARED;
|
---|
1479 | rdr_log_dbg(rdr, D_EMM, "SHARED");
|
---|
1480 | memset(ep->hexserial, 0, 8);
|
---|
1481 | memcpy(ep->hexserial, ep->emm + 3, 3);
|
---|
1482 | // local reader
|
---|
1483 | int8_t i;
|
---|
1484 | for(i = 0; i < rdr->nprov; i++)
|
---|
1485 | {
|
---|
1486 | if(!memcmp(&rdr->prid[i][2], ep->hexserial+1, 2))
|
---|
1487 | {
|
---|
1488 | return 1;
|
---|
1489 | }
|
---|
1490 | return (!memcmp(&rdr->sa[0][0], ep->hexserial, 3));
|
---|
1491 | } /* fallthrough */
|
---|
1492 | default:
|
---|
1493 | ep->type = UNKNOWN;
|
---|
1494 | rdr_log_dbg(rdr, D_EMM, "UNKNOWN");
|
---|
1495 | return 1;
|
---|
1496 | }
|
---|
1497 | }
|
---|
1498 | static int32_t viaccess_get_emm_filter(struct s_reader *rdr, struct s_csystem_emm_filter **emm_filters, unsigned int *filter_count)
|
---|
1499 | {
|
---|
1500 | if(*emm_filters == NULL)
|
---|
1501 | {
|
---|
1502 | bool network = is_network_reader(rdr);
|
---|
1503 | int8_t device_emm = ((rdr->deviceemm > 0) ? 1 : 0); // set to 1 if device specific emms should be catched too
|
---|
1504 | const unsigned int max_filter_count = 4 + ((device_emm != 0 && rdr->nprov > 0) ? 1:0) + (3 * ((rdr->nprov > 0) ? (rdr->nprov - 1) : 0));
|
---|
1505 | if(!cs_malloc(emm_filters, max_filter_count * sizeof(struct s_csystem_emm_filter)))
|
---|
1506 | {
|
---|
1507 | return ERROR;
|
---|
1508 | }
|
---|
1509 | struct s_csystem_emm_filter *filters = *emm_filters;
|
---|
1510 | *filter_count = 0;
|
---|
1511 | int32_t idx = 0;
|
---|
1512 | int32_t prov;
|
---|
1513 | if(rdr->nprov > 0 && device_emm == 1)
|
---|
1514 | {
|
---|
1515 | filters[idx].type = EMM_GLOBAL; // 8A or 8B no reassembly needed!
|
---|
1516 | filters[idx].enabled = 1;
|
---|
1517 | filters[idx].filter[0] = 0x8A;
|
---|
1518 | filters[idx].mask[0] = 0xFE;
|
---|
1519 | filters[idx].filter[3] = 0x80; // device specific emms
|
---|
1520 | filters[idx].mask[3] = 0x80;
|
---|
1521 | idx++;
|
---|
1522 | }
|
---|
1523 | // shared are most important put them on top, define first since viaccess produces a lot of filters!
|
---|
1524 | for(prov = 0; (prov < rdr->nprov); prov++)
|
---|
1525 | {
|
---|
1526 | if((rdr->prid[prov][2] &0xF0) == 0xF0) // skip this not useful provider
|
---|
1527 | {
|
---|
1528 | continue;
|
---|
1529 | }
|
---|
1530 | filters[idx].type = EMM_SHARED; // 8C or 8D always first part of shared, second part delivered by 8E!
|
---|
1531 | filters[idx].enabled = 1;
|
---|
1532 | filters[idx].filter[0] = 0x8C;
|
---|
1533 | filters[idx].mask[0] = 0xFE;
|
---|
1534 | if(rdr->nprov > 0)
|
---|
1535 | {
|
---|
1536 | memcpy(&filters[idx].filter[4], &rdr->prid[prov][2], 2);
|
---|
1537 | filters[idx].mask[4] = 0xFF;
|
---|
1538 | filters[idx].mask[5] = 0xF0; // ignore last digit since this is key on card indicator!
|
---|
1539 | }
|
---|
1540 | idx++;
|
---|
1541 | filters[idx].type = EMM_SHARED; // 8E second part reassembly with 8c/8d needed!
|
---|
1542 | filters[idx].enabled = 1;
|
---|
1543 | filters[idx].filter[0] = 0x8E;
|
---|
1544 | filters[idx].mask[0] = 0xFF;
|
---|
1545 | if(rdr->nprov > 0)
|
---|
1546 | {
|
---|
1547 | memcpy(&filters[idx].filter[1], &rdr->sa[prov][0], 3);
|
---|
1548 | memset(&filters[idx].mask[1], 0xFF, 3);
|
---|
1549 | }
|
---|
1550 | idx++;
|
---|
1551 | }
|
---|
1552 | // globals are less important, define last since viaccess produces a lot of filters!
|
---|
1553 | for(prov = 0; (prov < rdr->nprov); prov++)
|
---|
1554 | {
|
---|
1555 | if((rdr->prid[prov][2] &0xF0) == 0xF0) // skip this not useful provider
|
---|
1556 | {
|
---|
1557 | continue;
|
---|
1558 | }
|
---|
1559 | filters[idx].type = EMM_GLOBAL; // 8A or 8B no reassembly needed!
|
---|
1560 | filters[idx].enabled = 1;
|
---|
1561 | filters[idx].filter[0] = 0x8A;
|
---|
1562 | filters[idx].mask[0] = 0xFE;
|
---|
1563 | if(rdr->nprov > 0)
|
---|
1564 | {
|
---|
1565 | memcpy(&filters[idx].filter[4], &rdr->prid[prov][2], 2);
|
---|
1566 | filters[idx].mask[4] = 0xFF;
|
---|
1567 | filters[idx].mask[5] = 0xF0; // ignore last digit since this is key on card indicator!
|
---|
1568 | }
|
---|
1569 | else if (device_emm == 0)
|
---|
1570 | {
|
---|
1571 | filters[idx].filter[3] = 0x00; // additional filter to cancel device specific emms
|
---|
1572 | filters[idx].mask[3] = 0x80;
|
---|
1573 | }
|
---|
1574 | idx++;
|
---|
1575 | }
|
---|
1576 | filters[idx].type = EMM_UNIQUE;
|
---|
1577 | filters[idx].enabled = 1;
|
---|
1578 | filters[idx].filter[0] = 0x88;
|
---|
1579 | filters[idx].mask[0] = 0xFF;
|
---|
1580 | if(!network) // network has only 3 digits out of 4
|
---|
1581 | {
|
---|
1582 | memcpy(&filters[idx].filter[1], rdr->hexserial + 1, 4);
|
---|
1583 | memset(&filters[idx].mask[1], 0xFF, 4);
|
---|
1584 | }
|
---|
1585 | else
|
---|
1586 | {
|
---|
1587 | memcpy(&filters[idx].filter[1], rdr->hexserial + 1, 3);
|
---|
1588 | memset(&filters[idx].mask[1], 0xFF, 3);
|
---|
1589 | }
|
---|
1590 | idx++;
|
---|
1591 | *filter_count = idx;
|
---|
1592 | }
|
---|
1593 | return OK;
|
---|
1594 | }
|
---|
1595 | static int32_t viaccess_do_emm(struct s_reader *reader, EMM_PACKET *ep)
|
---|
1596 | {
|
---|
1597 | def_resp;
|
---|
1598 | static const uint8_t insa4[] = { 0xca, 0xa4, 0x04, 0x00, 0x03 }; // set provider id
|
---|
1599 | uint8_t insf0[] = { 0xca, 0xf0, 0x00, 0x01, 0x22 }; // set adf
|
---|
1600 | uint8_t insf4[] = { 0xca, 0xf4, 0x00, 0x01, 0x00 }; // set adf, encrypted
|
---|
1601 | uint8_t ins18[] = { 0xca, 0x18, 0x01, 0x01, 0x00 }; // set subscription
|
---|
1602 | uint8_t ins1c[] = { 0xca, 0x1c, 0x01, 0x01, 0x00 }; // set subscription, encrypted
|
---|
1603 | struct viaccess_data *csystem_data = reader->csystem_data;
|
---|
1604 | int32_t emmdatastart = 7;
|
---|
1605 | if (ep->emm[1] == 0x01) // emm from cccam
|
---|
1606 | {
|
---|
1607 | emmdatastart = 12;
|
---|
1608 | ep->emm[1] = 0x70; // (& 0x0f) of this byte is length, so 0x01 would increase the length by 256
|
---|
1609 | ep->emm[2] -= 1;
|
---|
1610 | if (ep->type == SHARED || ep->type == GLOBAL) // build missing 0x90 nano from provider at serial position
|
---|
1611 | {
|
---|
1612 | memcpy(ep->emm + 7, ep->emm + 3, 3);
|
---|
1613 | ep->emm[5] = 0x90;
|
---|
1614 | ep->emm[6] = 0x03;
|
---|
1615 | ep->emm[9] |= 0x01;
|
---|
1616 | ep->emm[10] = 0x9E;
|
---|
1617 | ep->emm[11] = 0x20;
|
---|
1618 | emmdatastart = 5;
|
---|
1619 | }
|
---|
1620 | }
|
---|
1621 | if(ep->type == UNIQUE)
|
---|
1622 | {
|
---|
1623 | emmdatastart++;
|
---|
1624 | }
|
---|
1625 | if(ep->type == GLOBAL && emmdatastart == 7)
|
---|
1626 | {
|
---|
1627 | emmdatastart -= 4;
|
---|
1628 | }
|
---|
1629 | int32_t emmLen = SCT_LEN(ep->emm) - emmdatastart;
|
---|
1630 | int32_t rc = 0;
|
---|
1631 | rdr_log_dump(reader, ep->emm, emmLen + emmdatastart, "RECEIVED EMM VIACCESS");
|
---|
1632 | int32_t emmUpToEnd;
|
---|
1633 | uint8_t *emmParsed = ep->emm + emmdatastart;
|
---|
1634 | int32_t provider_ok = 0;
|
---|
1635 | uint32_t emm_provid = 0;
|
---|
1636 | uint8_t keynr = 0;
|
---|
1637 | int32_t ins18Len = 0;
|
---|
1638 | uint8_t ins18Data[512];
|
---|
1639 | uint8_t insData[512];
|
---|
1640 | uint8_t *nano81Data = 0;
|
---|
1641 | uint8_t *nano91Data = 0;
|
---|
1642 | uint8_t *nano92Data = 0;
|
---|
1643 | uint8_t *nano9EData = 0;
|
---|
1644 | uint8_t *nanoF0Data = 0;
|
---|
1645 | uint8_t *nanoA9Data = 0;
|
---|
1646 | for(emmUpToEnd = emmLen; (emmParsed[1] != 0) && (emmUpToEnd > 0); emmUpToEnd -= (2 + emmParsed[1]), emmParsed += (2 + emmParsed[1]))
|
---|
1647 | {
|
---|
1648 | rdr_log_dump(reader, emmParsed, emmParsed[1] + 2, "NANO");
|
---|
1649 | if(emmParsed[0] == 0x90 && emmParsed[1] == 0x03)
|
---|
1650 | {
|
---|
1651 | /* identification of the service operator */
|
---|
1652 | uint8_t soid[3], ident[3], i;
|
---|
1653 | for(i = 0; i < 3; i++)
|
---|
1654 | {
|
---|
1655 | soid[i] = ident[i] = emmParsed[2 + i];
|
---|
1656 | }
|
---|
1657 | ident[2] &= 0xF0;
|
---|
1658 | emm_provid = b2i(3, ident);
|
---|
1659 | keynr = soid[2] & 0x0F;
|
---|
1660 | if(chk_prov(reader, ident, keynr))
|
---|
1661 | {
|
---|
1662 | provider_ok = 1;
|
---|
1663 | }
|
---|
1664 | else
|
---|
1665 | {
|
---|
1666 | rdr_log(reader, "EMM: ignored since provider or key not present on card (%x, %x)", emm_provid, keynr);
|
---|
1667 | return SKIPPED;
|
---|
1668 | }
|
---|
1669 | // check if the provider changes. If yes, set the new one. If not, don't... card will return an error if we do.
|
---|
1670 | if(csystem_data->last_geo.provid != emm_provid)
|
---|
1671 | {
|
---|
1672 | write_cmd(insa4, ident);
|
---|
1673 | if(cta_res[cta_lr - 2] != 0x90 || cta_res[cta_lr - 1] != 0x00)
|
---|
1674 | {
|
---|
1675 | rdr_log_dump(reader, insa4, 5, "set provider cmd:");
|
---|
1676 | rdr_log_dump(reader, soid, 3, "set provider data:");
|
---|
1677 | rdr_log(reader, "update error: %02X %02X", cta_res[cta_lr - 2], cta_res[cta_lr - 1]);
|
---|
1678 | return ERROR;
|
---|
1679 | }
|
---|
1680 | }
|
---|
1681 | // as we are maybe changing the used provider, clear the cache, so the next ecm will re-select the correct one
|
---|
1682 | csystem_data->last_geo.provid = 0;
|
---|
1683 | csystem_data->last_geo.geo_len = 0;
|
---|
1684 | csystem_data->last_geo.geo[0] = 0;
|
---|
1685 | }
|
---|
1686 | else if(emmParsed[0] == 0x9e && emmParsed[1] == 0x20)
|
---|
1687 | {
|
---|
1688 | /* adf */
|
---|
1689 | if(!nano91Data)
|
---|
1690 | {
|
---|
1691 | /* adf is not crypted, so test it */
|
---|
1692 | uint8_t custwp;
|
---|
1693 | uint8_t *afd;
|
---|
1694 | custwp = reader->sa[0][3];
|
---|
1695 | afd = (uint8_t *)emmParsed + 2;
|
---|
1696 | if(afd[31 - custwp / 8] & (1 << (custwp & 7)))
|
---|
1697 | {
|
---|
1698 | rdr_log_dbg(reader, D_READER, "emm for our card %08X", b2i(4, &reader->sa[0][0]));
|
---|
1699 | }
|
---|
1700 | else
|
---|
1701 | {
|
---|
1702 | rdr_log_dbg(reader, D_READER, "emm not suitable for our card %08X", b2i(4, &reader->sa[0][0]));
|
---|
1703 | return SKIPPED;
|
---|
1704 | }
|
---|
1705 | }
|
---|
1706 | // memorize
|
---|
1707 | nano9EData = emmParsed;
|
---|
1708 | }
|
---|
1709 | else if(emmParsed[0] == 0x81)
|
---|
1710 | {
|
---|
1711 | nano81Data = emmParsed;
|
---|
1712 | }
|
---|
1713 | else if(emmParsed[0] == 0x91 && emmParsed[1] == 0x08)
|
---|
1714 | {
|
---|
1715 | nano91Data = emmParsed;
|
---|
1716 | }
|
---|
1717 | else if(emmParsed[0] == 0x92 && emmParsed[1] == 0x08)
|
---|
1718 | {
|
---|
1719 | nano92Data = emmParsed;
|
---|
1720 | }
|
---|
1721 | else if(emmParsed[0] == 0xF0 && emmParsed[1] == 0x08)
|
---|
1722 | {
|
---|
1723 | nanoF0Data = emmParsed;
|
---|
1724 | }
|
---|
1725 | else if(emmParsed[0] == 0xF0 && emmParsed[1] == 0x10 && (emm_provid >> 8) == 0x0702)
|
---|
1726 | {
|
---|
1727 | nanoF0Data = emmParsed;
|
---|
1728 | }
|
---|
1729 | else if(emmParsed[0] == 0xD8 && emmParsed[2] == 0x45)
|
---|
1730 | {
|
---|
1731 | uint8_t pos = 4 + emmParsed[3];
|
---|
1732 | char *tmpbuf;
|
---|
1733 | if(emmParsed[pos] == 0x46 && ((emmParsed[pos+1] - emmParsed[1]) == pos))
|
---|
1734 | {
|
---|
1735 | if(cs_malloc(&tmpbuf, emmParsed[pos + 1]))
|
---|
1736 | {
|
---|
1737 | cs_strncpy(tmpbuf, (char *)emmParsed + pos + 2, emmParsed[pos + 1]);
|
---|
1738 | rdr_log(reader, "Viaccess EMM-text: %s", tmpbuf);
|
---|
1739 | NULLFREE(tmpbuf);
|
---|
1740 | }
|
---|
1741 | }
|
---|
1742 | }
|
---|
1743 | else
|
---|
1744 | {
|
---|
1745 | /* other nanos */
|
---|
1746 | show_subs(reader, emmParsed);
|
---|
1747 | if(emmParsed[0] == 0xA9 && ep->type == SHARED) // check on shared (reassembled) emm if all classes are present and up to date on card: error 90 40
|
---|
1748 | {
|
---|
1749 | if(!emm_provid)
|
---|
1750 | {
|
---|
1751 | rdr_log(reader, "no provid in shared emm -> skipped!");
|
---|
1752 | return SKIPPED;
|
---|
1753 | }
|
---|
1754 | int8_t match = add_find_class(reader, emm_provid, emmParsed + 2, emmParsed[1], 0);
|
---|
1755 | if(match == -2)
|
---|
1756 | {
|
---|
1757 | rdr_log(reader, "shared emm provid %06X all classes have entitlementdate already same or newer -> skipped!", emm_provid);
|
---|
1758 | return SKIPPED;
|
---|
1759 | }
|
---|
1760 | nanoA9Data = emmParsed;
|
---|
1761 | }
|
---|
1762 | memcpy(ins18Data + ins18Len, emmParsed, emmParsed[1] + 2);
|
---|
1763 | ins18Len += emmParsed [1] + 2;
|
---|
1764 | }
|
---|
1765 | }
|
---|
1766 | if(!provider_ok)
|
---|
1767 | {
|
---|
1768 | rdr_log_dbg(reader, D_READER, "provider not found in emm, continue anyway");
|
---|
1769 | // force key to 1...
|
---|
1770 | keynr = 1;
|
---|
1771 | ///return ERROR;
|
---|
1772 | }
|
---|
1773 | if(!nanoF0Data)
|
---|
1774 | {
|
---|
1775 | rdr_log_dump(reader, ep->emm, ep->emmlen, "can't find 0xf0 in emm...");
|
---|
1776 | return ERROR; // error
|
---|
1777 | }
|
---|
1778 | if(nano9EData)
|
---|
1779 | {
|
---|
1780 | if(!nano91Data)
|
---|
1781 | {
|
---|
1782 | // set adf
|
---|
1783 | insf0[3] = keynr; // key
|
---|
1784 | insf0[4] = nano9EData[1] + 2;
|
---|
1785 | write_cmd(insf0, nano9EData);
|
---|
1786 | if(cta_res[cta_lr - 2] != 0x90 || cta_res[cta_lr - 1] != 0x00)
|
---|
1787 | {
|
---|
1788 | rdr_log_dump(reader, insf0, 5, "set adf cmd:");
|
---|
1789 | rdr_log_dump(reader, nano9EData, insf0[4] , "set adf data:");
|
---|
1790 | rdr_log(reader, "update error: %02X %02X", cta_res[cta_lr - 2], cta_res[cta_lr - 1]);
|
---|
1791 | return ERROR;
|
---|
1792 | }
|
---|
1793 | }
|
---|
1794 | else
|
---|
1795 | {
|
---|
1796 | // set adf crypte
|
---|
1797 | insf4[3] = keynr; // key
|
---|
1798 | insf4[4] = nano91Data[1] + 2 + nano9EData[1] + 2;
|
---|
1799 | memcpy(insData, nano91Data, nano91Data[1] + 2);
|
---|
1800 | memcpy(insData + nano91Data[1] + 2, nano9EData, nano9EData[1] + 2);
|
---|
1801 | write_cmd(insf4, insData);
|
---|
1802 | if((cta_res[cta_lr - 2] != 0x90 && cta_res[cta_lr - 2] != 0x91) || cta_res[cta_lr - 1] != 0x00)
|
---|
1803 | {
|
---|
1804 | rdr_log_dump(reader, insf4, 5, "set adf encrypted cmd:");
|
---|
1805 | rdr_log_dump(reader, insData, insf4[4], "set adf encrypted data:");
|
---|
1806 | rdr_log(reader, "update error: %02X %02X", cta_res[cta_lr - 2], cta_res[cta_lr - 1]);
|
---|
1807 | return ERROR;
|
---|
1808 | }
|
---|
1809 | }
|
---|
1810 | }
|
---|
1811 | if(!nano92Data)
|
---|
1812 | {
|
---|
1813 | // send subscription
|
---|
1814 | ins18[2] = nano9EData ? 0x01 : 0x00; // found 9E nano ?
|
---|
1815 | ins18[3] = keynr; // key
|
---|
1816 | ins18[4] = ins18Len + nanoF0Data[1] + 2;
|
---|
1817 | memcpy(insData, ins18Data, ins18Len);
|
---|
1818 | memcpy(insData + ins18Len, nanoF0Data, nanoF0Data[1] + 2);
|
---|
1819 | write_cmd(ins18, insData);
|
---|
1820 | if((cta_res[cta_lr - 2] == 0x90 || cta_res[cta_lr - 2] == 0x91) && cta_res[cta_lr - 1] == 0x00)
|
---|
1821 | {
|
---|
1822 | if(nanoA9Data)
|
---|
1823 | {
|
---|
1824 | add_find_class(reader, emm_provid, nanoA9Data + 2, nanoA9Data[1], 1);
|
---|
1825 | rdr_log(reader, "Your subscription data was updated.");
|
---|
1826 | }
|
---|
1827 | rc = 1; // written
|
---|
1828 | }
|
---|
1829 | else
|
---|
1830 | {
|
---|
1831 | rdr_log_dump(reader, ins18, 5, "set subscription cmd:");
|
---|
1832 | rdr_log_dump(reader, insData, ins18[4], "set subscription data:");
|
---|
1833 | if(!(cta_res[cta_lr -2] == 0x90 && cta_res[cta_lr - 1] == 0x40)) // dont throw softerror 9040 in log!
|
---|
1834 | {
|
---|
1835 | rdr_log(reader, "update error: %02X %02X", cta_res[cta_lr - 2], cta_res[cta_lr - 1]);
|
---|
1836 | }
|
---|
1837 | else
|
---|
1838 | {
|
---|
1839 | rc = 2; // skipped
|
---|
1840 | }
|
---|
1841 | }
|
---|
1842 | }
|
---|
1843 | else
|
---|
1844 | {
|
---|
1845 | // send subscription encrypted
|
---|
1846 | if(!nano81Data)
|
---|
1847 | {
|
---|
1848 | rdr_log_dump(reader, ep->emm, ep->emmlen, "0x92 found, but can't find 0x81 in emm...");
|
---|
1849 | return ERROR; // error
|
---|
1850 | }
|
---|
1851 | ins1c[2] = nano9EData ? 0x01 : 0x00; // found 9E nano ?
|
---|
1852 | if(ep->type == UNIQUE)
|
---|
1853 | {
|
---|
1854 | ins1c[2] = 0x02;
|
---|
1855 | }
|
---|
1856 | ins1c[3] = keynr; // key
|
---|
1857 | ins1c[4] = nano92Data[1] + 2 + nano81Data[1] + 2 + nanoF0Data[1] + 2;
|
---|
1858 | memcpy(insData, nano92Data, nano92Data[1] + 2);
|
---|
1859 | memcpy(insData + nano92Data[1] + 2, nano81Data, nano81Data[1] + 2);
|
---|
1860 | memcpy(insData + nano92Data[1] + 2 + nano81Data[1] + 2, nanoF0Data, nanoF0Data[1] + 2);
|
---|
1861 | write_cmd(ins1c, insData);
|
---|
1862 | if((cta_res[cta_lr - 2] == 0x90 || cta_res[cta_lr - 2] == 0x91) && (cta_res[cta_lr - 1] == 0x00 || cta_res[cta_lr - 1] == 0x08))
|
---|
1863 | {
|
---|
1864 | rdr_log(reader, "update successfully written");
|
---|
1865 | }
|
---|
1866 | if(cta_res[cta_lr - 2] == 0x98 && cta_res[cta_lr - 1] == 0x00 )
|
---|
1867 | {
|
---|
1868 | static const uint8_t insFAC[] = { 0x87, 0x02, 0x00, 0x00, 0x03 }; // init FAC
|
---|
1869 | static uint8_t ins8702_data[] = { 0x00, 0x00, 0x11};
|
---|
1870 | static uint8_t ins8704[] = { 0x87, 0x04, 0x00, 0x00, 0x07 };
|
---|
1871 | static uint8_t ins8706[] = { 0x87, 0x06, 0x00, 0x00, 0x04 };
|
---|
1872 | write_cmd(insFAC, ins8702_data);
|
---|
1873 | if((cta_res[cta_lr - 2] == 0x90) && (cta_res[cta_lr - 1] == 0x00))
|
---|
1874 | {
|
---|
1875 | write_cmd(ins8704, NULL);
|
---|
1876 | if((cta_res[cta_lr - 2] == 0x90) && (cta_res[cta_lr - 1] == 0x00))
|
---|
1877 | {
|
---|
1878 | write_cmd(ins8706, NULL);
|
---|
1879 | if((cta_res[cta_lr - 2] == 0x90) && (cta_res[cta_lr - 1] == 0x00))
|
---|
1880 | {
|
---|
1881 | csystem_data->last_geo.number_ecm = (cta_res[2] << 8) | (cta_res[3]);
|
---|
1882 | rdr_log(reader, "using ecm #%x for long viaccess ecm", csystem_data->last_geo.number_ecm);
|
---|
1883 | }
|
---|
1884 | }
|
---|
1885 | }
|
---|
1886 | }
|
---|
1887 | rc = 1;
|
---|
1888 | }
|
---|
1889 | return rc;
|
---|
1890 | }
|
---|
1891 | static int32_t viaccess_card_info(struct s_reader *reader)
|
---|
1892 | {
|
---|
1893 | def_resp;
|
---|
1894 | int32_t i, l;
|
---|
1895 | time_t now;
|
---|
1896 | struct tm timeinfo;
|
---|
1897 | uint16_t tmpdate;
|
---|
1898 | uint8_t insac[] = { 0xca, 0xac, 0x00, 0x00, 0x00 }; // select data
|
---|
1899 | uint8_t insb8[] = { 0xca, 0xb8, 0x00, 0x00, 0x00 }; // read selected data
|
---|
1900 | uint8_t insa4[] = { 0xca, 0xa4, 0x00, 0x00, 0x00 }; // select issuer
|
---|
1901 | uint8_t insc0[] = { 0xca, 0xc0, 0x00, 0x00, 0x00 }; // read data item
|
---|
1902 | static const uint8_t ins24[] = { 0xca, 0x24, 0x00, 0x00, 0x09 }; // set pin
|
---|
1903 | uint8_t cls[] = { 0x00, 0x21, 0xff, 0x9f};
|
---|
1904 | uint8_t prebook[] = {0x00,0x00,0x00,0xFF,0xFF,0xFF };
|
---|
1905 | static const uint8_t pin[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04};
|
---|
1906 | struct viaccess_data *csystem_data = reader->csystem_data;
|
---|
1907 | csystem_data->last_geo.provid = 0;
|
---|
1908 | csystem_data->last_geo.geo_len = 0;
|
---|
1909 | csystem_data->last_geo.geo[0] = 0;
|
---|
1910 | rdr_log(reader, "card detected");
|
---|
1911 | cs_clear_entitlement(reader); //reset the entitlements
|
---|
1912 | // set pin
|
---|
1913 | write_cmd(ins24, pin);
|
---|
1914 | insac[2] = 0xa4;
|
---|
1915 | write_cmd(insac, NULL); // request unique id
|
---|
1916 | insb8[4] = 0x07;
|
---|
1917 | write_cmd(insb8, NULL); // read unique id
|
---|
1918 | rdr_log_sensitive(reader, "serial: {%llu}", (unsigned long long) b2ll(5, cta_res + 2));
|
---|
1919 | insa4[2] = 0x00;
|
---|
1920 | write_cmd(insa4, NULL); // select issuer 0
|
---|
1921 | for(i = 1; (cta_res[cta_lr - 2] == 0x90) && (cta_res[cta_lr - 1] == 0); i++)
|
---|
1922 | {
|
---|
1923 | bool added = false;
|
---|
1924 | uint32_t l_provid, l_sa;
|
---|
1925 | uint8_t l_name[64];
|
---|
1926 | insc0[4] = 0x1a;
|
---|
1927 | write_cmd(insc0, NULL); // show provider properties
|
---|
1928 | cta_res[2] &= 0xF0;
|
---|
1929 | l_provid = b2i(3, cta_res);
|
---|
1930 | insac[2] = 0xa5;
|
---|
1931 | write_cmd(insac, NULL); // request sa
|
---|
1932 | insb8[4] = 0x06;
|
---|
1933 | write_cmd(insb8, NULL); // read sa
|
---|
1934 | l_sa = b2i(4, cta_res + 2);
|
---|
1935 | insac[2] = 0xa7;
|
---|
1936 | write_cmd(insac, NULL); // request name
|
---|
1937 | insb8[4] = 0x02;
|
---|
1938 | write_cmd(insb8, NULL); // read name nano + len
|
---|
1939 | l = cta_res[1];
|
---|
1940 | insb8[4] = l;
|
---|
1941 | write_cmd(insb8, NULL); // read name
|
---|
1942 | cta_res[l] = 0;
|
---|
1943 | trim((char *)cta_res);
|
---|
1944 | if(cta_res[0])
|
---|
1945 | {
|
---|
1946 | snprintf((char *)l_name, sizeof(l_name), ", name: %.55s", cta_res);
|
---|
1947 | }
|
---|
1948 | else
|
---|
1949 | {
|
---|
1950 | l_name[0] = 0;
|
---|
1951 | }
|
---|
1952 | // read GEO
|
---|
1953 | insac[2] = 0xa6;
|
---|
1954 | write_cmd(insac, NULL); // request GEO
|
---|
1955 | insb8[4] = 0x02;
|
---|
1956 | write_cmd(insb8, NULL); // read GEO nano + len
|
---|
1957 | l = cta_res[1];
|
---|
1958 | char tmp[l * 3 + 1];
|
---|
1959 | insb8[4] = l;
|
---|
1960 | write_cmd(insb8, NULL); // read geo
|
---|
1961 | rdr_log_sensitive(reader, "provider: %d, id: {%06X%s}, sa: {%08X}, geo: %s", i, l_provid, l_name, l_sa, (l < 4) ? "empty" : cs_hexdump(1, cta_res, l, tmp, sizeof(tmp)));
|
---|
1962 | // read classes subscription
|
---|
1963 | insac[2] = 0xa9;
|
---|
1964 | insac[4] = 4;
|
---|
1965 | if(!reader->read_old_classes)
|
---|
1966 | {
|
---|
1967 | now = time(NULL) - (24*60*60);
|
---|
1968 | cs_gmtime_r(&now, &timeinfo);
|
---|
1969 | tmpdate = timeinfo.tm_mday | ((timeinfo.tm_mon + 1) << 5) | ((timeinfo.tm_year - 80) << 9);
|
---|
1970 | cls[0] = tmpdate >> 8;
|
---|
1971 | cls[1] = tmpdate & 0xff;
|
---|
1972 | }
|
---|
1973 | write_cmd(insac, cls); // request class subs
|
---|
1974 | while((cta_res[cta_lr - 2] == 0x90) && (cta_res[cta_lr - 1] == 0))
|
---|
1975 | {
|
---|
1976 | insb8[4] = 0x02;
|
---|
1977 | write_cmd(insb8, NULL); // read class subs nano + len
|
---|
1978 | if((cta_res[cta_lr - 2] == 0x90) && (cta_res[cta_lr - 1] == 0))
|
---|
1979 | {
|
---|
1980 | l = cta_res[1];
|
---|
1981 | insb8[4] = l;
|
---|
1982 | write_cmd(insb8, NULL); // read class subs
|
---|
1983 | if((cta_res[cta_lr - 2] == 0x90) && (cta_res[cta_lr - 1] == 0x00 || cta_res[cta_lr - 1] == 0x08))
|
---|
1984 | {
|
---|
1985 | show_class(reader, NULL, l_provid, cta_res, cta_lr - 2);
|
---|
1986 | added = true;
|
---|
1987 | }
|
---|
1988 | }
|
---|
1989 | }
|
---|
1990 | if(!added)
|
---|
1991 | {
|
---|
1992 | // add entitlement info for provid without class
|
---|
1993 | cs_add_entitlement(reader, reader->caid, l_provid, 0, 0, 0, 0, 5, 1);
|
---|
1994 | }
|
---|
1995 | // Read List of «pre-booked pay-per-view per programme» entitlements within the range [INUMB, FNUMB]
|
---|
1996 | insac[2] = 0xaa;
|
---|
1997 | insac[4] = 6;
|
---|
1998 | write_cmd(insac, prebook ); // request class subs
|
---|
1999 | while((cta_res[cta_lr - 2] == 0x90) && (cta_res[cta_lr - 1] == 0x00))
|
---|
2000 | {
|
---|
2001 | insb8[4] = 0x08;
|
---|
2002 | write_cmd(insb8, NULL); // read PVV
|
---|
2003 | if((cta_res[cta_lr - 2] == 0x90) && (cta_res[cta_lr - 1] == 0))
|
---|
2004 | {
|
---|
2005 | l = cta_res[1];
|
---|
2006 | write_cmd(insb8, NULL); // read PPV
|
---|
2007 | if((cta_res[cta_lr - 2] == 0x90) && (cta_res[cta_lr - 1] == 0x00 || cta_res[cta_lr - 1] == 0x08))
|
---|
2008 | {
|
---|
2009 | cs_add_entitlement(reader, reader->caid, l_provid, b2i(3, cta_res+2), 0 , 0, 0, 2, 1);
|
---|
2010 | cs_add_entitlement(reader, reader->caid, l_provid, b2i(3, cta_res+5), 0 , 0, 0, 2, 1);
|
---|
2011 | }
|
---|
2012 | }
|
---|
2013 | }
|
---|
2014 | insac[4] = 0;
|
---|
2015 | insa4[2] = 0x02;
|
---|
2016 | write_cmd(insa4, NULL); // select next provider
|
---|
2017 | }
|
---|
2018 | //return ERROR;
|
---|
2019 | // Start process init CA 28
|
---|
2020 | reader->initCA28=0;
|
---|
2021 | int32_t lenboxkey = reader->boxkey_length;
|
---|
2022 | int32_t lendeskey = reader->des_key_length;
|
---|
2023 | if ((lenboxkey >= 4) && (lendeskey > 0))
|
---|
2024 | {
|
---|
2025 | uint8_t ins28[] = { 0xCA, 0x28, 0x00, 0x00, 0x04 }; //Init for nanoE0 ca28
|
---|
2026 | ins28[4] = (uint8_t) lenboxkey;
|
---|
2027 | uint8_t ins28_data[4];
|
---|
2028 | memcpy(ins28_data, reader->boxkey, 4);
|
---|
2029 | write_cmd(ins28, ins28_data); // unlock card to reply on E002xxyy
|
---|
2030 | if((cta_res[cta_lr - 2] == 0x90) && (cta_res[cta_lr - 1] == 0))
|
---|
2031 | {
|
---|
2032 | rdr_log(reader, "CA 28 initialisation successful!");
|
---|
2033 | // init 3DES key
|
---|
2034 | des_set_key(reader->des_key, reader->key_schedule1);
|
---|
2035 | des_set_key(reader->des_key+8, reader->key_schedule2);
|
---|
2036 | reader->initCA28=1;
|
---|
2037 | }
|
---|
2038 | else
|
---|
2039 | {
|
---|
2040 | rdr_log(reader, "CA 28 initialisation failed! CA 28 refused");
|
---|
2041 | }
|
---|
2042 | }
|
---|
2043 | //end process init CA 28
|
---|
2044 | return OK;
|
---|
2045 | }
|
---|
2046 | static int32_t viaccess_reassemble_emm(struct s_reader *rdr, struct s_client *client, EMM_PACKET *ep)
|
---|
2047 | {
|
---|
2048 | uint8_t *buffer = ep->emm;
|
---|
2049 | int16_t *len = &ep->emmlen;
|
---|
2050 | int32_t pos = 0, i;
|
---|
2051 | int16_t k;
|
---|
2052 | int32_t prov, provid = 0;
|
---|
2053 | struct emm_rass *r_emm = NULL;
|
---|
2054 | // Viaccess
|
---|
2055 | if(*len > 500)
|
---|
2056 | {
|
---|
2057 | return 0;
|
---|
2058 | }
|
---|
2059 | switch(buffer[0])
|
---|
2060 | {
|
---|
2061 | case 0x8c:
|
---|
2062 | case 0x8d:
|
---|
2063 | // emm-s part 1
|
---|
2064 | provid = b2i(3, ep->emm + 5); // extract provid from emm
|
---|
2065 | provid &= 0xFFFFF0; // last digit is dont care
|
---|
2066 | r_emm = find_rabuf(client, provid, (uint8_t) buffer[0], 1);
|
---|
2067 | if(!r_emm)
|
---|
2068 | {
|
---|
2069 | cs_log("[viaccess] ERROR: Can't allocate EMM reassembly buffer.");
|
---|
2070 | return 0;
|
---|
2071 | }
|
---|
2072 | if(!memcmp(&r_emm->emm, &buffer[0], *len)) // skip same shared emm, this make sure emmlen isnt replaced. emmlen = 0 means this shared emm has been used for reassembly
|
---|
2073 | {
|
---|
2074 | return 0;
|
---|
2075 | }
|
---|
2076 | memset(&r_emm->emm[0], 0, sizeof(r_emm->emm)); // zero it!
|
---|
2077 | memcpy(&r_emm->emm[0], &buffer[0], *len); // put the fresh new shared emm
|
---|
2078 | r_emm->emmlen = *len; // put the emmlen indicating that this shared emm isnt being reassembled
|
---|
2079 | rdr_log_dump_dbg(rdr, D_EMM, r_emm->emm, r_emm->emmlen, "%s: received fresh emm-gh for provid %06X", __func__, provid);
|
---|
2080 | return 0;
|
---|
2081 | case 0x8e:
|
---|
2082 | // emm-s part 2
|
---|
2083 | for(prov = 0; prov < rdr->nprov ; prov++)
|
---|
2084 | {
|
---|
2085 | if(!memcmp(&buffer[3], &rdr->sa[prov][0], 3))
|
---|
2086 | {
|
---|
2087 | //matching sa found!
|
---|
2088 | if(is_network_reader(rdr))
|
---|
2089 | {
|
---|
2090 | provid = b2i(4, ep->provid); // use provid from emm since we have nothing better!
|
---|
2091 | provid &= 0xFFFFF0; // last digit is dont care
|
---|
2092 | }
|
---|
2093 | else
|
---|
2094 | {
|
---|
2095 | provid = b2i(4, rdr->prid[prov]); // get corresponding provid from reader since there is no provid in emm payload!
|
---|
2096 | provid &= 0xFFFFF0; // last digit is dont care
|
---|
2097 | }
|
---|
2098 | r_emm = find_rabuf(client, provid, 0, 0); // nano = don't care, the shared 8c or 8d not been written gets returned!
|
---|
2099 | if(!r_emm || !r_emm->emmlen)
|
---|
2100 | {
|
---|
2101 | continue; // match but no emm-gh found for this provider
|
---|
2102 | }
|
---|
2103 | else
|
---|
2104 | {
|
---|
2105 | break; // stop searching-> emm-gh found!
|
---|
2106 | }
|
---|
2107 | }
|
---|
2108 | }
|
---|
2109 | if(!r_emm || !r_emm->emmlen)
|
---|
2110 | {
|
---|
2111 | return 0; // stop -> no emm-gh found!
|
---|
2112 | }
|
---|
2113 | //extract nanos from emm-gh and emm-s
|
---|
2114 | uint8_t emmbuf[512];
|
---|
2115 | rdr_log_dbg(rdr, D_EMM, "%s: start extracting nanos", __func__);
|
---|
2116 | //extract from emm-gh
|
---|
2117 | for(i = 3; i < r_emm->emmlen; i += r_emm->emm[i + 1] + 2)
|
---|
2118 | {
|
---|
2119 | //copy nano (length determined by i+1)
|
---|
2120 | memcpy(emmbuf + pos, r_emm->emm + i, r_emm->emm[i + 1] + 2);
|
---|
2121 | pos += r_emm->emm[i + 1] + 2;
|
---|
2122 | }
|
---|
2123 | if(buffer[2] == 0x2c)
|
---|
2124 | {
|
---|
2125 | //add 9E 20 nano + first 32 uint8_ts of emm content
|
---|
2126 | memcpy(emmbuf + pos, "\x9E\x20", 2);
|
---|
2127 | memcpy(emmbuf + pos + 2, buffer + 7, 32);
|
---|
2128 | pos += 34;
|
---|
2129 | //add F0 08 nano + 8 subsequent uint8_ts of emm content
|
---|
2130 | memcpy(emmbuf + pos, "\xF0\x08", 2);
|
---|
2131 | memcpy(emmbuf + pos + 2, buffer + 39, 8);
|
---|
2132 | pos += 10;
|
---|
2133 | }
|
---|
2134 | else if(buffer[2] == 0x34 && (provid >> 8) == 0x0702)
|
---|
2135 | {
|
---|
2136 | //add 9E 20 nano + first 32 uint8_ts of emm content
|
---|
2137 | memcpy(emmbuf + pos, "\x9E\x20", 2);
|
---|
2138 | memcpy(emmbuf + pos + 2, buffer + 7, 32);
|
---|
2139 | pos += 34;
|
---|
2140 | //add F0 10 nano + 16 subsequent uint8_ts of emm content
|
---|
2141 | memcpy(emmbuf + pos, "\xF0\x10", 2);
|
---|
2142 | memcpy(emmbuf + pos + 2, buffer + 39, 16);
|
---|
2143 | pos += 18;
|
---|
2144 | }
|
---|
2145 | else
|
---|
2146 | {
|
---|
2147 | //extract from variable emm-s
|
---|
2148 | for(k = 7; k < (*len); k += buffer[k + 1] + 2)
|
---|
2149 | {
|
---|
2150 | //copy nano (length determined by k+1)
|
---|
2151 | memcpy(emmbuf + pos, buffer + k, buffer[k + 1] + 2);
|
---|
2152 | pos += buffer[k + 1] + 2;
|
---|
2153 | }
|
---|
2154 | }
|
---|
2155 | rdr_log_dump_dbg(rdr, D_EMM, buffer, *len, "%s: %s emm-s", __func__, (buffer[2] == 0x2c) ? "fixed" : "variable");
|
---|
2156 | emm_sort_nanos(buffer + 7, emmbuf, pos);
|
---|
2157 | pos += 7;
|
---|
2158 | //calculate emm length and set it on position 2
|
---|
2159 | buffer[2] = pos - 3;
|
---|
2160 | rdr_log_dump_dbg(rdr, D_EMM, r_emm->emm, r_emm->emmlen, "%s: emm-gh provid %06X", __func__, provid);
|
---|
2161 | rdr_log_dump_dbg(rdr, D_EMM, buffer, pos, "%s: assembled emm", __func__);
|
---|
2162 | *len = pos;
|
---|
2163 | r_emm->emmlen = 0; // mark this shared 8c or 8d as being used for reassembly and send to reader!
|
---|
2164 | break;
|
---|
2165 | }
|
---|
2166 | return 1;
|
---|
2167 | }
|
---|
2168 | const struct s_cardsystem reader_viaccess =
|
---|
2169 | {
|
---|
2170 | .desc = "viaccess",
|
---|
2171 | .caids = (uint16_t[]){ 0x05, 0 },
|
---|
2172 | .do_emm_reassembly = viaccess_reassemble_emm,
|
---|
2173 | .do_emm = viaccess_do_emm,
|
---|
2174 | .do_ecm = viaccess_do_ecm,
|
---|
2175 | .card_info = viaccess_card_info,
|
---|
2176 | .card_init = viaccess_card_init,
|
---|
2177 | .get_emm_type = viaccess_get_emm_type,
|
---|
2178 | .get_emm_filter = viaccess_get_emm_filter,
|
---|
2179 | };
|
---|
2180 | #endif
|
---|