Attempt to count descramblers used properly
[oscam.git] / reader-viaccess.c
blob1624e052df75acd12a6667ebdfa04399e41d4a1f
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"
10 struct geo_cache
12 uint32_t provid;
13 uint8_t geo[256];
14 uint8_t geo_len;
15 int32_t number_ecm;
18 struct viaccess_data
20 struct geo_cache last_geo;
21 uint8_t availkeys[CS_MAXPROV][16];
24 struct via_date
26 uint16_t day_s : 5;
27 uint16_t month_s : 4;
28 uint16_t year_s : 7;
30 uint16_t day_e : 5;
31 uint16_t month_e : 4;
32 uint16_t year_e : 7;
35 static void parse_via_date(const uint8_t *buf, struct via_date *vd, int32_t fend)
37 uint16_t date;
39 date = (buf[0] << 8) | buf[1];
40 vd->day_s = date & 0x1f;
41 vd->month_s = (date >> 5) & 0x0f;
42 vd->year_s = (date >> 9) & 0x7f;
44 if(fend)
46 date = (buf[2] << 8) | buf[3];
47 vd->day_e = date & 0x1f;
48 vd->month_e = (date >> 5) & 0x0f;
49 vd->year_e = (date >> 9) & 0x7f;
53 struct emm_rass *find_rabuf(struct s_client *client, int32_t provid, uint8_t nano, int8_t add)
55 struct emm_rass *e;
56 LL_ITER it;
58 if(!client->ra_buf)
60 client->ra_buf = ll_create("client->ra_buf");
63 it = ll_iter_create(client->ra_buf);
65 while((e = ll_iter_next(&it)) != NULL)
67 if(!add && e->provid == provid && e->emmlen != 0)
69 return e;
72 if(add && e->provid == provid && e->emm[0] == nano)
74 return e;
78 if(!add)
80 return NULL;
83 if(!cs_malloc(&e, sizeof(struct emm_rass)))
85 return NULL;
88 e->provid = provid;
89 ll_append(client->ra_buf, e);
90 return e;
93 static void show_class(struct s_reader *reader, const char *p, uint32_t provid, const uint8_t *b, int32_t l)
95 int32_t i, j;
97 // b -> via date (4 uint8_ts)
98 b += 4;
99 l -= 4;
101 j = l - 1;
102 for(; j >= 0; j--)
104 for(i = 0; i < 8; i++)
106 if(b[j] & (1 << (i & 7)))
108 uint8_t cls;
109 struct via_date vd;
110 parse_via_date(b - 4, &vd, 1);
111 cls = (l - (j + 1)) * 8 + i;
113 if(p) // just show class info, dont add entitlement!
115 rdr_log(reader, "%sclass: %02X, expiry date: %04d/%02d/%02d - %04d/%02d/%02d", p, cls,
116 vd.year_s + 1980, vd.month_s, vd.day_s,
117 vd.year_e + 1980, vd.month_e, vd.day_e);
119 else
121 rdr_log(reader, "class: %02X, expiry date: %04d/%02d/%02d - %04d/%02d/%02d", cls,
122 vd.year_s + 1980, vd.month_s, vd.day_s,
123 vd.year_e + 1980, vd.month_e, vd.day_e);
125 //convert time:
126 time_t start_t, end_t;
127 struct tm tm;
128 memset(&tm, 0, sizeof(tm));
129 tm.tm_year = vd.year_s + 80; //via year starts in 1980, tm_year starts in 1900
130 tm.tm_mon = vd.month_s - 1; // january is 0 in tm_mon
131 tm.tm_mday = vd.day_s;
132 start_t = cs_timegm(&tm);
134 tm.tm_year = vd.year_e + 80; //via year starts in 1980, tm_year starts in 1900
135 tm.tm_mon = vd.month_e - 1; // january is 0 in tm_mon
136 tm.tm_mday = vd.day_e;
137 end_t = cs_timegm(&tm);
138 cs_add_entitlement(reader, reader->caid, provid, cls, cls, start_t, end_t, 5, 1);
145 static int8_t add_find_class(struct s_reader *reader, uint32_t provid, const uint8_t *b, int32_t l, int8_t add)
147 int32_t i, j, freshdate = 0;
149 // b -> via date (4 uint8_ts)
150 b += 4;
151 l -= 4;
153 j = l - 1;
154 for(; j >= 0; j--)
156 for(i = 0; i < 8; i++)
158 if(b[j] & (1 << (i & 7)))
160 uint8_t cls;
161 cls = (l - (j + 1)) * 8 + i;
162 if(cs_add_entitlement(reader, reader->caid, provid, cls, cls, 0, 0, 5, 0) == NULL && !add)
164 rdr_log(reader, "provid %06X class %02X not found", provid, cls);
165 freshdate = 1;
167 else
169 if(!add)
171 rdr_log(reader, "provid %06X has matching class %02X", provid, cls);
173 struct via_date vd;
174 parse_via_date(b - 4, &vd, 1);
175 time_t start_t, end_t;
176 struct tm tm;
178 //convert time:
179 memset(&tm, 0, sizeof(tm));
180 tm.tm_year = vd.year_s + 80; // via year starts in 1980, tm_year starts in 1900
181 tm.tm_mon = vd.month_s - 1; // january is 0 in tm_mon
182 tm.tm_mday = vd.day_s;
183 start_t = cs_timegm(&tm);
185 tm.tm_year = vd.year_e + 80; // via year starts in 1980, tm_year starts in 1900
186 tm.tm_mon = vd.month_e - 1; // january is 0 in tm_mon
187 tm.tm_mday = vd.day_e;
188 end_t = cs_timegm(&tm);
190 if(cs_add_entitlement(reader, reader->caid, provid, cls, cls, start_t, end_t, 5, add) != NULL)
192 if(!add)
194 rdr_log(reader, "class %02X provid %06X has already this daterange or newer entitled", cls, provid);
197 else
199 freshdate = 1;
206 if(freshdate == 0)
208 return -2;
211 return 1; // emmdate is fresh!
214 static void show_subs(struct s_reader *reader, const uint8_t *emm)
216 switch(emm[0])
218 case 0xA9:
220 show_class(reader, "nano A9: ", 1, emm + 2, emm[1]);
221 break;
224 case 0xA6:
226 char szGeo[256];
228 memset(szGeo, 0, 256);
229 cs_strncpy(szGeo, (char *)emm + 2, emm[1]);
230 rdr_log(reader, "nano A6: geo %s", szGeo);
231 break;
234 case 0xB6:
236 uint8_t m; // modexp
237 struct via_date vd;
239 m = emm[emm[1] + 1];
240 parse_via_date(emm + 2, &vd, 0);
241 rdr_log(reader, "nano B6: modexp %d%d%d%d%d%d: %02d/%02d/%04d",
242 (m & 0x20) ? 1 : 0,
243 (m & 0x10) ? 1 : 0,
244 (m & 0x08) ? 1 : 0,
245 (m & 0x04) ? 1 : 0,
246 (m & 0x02) ? 1 : 0,
247 (m & 0x01) ? 1 : 0,
248 vd.day_s, vd.month_s, vd.year_s + 1980);
249 break;
254 static int32_t chk_prov(struct s_reader *reader, uint8_t *id, uint8_t keynr)
256 struct viaccess_data *csystem_data = reader->csystem_data;
257 int32_t i, j, rc;
259 for(rc = i = 0; (!rc) && (i < reader->nprov); i++)
261 if(!memcmp(&reader->prid[i][1], id, 3))
263 for(j = 0; (!rc) && (j < 16); j++)
265 if(csystem_data->availkeys[i][j] == keynr)
267 rc = 1;
272 return (rc);
275 static int32_t get_maturity(struct s_reader *reader)
277 /* retrieve maturity rating on the card */
279 def_resp;
281 uint8_t insac[] = { 0xca, 0xac, 0x00, 0x00, 0x00 }; // select data
282 uint8_t insb8[] = { 0xca, 0xb8, 0x00, 0x00, 0x00 }; // read selected data
284 insac[2] = 0x06;
285 write_cmd(insac, NULL); // request maturity rating
287 insb8[4] = 0x02;
288 write_cmd(insb8, NULL); // read maturity rating nano + len
290 insb8[4] = cta_res[1];
291 write_cmd(insb8, NULL); // read maturity rating
293 reader->maturity = cta_res[cta_lr - 3] & 0x0F;
294 if (reader->maturity < 0xF)
296 rdr_log(reader, "Maturity level [%X]= older than %i years", reader->maturity, reader->maturity);
298 else
300 rdr_log(reader, "Maturity level [%X]=no age limit", reader->maturity);
302 return 0;
305 static int32_t unlock_parental(struct s_reader *reader)
307 /* disabling parental lock. assuming pin "0000" if no pin code is provided in the config */
309 static const uint8_t inDPL[] = { 0xca, 0x24, 0x02, 0x00, 0x09 };
310 uint8_t cmDPL[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F };
311 def_resp;
313 if(strcmp(reader->pincode, "none"))
315 rdr_log(reader, "Using PIN %s", reader->pincode);
316 // the pin need to be coded in bcd, so we need to convert from ascii to bcd, so '1234' -> 0x12 0x34
317 cmDPL[6] = ((reader->pincode[0] - 0x30) << 4) | ((reader->pincode[1] - 0x30) & 0x0f);
318 cmDPL[7] = ((reader->pincode[2] - 0x30) << 4) | ((reader->pincode[3] - 0x30) & 0x0f);
320 else
322 rdr_log(reader, "Using PIN 0000!");
324 write_cmd(inDPL, cmDPL);
326 if(!(cta_res[cta_lr - 2] == 0x90 && cta_res[cta_lr - 1] == 0))
328 if(strcmp(reader->pincode, "none"))
330 rdr_log(reader, "Can't disable parental lock. Wrong PIN? OSCam used %s!", reader->pincode);
332 else
334 rdr_log(reader, "Can't disable parental lock. Wrong PIN? OSCam used 0000!");
337 else
339 rdr_log(reader, "Parental lock disabled");
340 get_maturity(reader);
343 return 0;
346 int32_t hdSurEncBasicCrypt_D2_0F_11(int32_t Value, int32_t XorVal)
348 int32_t i = (Value << 13) - Value + 0x1B59;
349 i = (i * Value) + 0x07CF;
350 return (i ^ XorVal);
353 int32_t hdSurEncCryptLookup_D2_0F_11(uint8_t Value, uint8_t AddrInd)
355 static const uint8_t lookup[] =
357 0x94, 0xB2, 0xA9, 0x79, 0xC4, 0xC7, 0x0D, 0x36, 0x6F, 0x24, 0x11, 0xD1, 0xDB, 0x59, 0xD2, 0xA5,
358 0xE1, 0x00, 0xD4, 0x97, 0xA3, 0x2B, 0x11, 0xFA, 0x5F, 0xF1, 0xC1, 0x44, 0xBF, 0x9B, 0x5A, 0xC8,
359 0xF1, 0xE1, 0x99, 0x82, 0x0E, 0xB2, 0x01, 0x09, 0x0C, 0xC8, 0xB3, 0x3B, 0xD1, 0x80, 0x50, 0xE8,
360 0xF5, 0x52, 0x4C, 0xE6, 0x82, 0xAC, 0x58, 0x40, 0xD4, 0x71, 0x87, 0x52, 0x06, 0xEA, 0xA6, 0x27,
361 0xB7, 0xFE, 0x6C, 0x49, 0x47, 0x3B, 0x70, 0x6C, 0xEB, 0xCD, 0xC5, 0x0B, 0x8C, 0x31, 0x29, 0x42,
362 0x4E, 0x10, 0x2B, 0x2D, 0x46, 0xEC, 0x39, 0xA3, 0x90, 0x4B, 0x25, 0x60, 0x9C, 0x62, 0xD4, 0x20,
363 0xF6, 0x16, 0xA8, 0x9C, 0xE4, 0x20, 0xED, 0xC7, 0xBA, 0x5E, 0xB6, 0x4E, 0x03, 0x15, 0xA6, 0xF6,
364 0x23, 0x98, 0x32, 0xC0, 0xAE, 0xA3, 0xFD, 0xD3, 0x7F, 0xF8, 0xED, 0xF0, 0x29, 0x29, 0x12, 0xB3,
365 0xB7, 0x58, 0xAD, 0xA2, 0x58, 0x2C, 0x70, 0x1B, 0xA4, 0x25, 0xE8, 0xA5, 0x43, 0xF1, 0xB9, 0x8F,
366 0x1E, 0x3B, 0x10, 0xDF, 0x52, 0xFE, 0x58, 0x29, 0xAD, 0x3F, 0x99, 0x4D, 0xDF, 0xD2, 0x08, 0x06,
367 0xA1, 0x1C, 0x66, 0x29, 0x26, 0x80, 0x52, 0x8A, 0x5A, 0x73, 0xE7, 0xDF, 0xC1, 0xC4, 0x47, 0x82,
368 0xAB, 0x5C, 0x32, 0xAE, 0x96, 0x04, 0x2B, 0xC3, 0x2D, 0x5A, 0xD2, 0xB0, 0x64, 0x88, 0x97, 0xBF,
369 0x7E, 0x99, 0x60, 0xCC, 0x63, 0x76, 0x66, 0xE9, 0x9A, 0x3D, 0xBB, 0xF7, 0x7F, 0xE4, 0x7C, 0x3F,
370 0xB8, 0x4D, 0x10, 0x8D, 0x2A, 0xEA, 0x3C, 0xD3, 0x03, 0x74, 0xE6, 0x46, 0xC0, 0x29, 0xAE, 0xB0,
371 0x79, 0xBE, 0xCB, 0x18, 0x34, 0xBE, 0x5A, 0xE9, 0x19, 0x8F, 0xA3, 0x8F, 0xD6, 0x6A, 0x6C, 0x88,
372 0x1E, 0x21, 0x08, 0x15, 0xC4, 0xE7, 0xE6, 0xBA, 0x97, 0x9C, 0x4F, 0x89, 0x9F, 0x1A, 0x67, 0x4F,
373 0xC0, 0xD5, 0x72, 0x51, 0x16, 0xB4, 0xD3, 0x8A, 0x1F, 0xE3, 0x92, 0x02, 0x7F, 0x59, 0x56, 0x8F,
374 0x07, 0x8D, 0xC1, 0xC2, 0x42, 0x69, 0x3C, 0xA6, 0xBF, 0x3D, 0xDF, 0x0D, 0xAA, 0x4F, 0x7E, 0x80,
375 0x07, 0x11, 0xE2, 0x94, 0x19, 0x9B, 0x16, 0x26, 0x1A, 0x46, 0x09, 0x0D, 0xB5, 0xB8, 0x8E, 0x01,
376 0x9C, 0xFE, 0x09, 0xB3, 0x60, 0xC2, 0xAE, 0x50, 0x3C, 0x68, 0x75, 0x4A, 0x57, 0xD8, 0x4F, 0xD7,
377 0xA2, 0x76, 0x2C, 0xC1, 0xA2, 0x23, 0xBC, 0x54, 0x2A, 0xDD, 0xF3, 0xDD, 0xA7, 0x34, 0xF7, 0x5C,
378 0xF4, 0x86, 0x23, 0x48, 0x7C, 0x3F, 0x05, 0x40, 0x0E, 0xB0, 0xE5, 0xEB, 0x3E, 0xDF, 0x6A, 0x83,
379 0x65, 0xA0, 0xB2, 0x06, 0xD1, 0x40, 0x79, 0x0D, 0xDE, 0x95, 0x84, 0x96, 0x87, 0x6F, 0xCE, 0x48,
380 0x24, 0x13, 0x0B, 0xF5, 0xC7, 0xF5, 0xA8, 0x7F, 0x2E, 0xC7, 0xE1, 0xBA, 0xAE, 0x2B, 0xF7, 0xF0,
381 0x8E, 0xF7, 0x54, 0x0B, 0xF0, 0xD2, 0x41, 0x81, 0x68, 0x3B, 0x1E, 0x35, 0xAB, 0xD9, 0x2B, 0x46,
382 0x57, 0xE8, 0x53, 0xDF, 0xDE, 0x10, 0xEF, 0xCB, 0x4C, 0xE0, 0x52, 0x18, 0x2C, 0x4E, 0xB9, 0x20,
383 0xE9, 0x7E, 0x85, 0xDF, 0x75, 0x32, 0xE6, 0x10, 0xE9, 0x9C, 0x7B, 0x2E, 0x4C, 0xDA, 0x46, 0xE6,
384 0xCC, 0x77, 0x36, 0x1D, 0x4A, 0x15, 0xF5, 0x32, 0x18, 0x6B, 0x7E, 0xAA, 0xCC, 0x97, 0xCC, 0xD1,
385 0x2F, 0xE5, 0x58, 0x03, 0x35, 0x35, 0x3D, 0xA0, 0x2B, 0x13, 0x3A, 0x65, 0xFF, 0x24, 0x72, 0xCF,
386 0xA7, 0x6D, 0x52, 0x55, 0xF6, 0xC2, 0x30, 0x23, 0x7D, 0x9B, 0x9E, 0xB0, 0x94, 0x02, 0xAD, 0x60,
387 0x8A, 0x9F, 0xBC, 0xC8, 0xE4, 0x2B, 0x92, 0x96, 0xF5, 0xAE, 0x04, 0xA4, 0x33, 0x0C, 0x90, 0x67,
388 0xF0, 0xB9, 0x1E, 0x7E, 0xBE, 0x02, 0x18, 0xB2, 0x03, 0xB6, 0x40, 0xBF, 0x05, 0xE3, 0x76, 0x98,
389 0x21, 0x38, 0xC9, 0x5F, 0xD3, 0x51, 0x8B, 0x43, 0x0B, 0x1A, 0x0B, 0xF9, 0x3C, 0x21, 0x6C, 0x3D,
390 0xB8, 0xA0, 0x57, 0xCA, 0x68, 0xCD, 0x1E, 0xD2, 0x2C, 0x50, 0xEE, 0xC0, 0xDF, 0x25, 0x88, 0x52,
391 0x37, 0xE1, 0x44, 0xC6, 0x76, 0x3B, 0x91, 0x95, 0x86, 0x76, 0x87, 0x49, 0x21, 0x93, 0x44, 0x0A,
392 0x52, 0xB9, 0x2D, 0x2B, 0xE3, 0x1D, 0xB0, 0xE4, 0x98, 0xC6, 0xEE, 0x3D, 0x96, 0x53, 0x4B, 0xFF,
393 0x39, 0x00, 0xD5, 0x42, 0x7E, 0xE1, 0x4C, 0x6F, 0xD5, 0xB7, 0xE6, 0x99, 0x2A, 0x5B, 0x67, 0xEE,
394 0x3E, 0xBA, 0xF7, 0xEC, 0x43, 0x2A, 0x1C, 0xB6, 0xB5, 0x04, 0x26, 0x59, 0xB1, 0x4C, 0x17, 0xCC,
395 0x83, 0xB9, 0x00, 0x3E, 0x36, 0x91, 0x90, 0xF7, 0x5E, 0x38, 0xDC, 0xE4, 0x15, 0xC7, 0x67, 0xF0,
396 0xCA, 0xC8, 0xD2, 0x91, 0x5D, 0x74, 0xAC, 0x97, 0x56, 0x36, 0x1A, 0x82, 0x0A, 0xAA, 0xB4, 0x4E,
397 0xBF, 0x29, 0x5C, 0xBF, 0x58, 0xB3, 0x97, 0xF9, 0xEB, 0x7C, 0x85, 0xB4, 0xA5, 0x13, 0x2F, 0xD1,
398 0xDE, 0x1C, 0xEC, 0x97, 0xDD, 0xE2, 0x39, 0xE4, 0xFB, 0x0A, 0x02, 0xE0, 0xC3, 0xBA, 0x39, 0x79,
399 0xAA, 0x1C, 0x37, 0x75, 0x25, 0x54, 0xBE, 0x85, 0x74, 0x2C, 0xFA, 0x0C, 0xFA, 0x50, 0xF6, 0xBE,
400 0x9F, 0x2A, 0x53, 0x7C, 0x27, 0x46, 0x68, 0x2D, 0x74, 0x2B, 0x46, 0xDA, 0xF5, 0x07, 0x95, 0x09,
401 0x6A, 0x91, 0xB7, 0xB1, 0x34, 0x07, 0x5F, 0xEA, 0xBE, 0x0F, 0x87, 0x28, 0x68, 0x97, 0x43, 0x77,
402 0xD5, 0x38, 0x2B, 0x11, 0x11, 0x4F, 0xD9, 0x75, 0x5E, 0xE1, 0x06, 0xA0, 0x3B, 0xAC, 0x32, 0xFE,
403 0xBF, 0x73, 0x59, 0x5B, 0xA2, 0xA8, 0x7E, 0x10, 0x4C, 0x6E, 0x78, 0xF0, 0x4A, 0x4E, 0x95, 0xD6,
404 0xDD, 0x05, 0x7A, 0xBB, 0xF1, 0xEB, 0xA8, 0xA4, 0x5D, 0x91, 0xF0, 0xED, 0xDB, 0xB8, 0x01, 0x41,
405 0xF8, 0x97, 0x7F, 0xC3, 0x91, 0x53, 0xBF, 0xE9, 0xEA, 0x33, 0x1F, 0xDC, 0xA6, 0xE6, 0x8D, 0xCB,
406 0x75, 0xD0, 0x69, 0xD0, 0xA4, 0x59, 0xA5, 0x02, 0xFC, 0x60, 0x0D, 0x6A, 0xA0, 0x05, 0x1A, 0x54,
407 0x8A, 0xA7, 0x57, 0xA3, 0xF0, 0x90, 0x8A, 0xD5, 0x6F, 0x1E, 0x2E, 0x10, 0x9A, 0x93, 0x2B, 0x51,
408 0x2C, 0xFD, 0x99, 0xE5, 0x9B, 0x5D, 0xB2, 0xA7, 0x37, 0x99, 0x26, 0x35, 0xCA, 0xDD, 0x22, 0x19,
409 0x59, 0x2A, 0xB0, 0x99, 0x23, 0xDF, 0xA7, 0xA9, 0x85, 0x12, 0xCF, 0xBF, 0xFC, 0x74, 0x80, 0x87,
410 0xE1, 0x97, 0xD0, 0xF9, 0xEF, 0x5F, 0x1B, 0x45, 0xF7, 0x76, 0xDB, 0x66, 0x39, 0x05, 0x43, 0x06,
411 0xA9, 0x9F, 0x2E, 0x14, 0x9F, 0x1C, 0x0C, 0x1F, 0xD5, 0xD9, 0xA4, 0x8D, 0x18, 0x6F, 0x08, 0x53,
412 0x0B, 0x92, 0x9A, 0x0C, 0xEA, 0x4C, 0xE4, 0x1D, 0x9E, 0x9A, 0x51, 0xB8, 0x7E, 0x2D, 0xE7, 0x3C,
413 0xFF, 0x84, 0x5C, 0xBF, 0x8F, 0x8C, 0x89, 0x09, 0x1B, 0x7E, 0x4B, 0xE7, 0x85, 0xEC, 0x04, 0xB5,
414 0x20, 0x18, 0x1E, 0x55, 0xD5, 0x5B, 0xAC, 0xC6, 0x25, 0x5A, 0xA1, 0x81, 0xC1, 0x31, 0x9C, 0xF5,
415 0xB5, 0x54, 0x07, 0x65, 0x0A, 0x5B, 0x90, 0x06, 0x4F, 0x84, 0xB2, 0x7F, 0xD1, 0xAD, 0x16, 0x81,
416 0x25, 0xAF, 0xAF, 0xE2, 0x03, 0xA9, 0x1F, 0x13, 0x02, 0x5D, 0x54, 0x89, 0xCD, 0x44, 0x51, 0xEB,
417 0xA4, 0x2B, 0xBD, 0x47, 0xB0, 0xB6, 0x27, 0x1D, 0x9B, 0x14, 0x6F, 0xBF, 0xCD, 0x59, 0xBC, 0x0A,
418 0x37, 0xA8, 0x74, 0x7D, 0x16, 0x90, 0x28, 0xD5, 0x94, 0xC3, 0xE4, 0x23, 0xC4, 0x98, 0x91, 0xCE,
419 0x55, 0xBD, 0x21, 0x3B, 0x84, 0xBD, 0x44, 0x3C, 0xF9, 0xCD, 0x37, 0x43, 0x4A, 0xC6, 0x8C, 0x23,
420 0x04, 0x28, 0x63, 0x7A, 0x03, 0x85, 0xD2, 0x46, 0x93, 0xCA, 0xFE, 0xC3, 0x83, 0x0B, 0x13, 0xCC,
421 0x5D, 0xCB, 0xBA, 0xCA, 0x68, 0xAB, 0x05, 0xF7, 0xEC, 0x4A, 0x9C, 0x0F, 0xD5, 0xC4, 0x5A, 0xA5,
422 0xA0, 0x04, 0x41, 0x6A, 0xF6, 0xEF, 0x16, 0x9B, 0x69, 0x38, 0xF6, 0x2D, 0xAA, 0xEB, 0x2D, 0xE2,
423 0x82, 0xA2, 0x9F, 0x6F, 0xBD, 0x2A, 0xE3, 0x66, 0x6B, 0x21, 0xDA, 0x56, 0xAD, 0x82, 0x2B, 0x93,
424 0xF3, 0x25, 0xEA, 0xFC, 0xFD, 0xFD, 0x1B, 0xA9, 0xFC, 0xB8, 0xC6, 0x98, 0x45, 0xF2, 0x70, 0x03,
425 0x4A, 0x9C, 0x60, 0x82, 0x65, 0xB6, 0x68, 0x4C, 0xE7, 0x41, 0x10, 0x9D, 0x59, 0x40, 0x03, 0x02,
426 0x07, 0x12, 0x33, 0xAF, 0x79, 0xE1, 0xC4, 0xEB, 0xB8, 0xCE, 0x6A, 0x90, 0x72, 0x61, 0x5D, 0x56,
427 0xC7, 0x59, 0x31, 0xCB, 0x45, 0x2D, 0x42, 0x9F, 0x10, 0x1D, 0x09, 0x63, 0x59, 0x8C, 0x6C, 0xDB,
428 0x11, 0xCF, 0xA1, 0xDF, 0x5F, 0x4D, 0xDF, 0xB4, 0xC3, 0x82, 0xEE, 0x58, 0x16, 0xB4, 0x74, 0xFA,
429 0xBE, 0x11, 0x9C, 0x1E, 0x98, 0x29, 0xDE, 0xE3, 0xE5, 0x9E, 0xCF, 0xD7, 0x91, 0x0A, 0xA3, 0xA4,
430 0x42, 0xA1, 0x95, 0x09, 0x9E, 0x16, 0xD5, 0xA8, 0x24, 0x56, 0x5B, 0x23, 0xC8, 0x56, 0x4C, 0xCB,
431 0x89, 0x18, 0x69, 0xEB, 0x0C, 0x1F, 0xC0, 0x41, 0x5C, 0x63, 0x04, 0x68, 0xB2, 0x0F, 0x3F, 0x88,
432 0x36, 0xDD, 0x23, 0x4D, 0x4C, 0xC0, 0x81, 0xE3, 0xE9, 0xAD, 0xE0, 0x27, 0xD5, 0xE5, 0x46, 0xEB,
433 0xFF, 0x32, 0xA2, 0xB7, 0x14, 0x64, 0x0B, 0x6D, 0x1B, 0xE5, 0xD8, 0xAE, 0x9D, 0xE8, 0x55, 0xB9,
434 0x52, 0x70, 0x59, 0xB8, 0x72, 0x92, 0x69, 0x37, 0x95, 0x61, 0x0A, 0xE5, 0xF6, 0x55, 0x97, 0x1D,
435 0xBF, 0xF7, 0x29, 0x77, 0x0F, 0x72, 0x80, 0xB2, 0x7E, 0x56, 0xBF, 0xFD, 0xE9, 0xF5, 0x9B, 0x62,
436 0xE9, 0xBD, 0x0B, 0xC2, 0x07, 0x55, 0x31, 0x4C, 0x57, 0x3A, 0x05, 0xB9, 0x27, 0x41, 0x4A, 0xC3,
437 0xEC, 0x72, 0x20, 0xB3, 0x0C, 0xF9, 0xD9, 0x3A, 0x14, 0x6A, 0x03, 0x44, 0x6A, 0xF1, 0x41, 0x55,
438 0x7F, 0x81, 0xC2, 0x04, 0xA8, 0x05, 0xB9, 0x49, 0x2E, 0x43, 0xC4, 0x00, 0x87, 0x86, 0x04, 0xAC,
439 0xAF, 0x73, 0x78, 0x0E, 0xA4, 0x43, 0x5B, 0x36, 0xA2, 0x8F, 0x9C, 0xF7, 0x66, 0x4A, 0x5A, 0x09,
440 0x6B, 0xAA, 0x69, 0x6F, 0xB1, 0x20, 0x0D, 0x56, 0x85, 0x0A, 0x5E, 0x06, 0xBF, 0xE2, 0x32, 0xB4,
441 0x5C, 0x46, 0x33, 0x0D, 0x27, 0xA3, 0x6B, 0xE1, 0xB2, 0x6A, 0x7D, 0x4A, 0xA7, 0x81, 0x0F, 0x2B,
442 0x16, 0x7C, 0x51, 0xD6, 0xC0, 0x3D, 0xB9, 0xFE, 0xB4, 0x66, 0xC4, 0xB6, 0x54, 0x53, 0x67, 0xDA,
443 0x70, 0x96, 0x9A, 0x0A, 0x07, 0x1A, 0x26, 0xBA, 0x85, 0x50, 0xF5, 0x27, 0x53, 0x9C, 0x3A, 0x94,
444 0x0A, 0x7D, 0xDB, 0xE1, 0xC3, 0xE3, 0x6A, 0x3E, 0x9E, 0xD5, 0x13, 0x0A, 0xA3, 0xD2, 0x21, 0x75,
445 0x79, 0x17, 0x26, 0xAC, 0x48, 0x5F, 0x3D, 0xE1, 0x7D, 0xA4, 0xB1, 0x56, 0x0F, 0x92, 0x2C, 0x60,
446 0xE6, 0xCB, 0x87, 0x35, 0xB8, 0x75, 0xC3, 0xA2, 0x03, 0x50, 0x4B, 0xA2, 0x6E, 0x01, 0xE1, 0xDD,
447 0x87, 0xA5, 0x33, 0xC6, 0x2F, 0xA2, 0x41, 0xFC, 0x72, 0x98, 0xA2, 0x69, 0x4C, 0x3F, 0xF0, 0x53,
448 0xF5, 0x41, 0x2B, 0x23, 0x24, 0x3B, 0xCE, 0x9D, 0x39, 0x31, 0x17, 0x08, 0xE1, 0x3F, 0x5F, 0xFB,
449 0x00, 0xFA, 0xF1, 0xE3, 0xE1, 0x7B, 0x0C, 0xDF, 0x8D, 0xA2, 0xC4, 0xCD, 0x62, 0x3D, 0xAE, 0xC7,
450 0x48, 0x09, 0x1C, 0x66, 0xCB, 0x0E, 0x23, 0xE8, 0x1B, 0x9F, 0x1B, 0xCB, 0xF8, 0x14, 0xC3, 0x34,
451 0x91, 0x32, 0x2B, 0x39, 0x1C, 0xBA, 0x1C, 0xA0, 0x19, 0xF2, 0x57, 0x9D, 0x78, 0x00, 0x55, 0x1F,
452 0x15, 0x12, 0x9A, 0xA2, 0xF2, 0xC2, 0xB7, 0x4E, 0xEA, 0x46, 0x01, 0xC2, 0xE9, 0x76, 0xBF, 0xDE,
453 0xCF, 0x8B, 0xC7, 0x50, 0x80, 0xEE, 0x46, 0x91, 0x93, 0x1E, 0x5C, 0x48, 0x5D, 0xC8, 0xC8, 0x63,
454 0xD1, 0x89, 0x02, 0x29, 0xE9, 0x90, 0x9F, 0x0B, 0x0A, 0x1A, 0x44, 0x17, 0xE7, 0x4E, 0xAD, 0x58,
455 0x55, 0xF8, 0x38, 0xF6, 0x4F, 0xD8, 0x1C, 0x7E, 0x25, 0x9B, 0x59, 0x16, 0xBC, 0x65, 0x24, 0xC5,
456 0xA7, 0x56, 0xE5, 0x20, 0x3F, 0xD9, 0x27, 0xE0, 0x32, 0x24, 0xE1, 0x7B, 0xE1, 0x32, 0xEA, 0xF4,
457 0xFE, 0xD9, 0xA5, 0xFF, 0x35, 0xAE, 0xA9, 0x1B, 0x38, 0x28, 0x6A, 0xC0, 0x1A, 0x42, 0xD9, 0x5E,
458 0x14, 0x2C, 0xC2, 0x2D, 0x9B, 0x94, 0x5B, 0xCF, 0x83, 0x30, 0xB9, 0x06, 0xAF, 0x4B, 0xD7, 0xF6,
459 0x38, 0x7C, 0xFF, 0xB4, 0xA5, 0x1A, 0xA0, 0xE9, 0xF3, 0x01, 0xE3, 0x97, 0xC4, 0xA9, 0x57, 0xF5,
460 0xB9, 0x96, 0xA7, 0xA3, 0xB8, 0x10, 0x0E, 0xFB, 0x1D, 0x39, 0x44, 0x16, 0x97, 0x94, 0x3E, 0x5F,
461 0xAF, 0x0F, 0xE3, 0x99, 0xDC, 0xA0, 0xE9, 0x8D, 0x26, 0x2B, 0xD9, 0xAE, 0xEC, 0x4C, 0x4F, 0x09,
462 0x86, 0x7E, 0x7B, 0xC3, 0xE3, 0xC6, 0x17, 0xAE, 0x30, 0x9C, 0x31, 0xD1, 0x84, 0x47, 0xAF, 0xCB,
463 0xEA, 0x69, 0x2A, 0x08, 0x3E, 0x13, 0x00, 0xDE, 0xF6, 0x4A, 0x42, 0xD3, 0xBE, 0x33, 0xD9, 0x50,
464 0x6B, 0x8D, 0x59, 0x12, 0x1A, 0xD3, 0xA7, 0x7C, 0x0A, 0xE7, 0x87, 0x47, 0xCA, 0xAA, 0x33, 0xFD,
465 0xC1, 0xF6, 0x28, 0xC1, 0x62, 0xA2, 0x4C, 0x79, 0x83, 0x48, 0x86, 0x0E, 0xA4, 0x67, 0x34, 0x95,
466 0xAE, 0x7D, 0xD6, 0xEE, 0x91, 0x05, 0x35, 0x91, 0xE8, 0x34, 0x39, 0xA3, 0xE5, 0xE6, 0x80, 0x53,
467 0x76, 0x1F, 0x94, 0xA0, 0xF6, 0xA5, 0x41, 0x79, 0x82, 0xD3, 0xB0, 0x1F, 0xCE, 0xE1, 0x86, 0x64,
468 0x65, 0x0C, 0x8D, 0xD6, 0xFA, 0xC1, 0x10, 0x6C, 0x07, 0xD5, 0xF0, 0x77, 0x65, 0xB9, 0x0C, 0xBD,
469 0xAE, 0x2D, 0x62, 0x6C, 0x42, 0x7E, 0x2A, 0xBE, 0x5F, 0xC1, 0x17, 0x3B, 0x07, 0xFF, 0x5E, 0xD7,
470 0x31, 0x52, 0x26, 0x2F, 0x9F, 0x12, 0xD8, 0x2E, 0xA3, 0xF5, 0xB5, 0xD2, 0xFC, 0x6E, 0x08, 0x1F,
471 0xC8, 0x93, 0xA1, 0xEB, 0xF9, 0x13, 0x1D, 0x1F, 0x98, 0x5E, 0xB0, 0x0C, 0x65, 0x6C, 0xAE, 0x07,
472 0x78, 0xF8, 0x12, 0xD2, 0xD1, 0x1E, 0x77, 0x5C, 0x24, 0x62, 0xE5, 0x94, 0xD6, 0x6A, 0x8E, 0xD0,
473 0x72, 0x59, 0xDA, 0x48, 0x38, 0x2F, 0x31, 0x75, 0x0C, 0x52, 0xF0, 0x0C, 0x8F, 0x5C, 0xE9, 0x5E,
474 0x5A, 0x94, 0xE8, 0xD2, 0x80, 0xF8, 0x4F, 0xE7, 0xAA, 0x6C, 0xBE, 0x47, 0xFB, 0xDD, 0x57, 0x0A,
475 0xD8, 0x5E, 0xCC, 0x0D, 0x8F, 0x42, 0x5E, 0xDC, 0x5D, 0x95, 0x95, 0x60, 0x9B, 0x6F, 0x05, 0x5E,
476 0x08, 0x45, 0x91, 0xE4, 0xB8, 0x06, 0xB1, 0xF2, 0xC0, 0xD7, 0xE3, 0x47, 0xB7, 0x38, 0x08, 0xA8,
477 0x58, 0xE4, 0x55, 0xFC, 0xE2, 0x37, 0x1F, 0x38, 0xA2, 0x18, 0x9E, 0xC2, 0x0F, 0x90, 0x14, 0x20,
478 0x50, 0xD1, 0xD0, 0xAB, 0x36, 0x7F, 0xAA, 0x03, 0x1C, 0xE6, 0x0A, 0xF9, 0x8E, 0x41, 0xDB, 0x32,
479 0x1C, 0x68, 0xA0, 0xA0, 0xED, 0x4A, 0xF4, 0x4B, 0x09, 0xD0, 0xF0, 0x01, 0x8B, 0x17, 0x44, 0xE1,
480 0xEA, 0xC5, 0x9D, 0x3B, 0x37, 0x7A, 0x68, 0xF1, 0x78, 0x46, 0xCF, 0xB6, 0x57, 0xDB, 0x4B, 0x5C,
481 0x03, 0xE1, 0x9D, 0xC0, 0x37, 0x55, 0x8D, 0x03, 0xFB, 0x6A, 0x00, 0x82, 0x19, 0xD1, 0xC0, 0x76,
482 0x97, 0xEE, 0xC9, 0xAD, 0x0D, 0x72, 0x0B, 0xE9, 0xA8, 0x09, 0x92, 0x03, 0xA4, 0xAA, 0x2C, 0xCF,
483 0xFD, 0xDE, 0x86, 0xD0, 0x06, 0x4A, 0xAE, 0x7E, 0xC1, 0xB8, 0x2A, 0x4E, 0x9F, 0xA3, 0x5E, 0x8C,
484 0x12, 0x40, 0x74, 0x38, 0xE7, 0xEA, 0xB0, 0x51, 0xC2, 0xB9, 0x6D, 0x4A, 0x50, 0xBF, 0x59, 0x9C,
485 0x05, 0xB2, 0x42, 0xE2, 0x0F, 0x71, 0x44, 0xDB, 0x97, 0x0B, 0xD0, 0xDB, 0x44, 0x1F, 0x9A, 0x3B,
486 0x18, 0x2A, 0x7B, 0xD9, 0x03, 0x83, 0x0B, 0xCF, 0x27, 0x20, 0x43, 0xA6, 0x42, 0xED, 0x89, 0x63,
487 0xDB, 0x2D, 0x27, 0xC2, 0x3B, 0xE6, 0x0D, 0x3E, 0xB6, 0x96, 0x33, 0x70, 0xA6, 0xF3, 0xF5, 0x56,
488 0xEA, 0xEB, 0xF1, 0xE7, 0xD8, 0xCB, 0x04, 0x48, 0x99, 0x4C, 0x00, 0xA4, 0x2A, 0xA5, 0x8A, 0xF1,
489 0x58, 0xD5, 0x17, 0x4C, 0xC5, 0x88, 0x06, 0x8F, 0xA6, 0x67, 0xA6, 0x14, 0xC7, 0xB9, 0xE0, 0x86,
490 0xAC, 0x67, 0xFD, 0xB3, 0x5B, 0x3E, 0xDF, 0x03, 0xFD, 0xC8, 0xC4, 0x4A, 0x32, 0x78, 0x6B, 0xD1,
491 0xC1, 0xE2, 0x36, 0x9D, 0x0B, 0xF2, 0x54, 0x25, 0xB8, 0xB7, 0xB2, 0x10, 0x7A, 0xA6, 0x79, 0x52,
492 0xC2, 0xEE, 0x98, 0xA5, 0x3D, 0xF0, 0x07, 0x8D, 0x25, 0xC3, 0xAC, 0xFD, 0xCF, 0x83, 0x98, 0x80,
493 0x56, 0x95, 0xC4, 0x14, 0xA2, 0xA5, 0x93, 0xFE, 0x24, 0x59, 0x44, 0x73, 0xDF, 0xD6, 0x47, 0xDA,
494 0x22, 0x3A, 0x82, 0xC5, 0xD1, 0x59, 0x40, 0x9D, 0x0C, 0x1A, 0xB7, 0x79, 0x45, 0x9A, 0xF8, 0x6D,
495 0x5A, 0x5C, 0xC2, 0x80, 0xFC, 0xAA, 0x8A, 0xA4, 0xFE, 0x68, 0x61, 0x7D, 0xFE, 0x2C, 0x36, 0xE3,
496 0xE0, 0x59, 0x28, 0x40, 0x79, 0xAD, 0x2D, 0x28, 0x12, 0x30, 0xFC, 0x56, 0x2E, 0x1D, 0xEC, 0x48,
497 0x3A, 0xF0, 0xC5, 0x6C, 0x31, 0xE0, 0x2E, 0xB3, 0x91, 0x70, 0xB9, 0x9E, 0xBD, 0xE7, 0x96, 0x58,
498 0xCB, 0xBC, 0x1C, 0xE4, 0xC7, 0x78, 0xC7, 0x1E, 0x39, 0xDB, 0xB8, 0x77, 0x50, 0xB7, 0x65, 0x20,
499 0x04, 0x16, 0x8B, 0xFC, 0x66, 0xC4, 0x6D, 0x05, 0x8C, 0x3C, 0xB6, 0x32, 0x2F, 0xDE, 0xC3, 0x6F,
500 0xFC, 0x82, 0x06, 0x02, 0x87, 0x47, 0xFD, 0xD8, 0xDA, 0x75, 0xE0, 0x4E, 0x8C, 0x40, 0x00, 0xB2,
501 0x9B, 0x35, 0x78, 0xA4, 0x61, 0x64, 0x96, 0x62, 0x37, 0xF6, 0x3E, 0x39, 0xFA, 0x14, 0x5B, 0xC4,
502 0x70, 0x17, 0xDC, 0x0C, 0x9E, 0x31, 0x82, 0x2C, 0x63, 0xCC, 0x8A, 0x43, 0x7C, 0x69, 0x12, 0x05,
503 0x18, 0xA3, 0x62, 0xCC, 0xA2, 0x13, 0x96, 0x25, 0xA6, 0x1B, 0xF2, 0x10, 0xC8, 0x73, 0x4F, 0xCB,
504 0x80, 0xCA, 0xAF, 0x73, 0xC9, 0x78, 0xB1, 0xAE, 0x87, 0xB8, 0xDF, 0x50, 0xD3, 0x55, 0x1E, 0x3A,
505 0x81, 0xF6, 0x84, 0xD6, 0x57, 0x36, 0xCF, 0x38, 0xB7, 0xBC, 0xBC, 0x1E, 0x48, 0x62, 0x9F, 0x0F,
506 0x0C, 0xE5, 0xF0, 0x63, 0x33, 0xE6, 0x59, 0x6B, 0x1E, 0xE6, 0x1C, 0x8A, 0xF9, 0xDD, 0x6B, 0xA3,
507 0xDC, 0x02, 0x4A, 0x2F, 0x8C, 0x6A, 0x8D, 0x16, 0x7E, 0x2F, 0xF1, 0x75, 0xD5, 0x15, 0x93, 0x07,
508 0x27, 0xD9, 0x6F, 0x1A, 0x5D, 0x43, 0xF3, 0x47, 0xC4, 0xED, 0xAD, 0x05, 0x9F, 0xEC, 0x8F, 0xD0,
509 0xBE, 0xB5, 0x58, 0xF4, 0xF6, 0xBE, 0x08, 0x73, 0x96, 0x19, 0x05, 0x25, 0xEC, 0x3D, 0x26, 0xF4,
510 0x93, 0xDB, 0x9F, 0x56, 0x48, 0x4C, 0xBC, 0xD0, 0x02, 0x59, 0xD1, 0x40, 0x4C, 0xA6, 0x06, 0x41,
511 0xE8, 0x7D, 0x47, 0xAE, 0x3A, 0x9E, 0x1A, 0x71, 0x52, 0xD4, 0x67, 0xC1, 0x14, 0x7E, 0x40, 0x6F,
512 0x1C, 0x75, 0x30, 0x7B, 0x70, 0x3A, 0xE0, 0x37, 0xB7, 0x41, 0x7F, 0xCB, 0x4A, 0xBA, 0xA7, 0xCE,
513 0x56, 0x54, 0xC5, 0x46, 0x65, 0x6F, 0xB4, 0xB6, 0xF0, 0x57, 0xCE, 0x2E, 0x4F, 0xA9, 0xF0, 0x14,
514 0x50, 0xC3, 0x30, 0xC5, 0xBA, 0xE1, 0x5E, 0xD6, 0xDC, 0xC5, 0x78, 0x55, 0x32, 0xAA, 0xCB, 0x29,
515 0x35, 0x81, 0x46, 0x5E, 0x92, 0xE7, 0xDE, 0xCC, 0x92, 0x29, 0x86, 0xE0, 0x8F, 0x91, 0x3C, 0x74,
516 0x97, 0x79, 0x63, 0x97, 0x4A, 0xCC, 0x88, 0xB5, 0xA3, 0x7A, 0xF0, 0xF0, 0x33, 0x87, 0xCD, 0xBD
518 uint8_t b = Value ^ hdSurEncBasicCrypt_D2_0F_11(Value, lookup[(((AddrInd * 2) + 0) * 256) + Value]);
519 return (Value ^ hdSurEncBasicCrypt_D2_0F_11(b, lookup[(((AddrInd * 2) + 1) * 256) + b]));
522 void hdSurEncPhase1_D2_0F_11(uint8_t *CWs)
524 static const uint8_t lookup1[] =
526 0x16, 0x71, 0xCA, 0x14, 0xC4, 0xF4, 0xA3, 0x5A, 0x9D, 0x5F, 0x85, 0x8B, 0xA6, 0x77, 0xFD, 0x3C,
527 0x5F, 0x13, 0x2A, 0x5F, 0x61, 0x36, 0xE4, 0xDC, 0x0D, 0x82, 0x92, 0xC5, 0x25, 0xE1, 0x7A, 0x1C,
528 0x29, 0x19, 0x94, 0x2F, 0xC5, 0xD2, 0xDC, 0xBA, 0x86, 0x60, 0x64, 0x60, 0x86, 0x92, 0xA3, 0x4E,
529 0x3D, 0x9B, 0xCC, 0x16, 0xBB, 0xBA, 0xD2, 0xF0, 0x6A, 0xD3, 0x2F, 0x07, 0x75, 0xBD, 0x28, 0xDB
531 static const int8_t lookup2[] = { 1, -1, -1, 1, -1, 2, 1, -2, -1, 1, 2, -2, 1, -2, -2, 4 };
532 static const int8_t CAddrIndex[] = { 0, 1, 3, 4 };
533 int32_t i, j, i1, i2, i3;
535 for(i = 3; i >= 0; --i)
537 for(j = 0; j <= 15; ++j)
539 CWs[j] = CWs[j] ^ hdSurEncBasicCrypt_D2_0F_11(j , lookup1 [(16 * i) + j]);
542 uint8_t Buffer[16];
543 uint32_t k;
544 for(i1 = 0; i1 <= 3; ++i1)
546 for(i2 = 0; i2 <= 3; ++i2)
548 k = 0;
549 for(i3 = 0; i3 <= 3; ++i3)
551 k = k + (CWs[(i2 * 4) + i3] * lookup2[(i3 * 4) + i1]);
552 Buffer[(i2 * 4) + i1] = (uint8_t)k;
556 memcpy(CWs, Buffer, 16);
558 // CW positions are mixed around here
559 uint8_t a4[4];
560 for(i1 = 1; i1 <= 3; ++i1)
562 for(i2 = 0; i2 <= 3; ++i2)
564 a4[i2] = i1 + (i2 * 4);
567 for(i2 = 0; i2 <= i1 - 1; ++i2) // the given code in Func1_3 seems to be wrong here(3 instead of i1-1)!
569 uint8_t tmp = CWs[a4[0]];
571 for(i3 = 1; i3 <= 3; ++i3)
573 CWs[a4[i3 - 1]] = CWs[a4[i3]];
575 CWs[a4[3]] = tmp;
579 for(i1 = 0; i1 <= 15; ++i1)
581 CWs[i1] = hdSurEncCryptLookup_D2_0F_11(CWs[i1], CAddrIndex[i1 & 3]);
586 void hdSurEncPhase2_D2_0F_11_sub(uint8_t *CWa, uint8_t *CWb, uint8_t AddrInd)
588 uint8_t Buffer[8];
589 uint8_t tmp, i;
591 for(i = 0; i <= 7; ++i)
593 Buffer[i] = hdSurEncCryptLookup_D2_0F_11(CWb[i], AddrInd);
596 // some bitshifting
597 tmp = Buffer[7];
598 for(i = 7; i >= 1; --i)
600 Buffer[i] = ((Buffer[1] >> 4) & 0xFF) | ((Buffer[i - 1] << 4) & 0xFF);
602 Buffer[0] = ((Buffer[0] >> 4) & 0xFF) | ((tmp << 4) & 0xFF);
604 // saving the result
605 for(i = 0; i <= 7; ++i)
607 CWa[i] = CWa[i] ^ Buffer[i];
611 void hdSurEncPhase2_D2_0F_11(uint8_t *CWs)
613 hdSurEncPhase2_D2_0F_11_sub(CWs, CWs + 8, 0);
614 hdSurEncPhase2_D2_0F_11_sub(CWs + 8, CWs, 1);
615 hdSurEncPhase2_D2_0F_11_sub(CWs, CWs + 8, 2);
616 hdSurEncPhase2_D2_0F_11_sub(CWs + 8, CWs, 3);
617 hdSurEncPhase2_D2_0F_11_sub(CWs, CWs + 8, 4);
620 void CommonMain_1_D2_13_15(const uint8_t *datain, uint8_t *dataout)
622 const uint8_t Tab3[88] = {
623 0x1B, 0x12, 0x12, 0x0C, 0x12, 0x0C, 0x0C, 0x08, 0x09, 0x09, 0x06, 0x06, 0x06, 0x06, 0x04, 0x04,
624 0x08, 0x04, 0x04, 0x02, 0x04, 0x02, 0x02, 0x01, 0x09, 0x06, 0x09, 0x06, 0x06, 0x04, 0x06, 0x04,
625 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x02, 0x04, 0x04, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01,
626 0x09, 0x06, 0x06, 0x04, 0x09, 0x06, 0x06, 0x04, 0x03, 0x03, 0x02, 0x02, 0x03, 0x03, 0x02, 0x02,
627 0x04, 0x02, 0x04, 0x02, 0x02, 0x01, 0x02, 0x01, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02,
628 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 };
630 int i1,i2;
631 unsigned long bb;
633 for (i1 = 0; i1 < 11; i1++)
635 bb = 0;
636 for (i2 = 0; i2 < 8; i2++)
638 bb += (Tab3[(i1 * 8) + i2] * datain[i2]);
640 dataout[i1] = (bb & 0xFF);
645 unsigned short CommonMain_2_D2_13_15(const uint8_t *data, const unsigned long num)
647 unsigned long bb1, bb2;
649 bb1 = num >> 3;
650 bb2 = (data[bb1] << 24) + (data[bb1 + 1] << 16) + (data[bb1 + 2] << 8);
652 return ((bb2 >> (21 - (num & 7))) & 0x7FF);
655 void CommonMain_3_D2_13_15(uint8_t *data0, uint8_t *data1, int nbrloop)
657 int i;
658 unsigned long bb1, bb2;
660 bb1 = 0;
661 bb2 = 0;
662 for (i = nbrloop - 1; i >= 0; i--)
664 bb1 += (data0[i] * 2) + data1[i];
665 bb2 += data0[i] + data1[i];
666 data0[i] = (bb1 & 0xFF);
667 data1[i] = (bb2 & 0xFF);
668 bb1 >>= 8;
669 bb2 >>= 8;
673 void CommonMain_D2_13_15(const uint8_t *datain, uint8_t *dataout, int loopval)
676 const uint8_t Tab0_Comp[0x800] = {
677 0x54,0x75,0x01,0x0C,0x7C,0xE2,0xC3,0xC2,0x5E,0x13,0x26,0xCA,0xB2,0xCD,0xB8,0x3D,
678 0x02,0x2C,0xE4,0x19,0x41,0x3D,0xE4,0x0F,0xEC,0xF1,0x45,0x83,0xE2,0xE2,0x72,0xF9,
679 0xCD,0x75,0x1E,0x41,0xCC,0x0C,0x1F,0x39,0x87,0x9B,0x46,0xFF,0x68,0x1F,0x00,0xD8,
680 0x41,0x82,0xCA,0xC6,0xEF,0x87,0x90,0xA2,0x7E,0xD9,0xDE,0xC8,0x25,0xEA,0xC9,0x75,
681 0x6E,0x18,0x81,0xD8,0x5A,0xA6,0x74,0x05,0xAF,0xAE,0xE0,0x4F,0x85,0xAD,0x94,0xF6,
682 0x45,0xF4,0xF5,0x55,0xA8,0xEB,0xEC,0xDB,0x6C,0xFF,0x2F,0xC2,0xC3,0x7D,0x93,0xE6,
683 0xF5,0x31,0x96,0xB7,0x9A,0xDB,0xE5,0x76,0x66,0xFB,0xDD,0xBC,0x19,0x18,0x42,0xC6,
684 0x36,0xCD,0x46,0x33,0xEA,0xF1,0x4C,0xC0,0x72,0x07,0xCD,0x61,0xCE,0x0E,0x08,0x01,
685 0xA3,0xFA,0x84,0x21,0xF2,0x43,0x37,0x1C,0xDE,0x25,0x8A,0x1A,0xF4,0xBB,0x40,0xF3,
686 0x53,0xFE,0x17,0x60,0x91,0x6D,0x7B,0x6D,0x5F,0x1C,0x15,0x73,0xCC,0x6E,0x73,0x46,
687 0x27,0x73,0xA3,0x10,0x16,0x32,0xB3,0x39,0x45,0xA6,0x55,0xE7,0x91,0x32,0x24,0xC8,
688 0xAE,0xAF,0x1B,0x28,0x69,0x22,0x2F,0xE9,0x77,0x72,0xBF,0x4B,0x8B,0x07,0x82,0x31,
689 0xB0,0x95,0x10,0x78,0x9F,0xC5,0xF3,0x73,0xE1,0xF8,0x36,0x84,0xFE,0x1B,0x92,0xB2,
690 0xE6,0xA5,0xCE,0xDA,0x56,0x48,0x52,0x77,0x9D,0x9D,0x8E,0x37,0x4B,0xC8,0x35,0x7E,
691 0xB9,0x5D,0xA4,0xAE,0x3F,0xD0,0xAA,0x60,0xA8,0x4C,0x85,0x49,0xF6,0x0C,0x27,0xE8,
692 0x94,0x84,0xA0,0xAA,0x06,0x4D,0xAC,0x58,0x8B,0x61,0x29,0x3D,0x68,0x25,0xD3,0xD3,
693 0x8E,0xA1,0xE0,0x71,0xBF,0x21,0x0C,0xC7,0x18,0x19,0xF1,0x25,0x98,0x5F,0x79,0x5E,
694 0x51,0xBA,0x8C,0x2F,0x52,0x43,0xF3,0x5A,0xE3,0x58,0x97,0x64,0x23,0xE0,0x44,0x4F,
695 0x30,0x2A,0xE0,0x16,0x8D,0x4D,0xD1,0x1F,0x7B,0xC9,0xC5,0x74,0x11,0x23,0x5D,0x95,
696 0xAC,0x7F,0x2E,0x30,0xBE,0x2D,0xE3,0xB5,0xC6,0xA7,0x69,0x99,0x1F,0x18,0x3C,0x96,
697 0x30,0x45,0x99,0x71,0x28,0x08,0x3C,0xF7,0x37,0x4F,0x6A,0xD6,0xAE,0x9B,0x57,0xC1,
698 0xCC,0x2C,0xE2,0x0F,0x7D,0x66,0xF4,0x36,0x0C,0x3B,0x35,0xF6,0x28,0x03,0xA3,0x7A,
699 0x83,0x15,0xF5,0x61,0x5E,0xE8,0xB7,0xD8,0x54,0x33,0x93,0x63,0x80,0x40,0x43,0xD0,
700 0x9C,0xAA,0x3A,0x98,0x50,0xD2,0xB8,0x80,0x5D,0x16,0xDF,0x1C,0x03,0xAA,0x87,0xC7,
701 0x63,0xA5,0x8D,0xA9,0x2E,0xFB,0x4F,0x7C,0x2B,0xF5,0xF9,0x57,0xB5,0x90,0xD8,0x75,
702 0xAB,0x81,0x4C,0x1B,0xAF,0x6C,0x0E,0xCB,0xB1,0x4F,0xD3,0xE3,0x69,0x18,0x8C,0x7A,
703 0x3C,0xE1,0x11,0x86,0x47,0x78,0x11,0xA0,0xD4,0x28,0xC3,0x0D,0xAC,0xC6,0x17,0xA1,
704 0x32,0x9F,0x8F,0x42,0xD9,0x3F,0x66,0xD7,0x2D,0x87,0x7B,0x65,0xD3,0xD6,0x90,0x83,
705 0xA2,0x75,0xE8,0x98,0x90,0x9D,0xDE,0x81,0x9E,0x3D,0xE4,0xA9,0xE4,0x0B,0xBC,0xBA,
706 0x96,0xDD,0x05,0xCA,0xAE,0x78,0x69,0x24,0xDB,0xA7,0x3E,0x7A,0x3B,0xB4,0xC4,0x59,
707 0x61,0xD2,0xF2,0xE3,0x99,0x8F,0x8F,0x8A,0x82,0x33,0xB8,0x17,0x5E,0x7A,0x32,0x41,
708 0x10,0x8D,0xC2,0xEF,0xAA,0xF8,0x5A,0xF7,0xD2,0x1D,0xC0,0xCB,0x5E,0xB7,0x8A,0x78,
709 0x49,0x42,0xEB,0x19,0x1B,0x61,0xA0,0x77,0x5A,0xF4,0x6D,0x55,0xDA,0xEB,0xCE,0x4E,
710 0xB8,0xE6,0x32,0xD7,0x51,0x3F,0x73,0x14,0x34,0x6E,0x38,0xD6,0xA7,0x28,0x87,0x4A,
711 0x59,0xCA,0x1C,0x80,0xB5,0x8C,0x9D,0x94,0xCB,0xFE,0x29,0x41,0xE5,0x69,0xCF,0xFD,
712 0x0B,0xE1,0x7C,0xA1,0x70,0x12,0x76,0x43,0xDA,0xB9,0xD4,0xC3,0x31,0xBC,0x94,0x77,
713 0x04,0xB4,0x1C,0xAA,0xEC,0x6F,0xA5,0x12,0x9D,0x6F,0x34,0x65,0x77,0xA0,0xD2,0x6F,
714 0x60,0xC6,0x47,0xC2,0xDF,0x6A,0x10,0x53,0xD4,0xBA,0xF3,0xB7,0x38,0x79,0x63,0xC9,
715 0xD4,0x77,0xBC,0x54,0xE9,0x79,0x42,0xD5,0xE0,0x71,0xE7,0x9E,0x5A,0x62,0x0C,0xAD,
716 0x01,0x09,0xA8,0x9F,0x8E,0x67,0x4A,0x30,0xA4,0xB1,0x08,0xFC,0x0A,0xEA,0x7A,0x1D,
717 0x4C,0x4A,0x21,0xDE,0x00,0xD7,0x41,0x98,0x6B,0x38,0x50,0x3E,0x1F,0x25,0x06,0xE3,
718 0x6C,0xA3,0x84,0x5B,0xC1,0xED,0x47,0xDD,0xB3,0x83,0x46,0x72,0x69,0xCE,0x72,0x04,
719 0x43,0x67,0x3A,0x19,0xD9,0x0A,0xF7,0x43,0x88,0xCA,0xC7,0x31,0x34,0x21,0x4E,0x4C,
720 0xE8,0xD1,0x70,0x00,0xBD,0xB1,0xB6,0x76,0x6F,0x5B,0xF9,0xF5,0xF4,0x19,0x20,0x21,
721 0xC1,0xF0,0x11,0x36,0x66,0xAB,0x15,0xBD,0x69,0x92,0xC6,0x46,0xDE,0xDC,0xE9,0x9A,
722 0xF8,0x6C,0x15,0x29,0x15,0xA6,0x35,0x3E,0x08,0xE5,0x90,0x62,0x9F,0x86,0x56,0x83,
723 0x5D,0x60,0x0D,0x22,0x77,0xA7,0x60,0x9B,0x26,0x80,0x16,0x67,0xB4,0x46,0xBF,0x74,
724 0x55,0x92,0x5B,0x34,0xFF,0xC8,0x28,0x37,0xFF,0x14,0x62,0xFA,0xBD,0x03,0x78,0x04,
725 0x1B,0x65,0x7F,0x99,0x05,0x27,0x14,0xC0,0x06,0x4D,0x4B,0x0E,0x98,0x34,0x6A,0xB3,
726 0xA1,0xFE,0xBC,0x45,0x7D,0x52,0x50,0x0E,0x2C,0xFB,0x91,0xF5,0xFB,0x2A,0xB7,0xD9,
727 0xB8,0xB8,0x54,0x31,0x81,0x03,0x93,0x2C,0xE1,0x5C,0xB9,0x2C,0xE8,0x38,0xC0,0xA7,
728 0x58,0x18,0x92,0xC5,0x8B,0xEF,0x1E,0x33,0xA4,0xBA,0x86,0x2B,0xE9,0xEE,0xB1,0xDF,
729 0xAB,0xB8,0x48,0xDA,0x84,0xF1,0x68,0x05,0x4E,0xDE,0xB5,0x9E,0x88,0x12,0xC9,0x60,
730 0x50,0x58,0x56,0x9D,0x26,0x84,0xB6,0x1A,0xE6,0x4B,0x40,0x94,0x6D,0xE9,0x1D,0x0D,
731 0x8A,0xF9,0x2A,0xB5,0xBC,0xDB,0x06,0x8F,0x13,0x7E,0x1D,0x1C,0xC7,0xFD,0x8F,0x78,
732 0x55,0x3F,0x16,0x84,0x48,0xDA,0x1A,0xD1,0x93,0x95,0x20,0x58,0x92,0x39,0xF6,0x73,
733 0x4E,0x9E,0x7B,0x70,0xFC,0x1E,0x5B,0x20,0x48,0x96,0xB3,0x7C,0x50,0x09,0x5B,0x61,
734 0x57,0x97,0x36,0x04,0x29,0x2C,0x32,0x8E,0x93,0x4A,0x45,0xFA,0xD5,0x24,0x14,0x1A,
735 0x28,0x9C,0x1A,0x71,0xAE,0x85,0x4B,0x26,0x79,0x99,0x65,0xD0,0x07,0x98,0xED,0xC9,
736 0x1B,0x39,0x57,0x5B,0xDB,0x3D,0x87,0x69,0x66,0x9B,0x03,0x23,0x54,0x6B,0x4B,0xAC,
737 0x6E,0x7A,0x25,0x1E,0xB6,0x97,0xCF,0x1D,0x07,0xCB,0x2A,0x3E,0x85,0x02,0x93,0x31,
738 0x12,0x27,0xF0,0xA6,0x6D,0x0F,0x9A,0xB6,0xFC,0x22,0x79,0x6C,0x77,0xFD,0x3F,0xDC,
739 0x19,0xD0,0xDF,0xBD,0x9E,0xE0,0xBE,0x20,0x13,0xA3,0x0A,0x0B,0x22,0xF2,0xC8,0x6B,
740 0xA1,0xDD,0x6C,0x67,0xB3,0xFD,0x71,0xC2,0x7B,0x08,0x3B,0xF1,0x37,0xB5,0x0F,0x86,
741 0xFA,0xA9,0xE9,0x42,0xD1,0xE8,0xCD,0x05,0xEF,0xD3,0xCC,0x0B,0x70,0x51,0x5B,0x97,
742 0x06,0xC4,0x9D,0x88,0x11,0x3E,0x99,0x9F,0xBE,0x76,0x8C,0x8D,0xE6,0xBA,0xDA,0x48,
743 0xD0,0x04,0x86,0x4F,0xA9,0xC6,0xB0,0xED,0xA4,0x94,0x46,0x96,0x27,0xEE,0x9F,0xBD,
744 0xDA,0x9B,0x3D,0x11,0x80,0xD3,0x7B,0x5A,0x48,0x94,0xE5,0xCC,0x48,0xEA,0xE4,0x18,
745 0xDF,0x51,0xB3,0x02,0x57,0x20,0x4B,0x0F,0x07,0xFF,0x41,0x33,0x0F,0x6B,0x2E,0xAA,
746 0xDE,0xB2,0x56,0xF7,0xFB,0xA2,0x48,0x3C,0x97,0x1A,0x64,0x2C,0xD1,0x74,0x40,0xCF,
747 0x65,0x7F,0x14,0x08,0x59,0xC4,0x35,0xD3,0x8A,0x0F,0xFD,0x71,0x7A,0x71,0xAC,0x2D,
748 0xF3,0xFD,0x7B,0x12,0x5F,0xC0,0xBC,0x4E,0x96,0x12,0xF2,0x8E,0x41,0x84,0x01,0x0F,
749 0xED,0x7B,0xC1,0xB9,0x39,0x03,0x35,0x40,0x49,0x53,0xB8,0xB4,0x6B,0xA6,0xE7,0x0A,
750 0x14,0xBB,0x29,0x16,0xEC,0x2A,0x3A,0xD6,0x09,0xBB,0x5C,0x20,0xF8,0x09,0xFD,0x86,
751 0xC4,0x25,0x09,0x85,0x0B,0xD5,0xD8,0x51,0xB1,0xA2,0xCB,0xDC,0xC4,0xDD,0x34,0xDF,
752 0xE2,0x85,0xA9,0xCC,0x4E,0x66,0x51,0xFA,0x9C,0x4D,0xB7,0x1E,0x3E,0x49,0x34,0x9C,
753 0x21,0x66,0x07,0x44,0xB2,0xEC,0x73,0xC5,0xBB,0x27,0x9A,0xA5,0x91,0x5A,0xB9,0x9F,
754 0xBE,0xC8,0xA2,0x27,0x89,0x21,0xA7,0xEE,0x50,0x4D,0x43,0x50,0x67,0xC2,0x3B,0x7C,
755 0x20,0x0B,0x95,0x40,0xBE,0xEA,0xB5,0xD9,0x82,0xD7,0x9C,0xB5,0x21,0xAD,0xA6,0xF9,
756 0x70,0xEA,0xCD,0x04,0xDD,0x58,0x91,0x89,0xB2,0xA9,0xF9,0xB4,0x12,0xA2,0x63,0x89,
757 0x40,0x8E,0xEA,0x62,0xEE,0x0B,0x01,0x82,0x6F,0xB3,0x5E,0x5C,0x36,0xBE,0xF4,0x97,
758 0x2C,0xCF,0x96,0x7C,0x0D,0xAD,0x62,0xCE,0xD4,0x38,0xC5,0x32,0x02,0x24,0x57,0x27,
759 0xE0,0xCF,0x56,0xA5,0x72,0x6D,0x90,0x89,0x2D,0x4C,0x34,0xF6,0x1D,0xDD,0x88,0x5E,
760 0x7A,0x23,0xE3,0x6F,0x42,0xA3,0xD9,0x58,0x7E,0xE3,0x52,0x74,0x57,0x63,0xB7,0xB2,
761 0xC1,0xA3,0x30,0x92,0x2E,0xB0,0x91,0x01,0x13,0x36,0x9A,0x6A,0xA7,0x5B,0x3C,0x07,
762 0xFB,0xD8,0x1E,0x7E,0xCF,0x49,0xAB,0x3F,0xCA,0xCE,0x74,0x40,0x54,0x8D,0x83,0x61,
763 0xCA,0xC3,0x76,0x59,0x5C,0x9F,0x49,0x8A,0x7D,0xD1,0x17,0x9C,0xA4,0xDB,0xB9,0x16,
764 0x4D,0x64,0xF7,0xC7,0xF0,0x24,0xE7,0x00,0xB6,0x98,0xD5,0x8B,0x54,0xCB,0x1E,0x8B,
765 0xA2,0x2B,0x7D,0x50,0x51,0x8A,0xF0,0xEF,0x47,0xAE,0xD0,0xD6,0xA0,0x42,0x8A,0xD8,
766 0x22,0xAF,0x02,0x99,0x4A,0xE0,0x8D,0x8D,0xBF,0x11,0x05,0xA4,0xC4,0x9D,0xB3,0x89,
767 0xB4,0x4C,0xC9,0xF7,0x4D,0xC5,0x2A,0x35,0x95,0x30,0xF3,0x0E,0x2F,0xEC,0x6E,0x3A,
768 0x8B,0x05,0x76,0xED,0x1A,0x7C,0xC0,0xE7,0x22,0xCB,0x59,0xFF,0xE6,0x37,0x78,0x44,
769 0xD4,0xEE,0xAD,0xD7,0xBD,0x2E,0xB7,0x6A,0xA4,0x4E,0x0E,0xFB,0xB0,0xF5,0xCB,0x87,
770 0xCF,0xC3,0x18,0x64,0x6F,0x26,0x5C,0xD7,0x16,0xC8,0x7F,0xAB,0x29,0xC4,0xBA,0xFF,
771 0xCD,0x1C,0xE4,0x3A,0xF2,0xEB,0x6A,0x38,0xE4,0x65,0xC2,0x33,0x03,0x26,0x7D,0x9B,
772 0x7E,0x1D,0x83,0x00,0x04,0x2D,0x2B,0x5F,0xFE,0x39,0x7E,0xF1,0x3C,0xA2,0x8C,0x52,
773 0x95,0xBF,0x46,0x81,0x24,0x44,0xF8,0x10,0xC3,0x87,0x8E,0x64,0x80,0x17,0x44,0xE2,
774 0x8B,0xD1,0x3C,0x4A,0xE2,0x1F,0xA9,0xDE,0x75,0x13,0xFC,0x2E,0x86,0x0A,0x5C,0x5F,
775 0x92,0x2B,0x92,0x2D,0x2A,0xEC,0xD2,0x5C,0x82,0x6B,0x76,0x1E,0xED,0xE6,0x56,0xF7,
776 0xD2,0xDB,0x96,0x68,0x02,0x68,0x99,0x49,0xEE,0x88,0x66,0xCE,0x5D,0x08,0x88,0xA8,
777 0xB9,0x24,0xB0,0xB4,0xDC,0xA6,0xC9,0xD8,0x68,0x80,0xBF,0x6B,0x32,0x57,0x7F,0x91,
778 0x0E,0x37,0x59,0xF6,0x76,0xD2,0xC5,0x0B,0xF3,0x23,0xBF,0x38,0x52,0x0D,0x97,0x81,
779 0x17,0xBB,0x9A,0xC2,0x55,0x44,0x72,0xCE,0xEE,0xFA,0xBB,0xDA,0xAB,0xB0,0x09,0xEA,
780 0xDB,0xBF,0x45,0x95,0x07,0x88,0xD4,0xD2,0x0D,0x2E,0x15,0x31,0xBE,0x6A,0xF4,0xEF,
781 0xA3,0x7D,0x22,0x81,0x3B,0xA8,0x83,0xF9,0x42,0xE5,0x9B,0x79,0x01,0xF5,0xDC,0x19,
782 0x64,0xEB,0x47,0x67,0xAF,0xA4,0xB2,0xAE,0xF8,0xF9,0x4D,0x63,0xAD,0x54,0xE1,0x02,
783 0x56,0x89,0x4E,0x0A,0xE8,0x3E,0x03,0xFA,0x33,0x61,0x58,0x80,0x64,0x55,0x3C,0x8C,
784 0x2A,0x3D,0x70,0x3E,0xE5,0xC1,0xA7,0x75,0xFC,0x91,0x75,0x05,0x8C,0x6E,0x3A,0x74,
785 0x10,0xF1,0x30,0xE6,0xF6,0xF7,0xAB,0x6C,0xB1,0x2B,0xF0,0x2F,0x13,0x6E,0xD4,0x0A,
786 0x64,0x29,0xF8,0xBB,0xA1,0xAA,0x55,0x09,0x93,0x47,0x2F,0x8C,0x7D,0xF1,0x2D,0x81,
787 0xFE,0x78,0xFC,0xEE,0x3F,0xDD,0x49,0xDC,0x0D,0x52,0x5C,0x3B,0x8F,0x08,0xB0,0xDF,
788 0xDC,0xFC,0xBE,0x5F,0x3B,0x53,0x82,0xE2,0xBD,0x6D,0x5D,0xF2,0x8D,0xFB,0x5A,0x1D,
789 0x15,0x1B,0xE4,0xB1,0x56,0x06,0x1A,0xF8,0x9C,0xB9,0x44,0xF2,0xD9,0xF4,0xB2,0x00,
790 0x9A,0x94,0x62,0x33,0x7E,0x0A,0xB0,0x0C,0xD5,0xEF,0x8E,0xA8,0xEB,0x47,0xE9,0x20,
791 0xA8,0x68,0xEF,0x53,0xA0,0x59,0x1B,0xA0,0x2B,0xC5,0x2B,0x30,0xB6,0x5D,0xAB,0xB4,
792 0x5F,0x86,0x71,0x95,0x89,0xFC,0xC7,0x9A,0xC3,0xED,0x82,0xA0,0x3D,0x73,0xC1,0x36,
793 0x01,0x5F,0x9E,0xD7,0xE3,0xC0,0x62,0x74,0xED,0x13,0xB6,0xD6,0xD5,0x37,0x17,0xE1,
794 0x39,0xC7,0x6D,0x31,0xBA,0x02,0xAF,0xD5,0xCC,0x51,0xA8,0x09,0x3F,0x00,0x4A,0x8F,
795 0xA6,0x23,0x13,0x88,0xCD,0x1F,0x38,0x60,0xE7,0xE7,0x53,0xDC,0x65,0xE8,0x53,0x26,
796 0xBB,0xE1,0x1F,0x65,0xF0,0xAD,0x53,0x3B,0xBD,0xAD,0x97,0xAC,0xD1,0xA5,0xD0,0xE9,
797 0xEB,0xD6,0x11,0xD5,0x00,0xDF,0x72,0x9C,0xCC,0x7F,0xD3,0x67,0xA1,0x3A,0x79,0xE1,
798 0x85,0x70,0xE5,0x43,0xC9,0x28,0xA5,0x2F,0x9E,0xE7,0xFE,0xEB,0x14,0x10,0x23,0xC7,
799 0xAF,0xB1,0x24,0xC8,0xE5,0x44,0x6F,0x4C,0x04,0xEC,0xC1,0xF0,0x23,0x1C,0xF6,0xAC,
800 0xAF,0xC4,0x0E,0x2D,0x59,0x39,0x47,0xA9,0x9E,0xD9,0x2E,0x79,0xBA,0xFE,0x4F,0x12,
801 0x7F,0x63,0x7F,0x62,0x67,0x7C,0x52,0x2F,0xCA,0x8B,0x6B,0x4F,0x10,0x8F,0x14,0xC6,
802 0xA1,0x9B,0x45,0x15,0x90,0x63,0x22,0x5D,0x68,0x4B,0xCF,0xFA,0x6A,0x06,0xF0,0x26,
803 0xAC,0x6C,0x3A,0x89,0x25,0xF3,0x5E,0x90,0x06,0x93,0xB6,0x35,0x0D,0x85,0x60,0x98,
804 0xBC,0x6E,0xF2,0xA5,0x17,0x29,0x70,0xD6,0xFF,0x0C,0xD0,0xC0,0x35,0xD7,0x4A,0xFD };
807 const uint8_t Tab1_Comp[11*8] = {
808 0x70,0x49,0xD7,0xE3,0xDF,0x3C,0x96,0x03,0x2A,0x70,0x82,0xA6,0x5F,0xDE,0xCC,0x0C,
809 0x2A,0x62,0x2A,0x3E,0xA4,0x0C,0x0A,0xAB,0x4F,0x06,0x5D,0xD4,0x14,0xAA,0xE1,0xC3,
810 0x96,0xDA,0x16,0x36,0x45,0x3C,0x63,0xC2,0x97,0x71,0x87,0xAB,0xFA,0xB2,0xFC,0xD6,
811 0x8F,0x85,0xC9,0x04,0x56,0xBA,0xEB,0x3F,0x42,0x9F,0xCB,0x66,0x55,0x45,0x1C,0x96,
812 0xFF,0x4D,0x35,0xDF,0x88,0x0E,0xDC,0xC8,0x4E,0x3F,0x81,0x74,0xD8,0x77,0x4C,0x8E,
813 0x00,0xC0,0x64,0x83,0x4E,0xBB,0xF0,0xB1 };
815 unsigned short buff8[8];
816 uint8_t buff11[11 + 1]; // +1 to avoid func2 bug
817 int i1, i2;
818 buff11[11] = 0;
820 CommonMain_1_D2_13_15(datain, buff11);
821 for (i1 = 0; i1 < 11; i1++)
823 buff11[i1] ^= Tab1_Comp[(loopval * 11) + i1];
826 for (i1 = 0; i1 < 8; i1++)
828 buff8[i1] = CommonMain_2_D2_13_15(buff11, i1 * 11);
831 for (i1 = 0; i1 < 8; i1++)
833 dataout[i1] = Tab0_Comp[buff8[i1]];
836 i1 = 1;
837 while (i1 < 8)
839 i2 = 0 ;
840 while (i2 < 8)
842 CommonMain_3_D2_13_15(&dataout[i2], &dataout[i1 + i2], i1);
843 i2 += (i1 * 2);
845 i1 *= 2;
849 void Common_D2_13_15(uint8_t *cw0, const uint8_t *cw1, int loopval)
851 int i;
852 uint8_t buff8[8];
854 CommonMain_D2_13_15(cw1, buff8, loopval);
855 for (i = 0; i < 8; i++)
857 cw0[i] ^= buff8[i];
861 void ExchangeCWs(uint8_t *cw0, uint8_t *cw1)
863 int i;
864 uint8_t b;
866 for (i = 0; i < 8; i++)
868 b = cw1[i];
869 cw1[i] = cw0[i];
870 cw0[i] = b;
875 void hdSurEncPhase1_D2_13_15(uint8_t *cws)
877 int i;
879 for (i = 0; i <= 7; i++)
881 // Possible code
882 if ((i & 1) == 0)
884 Common_D2_13_15((uint8_t *) &cws[0], (uint8_t *) &cws[8], i);
886 else
888 Common_D2_13_15((uint8_t *) &cws[8], (uint8_t *) &cws[0], i);
891 ExchangeCWs((uint8_t *) &cws[0], (uint8_t *) &cws[8]);
894 void hdSurEncPhase2_D2_13_15(uint8_t *cws)
896 int i;
898 for (i = 7; i >= 0; i--)
900 // Possible code
901 if ((i & 1) == 0)
903 Common_D2_13_15((uint8_t *) &cws[8], (uint8_t *) &cws[0], i);
905 else
907 Common_D2_13_15((uint8_t *) &cws[0], (uint8_t *) &cws[8], i);
910 ExchangeCWs((uint8_t *) &cws[8], (uint8_t *) &cws[0]);
914 static int32_t viaccess_card_init(struct s_reader *reader, ATR *newatr)
916 get_atr;
917 def_resp;
918 int32_t i;
919 uint8_t buf[256];
920 uint8_t insac[] = { 0xca, 0xac, 0x00, 0x00, 0x00 }; // select data
921 uint8_t insb8[] = { 0xca, 0xb8, 0x00, 0x00, 0x00 }; // read selected data
922 uint8_t insa4[] = { 0xca, 0xa4, 0x00, 0x00, 0x00 }; // select issuer
923 uint8_t insc0[] = { 0xca, 0xc0, 0x00, 0x00, 0x00 }; // read data item
924 static const uint8_t insFAC[] = { 0x87, 0x02, 0x00, 0x00, 0x03 }; // init FAC
925 static const uint8_t FacDat[] = { 0x00, 0x00, 0x28 };
926 static uint8_t ins8702_data[] = { 0x00, 0x00, 0x11};
927 static uint8_t ins8704[] = { 0x87, 0x04, 0x00, 0x00, 0x07 };
928 static uint8_t ins8706[] = { 0x87, 0x06, 0x00, 0x00, 0x04 };
930 if((atr[1] != 0x77) || ((atr[2] != 0x18) && (atr[2] != 0x11) && (atr[2] != 0x19)) || ((atr[9] != 0x68) && (atr[9] != 0x6C) && (atr[9] != 0x64)))
932 return ERROR;
935 write_cmd(insFAC, FacDat);
936 if(!(cta_res[cta_lr - 2] == 0x90 && cta_res[cta_lr - 1] == 0))
938 return ERROR;
941 if(!cs_malloc(&reader->csystem_data, sizeof(struct viaccess_data)))
943 return ERROR;
946 struct viaccess_data *csystem_data = reader->csystem_data;
948 write_cmd(insFAC, ins8702_data);
949 if((cta_res[cta_lr - 2] == 0x90) && (cta_res[cta_lr - 1] == 0x00))
951 write_cmd(ins8704, NULL);
952 if((cta_res[cta_lr - 2] == 0x90) && (cta_res[cta_lr - 1] == 0x00))
954 write_cmd(ins8706, NULL);
955 if((cta_res[cta_lr - 2] == 0x90) && (cta_res[cta_lr - 1] == 0x00))
957 csystem_data->last_geo.number_ecm = (cta_res[2] << 8) | (cta_res[3]);
958 rdr_log(reader, "using ecm #%x for long viaccess ecm", csystem_data->last_geo.number_ecm);
963 reader->caid = 0x500;
964 memset(reader->prid, 0xff, sizeof(reader->prid));
965 insac[2] = 0xa4;
966 write_cmd(insac, NULL); // request unique id
967 insb8[4] = 0x07;
968 write_cmd(insb8, NULL); // read unique id
969 memcpy(reader->hexserial, cta_res + 2, 5);
970 // rdr_log(reader, "[viaccess-reader] type: Viaccess, ver: %s serial: %llu", ver, b2ll(5, cta_res+2));
971 rdr_log_sensitive(reader, "type: Viaccess (%sstandard atr), caid: %04X, serial: {%llu}",
972 atr[9] == 0x68 ? "" : "non-", reader->caid, (unsigned long long) b2ll(5, cta_res + 2));
974 i = 0;
975 insa4[2] = 0x00;
976 write_cmd(insa4, NULL); // select issuer 0
977 buf[0] = 0;
978 while((cta_res[cta_lr - 2] == 0x90) && (cta_res[cta_lr - 1] == 0))
980 insc0[4] = 0x1a;
981 write_cmd(insc0, NULL); // show provider properties
982 cta_res[2] &= 0xF0;
983 reader->prid[i][0] = 0;
984 memcpy(&reader->prid[i][1], cta_res, 3);
985 memcpy(&csystem_data->availkeys[i][0], cta_res + 10, 16);
986 snprintf((char *)buf + strlen((char *)buf), sizeof(buf) - strlen((char *)buf), ",%06X", b2i(3, &reader->prid[i][1]));
987 // rdr_log(reader, "[viaccess-reader] buf: %s", buf);
989 insac[2] = 0xa5;
990 write_cmd(insac, NULL); // request sa
991 insb8[4] = 0x06;
992 write_cmd(insb8, NULL); // read sa
993 memcpy(&reader->sa[i][0], cta_res + 2, 4);
995 insa4[2] = 0x02;
996 write_cmd(insa4, NULL); // select next issuer
997 i++;
999 reader->nprov = i;
1000 rdr_log(reader, "providers: %d (%s)", reader->nprov, buf + 1);
1002 get_maturity(reader);
1003 if(cfg.ulparent)
1005 unlock_parental(reader);
1008 rdr_log(reader, "ready for requests");
1009 return OK;
1012 bool dcw_crc(uint8_t *dw)
1014 int8_t i;
1015 for(i = 0; i < 16; i += 4) if(dw[i + 3] != ((dw[i] + dw[i + 1] + dw[i + 2]) & 0xFF)) { return 0; }
1016 return 1;
1019 static int32_t viaccess_do_ecm(struct s_reader *reader, const ECM_REQUEST *er, struct s_ecm_answer *ea)
1021 def_resp;
1022 static const uint8_t insa4[] = { 0xca, 0xa4, 0x04, 0x00, 0x03 }; // set provider id
1023 uint8_t ins88[] = { 0xca, 0x88, 0x00, 0x00, 0x00 }; // set ecm
1024 uint8_t insf8[] = { 0xca, 0xf8, 0x00, 0x00, 0x00 }; // set geographic info
1025 static const uint8_t insc0[] = { 0xca, 0xc0, 0x00, 0x00, 0x12 }; // read dcw
1026 struct viaccess_data *csystem_data = reader->csystem_data;
1028 // //XXX what is the 4th uint8_t for ??
1029 int32_t ecm88Len = MIN(MAX_ECM_SIZE - 4, SCT_LEN(er->ecm) - 4);
1030 if(ecm88Len < 1)
1032 rdr_log(reader, "ECM: Size of ECM couldn't be correctly calculated.");
1033 return ERROR;
1035 uint8_t ecmData[ecm88Len];
1036 memset(ecmData, 0, ecm88Len);
1037 memcpy(ecmData, er->ecm + 4, ecm88Len);
1038 uint8_t *ecm88Data = &ecmData[0];
1039 uint32_t provid = 0;
1040 int32_t rc = 0;
1041 int32_t hasD2 = 0;
1042 uint8_t hasE0 = 0;
1043 int32_t curEcm88len = 0;
1044 int32_t nanoLen = 0;
1045 uint8_t *nextEcm;
1046 uint8_t DE04[MAX_ECM_SIZE];
1047 int32_t D2KeyID = 0;
1048 int32_t curnumber_ecm = 0;
1049 // nanoD2 d2 02 0d 02 -> D2 nano, len 2
1050 // 0b, 0f, 13 -> pre AES decrypt CW
1051 // 0d, 11, 15 -> post AES decrypt CW
1053 int32_t nanoD2 = 0; // knowns D2 nanos: 0x0b ,0x0d ,0x0f ,0x11, 0x13, 0x15
1055 memset(DE04, 0, sizeof(DE04)); //fix dorcel de04 bug
1057 nextEcm = ecm88Data;
1059 while(ecm88Len > 0 && !rc)
1062 if(ecm88Data[0] == 0x00 && ecm88Data[1] == 0x00)
1064 // nano 0x00 and len 0x00 aren't valid... something is obviously wrong with this ecm.
1065 rdr_log(reader, "ECM: Invalid ECM structure. Rejecting");
1066 return ERROR;
1069 // 80 33 nano 80 (ecm) + len (33)
1070 if(ecm88Data[0] == 0x80) // nano 80, give ecm len
1072 curEcm88len = ecm88Data[1];
1073 nextEcm = ecm88Data + curEcm88len + 2;
1074 ecm88Data += 2;
1075 ecm88Len -= 2;
1078 if(!curEcm88len) // there was no nano 80 -> simple ecm
1080 curEcm88len = ecm88Len;
1083 // d2 02 0d 02 -> D2 nano, len 2, select the AES key to be used
1084 if(ecm88Data[0] == 0xd2)
1086 // test if it needs AES decrypt
1087 if(ecm88Data[2] == 0x0b)
1089 nanoD2 = 0x0b;
1090 rdr_log_dbg(reader, D_READER, "ECM: nano D2 0x0b");
1093 if(ecm88Data[2] == 0x0d)
1095 nanoD2 = 0x0d;
1096 rdr_log_dbg(reader, D_READER, "ECM: nano D2 0x0d");
1099 if(ecm88Data[2] == 0x0f)
1101 nanoD2 = 0x0f;
1102 rdr_log_dbg(reader, D_READER, "ECM: nano D2 0x0f");
1105 if(ecm88Data[2] == 0x11)
1107 nanoD2 = 0x11;
1108 rdr_log_dbg(reader, D_READER, "ECM: nano D2 0x11");
1111 if(ecm88Data[2] == 0x13)
1113 nanoD2 = 0x13;
1114 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");
1123 // use the d2 arguments to get the key # to be used
1124 int32_t len = ecm88Data[1] + 2;
1125 D2KeyID = ecm88Data[3];
1126 ecm88Data += len;
1127 ecm88Len -= len;
1128 curEcm88len -= len;
1129 hasD2 = 1;
1131 else
1133 hasD2 = 0;
1136 // 40 07 03 0b 00 -> nano 40, len =7 ident 030B00 (tntsat), key #0 <== we're pointing here
1137 // 09 -> use key #9
1138 // 05 67 00
1139 if((ecm88Data[0] == 0x90 || ecm88Data[0] == 0x40) && (ecm88Data[1] == 0x03 || ecm88Data[1] == 0x07))
1141 uint8_t ident[3], keynr;
1142 uint8_t *ecmf8Data = 0;
1143 int32_t ecmf8Len = 0;
1145 nanoLen = ecm88Data[1] + 2;
1146 keynr = ecm88Data[4] & 0x0F;
1148 // 40 07 03 0b 00 -> nano 40, len =7 ident 030B00 (tntsat), key #0 <== we're pointing here
1149 // 09 -> use key #9
1150 if(nanoLen > 5)
1152 curnumber_ecm = (ecm88Data[6] << 8) | (ecm88Data[7]);
1153 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);
1154 // if we have an ecm number we check it.
1155 // we can't assume that if the nano len is 5 or more we have an ecm number
1156 // as some card don't support this
1157 if(csystem_data->last_geo.number_ecm > 0)
1159 if(csystem_data->last_geo.number_ecm == curnumber_ecm && !(ecm88Data[nanoLen - 1] == 0x01))
1161 keynr = ecm88Data[5];
1162 rdr_log_dbg(reader, D_READER, "keyToUse = %02x, ECM ending with %02x", ecm88Data[5], ecm88Data[nanoLen - 1]);
1164 else
1166 if(ecm88Data[nanoLen - 1] == 0x01)
1168 rdr_log_dbg(reader, D_READER, "Skip ECM ending with = %02x for ecm number (%x) for provider %02x%02x%02x",
1169 ecm88Data[nanoLen - 1], curnumber_ecm, ecm88Data[2], ecm88Data[3], ecm88Data[4]);
1171 rdr_log_dbg(reader, D_READER, "Skip ECM ending with = %02x for ecm number (%x)", ecm88Data[nanoLen - 1], curnumber_ecm);
1172 ecm88Data = nextEcm;
1173 ecm88Len -= curEcm88len;
1174 continue; // loop to next ecm
1177 else // long ecm but we don't have an ecm number so we have to try them all.
1179 keynr = ecm88Data[5];
1180 rdr_log_dbg(reader, D_READER, "keyToUse = %02x", ecm88Data[5]);
1184 memcpy(ident, &ecm88Data[2], sizeof(ident));
1185 provid = b2i(3, ident);
1186 ident[2] &= 0xF0;
1188 if(hasD2 && reader->aes_list)
1190 // check that we have the AES key to decode the CW
1191 // if not there is no need to send the ecm to the card
1192 if(!aes_present(reader->aes_list, 0x500, (uint32_t)(provid & 0xFFFFF0) , D2KeyID))
1194 return ERROR;
1198 if(!chk_prov(reader, ident, keynr))
1200 rdr_log_dbg(reader, D_READER, "ECM: provider or key not found on card");
1201 snprintf(ea->msglog, MSGLOGSIZE, "provider(%02x%02x%02x) or key(%d) not found on card", ident[0], ident[1], ident[2], keynr);
1202 return ERROR;
1205 ecm88Data += nanoLen;
1206 ecm88Len -= nanoLen;
1207 curEcm88len -= nanoLen;
1209 // DE04
1210 if(ecm88Data[0] == 0xDE && ecm88Data[1] == 0x04)
1212 memcpy(DE04, &ecm88Data[0], 6);
1213 ecm88Data += 6;
1216 // E0 (seen so far in logs: E0020002 or E0022002, but not in all cases delivers invalid cw so just detect!)
1217 if(ecm88Data[0] == 0xE0 && ecm88Data[1] == 0x02)
1219 rdr_log_dbg(reader, D_READER,"[viaccess-reader] nano E0 ECM detected!");
1220 hasE0=1;
1223 if(csystem_data->last_geo.provid != provid)
1225 csystem_data->last_geo.provid = provid;
1226 csystem_data->last_geo.geo_len = 0;
1227 csystem_data->last_geo.geo[0] = 0;
1228 write_cmd(insa4, ident); // set provider
1231 // Nano D2 0x0b, 0x0f, 0x13 -> pre AES decrypt CW
1232 if(hasD2 && (nanoD2 == 0x0b|| nanoD2 == 0x0f|| nanoD2 == 0x13))
1234 uint8_t *ecm88DataCW = ecm88Data;
1235 int32_t cwStart = 0;
1236 //int32_t cwStartRes = 0;
1237 int32_t must_exit = 0;
1238 // find CW start
1239 while(cwStart < curEcm88len - 1 && !must_exit)
1241 if(ecm88Data[cwStart] == 0xEA && ecm88Data[cwStart + 1] == 0x10)
1243 ecm88DataCW = ecm88DataCW + cwStart + 2;
1244 must_exit = 1;
1246 cwStart++;
1249 if(nanoD2 == 0x0f)
1251 hdSurEncPhase1_D2_0F_11(ecm88DataCW);
1252 hdSurEncPhase2_D2_0F_11(ecm88DataCW);
1255 if(nanoD2 == 0x13)
1257 hdSurEncPhase1_D2_13_15(ecm88DataCW);
1260 // use AES from list to decrypt CW
1261 rdr_log_dbg(reader, D_READER, "Decoding CW : using AES key id %d for provider %06x", D2KeyID, (provid & 0xFFFFF0));
1262 if(aes_decrypt_from_list(reader->aes_list, 0x500, (uint32_t)(provid & 0xFFFFF0), D2KeyID, &ecm88DataCW[0], 16) == 0)
1264 snprintf(ea->msglog, MSGLOGSIZE, "Missing AES key(%d)[aka E%X]",D2KeyID, D2KeyID);
1267 if(nanoD2 == 0x0f)
1269 hdSurEncPhase1_D2_0F_11(ecm88DataCW);
1272 if(nanoD2 == 0x13)
1274 hdSurEncPhase2_D2_13_15(ecm88DataCW);
1278 while(ecm88Len > 1 && ecm88Data[0] < 0xA0)
1280 nanoLen = ecm88Data[1] + 2;
1281 if(!ecmf8Data)
1283 ecmf8Data = (uint8_t *)ecm88Data;
1285 ecmf8Len += nanoLen;
1286 ecm88Len -= nanoLen;
1287 curEcm88len -= nanoLen;
1288 ecm88Data += nanoLen;
1291 if(ecmf8Len)
1293 if(csystem_data->last_geo.geo_len != ecmf8Len || memcmp(csystem_data->last_geo.geo, ecmf8Data, csystem_data->last_geo.geo_len))
1295 memcpy(csystem_data->last_geo.geo, ecmf8Data, ecmf8Len);
1296 csystem_data->last_geo.geo_len = ecmf8Len;
1297 insf8[3] = keynr;
1298 insf8[4] = ecmf8Len;
1299 write_cmd(insf8, ecmf8Data);
1302 ins88[2] = ecmf8Len ? 1 : 0;
1303 ins88[3] = keynr;
1304 ins88[4] = (curEcm88len > 0xFF) ? 0x00 : curEcm88len;
1306 // we should check the nano to make sure the ecm is valid
1307 // we should look for at least 1 E3 nano, 1 EA nano and the F0 signature nano
1309 // DE04
1310 if(DE04[0] == 0xDE)
1312 uint32_t l = curEcm88len - 6;
1313 if(l > MAX_ECM_SIZE || curEcm88len <= 6) //don't known if this is ok...
1315 rdr_log(reader, "ecm invalid/too long! len=%d", curEcm88len);
1316 return ERROR;
1318 memcpy(DE04 + 6, (uint8_t *)ecm88Data, l);
1319 write_cmd(ins88, DE04); // request dcw
1321 else
1323 write_cmd(ins88, (uint8_t *)ecm88Data); // request dcw
1326 write_cmd(insc0, NULL); // read dcw
1327 switch(cta_res[0])
1329 case 0xe8: // even
1330 if(cta_res[1] == 8)
1332 memcpy(ea->cw, cta_res + 2, 8);
1333 rc = 1;
1334 } break;
1336 case 0xe9: // odd
1337 if(cta_res[1] == 8)
1339 memcpy(ea->cw + 8, cta_res + 2, 8);
1340 rc = 1;
1341 } break;
1343 case 0xea: // complete
1344 if(cta_res[1] == 16)
1346 memcpy(ea->cw, cta_res + 2, 16);
1347 rc = 1;
1348 } break;
1350 default :
1351 ecm88Data = nextEcm;
1352 ecm88Len -= curEcm88len;
1353 rdr_log_dbg(reader, D_READER, "Error: card respondend %02X %02X, trying next ECM", cta_res[0], cta_res[1]);
1354 snprintf(ea->msglog, MSGLOGSIZE, "key to use is not the current one, trying next ECM");
1357 else
1359 //ecm88Data=nextEcm;
1360 //ecm88Len-=curEcm88len;
1361 rdr_log_dbg(reader, D_READER, "ECM: Unknown ECM type");
1362 snprintf(ea->msglog, MSGLOGSIZE, "Unknown ECM type");
1363 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
1369 if(hasD2 && !dcw_crc(ea->cw) && (nanoD2 == 0x0d || nanoD2 == 0x11 || nanoD2 == 0x15))
1371 if(nanoD2 == 0x11)
1373 hdSurEncPhase1_D2_0F_11(ea->cw);
1374 hdSurEncPhase2_D2_0F_11(ea->cw);
1377 if(nanoD2 == 0x15)
1379 hdSurEncPhase1_D2_13_15(ea->cw);
1381 rdr_log_dbg(reader, D_READER, "Decoding CW : using AES key id %d for provider %06x", D2KeyID, (provid & 0xFFFFF0));
1382 rc = aes_decrypt_from_list(reader->aes_list, 0x500, (uint32_t)(provid & 0xFFFFF0), D2KeyID, ea->cw, 16);
1384 if(rc == 0)
1386 snprintf(ea->msglog, MSGLOGSIZE, "Missing AES key(%d)[aka E%X]",D2KeyID, D2KeyID);
1389 if(nanoD2 == 0x11)
1391 hdSurEncPhase1_D2_0F_11(ea->cw);
1394 if(nanoD2 == 0x15)
1396 hdSurEncPhase2_D2_13_15(ea->cw);
1400 if (hasE0)
1402 if (reader->initCA28)
1404 rdr_log_dbg(reader, D_READER, "Decrypting nano E0 encrypted cw.");
1405 uint8_t returnedcw[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
1406 memcpy(returnedcw,ea->cw,16);
1408 // Processing 3DES
1409 // Processing even cw
1410 des(returnedcw, reader->key_schedule1, 0); // decrypt
1411 des(returnedcw, reader->key_schedule2, 1); // crypt
1412 des(returnedcw, reader->key_schedule1, 0); // decrypt
1414 // Processing odd cw
1415 des(returnedcw + 8, reader->key_schedule1, 0); // decrypt
1416 des(returnedcw + 8, reader->key_schedule2, 1); // crypt
1417 des(returnedcw + 8, reader->key_schedule1, 0); // decrypt
1419 // returning value
1420 memcpy(ea->cw,returnedcw, 16);
1422 else
1424 snprintf(ea->msglog, MSGLOGSIZE, "nano E0 detected, no valid boxkey / deskey defined: no decoding");
1427 return (rc ? OK : ERROR);
1430 static int32_t viaccess_get_emm_type(EMM_PACKET *ep, struct s_reader *rdr)
1432 uint32_t provid = 0;
1433 rdr_log_dbg(rdr, D_EMM, "Entered viaccess_get_emm_type ep->emm[0]=%02x", ep->emm[0]);
1435 if(ep->emm[3] == 0x90 && ep->emm[4] == 0x03)
1437 provid = b2i(3, ep->emm + 5);
1438 provid &= 0xFFFFF0;
1439 i2b_buf(4, provid, ep->provid);
1442 switch(ep->emm[0])
1444 case 0x88:
1445 ep->type = UNIQUE;
1446 memset(ep->hexserial, 0, 8);
1447 memcpy(ep->hexserial, ep->emm + 4, 4);
1448 rdr_log_dbg(rdr, D_EMM, "UNIQUE");
1449 if(!is_network_reader(rdr))
1451 return (!memcmp(rdr->hexserial + 1, ep->hexserial, 4)); // local reader
1453 else
1455 return 1; // let server decide!
1458 case 0x8A:
1459 case 0x8B:
1460 ep->type = GLOBAL;
1461 rdr_log_dbg(rdr, D_EMM, "GLOBAL");
1462 return 1;
1464 case 0x8C:
1465 case 0x8D:
1466 ep->type = SHARED;
1467 rdr_log_dbg(rdr, D_EMM, "SHARED (part)");
1468 // We need those packets to pass otherwise we would never
1469 // be able to complete EMM reassembly
1470 return 1;
1472 case 0x8E:
1473 ep->type = SHARED;
1474 rdr_log_dbg(rdr, D_EMM, "SHARED");
1475 memset(ep->hexserial, 0, 8);
1476 memcpy(ep->hexserial, ep->emm + 3, 3);
1478 // local reader
1479 int8_t i;
1480 for(i = 0; i < rdr->nprov; i++)
1482 if(!memcmp(&rdr->prid[i][2], ep->hexserial+1, 2))
1484 return 1;
1486 return (!memcmp(&rdr->sa[0][0], ep->hexserial, 3));
1487 } /* fallthrough */
1489 default:
1490 ep->type = UNKNOWN;
1491 rdr_log_dbg(rdr, D_EMM, "UNKNOWN");
1492 return 1;
1496 static int32_t viaccess_get_emm_filter(struct s_reader *rdr, struct s_csystem_emm_filter **emm_filters, unsigned int *filter_count)
1498 if(*emm_filters == NULL)
1500 bool network = is_network_reader(rdr);
1501 int8_t device_emm = ((rdr->deviceemm > 0) ? 1 : 0); // set to 1 if device specific emms should be catched too
1502 const unsigned int max_filter_count = 4 + ((device_emm != 0 && rdr->nprov > 0) ? 1:0) + (3 * ((rdr->nprov > 0) ? (rdr->nprov - 1) : 0));
1504 if(!cs_malloc(emm_filters, max_filter_count * sizeof(struct s_csystem_emm_filter)))
1506 return ERROR;
1509 struct s_csystem_emm_filter *filters = *emm_filters;
1510 *filter_count = 0;
1512 int32_t idx = 0;
1513 int32_t prov;
1515 if(rdr->nprov > 0 && device_emm == 1)
1517 filters[idx].type = EMM_GLOBAL; // 8A or 8B no reassembly needed!
1518 filters[idx].enabled = 1;
1519 filters[idx].filter[0] = 0x8A;
1520 filters[idx].mask[0] = 0xFE;
1521 filters[idx].filter[3] = 0x80; // device specific emms
1522 filters[idx].mask[3] = 0x80;
1523 idx++;
1526 // shared are most important put them on top, define first since viaccess produces a lot of filters!
1527 for(prov = 0; (prov < rdr->nprov); prov++)
1529 if((rdr->prid[prov][2] &0xF0) == 0xF0) // skip this not useful provider
1531 continue;
1534 filters[idx].type = EMM_SHARED; // 8C or 8D always first part of shared, second part delivered by 8E!
1535 filters[idx].enabled = 1;
1536 filters[idx].filter[0] = 0x8C;
1537 filters[idx].mask[0] = 0xFE;
1538 if(rdr->nprov > 0)
1540 memcpy(&filters[idx].filter[4], &rdr->prid[prov][2], 2);
1541 filters[idx].mask[4] = 0xFF;
1542 filters[idx].mask[5] = 0xF0; // ignore last digit since this is key on card indicator!
1544 idx++;
1546 filters[idx].type = EMM_SHARED; // 8E second part reassembly with 8c/8d needed!
1547 filters[idx].enabled = 1;
1548 filters[idx].filter[0] = 0x8E;
1549 filters[idx].mask[0] = 0xFF;
1550 if(rdr->nprov > 0)
1552 memcpy(&filters[idx].filter[1], &rdr->sa[prov][0], 3);
1553 memset(&filters[idx].mask[1], 0xFF, 3);
1555 idx++;
1558 // globals are less important, define last since viaccess produces a lot of filters!
1559 for(prov = 0; (prov < rdr->nprov); prov++)
1561 if((rdr->prid[prov][2] &0xF0) == 0xF0) // skip this not useful provider
1563 continue;
1566 filters[idx].type = EMM_GLOBAL; // 8A or 8B no reassembly needed!
1567 filters[idx].enabled = 1;
1568 filters[idx].filter[0] = 0x8A;
1569 filters[idx].mask[0] = 0xFE;
1570 if(rdr->nprov > 0)
1572 memcpy(&filters[idx].filter[4], &rdr->prid[prov][2], 2);
1573 filters[idx].mask[4] = 0xFF;
1574 filters[idx].mask[5] = 0xF0; // ignore last digit since this is key on card indicator!
1576 else if (device_emm == 0)
1578 filters[idx].filter[3] = 0x00; // additional filter to cancel device specific emms
1579 filters[idx].mask[3] = 0x80;
1581 idx++;
1584 filters[idx].type = EMM_UNIQUE;
1585 filters[idx].enabled = 1;
1586 filters[idx].filter[0] = 0x88;
1587 filters[idx].mask[0] = 0xFF;
1588 if(!network) // network has only 3 digits out of 4
1590 memcpy(&filters[idx].filter[1], rdr->hexserial + 1, 4);
1591 memset(&filters[idx].mask[1], 0xFF, 4);
1593 else
1595 memcpy(&filters[idx].filter[1], rdr->hexserial + 1, 3);
1596 memset(&filters[idx].mask[1], 0xFF, 3);
1598 idx++;
1600 *filter_count = idx;
1603 return OK;
1606 static int32_t viaccess_do_emm(struct s_reader *reader, EMM_PACKET *ep)
1608 def_resp;
1609 static const uint8_t insa4[] = { 0xca, 0xa4, 0x04, 0x00, 0x03 }; // set provider id
1610 uint8_t insf0[] = { 0xca, 0xf0, 0x00, 0x01, 0x22 }; // set adf
1611 uint8_t insf4[] = { 0xca, 0xf4, 0x00, 0x01, 0x00 }; // set adf, encrypted
1612 uint8_t ins18[] = { 0xca, 0x18, 0x01, 0x01, 0x00 }; // set subscription
1613 uint8_t ins1c[] = { 0xca, 0x1c, 0x01, 0x01, 0x00 }; // set subscription, encrypted
1614 struct viaccess_data *csystem_data = reader->csystem_data;
1616 int32_t emmdatastart = 7;
1618 if (ep->emm[1] == 0x01) // emm from cccam
1620 emmdatastart = 12;
1621 ep->emm[1] = 0x70; // (& 0x0f) of this byte is length, so 0x01 would increase the length by 256
1622 ep->emm[2] -= 1;
1623 if (ep->type == SHARED || ep->type == GLOBAL) // build missing 0x90 nano from provider at serial position
1625 memcpy(ep->emm + 7, ep->emm + 3, 3);
1626 ep->emm[5] = 0x90;
1627 ep->emm[6] = 0x03;
1628 ep->emm[9] |= 0x01;
1629 ep->emm[10] = 0x9E;
1630 ep->emm[11] = 0x20;
1631 emmdatastart = 5;
1635 if(ep->type == UNIQUE)
1637 emmdatastart++;
1640 if(ep->type == GLOBAL && emmdatastart == 7)
1642 emmdatastart -= 4;
1645 int32_t emmLen = SCT_LEN(ep->emm) - emmdatastart;
1646 int32_t rc = 0;
1648 rdr_log_dump(reader, ep->emm, emmLen + emmdatastart, "RECEIVED EMM VIACCESS");
1650 int32_t emmUpToEnd;
1651 uint8_t *emmParsed = ep->emm + emmdatastart;
1652 int32_t provider_ok = 0;
1653 uint32_t emm_provid = 0;
1654 uint8_t keynr = 0;
1655 int32_t ins18Len = 0;
1656 uint8_t ins18Data[512];
1657 uint8_t insData[512];
1658 uint8_t *nano81Data = 0;
1659 uint8_t *nano91Data = 0;
1660 uint8_t *nano92Data = 0;
1661 uint8_t *nano9EData = 0;
1662 uint8_t *nanoF0Data = 0;
1663 uint8_t *nanoA9Data = 0;
1665 for(emmUpToEnd = emmLen; (emmParsed[1] != 0) && (emmUpToEnd > 0); emmUpToEnd -= (2 + emmParsed[1]), emmParsed += (2 + emmParsed[1]))
1667 rdr_log_dump(reader, emmParsed, emmParsed[1] + 2, "NANO");
1669 if(emmParsed[0] == 0x90 && emmParsed[1] == 0x03)
1671 /* identification of the service operator */
1673 uint8_t soid[3], ident[3], i;
1675 for(i = 0; i < 3; i++)
1677 soid[i] = ident[i] = emmParsed[2 + i];
1679 ident[2] &= 0xF0;
1680 emm_provid = b2i(3, ident);
1681 keynr = soid[2] & 0x0F;
1683 if(chk_prov(reader, ident, keynr))
1685 provider_ok = 1;
1687 else
1689 rdr_log(reader, "EMM: ignored since provider or key not present on card (%x, %x)", emm_provid, keynr);
1690 return SKIPPED;
1693 // check if the provider changes. If yes, set the new one. If not, don't... card will return an error if we do.
1694 if(csystem_data->last_geo.provid != emm_provid)
1696 write_cmd(insa4, ident);
1697 if(cta_res[cta_lr - 2] != 0x90 || cta_res[cta_lr - 1] != 0x00)
1699 rdr_log_dump(reader, insa4, 5, "set provider cmd:");
1700 rdr_log_dump(reader, soid, 3, "set provider data:");
1701 rdr_log(reader, "update error: %02X %02X", cta_res[cta_lr - 2], cta_res[cta_lr - 1]);
1702 return ERROR;
1705 // as we are maybe changing the used provider, clear the cache, so the next ecm will re-select the correct one
1706 csystem_data->last_geo.provid = 0;
1707 csystem_data->last_geo.geo_len = 0;
1708 csystem_data->last_geo.geo[0] = 0;
1711 else if(emmParsed[0] == 0x9e && emmParsed[1] == 0x20)
1713 /* adf */
1715 if(!nano91Data)
1717 /* adf is not crypted, so test it */
1719 uint8_t custwp;
1720 uint8_t *afd;
1722 custwp = reader->sa[0][3];
1723 afd = (uint8_t *)emmParsed + 2;
1725 if(afd[31 - custwp / 8] & (1 << (custwp & 7)))
1727 rdr_log_dbg(reader, D_READER, "emm for our card %08X", b2i(4, &reader->sa[0][0]));
1729 else
1731 rdr_log_dbg(reader, D_READER, "emm not suitable for our card %08X", b2i(4, &reader->sa[0][0]));
1732 return SKIPPED;
1736 // memorize
1737 nano9EData = emmParsed;
1740 else if(emmParsed[0] == 0x81)
1742 nano81Data = emmParsed;
1744 else if(emmParsed[0] == 0x91 && emmParsed[1] == 0x08)
1746 nano91Data = emmParsed;
1748 else if(emmParsed[0] == 0x92 && emmParsed[1] == 0x08)
1750 nano92Data = emmParsed;
1752 else if(emmParsed[0] == 0xF0 && emmParsed[1] == 0x08)
1754 nanoF0Data = emmParsed;
1756 else if(emmParsed[0] == 0xD8 && emmParsed[2] == 0x45)
1758 uint8_t pos = 4 + emmParsed[3];
1759 char *tmpbuf;
1760 if(emmParsed[pos] == 0x46 && ((emmParsed[pos+1] - emmParsed[1]) == pos))
1762 if(cs_malloc(&tmpbuf, emmParsed[pos + 1]))
1764 cs_strncpy(tmpbuf, (char *)emmParsed + pos + 2, emmParsed[pos + 1]);
1765 rdr_log(reader, "Viaccess EMM-text: %s", tmpbuf);
1766 NULLFREE(tmpbuf);
1770 else
1772 /* other nanos */
1773 show_subs(reader, emmParsed);
1774 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
1776 if(!emm_provid)
1778 rdr_log(reader, "no provid in shared emm -> skipped!");
1779 return SKIPPED;
1781 int8_t match = add_find_class(reader, emm_provid, emmParsed + 2, emmParsed[1], 0);
1783 if(match == -2)
1785 rdr_log(reader, "shared emm provid %06X all classes have entitlementdate already same or newer -> skipped!", emm_provid);
1786 return SKIPPED;
1788 nanoA9Data = emmParsed;
1791 memcpy(ins18Data + ins18Len, emmParsed, emmParsed[1] + 2);
1792 ins18Len += emmParsed [1] + 2;
1796 if(!provider_ok)
1798 rdr_log_dbg(reader, D_READER, "provider not found in emm, continue anyway");
1799 // force key to 1...
1800 keynr = 1;
1801 ///return ERROR;
1804 if(!nanoF0Data)
1806 rdr_log_dump(reader, ep->emm, ep->emmlen, "can't find 0xf0 in emm...");
1807 return ERROR; // error
1810 if(nano9EData)
1812 if(!nano91Data)
1814 // set adf
1815 insf0[3] = keynr; // key
1816 insf0[4] = nano9EData[1] + 2;
1817 write_cmd(insf0, nano9EData);
1818 if(cta_res[cta_lr - 2] != 0x90 || cta_res[cta_lr - 1] != 0x00)
1820 rdr_log_dump(reader, insf0, 5, "set adf cmd:");
1821 rdr_log_dump(reader, nano9EData, insf0[4] , "set adf data:");
1822 rdr_log(reader, "update error: %02X %02X", cta_res[cta_lr - 2], cta_res[cta_lr - 1]);
1823 return ERROR;
1826 else
1828 // set adf crypte
1829 insf4[3] = keynr; // key
1830 insf4[4] = nano91Data[1] + 2 + nano9EData[1] + 2;
1831 memcpy(insData, nano91Data, nano91Data[1] + 2);
1832 memcpy(insData + nano91Data[1] + 2, nano9EData, nano9EData[1] + 2);
1833 write_cmd(insf4, insData);
1835 if((cta_res[cta_lr - 2] != 0x90 && cta_res[cta_lr - 2] != 0x91) || cta_res[cta_lr - 1] != 0x00)
1837 rdr_log_dump(reader, insf4, 5, "set adf encrypted cmd:");
1838 rdr_log_dump(reader, insData, insf4[4], "set adf encrypted data:");
1839 rdr_log(reader, "update error: %02X %02X", cta_res[cta_lr - 2], cta_res[cta_lr - 1]);
1840 return ERROR;
1845 if(!nano92Data)
1847 // send subscription
1848 ins18[2] = nano9EData ? 0x01 : 0x00; // found 9E nano ?
1849 ins18[3] = keynr; // key
1850 ins18[4] = ins18Len + nanoF0Data[1] + 2;
1851 memcpy(insData, ins18Data, ins18Len);
1852 memcpy(insData + ins18Len, nanoF0Data, nanoF0Data[1] + 2);
1853 write_cmd(ins18, insData);
1855 if((cta_res[cta_lr - 2] == 0x90 || cta_res[cta_lr - 2] == 0x91) && cta_res[cta_lr - 1] == 0x00)
1857 if(nanoA9Data)
1859 add_find_class(reader, emm_provid, nanoA9Data + 2, nanoA9Data[1], 1);
1860 rdr_log(reader, "Your subscription data was updated.");
1862 rc = 1; // written
1864 else
1866 rdr_log_dump(reader, ins18, 5, "set subscription cmd:");
1867 rdr_log_dump(reader, insData, ins18[4], "set subscription data:");
1869 if(!(cta_res[cta_lr -2] == 0x90 && cta_res[cta_lr - 1] == 0x40)) // dont throw softerror 9040 in log!
1871 rdr_log(reader, "update error: %02X %02X", cta_res[cta_lr - 2], cta_res[cta_lr - 1]);
1873 else
1875 rc = 2; // skipped
1880 else
1882 // send subscription encrypted
1884 if(!nano81Data)
1886 rdr_log_dump(reader, ep->emm, ep->emmlen, "0x92 found, but can't find 0x81 in emm...");
1887 return ERROR; // error
1890 ins1c[2] = nano9EData ? 0x01 : 0x00; // found 9E nano ?
1891 if(ep->type == UNIQUE)
1893 ins1c[2] = 0x02;
1896 ins1c[3] = keynr; // key
1897 ins1c[4] = nano92Data[1] + 2 + nano81Data[1] + 2 + nanoF0Data[1] + 2;
1898 memcpy(insData, nano92Data, nano92Data[1] + 2);
1899 memcpy(insData + nano92Data[1] + 2, nano81Data, nano81Data[1] + 2);
1900 memcpy(insData + nano92Data[1] + 2 + nano81Data[1] + 2, nanoF0Data, nanoF0Data[1] + 2);
1901 write_cmd(ins1c, insData);
1903 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))
1905 rdr_log(reader, "update successfully written");
1906 rc = 1; // written
1908 rc = 1;
1911 return rc;
1914 static int32_t viaccess_card_info(struct s_reader *reader)
1916 def_resp;
1917 int32_t i, l;
1918 time_t now;
1919 struct tm timeinfo;
1920 uint16_t tmpdate;
1921 uint8_t insac[] = { 0xca, 0xac, 0x00, 0x00, 0x00 }; // select data
1922 uint8_t insb8[] = { 0xca, 0xb8, 0x00, 0x00, 0x00 }; // read selected data
1923 uint8_t insa4[] = { 0xca, 0xa4, 0x00, 0x00, 0x00 }; // select issuer
1924 uint8_t insc0[] = { 0xca, 0xc0, 0x00, 0x00, 0x00 }; // read data item
1925 static const uint8_t ins24[] = { 0xca, 0x24, 0x00, 0x00, 0x09 }; // set pin
1927 uint8_t cls[] = { 0x00, 0x21, 0xff, 0x9f};
1928 static const uint8_t pin[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04};
1929 struct viaccess_data *csystem_data = reader->csystem_data;
1931 csystem_data->last_geo.provid = 0;
1932 csystem_data->last_geo.geo_len = 0;
1933 csystem_data->last_geo.geo[0] = 0;
1935 rdr_log(reader, "card detected");
1937 cs_clear_entitlement(reader); //reset the entitlements
1939 // set pin
1940 write_cmd(ins24, pin);
1942 insac[2] = 0xa4;
1943 write_cmd(insac, NULL); // request unique id
1944 insb8[4] = 0x07;
1945 write_cmd(insb8, NULL); // read unique id
1946 rdr_log_sensitive(reader, "serial: {%llu}", (unsigned long long) b2ll(5, cta_res + 2));
1948 insa4[2] = 0x00;
1949 write_cmd(insa4, NULL); // select issuer 0
1951 for(i = 1; (cta_res[cta_lr - 2] == 0x90) && (cta_res[cta_lr - 1] == 0); i++)
1953 bool added = false;
1954 uint32_t l_provid, l_sa;
1955 uint8_t l_name[64];
1956 insc0[4] = 0x1a;
1957 write_cmd(insc0, NULL); // show provider properties
1958 cta_res[2] &= 0xF0;
1959 l_provid = b2i(3, cta_res);
1961 insac[2] = 0xa5;
1962 write_cmd(insac, NULL); // request sa
1963 insb8[4] = 0x06;
1964 write_cmd(insb8, NULL); // read sa
1965 l_sa = b2i(4, cta_res + 2);
1967 insac[2] = 0xa7;
1968 write_cmd(insac, NULL); // request name
1969 insb8[4] = 0x02;
1970 write_cmd(insb8, NULL); // read name nano + len
1971 l = cta_res[1];
1972 insb8[4] = l;
1973 write_cmd(insb8, NULL); // read name
1974 cta_res[l] = 0;
1975 trim((char *)cta_res);
1977 if(cta_res[0])
1979 snprintf((char *)l_name, sizeof(l_name), ", name: %.55s", cta_res);
1981 else
1983 l_name[0] = 0;
1986 // read GEO
1987 insac[2] = 0xa6;
1988 write_cmd(insac, NULL); // request GEO
1989 insb8[4] = 0x02;
1990 write_cmd(insb8, NULL); // read GEO nano + len
1991 l = cta_res[1];
1992 char tmp[l * 3 + 1];
1993 insb8[4] = l;
1994 write_cmd(insb8, NULL); // read geo
1995 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)));
1997 // read classes subscription
1998 insac[2] = 0xa9;
1999 insac[4] = 4;
2000 if(!reader->read_old_classes)
2002 now = time(NULL) - (24*60*60);
2003 cs_gmtime_r(&now, &timeinfo);
2004 tmpdate = timeinfo.tm_mday | ((timeinfo.tm_mon + 1) << 5) | ((timeinfo.tm_year - 80) << 9);
2005 cls[0] = tmpdate >> 8;
2006 cls[1] = tmpdate & 0xff;
2008 write_cmd(insac, cls); // request class subs
2010 while((cta_res[cta_lr - 2] == 0x90) && (cta_res[cta_lr - 1] == 0))
2012 insb8[4] = 0x02;
2013 write_cmd(insb8, NULL); // read class subs nano + len
2014 if((cta_res[cta_lr - 2] == 0x90) && (cta_res[cta_lr - 1] == 0))
2016 l = cta_res[1];
2017 insb8[4] = l;
2018 write_cmd(insb8, NULL); // read class subs
2019 if((cta_res[cta_lr - 2] == 0x90) && (cta_res[cta_lr - 1] == 0x00 || cta_res[cta_lr - 1] == 0x08))
2021 show_class(reader, NULL, l_provid, cta_res, cta_lr - 2);
2022 added = true;
2027 if(!added)
2029 // add entitlement info for provid without class
2030 cs_add_entitlement(reader, reader->caid, l_provid, 0, 0, 0, 0, 5, 1);
2033 insac[4] = 0;
2034 insa4[2] = 0x02;
2035 write_cmd(insa4, NULL); // select next provider
2037 //return ERROR;
2038 // Start process init CA 28
2039 reader->initCA28=0;
2040 int32_t lenboxkey = reader->boxkey_length;
2041 int32_t lendeskey = reader->des_key_length;
2042 if ((lenboxkey >= 4) && (lendeskey > 0))
2044 uint8_t ins28[] = { 0xCA, 0x28, 0x00, 0x00, 0x04 }; //Init for nanoE0 ca28
2045 ins28[4] = (uint8_t) lenboxkey;
2046 uint8_t ins28_data[4];
2047 memcpy(ins28_data, reader->boxkey, 4);
2048 write_cmd(ins28, ins28_data); // unlock card to reply on E002xxyy
2050 if((cta_res[cta_lr - 2] == 0x90) && (cta_res[cta_lr - 1] == 0))
2052 rdr_log(reader, "CA 28 initialisation successful!");
2053 // init 3DES key
2054 des_set_key(reader->des_key, reader->key_schedule1);
2055 des_set_key(reader->des_key+8, reader->key_schedule2);
2056 reader->initCA28=1;
2058 else
2060 rdr_log(reader, "CA 28 initialisation failed! CA 28 refused");
2063 //end process init CA 28
2064 return OK;
2067 static int32_t viaccess_reassemble_emm(struct s_reader *rdr, struct s_client *client, EMM_PACKET *ep)
2069 uint8_t *buffer = ep->emm;
2070 int16_t *len = &ep->emmlen;
2071 int32_t pos = 0, i;
2072 int16_t k;
2073 int32_t prov, provid = 0;
2074 struct emm_rass *r_emm = NULL;
2076 // Viaccess
2077 if(*len > 500)
2079 return 0;
2082 switch(buffer[0])
2084 case 0x8c:
2085 case 0x8d:
2086 // emm-s part 1
2087 provid = b2i(3, ep->emm + 5); // extract provid from emm
2088 provid &= 0xFFFFF0; // last digit is dont care
2089 r_emm = find_rabuf(client, provid, (uint8_t) buffer[0], 1);
2091 if(!r_emm)
2093 cs_log("[viaccess] ERROR: Can't allocate EMM reassembly buffer.");
2094 return 0;
2097 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
2099 return 0;
2102 memset(&r_emm->emm[0], 0, sizeof(r_emm->emm)); // zero it!
2103 memcpy(&r_emm->emm[0], &buffer[0], *len); // put the fresh new shared emm
2104 r_emm->emmlen = *len; // put the emmlen indicating that this shared emm isnt being reassembled
2105 rdr_log_dump_dbg(rdr, D_EMM, r_emm->emm, r_emm->emmlen, "%s: received fresh emm-gh for provid %06X", __func__, provid);
2106 return 0;
2108 case 0x8e:
2109 // emm-s part 2
2110 for(prov = 0; prov < rdr->nprov ; prov++)
2112 if(!memcmp(&buffer[3], &rdr->sa[prov][0], 3))
2114 //matching sa found!
2115 if(is_network_reader(rdr))
2117 provid = b2i(4, ep->provid); // use provid from emm since we have nothing better!
2118 provid &= 0xFFFFF0; // last digit is dont care
2121 else
2123 provid = b2i(4, rdr->prid[prov]); // get corresponding provid from reader since there is no provid in emm payload!
2124 provid &= 0xFFFFF0; // last digit is dont care
2126 r_emm = find_rabuf(client, provid, 0, 0); // nano = don't care, the shared 8c or 8d not been written gets returned!
2128 if(!r_emm || !r_emm->emmlen)
2130 continue; // match but no emm-gh found for this provider
2132 else
2134 break; // stop searching-> emm-gh found!
2139 if(!r_emm || !r_emm->emmlen)
2141 return 0; // stop -> no emm-gh found!
2143 //extract nanos from emm-gh and emm-s
2144 uint8_t emmbuf[512];
2146 rdr_log_dbg(rdr, D_EMM, "%s: start extracting nanos", __func__);
2147 //extract from emm-gh
2148 for(i = 3; i < r_emm->emmlen; i += r_emm->emm[i + 1] + 2)
2150 //copy nano (length determined by i+1)
2151 memcpy(emmbuf + pos, r_emm->emm + i, r_emm->emm[i + 1] + 2);
2152 pos += r_emm->emm[i + 1] + 2;
2155 if(buffer[2] == 0x2c)
2157 //add 9E 20 nano + first 32 uint8_ts of emm content
2158 memcpy(emmbuf + pos, "\x9E\x20", 2);
2159 memcpy(emmbuf + pos + 2, buffer + 7, 32);
2160 pos += 34;
2162 //add F0 08 nano + 8 subsequent uint8_ts of emm content
2163 memcpy(emmbuf + pos, "\xF0\x08", 2);
2164 memcpy(emmbuf + pos + 2, buffer + 39, 8);
2165 pos += 10;
2167 else
2169 //extract from variable emm-s
2170 for(k = 7; k < (*len); k += buffer[k + 1] + 2)
2172 //copy nano (length determined by k+1)
2173 memcpy(emmbuf + pos, buffer + k, buffer[k + 1] + 2);
2174 pos += buffer[k + 1] + 2;
2178 rdr_log_dump_dbg(rdr, D_EMM, buffer, *len, "%s: %s emm-s", __func__, (buffer[2] == 0x2c) ? "fixed" : "variable");
2180 emm_sort_nanos(buffer + 7, emmbuf, pos);
2181 pos += 7;
2183 //calculate emm length and set it on position 2
2184 buffer[2] = pos - 3;
2186 rdr_log_dump_dbg(rdr, D_EMM, r_emm->emm, r_emm->emmlen, "%s: emm-gh provid %06X", __func__, provid);
2187 rdr_log_dump_dbg(rdr, D_EMM, buffer, pos, "%s: assembled emm", __func__);
2189 *len = pos;
2190 r_emm->emmlen = 0; // mark this shared 8c or 8d as being used for reassembly and send to reader!
2191 break;
2193 return 1;
2196 const struct s_cardsystem reader_viaccess =
2198 .desc = "viaccess",
2199 .caids = (uint16_t[]){ 0x05, 0 },
2200 .do_emm_reassembly = viaccess_reassemble_emm,
2201 .do_emm = viaccess_do_emm,
2202 .do_ecm = viaccess_do_ecm,
2203 .card_info = viaccess_card_info,
2204 .card_init = viaccess_card_init,
2205 .get_emm_type = viaccess_get_emm_type,
2206 .get_emm_filter = viaccess_get_emm_filter,
2209 #endif