- fix Building without Nagra not possible at Nagra_Merlin https://trac.streamboard...
[oscam.git] / reader-viaccess.c
blobdbf916e73399ff30b2c2da2d9bc15b17bd6a9e98
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)
24 return (number >> bt ) & 1;
26 void SBitslice(uint* Iarray, int offsetin, uint* Oarray, int offsetout, int row, char* box)
28 int bi,input,l,output;
29 uint calcArray[4] = {0,0,0,0};
30 for (bi = 0; bi < 32; bi++)
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;
39 for (l = 0; l < 4; l++)
40 Oarray[l+offsetout] = calcArray[l];
42 void xorBlock(uint* data, int offset)
44 int i;
45 for (i = 0; i < 4; i++)
46 data[i] ^= KeyS[i + 4*offset];
48 uint rotr(uint val, int nbits)
50 return ((val >> nbits) + (val << (32 - nbits)));
52 void LTBitsliceInverse(uint* data)
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;
73 void N98_decrypt(byte* data)
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
82 if (r == 31) {
83 xorBlock(N98,32);
84 } else {
85 LTBitsliceInverse(N98); // inverse Linear Transform
87 SBitslice(N98,0,N98,0, (r & 7), SBoxInverse); // SBox inverse, bitslice mode
88 xorBlock(N98, r);
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;
94 void MakeSubKeys(uint* KeySch, char key98Idx)
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
104 for(j = 0; j < 16; j++) // search for column
106 k=0;
107 while (SBoxInverse[k+16*i] != j)
108 k = k +1;
109 Sbox[j+16*i] = k;
112 switch (key98Idx)
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;
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
123 struct geo_cache
125 uint32_t provid;
126 uint8_t geo[256];
127 uint8_t geo_len;
128 int32_t number_ecm;
130 struct viaccess_data
132 struct geo_cache last_geo;
133 uint8_t availkeys[CS_MAXPROV][16];
135 struct via_date
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;
144 static void parse_via_date(const uint8_t *buf, struct via_date *vd, int32_t fend)
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)
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;
159 struct emm_rass *find_rabuf(struct s_client *client, int32_t provid, uint8_t nano, int8_t add)
161 struct emm_rass *e;
162 LL_ITER it;
163 if(!client->ra_buf)
165 client->ra_buf = ll_create("client->ra_buf");
167 it = ll_iter_create(client->ra_buf);
168 while((e = ll_iter_next(&it)) != NULL)
170 if(!add && e->provid == provid && e->emmlen != 0)
172 return e;
174 if(add && e->provid == provid && e->emm[0] == nano)
176 return e;
179 if(!add)
181 return NULL;
183 if(!cs_malloc(&e, sizeof(struct emm_rass)))
185 return NULL;
187 e->provid = provid;
188 ll_append(client->ra_buf, e);
189 return e;
191 static void show_class(struct s_reader *reader, const char *p, uint32_t provid, const uint8_t *b, int32_t l)
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--)
200 for(i = 0; i < 8; i++)
202 if(b[j] & (1 << (i & 7)))
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!
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);
214 else
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);
237 static int8_t add_find_class(struct s_reader *reader, uint32_t provid, const uint8_t *b, int32_t l, int8_t add)
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--)
246 for(i = 0; i < 8; i++)
248 if(b[j] & (1 << (i & 7)))
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)
254 rdr_log(reader, "provid %06X class %02X not found", provid, cls);
255 freshdate = 1;
257 else
259 if(!add)
261 rdr_log(reader, "provid %06X has matching class %02X", provid, cls);
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);
278 if(cs_add_entitlement(reader, reader->caid, provid, cls, cls, start_t, end_t, 5, add) != NULL)
280 if(!add)
282 rdr_log(reader, "class %02X provid %06X has already this daterange or newer entitled", cls, provid);
285 else
287 freshdate = 1;
293 if(freshdate == 0)
295 return -2;
297 return 1; // emmdate is fresh!
299 static void show_subs(struct s_reader *reader, const uint8_t *emm)
301 switch(emm[0])
303 case 0xA9:
305 show_class(reader, "nano A9: ", 1, emm + 2, emm[1]);
306 break;
308 case 0xA6:
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;
316 case 0xB6:
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;
334 static int32_t chk_prov(struct s_reader *reader, uint8_t *id, uint8_t keynr)
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++)
340 if(!memcmp(&reader->prid[i][1], id, 3))
342 for(j = 0; (!rc) && (j < 16); j++)
344 if(csystem_data->availkeys[i][j] == keynr)
346 rc = 1;
351 return (rc);
353 static int32_t get_maturity(struct s_reader *reader)
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)
368 rdr_log(reader, "Maturity level [%X]= older than %i years", reader->maturity, reader->maturity);
370 else
372 rdr_log(reader, "Maturity level [%X]=no age limit", reader->maturity);
374 return 0;
376 static int32_t unlock_parental(struct s_reader *reader)
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"))
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);
389 else
391 rdr_log(reader, "Using PIN 0000!");
393 write_cmd(inDPL, cmDPL);
394 if(!(cta_res[cta_lr - 2] == 0x90 && cta_res[cta_lr - 1] == 0))
396 if(strcmp(reader->pincode, "none"))
398 rdr_log(reader, "Can't disable parental lock. Wrong PIN? OSCam used %s!", reader->pincode);
400 else
402 rdr_log(reader, "Can't disable parental lock. Wrong PIN? OSCam used 0000!");
405 else
407 rdr_log(reader, "Parental lock disabled");
408 get_maturity(reader);
410 return 0;
412 int32_t hdSurEncBasicCrypt_D2_0F_11(int32_t Value, int32_t XorVal)
414 int32_t i = (Value << 13) - Value + 0x1B59;
415 i = (i * Value) + 0x07CF;
416 return (i ^ XorVal);
418 int32_t hdSurEncCryptLookup_D2_0F_11(uint8_t Value, uint8_t AddrInd)
420 static const uint8_t lookup[] =
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
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]));
586 void hdSurEncPhase1_D2_0F_11(uint8_t *CWs)
588 static const uint8_t lookup1[] =
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
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)
600 for(j = 0; j <= 15; ++j)
602 CWs[j] = CWs[j] ^ hdSurEncBasicCrypt_D2_0F_11(j , lookup1 [(16 * i) + j]);
604 uint8_t Buffer[16];
605 uint32_t k;
606 for(i1 = 0; i1 <= 3; ++i1)
608 for(i2 = 0; i2 <= 3; ++i2)
610 k = 0;
611 for(i3 = 0; i3 <= 3; ++i3)
613 k = k + (CWs[(i2 * 4) + i3] * lookup2[(i3 * 4) + i1]);
614 Buffer[(i2 * 4) + i1] = (uint8_t)k;
618 memcpy(CWs, Buffer, 16);
619 // CW positions are mixed around here
620 uint8_t a4[4];
621 for(i1 = 1; i1 <= 3; ++i1)
623 for(i2 = 0; i2 <= 3; ++i2)
625 a4[i2] = i1 + (i2 * 4);
627 for(i2 = 0; i2 <= i1 - 1; ++i2) // the given code in Func1_3 seems to be wrong here(3 instead of i1-1)!
629 uint8_t tmp = CWs[a4[0]];
630 for(i3 = 1; i3 <= 3; ++i3)
632 CWs[a4[i3 - 1]] = CWs[a4[i3]];
634 CWs[a4[3]] = tmp;
637 for(i1 = 0; i1 <= 15; ++i1)
639 CWs[i1] = hdSurEncCryptLookup_D2_0F_11(CWs[i1], CAddrIndex[i1 & 3]);
643 void hdSurEncPhase2_D2_0F_11_sub(uint8_t *CWa, uint8_t *CWb, uint8_t AddrInd)
645 uint8_t Buffer[8];
646 uint8_t tmp, i;
647 for(i = 0; i <= 7; ++i)
649 Buffer[i] = hdSurEncCryptLookup_D2_0F_11(CWb[i], AddrInd);
651 // some bitshifting
652 tmp = Buffer[7];
653 for(i = 7; i >= 1; --i)
655 Buffer[i] = ((Buffer[1] >> 4) & 0xFF) | ((Buffer[i - 1] << 4) & 0xFF);
657 Buffer[0] = ((Buffer[0] >> 4) & 0xFF) | ((tmp << 4) & 0xFF);
658 // saving the result
659 for(i = 0; i <= 7; ++i)
661 CWa[i] = CWa[i] ^ Buffer[i];
664 void hdSurEncPhase2_D2_0F_11(uint8_t *CWs)
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);
672 void CommonMain_1_D2_13_15(const uint8_t *datain, uint8_t *dataout)
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++)
685 bb = 0;
686 for (i2 = 0; i2 < 8; i2++)
688 bb += (Tab3[(i1 * 8) + i2] * datain[i2]);
690 dataout[i1] = (bb & 0xFF);
693 unsigned short CommonMain_2_D2_13_15(const uint8_t *data, const unsigned long num)
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);
700 void CommonMain_3_D2_13_15(uint8_t *data0, uint8_t *data1, int nbrloop)
702 int i;
703 unsigned long bb1, bb2;
704 bb1 = 0;
705 bb2 = 0;
706 for (i = nbrloop - 1; i >= 0; i--)
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;
716 void CommonMain_D2_13_15(const uint8_t *datain, uint8_t *dataout, int loopval)
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++)
861 buff11[i1] ^= Tab1_Comp[(loopval * 11) + i1];
863 for (i1 = 0; i1 < 8; i1++)
865 buff8[i1] = CommonMain_2_D2_13_15(buff11, i1 * 11);
867 for (i1 = 0; i1 < 8; i1++)
869 dataout[i1] = Tab0_Comp[buff8[i1]];
871 i1 = 1;
872 while (i1 < 8)
874 i2 = 0 ;
875 while (i2 < 8)
877 CommonMain_3_D2_13_15(&dataout[i2], &dataout[i1 + i2], i1);
878 i2 += (i1 * 2);
880 i1 *= 2;
883 void Common_D2_13_15(uint8_t *cw0, const uint8_t *cw1, int loopval)
885 int i;
886 uint8_t buff8[8];
887 CommonMain_D2_13_15(cw1, buff8, loopval);
888 for (i = 0; i < 8; i++)
890 cw0[i] ^= buff8[i];
893 void ExchangeCWs(uint8_t *cw0, uint8_t *cw1)
895 int i;
896 uint8_t b;
897 for (i = 0; i < 8; i++)
899 b = cw1[i];
900 cw1[i] = cw0[i];
901 cw0[i] = b;
904 void hdSurEncPhase1_D2_13_15(uint8_t *cws)
906 int i;
907 for (i = 0; i <= 7; i++)
909 // Possible code
910 if ((i & 1) == 0)
912 Common_D2_13_15((uint8_t *) &cws[0], (uint8_t *) &cws[8], i);
914 else
916 Common_D2_13_15((uint8_t *) &cws[8], (uint8_t *) &cws[0], i);
919 ExchangeCWs((uint8_t *) &cws[0], (uint8_t *) &cws[8]);
921 void hdSurEncPhase2_D2_13_15(uint8_t *cws)
923 int i;
924 for (i = 7; i >= 0; i--)
926 // Possible code
927 if ((i & 1) == 0)
929 Common_D2_13_15((uint8_t *) &cws[8], (uint8_t *) &cws[0], i);
931 else
933 Common_D2_13_15((uint8_t *) &cws[0], (uint8_t *) &cws[8], i);
936 ExchangeCWs((uint8_t *) &cws[8], (uint8_t *) &cws[0]);
938 static int32_t viaccess_card_init(struct s_reader *reader, ATR *newatr)
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)))
955 return ERROR;
957 write_cmd(insFAC, FacDat);
958 if(!(cta_res[cta_lr - 2] == 0x90 && cta_res[cta_lr - 1] == 0))
960 return ERROR;
962 if(!cs_malloc(&reader->csystem_data, sizeof(struct viaccess_data)))
964 return ERROR;
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))
970 write_cmd(ins8704, NULL);
971 if((cta_res[cta_lr - 2] == 0x90) && (cta_res[cta_lr - 1] == 0x00))
973 write_cmd(ins8706, NULL);
974 if((cta_res[cta_lr - 2] == 0x90) && (cta_res[cta_lr - 1] == 0x00))
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);
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))
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++;
1014 reader->nprov = i;
1015 rdr_log(reader, "providers: %d (%s)", reader->nprov, buf + 1);
1016 get_maturity(reader);
1017 if(cfg.ulparent)
1019 unlock_parental(reader);
1021 rdr_log(reader, "ready for requests");
1022 return OK;
1024 bool dcw_crc(uint8_t *dw)
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;
1030 static int32_t viaccess_do_ecm(struct s_reader *reader, const ECM_REQUEST *er, struct s_ecm_answer *ea)
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)
1042 rdr_log(reader, "ECM: Size of ECM couldn't be correctly calculated.");
1043 return ERROR;
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)
1070 if(ecm88Data[0] == 0x00 && ecm88Data[1] == 0x00)
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;
1076 // 80 33 nano 80 (ecm) + len (33)
1077 if(ecm88Data[0] == 0x80) // nano 80, give ecm len
1079 curEcm88len = ecm88Data[1];
1080 nextEcm = ecm88Data + curEcm88len + 2;
1081 ecm88Data += 2;
1082 ecm88Len -= 2;
1084 if(!curEcm88len) // there was no nano 80 -> simple ecm
1086 curEcm88len = ecm88Len;
1088 // d2 02 0d 02 -> D2 nano, len 2, select the AES key to be used
1089 if(ecm88Data[0] == 0xd2)
1091 // test if it needs AES decrypt
1092 if(ecm88Data[2] == 0x0b)
1094 nanoD2 = 0x0b;
1095 rdr_log_dbg(reader, D_READER, "ECM: nano D2 0x0b");
1097 if(ecm88Data[2] == 0x0d)
1099 nanoD2 = 0x0d;
1100 rdr_log_dbg(reader, D_READER, "ECM: nano D2 0x0d");
1102 if(ecm88Data[2] == 0x0f)
1104 nanoD2 = 0x0f;
1105 rdr_log_dbg(reader, D_READER, "ECM: nano D2 0x0f");
1107 if(ecm88Data[2] == 0x11)
1109 nanoD2 = 0x11;
1110 rdr_log_dbg(reader, D_READER, "ECM: nano D2 0x11");
1112 if(ecm88Data[2] == 0x13)
1114 nanoD2 = 0x13;
1115 rdr_log_dbg(reader, D_READER, "ECM: nano D2 0x13");
1117 if(ecm88Data[2] == 0x15)
1119 nanoD2 = 0x15;
1120 rdr_log_dbg(reader, D_READER, "ECM: nano D2 0x15");
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;
1130 else
1132 hasD2 = 0;
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))
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)
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)
1155 if(csystem_data->last_geo.number_ecm == curnumber_ecm && !(ecm88Data[nanoLen - 1] == 0x00)) // select permut 4, accept 01 and FF
1157 keynr = ecm88Data[5];
1158 rdr_log_dbg(reader, D_READER, "keyToUse = %02x, ECM ending with %02x", ecm88Data[5], ecm88Data[nanoLen - 1]);
1160 else
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
1172 else // long ecm but we don't have an ecm number so we have to try them all.
1174 keynr = ecm88Data[5];
1175 rdr_log_dbg(reader, D_READER, "keyToUse = %02x", ecm88Data[5]);
1178 memcpy(ident, &ecm88Data[2], sizeof(ident));
1179 provid = b2i(3, ident);
1180 ident[2] &= 0xF0;
1181 if(hasD2 && reader->aes_list)
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))
1187 return ERROR;
1190 if(!chk_prov(reader, ident, keynr))
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;
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)
1202 memcpy(DE04, &ecm88Data[0], 6);
1203 ecm88Data += 6;
1205 if((ecm88Data[0] == 0xD9) && (ecm88Data[1] == 0x0A))
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]
1210 rdr_log_dbg(reader, D_READER,"[viaccess-reader] nano E0 ECM detected!");
1211 hasE0 = 1;
1213 if(((ecm88Data[16] ==0x98) || (ecm88Data[19] == 0x98)) && ((ecm88Data[17] == 0x08) || (ecm88Data[20] == 0x08)))
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);
1221 else
1223 if((ecm88Data[0] == 0xE0) && (ecm88Data[1] == 0x02) && (ecm88Data[3] == 0x02)) // accept parental data 0F for ecm88Data[2]
1225 rdr_log_dbg(reader, D_READER,"[viaccess-reader] nano E0 ECM detected!");
1226 hasE0 = 1;
1229 if((ecm88Data[4] == 0x98) && (ecm88Data[5] == 0x08))
1231 rdr_log_dbg(reader, D_READER,"[viaccess-reader] nano 98 ECM detected!");
1232 has98 = 1;
1233 key98Idx = ecm88Data[0x0D];
1235 if(csystem_data->last_geo.provid != provid)
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
1242 // Nano D2 0x0b, 0x0f, 0x13 -> pre AES decrypt CW
1243 if(hasD2 && (nanoD2 == 0x0b|| nanoD2 == 0x0f|| nanoD2 == 0x13))
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)
1252 if(ecm88Data[cwStart] == 0xEA && ecm88Data[cwStart + 1] == 0x10)
1254 ecm88DataCW = ecm88DataCW + cwStart + 2;
1255 must_exit = 1;
1257 cwStart = cwStart + ecm88Data[cwStart + 1] + 2; // parse via nanos
1258 // cwStart++; // error if EA 10 in nanos datas
1260 if(nanoD2 == 0x0f)
1262 hdSurEncPhase1_D2_0F_11(ecm88DataCW);
1263 hdSurEncPhase2_D2_0F_11(ecm88DataCW);
1265 if(nanoD2 == 0x13)
1267 hdSurEncPhase1_D2_13_15(ecm88DataCW);
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)
1273 snprintf(ea->msglog, MSGLOGSIZE, "Missing AES key(%d)[aka E%X]",D2KeyID, D2KeyID);
1275 if(nanoD2 == 0x0f)
1277 hdSurEncPhase1_D2_0F_11(ecm88DataCW);
1279 if(nanoD2 == 0x13)
1281 hdSurEncPhase2_D2_13_15(ecm88DataCW);
1284 while(ecm88Len > 1 && ecm88Data[0] < 0xA0)
1286 nanoLen = ecm88Data[1] + 2;
1287 if(!ecmf8Data)
1289 ecmf8Data = (uint8_t *)ecm88Data;
1291 ecmf8Len += nanoLen;
1292 ecm88Len -= nanoLen;
1293 curEcm88len -= nanoLen;
1294 ecm88Data += nanoLen;
1296 if(ecmf8Len)
1298 if(csystem_data->last_geo.geo_len != ecmf8Len || memcmp(csystem_data->last_geo.geo, ecmf8Data, csystem_data->last_geo.geo_len))
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);
1307 ins88[2] = ecmf8Len ? 1 : 0;
1308 ins88[3] = keynr;
1309 ins88[4] = (curEcm88len > 0xFF) ? 0x00 : curEcm88len;
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
1314 // DE04
1315 if(DE04[0] == 0xDE)
1317 uint32_t l = curEcm88len - 6;
1318 if(l > MAX_ECM_SIZE || curEcm88len <= 6) //don't known if this is ok...
1320 rdr_log(reader, "ecm invalid/too long! len=%d", curEcm88len);
1321 return ERROR;
1323 memcpy(DE04 + 6, (uint8_t *)ecm88Data, l);
1324 write_cmd(ins88, DE04); // request dcw
1326 else
1328 write_cmd(ins88, (uint8_t *)ecm88Data); // request dcw
1330 write_cmd(insc0, NULL); // read dcw
1331 switch(cta_res[0])
1333 case 0xe8: // even
1334 if(cta_res[1] == 8)
1336 memcpy(ea->cw, cta_res + 2, 8);
1337 rc = 1;
1338 } break;
1339 case 0xe9: // odd
1340 if(cta_res[1] == 8)
1342 memcpy(ea->cw + 8, cta_res + 2, 8);
1343 rc = 1;
1344 } break;
1345 case 0xea: // complete
1346 if(cta_res[1] == 16)
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");
1358 else
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.*/
1367 // Nano D2 0d, 11, 15 -> post AES decrypt CW
1368 if(hasD2 && !dcw_crc(ea->cw) && (nanoD2 == 0x0d || nanoD2 == 0x11 || nanoD2 == 0x15))
1370 if(nanoD2 == 0x11)
1372 hdSurEncPhase1_D2_0F_11(ea->cw);
1373 hdSurEncPhase2_D2_0F_11(ea->cw);
1375 if(nanoD2 == 0x15)
1377 hdSurEncPhase1_D2_13_15(ea->cw);
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)
1383 snprintf(ea->msglog, MSGLOGSIZE, "Missing AES key(%d)[aka E%X]",D2KeyID, D2KeyID);
1385 if(nanoD2 == 0x11)
1387 hdSurEncPhase1_D2_0F_11(ea->cw);
1389 if(nanoD2 == 0x15)
1391 hdSurEncPhase2_D2_13_15(ea->cw);
1394 if (has98)
1396 if (N98Init == 0)
1398 MakeSubKeys(KeyS, key98Idx);
1399 N98Init = 1;
1401 uint8_t inp[16];
1402 memcpy(inp,ea->cw,16);
1403 N98_decrypt(inp);
1404 memcpy(ea->cw,inp,16);
1406 if (hasE0)
1408 if (reader->initCA28)
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);
1424 else
1426 snprintf(ea->msglog, MSGLOGSIZE, "Nano E0 detected, no valid boxkey + deskey defined: no decoding");
1429 if (SubECM == 1)
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);
1438 return (rc ? OK : ERROR);
1440 static int32_t viaccess_get_emm_type(EMM_PACKET *ep, struct s_reader *rdr)
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)
1446 provid = b2i(3, ep->emm + 5);
1447 provid &= 0xFFFFF0;
1448 i2b_buf(4, provid, ep->provid);
1450 switch(ep->emm[0])
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))
1459 return (!memcmp(rdr->hexserial + 1, ep->hexserial, 4)); // local reader
1461 else
1463 return 1; // let server decide!
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++)
1486 if(!memcmp(&rdr->prid[i][2], ep->hexserial+1, 2))
1488 return 1;
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;
1498 static int32_t viaccess_get_emm_filter(struct s_reader *rdr, struct s_csystem_emm_filter **emm_filters, unsigned int *filter_count)
1500 if(*emm_filters == NULL)
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)))
1507 return ERROR;
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)
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++;
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++)
1526 if((rdr->prid[prov][2] &0xF0) == 0xF0) // skip this not useful provider
1528 continue;
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)
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!
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)
1547 memcpy(&filters[idx].filter[1], &rdr->sa[prov][0], 3);
1548 memset(&filters[idx].mask[1], 0xFF, 3);
1550 idx++;
1552 // globals are less important, define last since viaccess produces a lot of filters!
1553 for(prov = 0; (prov < rdr->nprov); prov++)
1555 if((rdr->prid[prov][2] &0xF0) == 0xF0) // skip this not useful provider
1557 continue;
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)
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!
1569 else if (device_emm == 0)
1571 filters[idx].filter[3] = 0x00; // additional filter to cancel device specific emms
1572 filters[idx].mask[3] = 0x80;
1574 idx++;
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
1582 memcpy(&filters[idx].filter[1], rdr->hexserial + 1, 4);
1583 memset(&filters[idx].mask[1], 0xFF, 4);
1585 else
1587 memcpy(&filters[idx].filter[1], rdr->hexserial + 1, 3);
1588 memset(&filters[idx].mask[1], 0xFF, 3);
1590 idx++;
1591 *filter_count = idx;
1593 return OK;
1595 static int32_t viaccess_do_emm(struct s_reader *reader, EMM_PACKET *ep)
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
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
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;
1621 if(ep->type == UNIQUE)
1623 emmdatastart++;
1625 if(ep->type == GLOBAL && emmdatastart == 7)
1627 emmdatastart -= 4;
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]))
1648 rdr_log_dump(reader, emmParsed, emmParsed[1] + 2, "NANO");
1649 if(emmParsed[0] == 0x90 && emmParsed[1] == 0x03)
1651 /* identification of the service operator */
1652 uint8_t soid[3], ident[3], i;
1653 for(i = 0; i < 3; i++)
1655 soid[i] = ident[i] = emmParsed[2 + i];
1657 ident[2] &= 0xF0;
1658 emm_provid = b2i(3, ident);
1659 keynr = soid[2] & 0x0F;
1660 if(chk_prov(reader, ident, keynr))
1662 provider_ok = 1;
1664 else
1666 rdr_log(reader, "EMM: ignored since provider or key not present on card (%x, %x)", emm_provid, keynr);
1667 return SKIPPED;
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)
1672 write_cmd(insa4, ident);
1673 if(cta_res[cta_lr - 2] != 0x90 || cta_res[cta_lr - 1] != 0x00)
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;
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;
1686 else if(emmParsed[0] == 0x9e && emmParsed[1] == 0x20)
1688 /* adf */
1689 if(!nano91Data)
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)))
1698 rdr_log_dbg(reader, D_READER, "emm for our card %08X", b2i(4, &reader->sa[0][0]));
1700 else
1702 rdr_log_dbg(reader, D_READER, "emm not suitable for our card %08X", b2i(4, &reader->sa[0][0]));
1703 return SKIPPED;
1706 // memorize
1707 nano9EData = emmParsed;
1709 else if(emmParsed[0] == 0x81)
1711 nano81Data = emmParsed;
1713 else if(emmParsed[0] == 0x91 && emmParsed[1] == 0x08)
1715 nano91Data = emmParsed;
1717 else if(emmParsed[0] == 0x92 && emmParsed[1] == 0x08)
1719 nano92Data = emmParsed;
1721 else if(emmParsed[0] == 0xF0 && emmParsed[1] == 0x08)
1723 nanoF0Data = emmParsed;
1725 else if(emmParsed[0] == 0xF0 && emmParsed[1] == 0x10 && (emm_provid >> 8) == 0x0702)
1727 nanoF0Data = emmParsed;
1729 else if(emmParsed[0] == 0xD8 && emmParsed[2] == 0x45)
1731 uint8_t pos = 4 + emmParsed[3];
1732 char *tmpbuf;
1733 if(emmParsed[pos] == 0x46 && ((emmParsed[pos+1] - emmParsed[1]) == pos))
1735 if(cs_malloc(&tmpbuf, emmParsed[pos + 1]))
1737 cs_strncpy(tmpbuf, (char *)emmParsed + pos + 2, emmParsed[pos + 1]);
1738 rdr_log(reader, "Viaccess EMM-text: %s", tmpbuf);
1739 NULLFREE(tmpbuf);
1743 else
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
1749 if(!emm_provid)
1751 rdr_log(reader, "no provid in shared emm -> skipped!");
1752 return SKIPPED;
1754 int8_t match = add_find_class(reader, emm_provid, emmParsed + 2, emmParsed[1], 0);
1755 if(match == -2)
1757 rdr_log(reader, "shared emm provid %06X all classes have entitlementdate already same or newer -> skipped!", emm_provid);
1758 return SKIPPED;
1760 nanoA9Data = emmParsed;
1762 memcpy(ins18Data + ins18Len, emmParsed, emmParsed[1] + 2);
1763 ins18Len += emmParsed [1] + 2;
1766 if(!provider_ok)
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;
1773 if(!nanoF0Data)
1775 rdr_log_dump(reader, ep->emm, ep->emmlen, "can't find 0xf0 in emm...");
1776 return ERROR; // error
1778 if(nano9EData)
1780 if(!nano91Data)
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)
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;
1794 else
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)
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;
1811 if(!nano92Data)
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)
1822 if(nanoA9Data)
1824 add_find_class(reader, emm_provid, nanoA9Data + 2, nanoA9Data[1], 1);
1825 rdr_log(reader, "Your subscription data was updated.");
1827 rc = 1; // written
1829 else
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!
1835 rdr_log(reader, "update error: %02X %02X", cta_res[cta_lr - 2], cta_res[cta_lr - 1]);
1837 else
1839 rc = 2; // skipped
1843 else
1845 // send subscription encrypted
1846 if(!nano81Data)
1848 rdr_log_dump(reader, ep->emm, ep->emmlen, "0x92 found, but can't find 0x81 in emm...");
1849 return ERROR; // error
1851 ins1c[2] = nano9EData ? 0x01 : 0x00; // found 9E nano ?
1852 if(ep->type == UNIQUE)
1854 ins1c[2] = 0x02;
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))
1864 rdr_log(reader, "update successfully written");
1866 if(cta_res[cta_lr - 2] == 0x98 && cta_res[cta_lr - 1] == 0x00 )
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))
1875 write_cmd(ins8704, NULL);
1876 if((cta_res[cta_lr - 2] == 0x90) && (cta_res[cta_lr - 1] == 0x00))
1878 write_cmd(ins8706, NULL);
1879 if((cta_res[cta_lr - 2] == 0x90) && (cta_res[cta_lr - 1] == 0x00))
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);
1887 rc = 1;
1889 return rc;
1891 static int32_t viaccess_card_info(struct s_reader *reader)
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++)
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])
1946 snprintf((char *)l_name, sizeof(l_name), ", name: %.55s", cta_res);
1948 else
1950 l_name[0] = 0;
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)
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;
1973 write_cmd(insac, cls); // request class subs
1974 while((cta_res[cta_lr - 2] == 0x90) && (cta_res[cta_lr - 1] == 0))
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))
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))
1985 show_class(reader, NULL, l_provid, cta_res, cta_lr - 2);
1986 added = true;
1990 if(!added)
1992 // add entitlement info for provid without class
1993 cs_add_entitlement(reader, reader->caid, l_provid, 0, 0, 0, 0, 5, 1);
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))
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))
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))
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);
2014 insac[4] = 0;
2015 insa4[2] = 0x02;
2016 write_cmd(insa4, NULL); // select next provider
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))
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))
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;
2038 else
2040 rdr_log(reader, "CA 28 initialisation failed! CA 28 refused");
2043 //end process init CA 28
2044 return OK;
2046 static int32_t viaccess_reassemble_emm(struct s_reader *rdr, struct s_client *client, EMM_PACKET *ep)
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)
2057 return 0;
2059 switch(buffer[0])
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)
2069 cs_log("[viaccess] ERROR: Can't allocate EMM reassembly buffer.");
2070 return 0;
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
2074 return 0;
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++)
2085 if(!memcmp(&buffer[3], &rdr->sa[prov][0], 3))
2087 //matching sa found!
2088 if(is_network_reader(rdr))
2090 provid = b2i(4, ep->provid); // use provid from emm since we have nothing better!
2091 provid &= 0xFFFFF0; // last digit is dont care
2093 else
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
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)
2101 continue; // match but no emm-gh found for this provider
2103 else
2105 break; // stop searching-> emm-gh found!
2109 if(!r_emm || !r_emm->emmlen)
2111 return 0; // stop -> no emm-gh found!
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)
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;
2123 if(buffer[2] == 0x2c)
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;
2134 else if(buffer[2] == 0x34 && (provid >> 8) == 0x0702)
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;
2145 else
2147 //extract from variable emm-s
2148 for(k = 7; k < (*len); k += buffer[k + 1] + 2)
2150 //copy nano (length determined by k+1)
2151 memcpy(emmbuf + pos, buffer + k, buffer[k + 1] + 2);
2152 pos += buffer[k + 1] + 2;
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;
2166 return 1;
2168 const struct s_cardsystem reader_viaccess =
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,
2180 #endif