revert breaks some stupid old compilers
[oscam.git] / reader-viaccess.c
bloba934c5c30e528d974cc70692d7f0a28ba192391e
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 uchar *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 //static void get_via_data(const uchar *b, int32_t l, time_t *start_t, time_t *end_t, uchar *cls)
54 //{
55 // int32_t i, j;
56 // struct via_date vd;
57 // struct tm tm;
58 // memset(&vd, 0, sizeof(struct via_date));
60 // // b -> via date (4 uint8_ts)
61 // b+=4;
62 // l-=4;
64 // j=l-1;
65 // for (; j>=0; j--)
66 // for (i=0; i<8; i++)
67 // if (b[j] & (1 << (i&7)))
68 // {
69 // parse_via_date(b-4, &vd, 1);
70 // *cls=(l-(j+1))*8+i;
71 // }
73 // memset(&tm, 0, sizeof(struct tm));
74 // tm.tm_year = vd.year_s + 80; //via year starts in 1980, tm_year starts in 1900
75 // tm.tm_mon = vd.month_s - 1; // january is 0 in tm_mon
76 // tm.tm_mday = vd.day_s;
77 // *start_t = mktime(&tm);
79 // tm.tm_year = vd.year_e + 80;
80 // tm.tm_mon = vd.month_e - 1;
81 // tm.tm_mday = vd.day_e;
82 // *end_t = mktime(&tm);
84 //}
85 struct emm_rass *find_rabuf(struct s_client *client, int32_t provid, uint8_t nano, int8_t add)
87 struct emm_rass *e;
88 LL_ITER it;
90 if(!client->ra_buf)
92 client->ra_buf = ll_create("client->ra_buf");
95 it = ll_iter_create(client->ra_buf);
97 while((e = ll_iter_next(&it)) != NULL)
99 if(!add && e->provid == provid && e->emmlen != 0) { return e; }
100 if(add && e->provid == provid && e->emm[0] == nano) { return e; }
102 if(!add) return NULL;
104 if(!cs_malloc(&e, sizeof(struct emm_rass)))
105 { return NULL; }
106 e->provid = provid;
107 ll_append(client->ra_buf, e);
108 return e;
111 static void show_class(struct s_reader *reader, const char *p, uint32_t provid, const uchar *b, int32_t l)
113 int32_t i, j;
115 // b -> via date (4 uint8_ts)
116 b += 4;
117 l -= 4;
119 j = l - 1;
120 for(; j >= 0; j--)
121 for(i = 0; i < 8; i++)
122 if(b[j] & (1 << (i & 7)))
124 uchar cls;
125 struct via_date vd;
126 parse_via_date(b - 4, &vd, 1);
127 cls = (l - (j + 1)) * 8 + i;
129 if(p) // just show class info, dont add entitlement!
131 rdr_log(reader, "%sclass: %02X, expiry date: %04d/%02d/%02d - %04d/%02d/%02d", p, cls,
132 vd.year_s + 1980, vd.month_s, vd.day_s,
133 vd.year_e + 1980, vd.month_e, vd.day_e);
135 else
137 rdr_log(reader, "class: %02X, expiry date: %04d/%02d/%02d - %04d/%02d/%02d", cls,
138 vd.year_s + 1980, vd.month_s, vd.day_s,
139 vd.year_e + 1980, vd.month_e, vd.day_e);
141 //convert time:
142 time_t start_t, end_t;
143 struct tm tm;
144 memset(&tm, 0, sizeof(tm));
145 tm.tm_year = vd.year_s + 80; //via year starts in 1980, tm_year starts in 1900
146 tm.tm_mon = vd.month_s - 1; // january is 0 in tm_mon
147 tm.tm_mday = vd.day_s;
148 start_t = cs_timegm(&tm);
150 tm.tm_year = vd.year_e + 80; //via year starts in 1980, tm_year starts in 1900
151 tm.tm_mon = vd.month_e - 1; // january is 0 in tm_mon
152 tm.tm_mday = vd.day_e;
153 end_t = cs_timegm(&tm);
154 cs_add_entitlement(reader, reader->caid, provid, cls, cls, start_t, end_t, 5, 1);
159 static int8_t add_find_class(struct s_reader *reader, uint32_t provid, const uchar *b, int32_t l, int8_t add)
161 int32_t i, j, freshdate = 0;
163 // b -> via date (4 uint8_ts)
164 b += 4;
165 l -= 4;
167 j = l - 1;
168 for(; j >= 0; j--)
169 for(i = 0; i < 8; i++)
170 if(b[j] & (1 << (i & 7)))
172 uchar cls;
173 cls = (l - (j + 1)) * 8 + i;
174 if(cs_add_entitlement(reader, reader->caid, provid, cls, cls, 0, 0, 5, 0) == NULL && !add)
176 rdr_log(reader, "provid %06X class %02X not found", provid, cls);
177 freshdate = 1;
179 else
181 if(!add)
183 rdr_log(reader, "provid %06X has matching class %02X", provid, cls);
185 struct via_date vd;
186 parse_via_date(b - 4, &vd, 1);
187 time_t start_t, end_t;
188 struct tm tm;
189 //convert time:
190 memset(&tm, 0, sizeof(tm));
191 tm.tm_year = vd.year_s + 80; //via year starts in 1980, tm_year starts in 1900
192 tm.tm_mon = vd.month_s - 1; // january is 0 in tm_mon
193 tm.tm_mday = vd.day_s;
194 start_t = cs_timegm(&tm);
196 tm.tm_year = vd.year_e + 80; //via year starts in 1980, tm_year starts in 1900
197 tm.tm_mon = vd.month_e - 1; // january is 0 in tm_mon
198 tm.tm_mday = vd.day_e;
199 end_t = cs_timegm(&tm);
201 if(cs_add_entitlement(reader, reader->caid, provid, cls, cls, start_t, end_t, 5, add) != NULL)
203 if(!add)
205 rdr_log(reader, "class %02X provid %06X has already this daterange or newer entitled", cls, provid);
208 else
210 freshdate = 1;
214 if(freshdate == 0) return -2;
215 return 1; // emmdate is fresh!
218 static void show_subs(struct s_reader *reader, const uchar *emm)
220 // emm -> A9, A6, B6
222 switch(emm[0])
224 case 0xA9:
226 show_class(reader, "nano A9: ", 1, emm + 2, emm[1]);
227 break;
230 case 0xA6:
232 char szGeo[256];
234 memset(szGeo, 0, 256);
235 strncpy(szGeo, (char *)emm + 2, emm[1]);
236 rdr_log(reader, "nano A6: geo %s", szGeo);
237 break;
240 case 0xB6:
242 uchar m; // modexp
243 struct via_date vd;
245 m = emm[emm[1] + 1];
246 parse_via_date(emm + 2, &vd, 0);
247 rdr_log(reader, "nano B6: modexp %d%d%d%d%d%d: %02d/%02d/%04d", (m & 0x20) ? 1 : 0,
248 (m & 0x10) ? 1 : 0, (m & 0x08) ? 1 : 0, (m & 0x04) ? 1 : 0, (m & 0x02) ? 1 : 0, (m & 0x01) ? 1 : 0,
249 vd.day_s, vd.month_s, vd.year_s + 1980);
250 break;
255 static int32_t chk_prov(struct s_reader *reader, uchar *id, uchar keynr)
257 struct viaccess_data *csystem_data = reader->csystem_data;
258 int32_t i, j, rc;
259 for(rc = i = 0; (!rc) && (i < reader->nprov); i++)
260 if(!memcmp(&reader->prid[i][1], id, 3))
261 for(j = 0; (!rc) && (j < 16); j++)
262 if(csystem_data->availkeys[i][j] == keynr)
263 { rc = 1; }
264 return (rc);
267 static int32_t get_maturity(struct s_reader *reader)
269 /* retrieve maturity rating on the card */
271 def_resp;
273 uchar insac[] = { 0xca, 0xac, 0x00, 0x00, 0x00 }; // select data
274 uchar insb8[] = { 0xca, 0xb8, 0x00, 0x00, 0x00 }; // read selected data
276 insac[2]=0x06; write_cmd(insac, NULL); // request maturity rating
277 insb8[4]=0x02; write_cmd(insb8, NULL); // read maturity rating nano + len
278 insb8[4]=cta_res[1]; write_cmd(insb8, NULL); // read maturity rating
280 reader->maturity= cta_res[cta_lr - 3] & 0x0F;
281 if (reader->maturity<0xF)
283 rdr_log(reader, "Maturity level [%X]= older than %i years", reader->maturity, reader->maturity);
285 else
287 rdr_log(reader, "Maturity level [%X]=no age limit", reader->maturity);
289 return 0;
292 static int32_t unlock_parental(struct s_reader *reader)
294 /* disabling parental lock. assuming pin "0000" if no pin code is provided in the config */
296 static const uchar inDPL[] = {0xca, 0x24, 0x02, 0x00, 0x09};
297 uchar cmDPL[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F};
298 def_resp;
300 if(strcmp(reader->pincode, "none"))
302 rdr_log(reader, "Using PIN %s", reader->pincode);
303 // the pin need to be coded in bcd, so we need to convert from ascii to bcd, so '1234' -> 0x12 0x34
304 cmDPL[6] = ((reader->pincode[0] - 0x30) << 4) | ((reader->pincode[1] - 0x30) & 0x0f);
305 cmDPL[7] = ((reader->pincode[2] - 0x30) << 4) | ((reader->pincode[3] - 0x30) & 0x0f);
307 else
309 rdr_log(reader, "Using PIN 0000!");
311 write_cmd(inDPL, cmDPL);
312 if(!(cta_res[cta_lr - 2] == 0x90 && cta_res[cta_lr - 1] == 0))
314 if(strcmp(reader->pincode, "none"))
316 rdr_log(reader, "Can't disable parental lock. Wrong PIN? OSCam used %s!", reader->pincode);
318 else
320 rdr_log(reader, "Can't disable parental lock. Wrong PIN? OSCam used 0000!");
323 else
325 rdr_log(reader, "Parental lock disabled");
326 get_maturity(reader);
329 return 0;
332 int32_t hdSurEncBasicCrypt_D2_0F_11(int32_t Value, int32_t XorVal)
334 int32_t i = (Value << 13) - Value + 0x1B59;
335 i = (i * Value) + 0x07CF;
336 return (i ^ XorVal);
339 int32_t hdSurEncCryptLookup_D2_0F_11(uint8_t Value, uint8_t AddrInd)
341 static const uint8_t lookup[] =
343 0x94, 0xB2, 0xA9, 0x79, 0xC4, 0xC7, 0x0D, 0x36, 0x6F, 0x24, 0x11, 0xD1, 0xDB, 0x59, 0xD2, 0xA5,
344 0xE1, 0x00, 0xD4, 0x97, 0xA3, 0x2B, 0x11, 0xFA, 0x5F, 0xF1, 0xC1, 0x44, 0xBF, 0x9B, 0x5A, 0xC8,
345 0xF1, 0xE1, 0x99, 0x82, 0x0E, 0xB2, 0x01, 0x09, 0x0C, 0xC8, 0xB3, 0x3B, 0xD1, 0x80, 0x50, 0xE8,
346 0xF5, 0x52, 0x4C, 0xE6, 0x82, 0xAC, 0x58, 0x40, 0xD4, 0x71, 0x87, 0x52, 0x06, 0xEA, 0xA6, 0x27,
347 0xB7, 0xFE, 0x6C, 0x49, 0x47, 0x3B, 0x70, 0x6C, 0xEB, 0xCD, 0xC5, 0x0B, 0x8C, 0x31, 0x29, 0x42,
348 0x4E, 0x10, 0x2B, 0x2D, 0x46, 0xEC, 0x39, 0xA3, 0x90, 0x4B, 0x25, 0x60, 0x9C, 0x62, 0xD4, 0x20,
349 0xF6, 0x16, 0xA8, 0x9C, 0xE4, 0x20, 0xED, 0xC7, 0xBA, 0x5E, 0xB6, 0x4E, 0x03, 0x15, 0xA6, 0xF6,
350 0x23, 0x98, 0x32, 0xC0, 0xAE, 0xA3, 0xFD, 0xD3, 0x7F, 0xF8, 0xED, 0xF0, 0x29, 0x29, 0x12, 0xB3,
351 0xB7, 0x58, 0xAD, 0xA2, 0x58, 0x2C, 0x70, 0x1B, 0xA4, 0x25, 0xE8, 0xA5, 0x43, 0xF1, 0xB9, 0x8F,
352 0x1E, 0x3B, 0x10, 0xDF, 0x52, 0xFE, 0x58, 0x29, 0xAD, 0x3F, 0x99, 0x4D, 0xDF, 0xD2, 0x08, 0x06,
353 0xA1, 0x1C, 0x66, 0x29, 0x26, 0x80, 0x52, 0x8A, 0x5A, 0x73, 0xE7, 0xDF, 0xC1, 0xC4, 0x47, 0x82,
354 0xAB, 0x5C, 0x32, 0xAE, 0x96, 0x04, 0x2B, 0xC3, 0x2D, 0x5A, 0xD2, 0xB0, 0x64, 0x88, 0x97, 0xBF,
355 0x7E, 0x99, 0x60, 0xCC, 0x63, 0x76, 0x66, 0xE9, 0x9A, 0x3D, 0xBB, 0xF7, 0x7F, 0xE4, 0x7C, 0x3F,
356 0xB8, 0x4D, 0x10, 0x8D, 0x2A, 0xEA, 0x3C, 0xD3, 0x03, 0x74, 0xE6, 0x46, 0xC0, 0x29, 0xAE, 0xB0,
357 0x79, 0xBE, 0xCB, 0x18, 0x34, 0xBE, 0x5A, 0xE9, 0x19, 0x8F, 0xA3, 0x8F, 0xD6, 0x6A, 0x6C, 0x88,
358 0x1E, 0x21, 0x08, 0x15, 0xC4, 0xE7, 0xE6, 0xBA, 0x97, 0x9C, 0x4F, 0x89, 0x9F, 0x1A, 0x67, 0x4F,
359 0xC0, 0xD5, 0x72, 0x51, 0x16, 0xB4, 0xD3, 0x8A, 0x1F, 0xE3, 0x92, 0x02, 0x7F, 0x59, 0x56, 0x8F,
360 0x07, 0x8D, 0xC1, 0xC2, 0x42, 0x69, 0x3C, 0xA6, 0xBF, 0x3D, 0xDF, 0x0D, 0xAA, 0x4F, 0x7E, 0x80,
361 0x07, 0x11, 0xE2, 0x94, 0x19, 0x9B, 0x16, 0x26, 0x1A, 0x46, 0x09, 0x0D, 0xB5, 0xB8, 0x8E, 0x01,
362 0x9C, 0xFE, 0x09, 0xB3, 0x60, 0xC2, 0xAE, 0x50, 0x3C, 0x68, 0x75, 0x4A, 0x57, 0xD8, 0x4F, 0xD7,
363 0xA2, 0x76, 0x2C, 0xC1, 0xA2, 0x23, 0xBC, 0x54, 0x2A, 0xDD, 0xF3, 0xDD, 0xA7, 0x34, 0xF7, 0x5C,
364 0xF4, 0x86, 0x23, 0x48, 0x7C, 0x3F, 0x05, 0x40, 0x0E, 0xB0, 0xE5, 0xEB, 0x3E, 0xDF, 0x6A, 0x83,
365 0x65, 0xA0, 0xB2, 0x06, 0xD1, 0x40, 0x79, 0x0D, 0xDE, 0x95, 0x84, 0x96, 0x87, 0x6F, 0xCE, 0x48,
366 0x24, 0x13, 0x0B, 0xF5, 0xC7, 0xF5, 0xA8, 0x7F, 0x2E, 0xC7, 0xE1, 0xBA, 0xAE, 0x2B, 0xF7, 0xF0,
367 0x8E, 0xF7, 0x54, 0x0B, 0xF0, 0xD2, 0x41, 0x81, 0x68, 0x3B, 0x1E, 0x35, 0xAB, 0xD9, 0x2B, 0x46,
368 0x57, 0xE8, 0x53, 0xDF, 0xDE, 0x10, 0xEF, 0xCB, 0x4C, 0xE0, 0x52, 0x18, 0x2C, 0x4E, 0xB9, 0x20,
369 0xE9, 0x7E, 0x85, 0xDF, 0x75, 0x32, 0xE6, 0x10, 0xE9, 0x9C, 0x7B, 0x2E, 0x4C, 0xDA, 0x46, 0xE6,
370 0xCC, 0x77, 0x36, 0x1D, 0x4A, 0x15, 0xF5, 0x32, 0x18, 0x6B, 0x7E, 0xAA, 0xCC, 0x97, 0xCC, 0xD1,
371 0x2F, 0xE5, 0x58, 0x03, 0x35, 0x35, 0x3D, 0xA0, 0x2B, 0x13, 0x3A, 0x65, 0xFF, 0x24, 0x72, 0xCF,
372 0xA7, 0x6D, 0x52, 0x55, 0xF6, 0xC2, 0x30, 0x23, 0x7D, 0x9B, 0x9E, 0xB0, 0x94, 0x02, 0xAD, 0x60,
373 0x8A, 0x9F, 0xBC, 0xC8, 0xE4, 0x2B, 0x92, 0x96, 0xF5, 0xAE, 0x04, 0xA4, 0x33, 0x0C, 0x90, 0x67,
374 0xF0, 0xB9, 0x1E, 0x7E, 0xBE, 0x02, 0x18, 0xB2, 0x03, 0xB6, 0x40, 0xBF, 0x05, 0xE3, 0x76, 0x98,
375 0x21, 0x38, 0xC9, 0x5F, 0xD3, 0x51, 0x8B, 0x43, 0x0B, 0x1A, 0x0B, 0xF9, 0x3C, 0x21, 0x6C, 0x3D,
376 0xB8, 0xA0, 0x57, 0xCA, 0x68, 0xCD, 0x1E, 0xD2, 0x2C, 0x50, 0xEE, 0xC0, 0xDF, 0x25, 0x88, 0x52,
377 0x37, 0xE1, 0x44, 0xC6, 0x76, 0x3B, 0x91, 0x95, 0x86, 0x76, 0x87, 0x49, 0x21, 0x93, 0x44, 0x0A,
378 0x52, 0xB9, 0x2D, 0x2B, 0xE3, 0x1D, 0xB0, 0xE4, 0x98, 0xC6, 0xEE, 0x3D, 0x96, 0x53, 0x4B, 0xFF,
379 0x39, 0x00, 0xD5, 0x42, 0x7E, 0xE1, 0x4C, 0x6F, 0xD5, 0xB7, 0xE6, 0x99, 0x2A, 0x5B, 0x67, 0xEE,
380 0x3E, 0xBA, 0xF7, 0xEC, 0x43, 0x2A, 0x1C, 0xB6, 0xB5, 0x04, 0x26, 0x59, 0xB1, 0x4C, 0x17, 0xCC,
381 0x83, 0xB9, 0x00, 0x3E, 0x36, 0x91, 0x90, 0xF7, 0x5E, 0x38, 0xDC, 0xE4, 0x15, 0xC7, 0x67, 0xF0,
382 0xCA, 0xC8, 0xD2, 0x91, 0x5D, 0x74, 0xAC, 0x97, 0x56, 0x36, 0x1A, 0x82, 0x0A, 0xAA, 0xB4, 0x4E,
383 0xBF, 0x29, 0x5C, 0xBF, 0x58, 0xB3, 0x97, 0xF9, 0xEB, 0x7C, 0x85, 0xB4, 0xA5, 0x13, 0x2F, 0xD1,
384 0xDE, 0x1C, 0xEC, 0x97, 0xDD, 0xE2, 0x39, 0xE4, 0xFB, 0x0A, 0x02, 0xE0, 0xC3, 0xBA, 0x39, 0x79,
385 0xAA, 0x1C, 0x37, 0x75, 0x25, 0x54, 0xBE, 0x85, 0x74, 0x2C, 0xFA, 0x0C, 0xFA, 0x50, 0xF6, 0xBE,
386 0x9F, 0x2A, 0x53, 0x7C, 0x27, 0x46, 0x68, 0x2D, 0x74, 0x2B, 0x46, 0xDA, 0xF5, 0x07, 0x95, 0x09,
387 0x6A, 0x91, 0xB7, 0xB1, 0x34, 0x07, 0x5F, 0xEA, 0xBE, 0x0F, 0x87, 0x28, 0x68, 0x97, 0x43, 0x77,
388 0xD5, 0x38, 0x2B, 0x11, 0x11, 0x4F, 0xD9, 0x75, 0x5E, 0xE1, 0x06, 0xA0, 0x3B, 0xAC, 0x32, 0xFE,
389 0xBF, 0x73, 0x59, 0x5B, 0xA2, 0xA8, 0x7E, 0x10, 0x4C, 0x6E, 0x78, 0xF0, 0x4A, 0x4E, 0x95, 0xD6,
390 0xDD, 0x05, 0x7A, 0xBB, 0xF1, 0xEB, 0xA8, 0xA4, 0x5D, 0x91, 0xF0, 0xED, 0xDB, 0xB8, 0x01, 0x41,
391 0xF8, 0x97, 0x7F, 0xC3, 0x91, 0x53, 0xBF, 0xE9, 0xEA, 0x33, 0x1F, 0xDC, 0xA6, 0xE6, 0x8D, 0xCB,
392 0x75, 0xD0, 0x69, 0xD0, 0xA4, 0x59, 0xA5, 0x02, 0xFC, 0x60, 0x0D, 0x6A, 0xA0, 0x05, 0x1A, 0x54,
393 0x8A, 0xA7, 0x57, 0xA3, 0xF0, 0x90, 0x8A, 0xD5, 0x6F, 0x1E, 0x2E, 0x10, 0x9A, 0x93, 0x2B, 0x51,
394 0x2C, 0xFD, 0x99, 0xE5, 0x9B, 0x5D, 0xB2, 0xA7, 0x37, 0x99, 0x26, 0x35, 0xCA, 0xDD, 0x22, 0x19,
395 0x59, 0x2A, 0xB0, 0x99, 0x23, 0xDF, 0xA7, 0xA9, 0x85, 0x12, 0xCF, 0xBF, 0xFC, 0x74, 0x80, 0x87,
396 0xE1, 0x97, 0xD0, 0xF9, 0xEF, 0x5F, 0x1B, 0x45, 0xF7, 0x76, 0xDB, 0x66, 0x39, 0x05, 0x43, 0x06,
397 0xA9, 0x9F, 0x2E, 0x14, 0x9F, 0x1C, 0x0C, 0x1F, 0xD5, 0xD9, 0xA4, 0x8D, 0x18, 0x6F, 0x08, 0x53,
398 0x0B, 0x92, 0x9A, 0x0C, 0xEA, 0x4C, 0xE4, 0x1D, 0x9E, 0x9A, 0x51, 0xB8, 0x7E, 0x2D, 0xE7, 0x3C,
399 0xFF, 0x84, 0x5C, 0xBF, 0x8F, 0x8C, 0x89, 0x09, 0x1B, 0x7E, 0x4B, 0xE7, 0x85, 0xEC, 0x04, 0xB5,
400 0x20, 0x18, 0x1E, 0x55, 0xD5, 0x5B, 0xAC, 0xC6, 0x25, 0x5A, 0xA1, 0x81, 0xC1, 0x31, 0x9C, 0xF5,
401 0xB5, 0x54, 0x07, 0x65, 0x0A, 0x5B, 0x90, 0x06, 0x4F, 0x84, 0xB2, 0x7F, 0xD1, 0xAD, 0x16, 0x81,
402 0x25, 0xAF, 0xAF, 0xE2, 0x03, 0xA9, 0x1F, 0x13, 0x02, 0x5D, 0x54, 0x89, 0xCD, 0x44, 0x51, 0xEB,
403 0xA4, 0x2B, 0xBD, 0x47, 0xB0, 0xB6, 0x27, 0x1D, 0x9B, 0x14, 0x6F, 0xBF, 0xCD, 0x59, 0xBC, 0x0A,
404 0x37, 0xA8, 0x74, 0x7D, 0x16, 0x90, 0x28, 0xD5, 0x94, 0xC3, 0xE4, 0x23, 0xC4, 0x98, 0x91, 0xCE,
405 0x55, 0xBD, 0x21, 0x3B, 0x84, 0xBD, 0x44, 0x3C, 0xF9, 0xCD, 0x37, 0x43, 0x4A, 0xC6, 0x8C, 0x23,
406 0x04, 0x28, 0x63, 0x7A, 0x03, 0x85, 0xD2, 0x46, 0x93, 0xCA, 0xFE, 0xC3, 0x83, 0x0B, 0x13, 0xCC,
407 0x5D, 0xCB, 0xBA, 0xCA, 0x68, 0xAB, 0x05, 0xF7, 0xEC, 0x4A, 0x9C, 0x0F, 0xD5, 0xC4, 0x5A, 0xA5,
408 0xA0, 0x04, 0x41, 0x6A, 0xF6, 0xEF, 0x16, 0x9B, 0x69, 0x38, 0xF6, 0x2D, 0xAA, 0xEB, 0x2D, 0xE2,
409 0x82, 0xA2, 0x9F, 0x6F, 0xBD, 0x2A, 0xE3, 0x66, 0x6B, 0x21, 0xDA, 0x56, 0xAD, 0x82, 0x2B, 0x93,
410 0xF3, 0x25, 0xEA, 0xFC, 0xFD, 0xFD, 0x1B, 0xA9, 0xFC, 0xB8, 0xC6, 0x98, 0x45, 0xF2, 0x70, 0x03,
411 0x4A, 0x9C, 0x60, 0x82, 0x65, 0xB6, 0x68, 0x4C, 0xE7, 0x41, 0x10, 0x9D, 0x59, 0x40, 0x03, 0x02,
412 0x07, 0x12, 0x33, 0xAF, 0x79, 0xE1, 0xC4, 0xEB, 0xB8, 0xCE, 0x6A, 0x90, 0x72, 0x61, 0x5D, 0x56,
413 0xC7, 0x59, 0x31, 0xCB, 0x45, 0x2D, 0x42, 0x9F, 0x10, 0x1D, 0x09, 0x63, 0x59, 0x8C, 0x6C, 0xDB,
414 0x11, 0xCF, 0xA1, 0xDF, 0x5F, 0x4D, 0xDF, 0xB4, 0xC3, 0x82, 0xEE, 0x58, 0x16, 0xB4, 0x74, 0xFA,
415 0xBE, 0x11, 0x9C, 0x1E, 0x98, 0x29, 0xDE, 0xE3, 0xE5, 0x9E, 0xCF, 0xD7, 0x91, 0x0A, 0xA3, 0xA4,
416 0x42, 0xA1, 0x95, 0x09, 0x9E, 0x16, 0xD5, 0xA8, 0x24, 0x56, 0x5B, 0x23, 0xC8, 0x56, 0x4C, 0xCB,
417 0x89, 0x18, 0x69, 0xEB, 0x0C, 0x1F, 0xC0, 0x41, 0x5C, 0x63, 0x04, 0x68, 0xB2, 0x0F, 0x3F, 0x88,
418 0x36, 0xDD, 0x23, 0x4D, 0x4C, 0xC0, 0x81, 0xE3, 0xE9, 0xAD, 0xE0, 0x27, 0xD5, 0xE5, 0x46, 0xEB,
419 0xFF, 0x32, 0xA2, 0xB7, 0x14, 0x64, 0x0B, 0x6D, 0x1B, 0xE5, 0xD8, 0xAE, 0x9D, 0xE8, 0x55, 0xB9,
420 0x52, 0x70, 0x59, 0xB8, 0x72, 0x92, 0x69, 0x37, 0x95, 0x61, 0x0A, 0xE5, 0xF6, 0x55, 0x97, 0x1D,
421 0xBF, 0xF7, 0x29, 0x77, 0x0F, 0x72, 0x80, 0xB2, 0x7E, 0x56, 0xBF, 0xFD, 0xE9, 0xF5, 0x9B, 0x62,
422 0xE9, 0xBD, 0x0B, 0xC2, 0x07, 0x55, 0x31, 0x4C, 0x57, 0x3A, 0x05, 0xB9, 0x27, 0x41, 0x4A, 0xC3,
423 0xEC, 0x72, 0x20, 0xB3, 0x0C, 0xF9, 0xD9, 0x3A, 0x14, 0x6A, 0x03, 0x44, 0x6A, 0xF1, 0x41, 0x55,
424 0x7F, 0x81, 0xC2, 0x04, 0xA8, 0x05, 0xB9, 0x49, 0x2E, 0x43, 0xC4, 0x00, 0x87, 0x86, 0x04, 0xAC,
425 0xAF, 0x73, 0x78, 0x0E, 0xA4, 0x43, 0x5B, 0x36, 0xA2, 0x8F, 0x9C, 0xF7, 0x66, 0x4A, 0x5A, 0x09,
426 0x6B, 0xAA, 0x69, 0x6F, 0xB1, 0x20, 0x0D, 0x56, 0x85, 0x0A, 0x5E, 0x06, 0xBF, 0xE2, 0x32, 0xB4,
427 0x5C, 0x46, 0x33, 0x0D, 0x27, 0xA3, 0x6B, 0xE1, 0xB2, 0x6A, 0x7D, 0x4A, 0xA7, 0x81, 0x0F, 0x2B,
428 0x16, 0x7C, 0x51, 0xD6, 0xC0, 0x3D, 0xB9, 0xFE, 0xB4, 0x66, 0xC4, 0xB6, 0x54, 0x53, 0x67, 0xDA,
429 0x70, 0x96, 0x9A, 0x0A, 0x07, 0x1A, 0x26, 0xBA, 0x85, 0x50, 0xF5, 0x27, 0x53, 0x9C, 0x3A, 0x94,
430 0x0A, 0x7D, 0xDB, 0xE1, 0xC3, 0xE3, 0x6A, 0x3E, 0x9E, 0xD5, 0x13, 0x0A, 0xA3, 0xD2, 0x21, 0x75,
431 0x79, 0x17, 0x26, 0xAC, 0x48, 0x5F, 0x3D, 0xE1, 0x7D, 0xA4, 0xB1, 0x56, 0x0F, 0x92, 0x2C, 0x60,
432 0xE6, 0xCB, 0x87, 0x35, 0xB8, 0x75, 0xC3, 0xA2, 0x03, 0x50, 0x4B, 0xA2, 0x6E, 0x01, 0xE1, 0xDD,
433 0x87, 0xA5, 0x33, 0xC6, 0x2F, 0xA2, 0x41, 0xFC, 0x72, 0x98, 0xA2, 0x69, 0x4C, 0x3F, 0xF0, 0x53,
434 0xF5, 0x41, 0x2B, 0x23, 0x24, 0x3B, 0xCE, 0x9D, 0x39, 0x31, 0x17, 0x08, 0xE1, 0x3F, 0x5F, 0xFB,
435 0x00, 0xFA, 0xF1, 0xE3, 0xE1, 0x7B, 0x0C, 0xDF, 0x8D, 0xA2, 0xC4, 0xCD, 0x62, 0x3D, 0xAE, 0xC7,
436 0x48, 0x09, 0x1C, 0x66, 0xCB, 0x0E, 0x23, 0xE8, 0x1B, 0x9F, 0x1B, 0xCB, 0xF8, 0x14, 0xC3, 0x34,
437 0x91, 0x32, 0x2B, 0x39, 0x1C, 0xBA, 0x1C, 0xA0, 0x19, 0xF2, 0x57, 0x9D, 0x78, 0x00, 0x55, 0x1F,
438 0x15, 0x12, 0x9A, 0xA2, 0xF2, 0xC2, 0xB7, 0x4E, 0xEA, 0x46, 0x01, 0xC2, 0xE9, 0x76, 0xBF, 0xDE,
439 0xCF, 0x8B, 0xC7, 0x50, 0x80, 0xEE, 0x46, 0x91, 0x93, 0x1E, 0x5C, 0x48, 0x5D, 0xC8, 0xC8, 0x63,
440 0xD1, 0x89, 0x02, 0x29, 0xE9, 0x90, 0x9F, 0x0B, 0x0A, 0x1A, 0x44, 0x17, 0xE7, 0x4E, 0xAD, 0x58,
441 0x55, 0xF8, 0x38, 0xF6, 0x4F, 0xD8, 0x1C, 0x7E, 0x25, 0x9B, 0x59, 0x16, 0xBC, 0x65, 0x24, 0xC5,
442 0xA7, 0x56, 0xE5, 0x20, 0x3F, 0xD9, 0x27, 0xE0, 0x32, 0x24, 0xE1, 0x7B, 0xE1, 0x32, 0xEA, 0xF4,
443 0xFE, 0xD9, 0xA5, 0xFF, 0x35, 0xAE, 0xA9, 0x1B, 0x38, 0x28, 0x6A, 0xC0, 0x1A, 0x42, 0xD9, 0x5E,
444 0x14, 0x2C, 0xC2, 0x2D, 0x9B, 0x94, 0x5B, 0xCF, 0x83, 0x30, 0xB9, 0x06, 0xAF, 0x4B, 0xD7, 0xF6,
445 0x38, 0x7C, 0xFF, 0xB4, 0xA5, 0x1A, 0xA0, 0xE9, 0xF3, 0x01, 0xE3, 0x97, 0xC4, 0xA9, 0x57, 0xF5,
446 0xB9, 0x96, 0xA7, 0xA3, 0xB8, 0x10, 0x0E, 0xFB, 0x1D, 0x39, 0x44, 0x16, 0x97, 0x94, 0x3E, 0x5F,
447 0xAF, 0x0F, 0xE3, 0x99, 0xDC, 0xA0, 0xE9, 0x8D, 0x26, 0x2B, 0xD9, 0xAE, 0xEC, 0x4C, 0x4F, 0x09,
448 0x86, 0x7E, 0x7B, 0xC3, 0xE3, 0xC6, 0x17, 0xAE, 0x30, 0x9C, 0x31, 0xD1, 0x84, 0x47, 0xAF, 0xCB,
449 0xEA, 0x69, 0x2A, 0x08, 0x3E, 0x13, 0x00, 0xDE, 0xF6, 0x4A, 0x42, 0xD3, 0xBE, 0x33, 0xD9, 0x50,
450 0x6B, 0x8D, 0x59, 0x12, 0x1A, 0xD3, 0xA7, 0x7C, 0x0A, 0xE7, 0x87, 0x47, 0xCA, 0xAA, 0x33, 0xFD,
451 0xC1, 0xF6, 0x28, 0xC1, 0x62, 0xA2, 0x4C, 0x79, 0x83, 0x48, 0x86, 0x0E, 0xA4, 0x67, 0x34, 0x95,
452 0xAE, 0x7D, 0xD6, 0xEE, 0x91, 0x05, 0x35, 0x91, 0xE8, 0x34, 0x39, 0xA3, 0xE5, 0xE6, 0x80, 0x53,
453 0x76, 0x1F, 0x94, 0xA0, 0xF6, 0xA5, 0x41, 0x79, 0x82, 0xD3, 0xB0, 0x1F, 0xCE, 0xE1, 0x86, 0x64,
454 0x65, 0x0C, 0x8D, 0xD6, 0xFA, 0xC1, 0x10, 0x6C, 0x07, 0xD5, 0xF0, 0x77, 0x65, 0xB9, 0x0C, 0xBD,
455 0xAE, 0x2D, 0x62, 0x6C, 0x42, 0x7E, 0x2A, 0xBE, 0x5F, 0xC1, 0x17, 0x3B, 0x07, 0xFF, 0x5E, 0xD7,
456 0x31, 0x52, 0x26, 0x2F, 0x9F, 0x12, 0xD8, 0x2E, 0xA3, 0xF5, 0xB5, 0xD2, 0xFC, 0x6E, 0x08, 0x1F,
457 0xC8, 0x93, 0xA1, 0xEB, 0xF9, 0x13, 0x1D, 0x1F, 0x98, 0x5E, 0xB0, 0x0C, 0x65, 0x6C, 0xAE, 0x07,
458 0x78, 0xF8, 0x12, 0xD2, 0xD1, 0x1E, 0x77, 0x5C, 0x24, 0x62, 0xE5, 0x94, 0xD6, 0x6A, 0x8E, 0xD0,
459 0x72, 0x59, 0xDA, 0x48, 0x38, 0x2F, 0x31, 0x75, 0x0C, 0x52, 0xF0, 0x0C, 0x8F, 0x5C, 0xE9, 0x5E,
460 0x5A, 0x94, 0xE8, 0xD2, 0x80, 0xF8, 0x4F, 0xE7, 0xAA, 0x6C, 0xBE, 0x47, 0xFB, 0xDD, 0x57, 0x0A,
461 0xD8, 0x5E, 0xCC, 0x0D, 0x8F, 0x42, 0x5E, 0xDC, 0x5D, 0x95, 0x95, 0x60, 0x9B, 0x6F, 0x05, 0x5E,
462 0x08, 0x45, 0x91, 0xE4, 0xB8, 0x06, 0xB1, 0xF2, 0xC0, 0xD7, 0xE3, 0x47, 0xB7, 0x38, 0x08, 0xA8,
463 0x58, 0xE4, 0x55, 0xFC, 0xE2, 0x37, 0x1F, 0x38, 0xA2, 0x18, 0x9E, 0xC2, 0x0F, 0x90, 0x14, 0x20,
464 0x50, 0xD1, 0xD0, 0xAB, 0x36, 0x7F, 0xAA, 0x03, 0x1C, 0xE6, 0x0A, 0xF9, 0x8E, 0x41, 0xDB, 0x32,
465 0x1C, 0x68, 0xA0, 0xA0, 0xED, 0x4A, 0xF4, 0x4B, 0x09, 0xD0, 0xF0, 0x01, 0x8B, 0x17, 0x44, 0xE1,
466 0xEA, 0xC5, 0x9D, 0x3B, 0x37, 0x7A, 0x68, 0xF1, 0x78, 0x46, 0xCF, 0xB6, 0x57, 0xDB, 0x4B, 0x5C,
467 0x03, 0xE1, 0x9D, 0xC0, 0x37, 0x55, 0x8D, 0x03, 0xFB, 0x6A, 0x00, 0x82, 0x19, 0xD1, 0xC0, 0x76,
468 0x97, 0xEE, 0xC9, 0xAD, 0x0D, 0x72, 0x0B, 0xE9, 0xA8, 0x09, 0x92, 0x03, 0xA4, 0xAA, 0x2C, 0xCF,
469 0xFD, 0xDE, 0x86, 0xD0, 0x06, 0x4A, 0xAE, 0x7E, 0xC1, 0xB8, 0x2A, 0x4E, 0x9F, 0xA3, 0x5E, 0x8C,
470 0x12, 0x40, 0x74, 0x38, 0xE7, 0xEA, 0xB0, 0x51, 0xC2, 0xB9, 0x6D, 0x4A, 0x50, 0xBF, 0x59, 0x9C,
471 0x05, 0xB2, 0x42, 0xE2, 0x0F, 0x71, 0x44, 0xDB, 0x97, 0x0B, 0xD0, 0xDB, 0x44, 0x1F, 0x9A, 0x3B,
472 0x18, 0x2A, 0x7B, 0xD9, 0x03, 0x83, 0x0B, 0xCF, 0x27, 0x20, 0x43, 0xA6, 0x42, 0xED, 0x89, 0x63,
473 0xDB, 0x2D, 0x27, 0xC2, 0x3B, 0xE6, 0x0D, 0x3E, 0xB6, 0x96, 0x33, 0x70, 0xA6, 0xF3, 0xF5, 0x56,
474 0xEA, 0xEB, 0xF1, 0xE7, 0xD8, 0xCB, 0x04, 0x48, 0x99, 0x4C, 0x00, 0xA4, 0x2A, 0xA5, 0x8A, 0xF1,
475 0x58, 0xD5, 0x17, 0x4C, 0xC5, 0x88, 0x06, 0x8F, 0xA6, 0x67, 0xA6, 0x14, 0xC7, 0xB9, 0xE0, 0x86,
476 0xAC, 0x67, 0xFD, 0xB3, 0x5B, 0x3E, 0xDF, 0x03, 0xFD, 0xC8, 0xC4, 0x4A, 0x32, 0x78, 0x6B, 0xD1,
477 0xC1, 0xE2, 0x36, 0x9D, 0x0B, 0xF2, 0x54, 0x25, 0xB8, 0xB7, 0xB2, 0x10, 0x7A, 0xA6, 0x79, 0x52,
478 0xC2, 0xEE, 0x98, 0xA5, 0x3D, 0xF0, 0x07, 0x8D, 0x25, 0xC3, 0xAC, 0xFD, 0xCF, 0x83, 0x98, 0x80,
479 0x56, 0x95, 0xC4, 0x14, 0xA2, 0xA5, 0x93, 0xFE, 0x24, 0x59, 0x44, 0x73, 0xDF, 0xD6, 0x47, 0xDA,
480 0x22, 0x3A, 0x82, 0xC5, 0xD1, 0x59, 0x40, 0x9D, 0x0C, 0x1A, 0xB7, 0x79, 0x45, 0x9A, 0xF8, 0x6D,
481 0x5A, 0x5C, 0xC2, 0x80, 0xFC, 0xAA, 0x8A, 0xA4, 0xFE, 0x68, 0x61, 0x7D, 0xFE, 0x2C, 0x36, 0xE3,
482 0xE0, 0x59, 0x28, 0x40, 0x79, 0xAD, 0x2D, 0x28, 0x12, 0x30, 0xFC, 0x56, 0x2E, 0x1D, 0xEC, 0x48,
483 0x3A, 0xF0, 0xC5, 0x6C, 0x31, 0xE0, 0x2E, 0xB3, 0x91, 0x70, 0xB9, 0x9E, 0xBD, 0xE7, 0x96, 0x58,
484 0xCB, 0xBC, 0x1C, 0xE4, 0xC7, 0x78, 0xC7, 0x1E, 0x39, 0xDB, 0xB8, 0x77, 0x50, 0xB7, 0x65, 0x20,
485 0x04, 0x16, 0x8B, 0xFC, 0x66, 0xC4, 0x6D, 0x05, 0x8C, 0x3C, 0xB6, 0x32, 0x2F, 0xDE, 0xC3, 0x6F,
486 0xFC, 0x82, 0x06, 0x02, 0x87, 0x47, 0xFD, 0xD8, 0xDA, 0x75, 0xE0, 0x4E, 0x8C, 0x40, 0x00, 0xB2,
487 0x9B, 0x35, 0x78, 0xA4, 0x61, 0x64, 0x96, 0x62, 0x37, 0xF6, 0x3E, 0x39, 0xFA, 0x14, 0x5B, 0xC4,
488 0x70, 0x17, 0xDC, 0x0C, 0x9E, 0x31, 0x82, 0x2C, 0x63, 0xCC, 0x8A, 0x43, 0x7C, 0x69, 0x12, 0x05,
489 0x18, 0xA3, 0x62, 0xCC, 0xA2, 0x13, 0x96, 0x25, 0xA6, 0x1B, 0xF2, 0x10, 0xC8, 0x73, 0x4F, 0xCB,
490 0x80, 0xCA, 0xAF, 0x73, 0xC9, 0x78, 0xB1, 0xAE, 0x87, 0xB8, 0xDF, 0x50, 0xD3, 0x55, 0x1E, 0x3A,
491 0x81, 0xF6, 0x84, 0xD6, 0x57, 0x36, 0xCF, 0x38, 0xB7, 0xBC, 0xBC, 0x1E, 0x48, 0x62, 0x9F, 0x0F,
492 0x0C, 0xE5, 0xF0, 0x63, 0x33, 0xE6, 0x59, 0x6B, 0x1E, 0xE6, 0x1C, 0x8A, 0xF9, 0xDD, 0x6B, 0xA3,
493 0xDC, 0x02, 0x4A, 0x2F, 0x8C, 0x6A, 0x8D, 0x16, 0x7E, 0x2F, 0xF1, 0x75, 0xD5, 0x15, 0x93, 0x07,
494 0x27, 0xD9, 0x6F, 0x1A, 0x5D, 0x43, 0xF3, 0x47, 0xC4, 0xED, 0xAD, 0x05, 0x9F, 0xEC, 0x8F, 0xD0,
495 0xBE, 0xB5, 0x58, 0xF4, 0xF6, 0xBE, 0x08, 0x73, 0x96, 0x19, 0x05, 0x25, 0xEC, 0x3D, 0x26, 0xF4,
496 0x93, 0xDB, 0x9F, 0x56, 0x48, 0x4C, 0xBC, 0xD0, 0x02, 0x59, 0xD1, 0x40, 0x4C, 0xA6, 0x06, 0x41,
497 0xE8, 0x7D, 0x47, 0xAE, 0x3A, 0x9E, 0x1A, 0x71, 0x52, 0xD4, 0x67, 0xC1, 0x14, 0x7E, 0x40, 0x6F,
498 0x1C, 0x75, 0x30, 0x7B, 0x70, 0x3A, 0xE0, 0x37, 0xB7, 0x41, 0x7F, 0xCB, 0x4A, 0xBA, 0xA7, 0xCE,
499 0x56, 0x54, 0xC5, 0x46, 0x65, 0x6F, 0xB4, 0xB6, 0xF0, 0x57, 0xCE, 0x2E, 0x4F, 0xA9, 0xF0, 0x14,
500 0x50, 0xC3, 0x30, 0xC5, 0xBA, 0xE1, 0x5E, 0xD6, 0xDC, 0xC5, 0x78, 0x55, 0x32, 0xAA, 0xCB, 0x29,
501 0x35, 0x81, 0x46, 0x5E, 0x92, 0xE7, 0xDE, 0xCC, 0x92, 0x29, 0x86, 0xE0, 0x8F, 0x91, 0x3C, 0x74,
502 0x97, 0x79, 0x63, 0x97, 0x4A, 0xCC, 0x88, 0xB5, 0xA3, 0x7A, 0xF0, 0xF0, 0x33, 0x87, 0xCD, 0xBD
504 uint8_t b = Value ^ hdSurEncBasicCrypt_D2_0F_11(Value, lookup[(((AddrInd * 2) + 0) * 256) + Value]);
505 return (Value ^ hdSurEncBasicCrypt_D2_0F_11(b, lookup[(((AddrInd * 2) + 1) * 256) + b]));
508 void hdSurEncPhase1_D2_0F_11(uint8_t *CWs)
510 static const uint8_t lookup1[] =
512 0x16, 0x71, 0xCA, 0x14, 0xC4, 0xF4, 0xA3, 0x5A, 0x9D, 0x5F, 0x85, 0x8B, 0xA6, 0x77, 0xFD, 0x3C,
513 0x5F, 0x13, 0x2A, 0x5F, 0x61, 0x36, 0xE4, 0xDC, 0x0D, 0x82, 0x92, 0xC5, 0x25, 0xE1, 0x7A, 0x1C,
514 0x29, 0x19, 0x94, 0x2F, 0xC5, 0xD2, 0xDC, 0xBA, 0x86, 0x60, 0x64, 0x60, 0x86, 0x92, 0xA3, 0x4E,
515 0x3D, 0x9B, 0xCC, 0x16, 0xBB, 0xBA, 0xD2, 0xF0, 0x6A, 0xD3, 0x2F, 0x07, 0x75, 0xBD, 0x28, 0xDB
517 static const int8_t lookup2[] = {1, -1, -1, 1, -1, 2, 1, -2, -1, 1, 2, -2, 1, -2, -2, 4};
518 static const int8_t CAddrIndex[] = {0, 1, 3, 4};
519 int32_t i, j, i1, i2, i3;
521 for(i = 3; i >= 0; --i)
523 for(j = 0; j <= 15; ++j)
525 CWs[j] = CWs[j] ^ hdSurEncBasicCrypt_D2_0F_11(j , lookup1 [(16 * i) + j]);
528 uint8_t Buffer[16];
529 uint32_t k;
530 for(i1 = 0; i1 <= 3; ++i1)
532 for(i2 = 0; i2 <= 3; ++i2)
534 k = 0;
535 for(i3 = 0; i3 <= 3; ++i3)
537 k = k + (CWs[(i2 * 4) + i3] * lookup2[(i3 * 4) + i1]);
538 Buffer[(i2 * 4) + i1] = (uint8_t)k;
542 memcpy(CWs, Buffer, 16);
544 // CW positions are mixed around here
545 uint8_t a4[4];
546 for(i1 = 1; i1 <= 3; ++i1)
548 for(i2 = 0; i2 <= 3; ++i2)
550 a4[i2] = i1 + (i2 * 4);
552 for(i2 = 0; i2 <= i1 - 1; ++i2) // the given code in Func1_3 seems to be wrong here(3 instead of i1-1)!
554 uint8_t tmp = CWs[a4[0]];
555 for(i3 = 1; i3 <= 3; ++i3)
557 CWs[a4[i3 - 1]] = CWs[a4[i3]];
559 CWs[a4[3]] = tmp;
563 for(i1 = 0; i1 <= 15; ++i1)
565 CWs[i1] = hdSurEncCryptLookup_D2_0F_11(CWs[i1], CAddrIndex[i1 & 3]);
570 void hdSurEncPhase2_D2_0F_11_sub(uint8_t *CWa, uint8_t *CWb, uint8_t AddrInd)
572 uint8_t Buffer[8];
573 uint8_t tmp, i;
574 for(i = 0; i <= 7; ++i)
576 Buffer[i] = hdSurEncCryptLookup_D2_0F_11(CWb[i], AddrInd);
579 // some bitshifting
580 tmp = Buffer[7];
581 for(i = 7; i >= 1; --i)
583 Buffer[i] = ((Buffer[1] >> 4) & 0xFF) | ((Buffer[i - 1] << 4) & 0xFF);
585 Buffer[0] = ((Buffer[0] >> 4) & 0xFF) | ((tmp << 4) & 0xFF);
587 // saving the result
588 for(i = 0; i <= 7; ++i)
590 CWa[i] = CWa[i] ^ Buffer[i];
594 void hdSurEncPhase2_D2_0F_11(uint8_t *CWs)
596 hdSurEncPhase2_D2_0F_11_sub(CWs, CWs + 8, 0);
597 hdSurEncPhase2_D2_0F_11_sub(CWs + 8, CWs, 1);
598 hdSurEncPhase2_D2_0F_11_sub(CWs, CWs + 8, 2);
599 hdSurEncPhase2_D2_0F_11_sub(CWs + 8, CWs, 3);
600 hdSurEncPhase2_D2_0F_11_sub(CWs, CWs + 8, 4);
603 void CommonMain_1_D2_13_15(const uint8_t *datain, uint8_t *dataout)
605 const uint8_t Tab3[88] = {
606 0x1B,0x12,0x12,0x0C,0x12,0x0C,0x0C,0x08,0x09,0x09,0x06,0x06,0x06,0x06,0x04,0x04,
607 0x08,0x04,0x04,0x02,0x04,0x02,0x02,0x01,0x09,0x06,0x09,0x06,0x06,0x04,0x06,0x04,
608 0x03,0x03,0x03,0x03,0x02,0x02,0x02,0x02,0x04,0x04,0x02,0x02,0x02,0x02,0x01,0x01,
609 0x09,0x06,0x06,0x04,0x09,0x06,0x06,0x04,0x03,0x03,0x02,0x02,0x03,0x03,0x02,0x02,
610 0x04,0x02,0x04,0x02,0x02,0x01,0x02,0x01,0x03,0x02,0x03,0x02,0x03,0x02,0x03,0x02,
611 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01 };
613 int i1,i2;
614 unsigned long bb;
616 for (i1 = 0; i1 < 11; i1++)
618 bb = 0;
619 for (i2 = 0; i2 < 8; i2++)
620 { bb += (Tab3[(i1 * 8) + i2] * datain[i2]); }
621 dataout[i1] = (bb & 0xFF);
626 unsigned short CommonMain_2_D2_13_15(const uint8_t *data, const unsigned long num)
628 unsigned long bb1, bb2;
630 bb1 = num >> 3;
631 bb2 = (data[bb1] << 24) + (data[bb1 + 1] << 16) + (data[bb1 + 2] << 8);
632 return ((bb2 >> (21 - (num & 7))) & 0x7FF);
635 void CommonMain_3_D2_13_15(uint8_t *data0, uint8_t *data1, int nbrloop)
637 int i;
638 unsigned long bb1, bb2;
640 bb1 = 0;
641 bb2 = 0;
642 for (i = nbrloop - 1; i >= 0; i--)
644 bb1 += (data0[i] * 2) + data1[i];
645 bb2 += data0[i] + data1[i];
646 data0[i] = (bb1 & 0xFF);
647 data1[i] = (bb2 & 0xFF);
648 bb1 >>= 8;
649 bb2 >>= 8;
653 void CommonMain_D2_13_15(const uint8_t *datain, uint8_t *dataout, int loopval)
656 const uint8_t Tab0_Comp[0x800] = {
657 0x54,0x75,0x01,0x0C,0x7C,0xE2,0xC3,0xC2,0x5E,0x13,0x26,0xCA,0xB2,0xCD,0xB8,0x3D,
658 0x02,0x2C,0xE4,0x19,0x41,0x3D,0xE4,0x0F,0xEC,0xF1,0x45,0x83,0xE2,0xE2,0x72,0xF9,
659 0xCD,0x75,0x1E,0x41,0xCC,0x0C,0x1F,0x39,0x87,0x9B,0x46,0xFF,0x68,0x1F,0x00,0xD8,
660 0x41,0x82,0xCA,0xC6,0xEF,0x87,0x90,0xA2,0x7E,0xD9,0xDE,0xC8,0x25,0xEA,0xC9,0x75,
661 0x6E,0x18,0x81,0xD8,0x5A,0xA6,0x74,0x05,0xAF,0xAE,0xE0,0x4F,0x85,0xAD,0x94,0xF6,
662 0x45,0xF4,0xF5,0x55,0xA8,0xEB,0xEC,0xDB,0x6C,0xFF,0x2F,0xC2,0xC3,0x7D,0x93,0xE6,
663 0xF5,0x31,0x96,0xB7,0x9A,0xDB,0xE5,0x76,0x66,0xFB,0xDD,0xBC,0x19,0x18,0x42,0xC6,
664 0x36,0xCD,0x46,0x33,0xEA,0xF1,0x4C,0xC0,0x72,0x07,0xCD,0x61,0xCE,0x0E,0x08,0x01,
665 0xA3,0xFA,0x84,0x21,0xF2,0x43,0x37,0x1C,0xDE,0x25,0x8A,0x1A,0xF4,0xBB,0x40,0xF3,
666 0x53,0xFE,0x17,0x60,0x91,0x6D,0x7B,0x6D,0x5F,0x1C,0x15,0x73,0xCC,0x6E,0x73,0x46,
667 0x27,0x73,0xA3,0x10,0x16,0x32,0xB3,0x39,0x45,0xA6,0x55,0xE7,0x91,0x32,0x24,0xC8,
668 0xAE,0xAF,0x1B,0x28,0x69,0x22,0x2F,0xE9,0x77,0x72,0xBF,0x4B,0x8B,0x07,0x82,0x31,
669 0xB0,0x95,0x10,0x78,0x9F,0xC5,0xF3,0x73,0xE1,0xF8,0x36,0x84,0xFE,0x1B,0x92,0xB2,
670 0xE6,0xA5,0xCE,0xDA,0x56,0x48,0x52,0x77,0x9D,0x9D,0x8E,0x37,0x4B,0xC8,0x35,0x7E,
671 0xB9,0x5D,0xA4,0xAE,0x3F,0xD0,0xAA,0x60,0xA8,0x4C,0x85,0x49,0xF6,0x0C,0x27,0xE8,
672 0x94,0x84,0xA0,0xAA,0x06,0x4D,0xAC,0x58,0x8B,0x61,0x29,0x3D,0x68,0x25,0xD3,0xD3,
673 0x8E,0xA1,0xE0,0x71,0xBF,0x21,0x0C,0xC7,0x18,0x19,0xF1,0x25,0x98,0x5F,0x79,0x5E,
674 0x51,0xBA,0x8C,0x2F,0x52,0x43,0xF3,0x5A,0xE3,0x58,0x97,0x64,0x23,0xE0,0x44,0x4F,
675 0x30,0x2A,0xE0,0x16,0x8D,0x4D,0xD1,0x1F,0x7B,0xC9,0xC5,0x74,0x11,0x23,0x5D,0x95,
676 0xAC,0x7F,0x2E,0x30,0xBE,0x2D,0xE3,0xB5,0xC6,0xA7,0x69,0x99,0x1F,0x18,0x3C,0x96,
677 0x30,0x45,0x99,0x71,0x28,0x08,0x3C,0xF7,0x37,0x4F,0x6A,0xD6,0xAE,0x9B,0x57,0xC1,
678 0xCC,0x2C,0xE2,0x0F,0x7D,0x66,0xF4,0x36,0x0C,0x3B,0x35,0xF6,0x28,0x03,0xA3,0x7A,
679 0x83,0x15,0xF5,0x61,0x5E,0xE8,0xB7,0xD8,0x54,0x33,0x93,0x63,0x80,0x40,0x43,0xD0,
680 0x9C,0xAA,0x3A,0x98,0x50,0xD2,0xB8,0x80,0x5D,0x16,0xDF,0x1C,0x03,0xAA,0x87,0xC7,
681 0x63,0xA5,0x8D,0xA9,0x2E,0xFB,0x4F,0x7C,0x2B,0xF5,0xF9,0x57,0xB5,0x90,0xD8,0x75,
682 0xAB,0x81,0x4C,0x1B,0xAF,0x6C,0x0E,0xCB,0xB1,0x4F,0xD3,0xE3,0x69,0x18,0x8C,0x7A,
683 0x3C,0xE1,0x11,0x86,0x47,0x78,0x11,0xA0,0xD4,0x28,0xC3,0x0D,0xAC,0xC6,0x17,0xA1,
684 0x32,0x9F,0x8F,0x42,0xD9,0x3F,0x66,0xD7,0x2D,0x87,0x7B,0x65,0xD3,0xD6,0x90,0x83,
685 0xA2,0x75,0xE8,0x98,0x90,0x9D,0xDE,0x81,0x9E,0x3D,0xE4,0xA9,0xE4,0x0B,0xBC,0xBA,
686 0x96,0xDD,0x05,0xCA,0xAE,0x78,0x69,0x24,0xDB,0xA7,0x3E,0x7A,0x3B,0xB4,0xC4,0x59,
687 0x61,0xD2,0xF2,0xE3,0x99,0x8F,0x8F,0x8A,0x82,0x33,0xB8,0x17,0x5E,0x7A,0x32,0x41,
688 0x10,0x8D,0xC2,0xEF,0xAA,0xF8,0x5A,0xF7,0xD2,0x1D,0xC0,0xCB,0x5E,0xB7,0x8A,0x78,
689 0x49,0x42,0xEB,0x19,0x1B,0x61,0xA0,0x77,0x5A,0xF4,0x6D,0x55,0xDA,0xEB,0xCE,0x4E,
690 0xB8,0xE6,0x32,0xD7,0x51,0x3F,0x73,0x14,0x34,0x6E,0x38,0xD6,0xA7,0x28,0x87,0x4A,
691 0x59,0xCA,0x1C,0x80,0xB5,0x8C,0x9D,0x94,0xCB,0xFE,0x29,0x41,0xE5,0x69,0xCF,0xFD,
692 0x0B,0xE1,0x7C,0xA1,0x70,0x12,0x76,0x43,0xDA,0xB9,0xD4,0xC3,0x31,0xBC,0x94,0x77,
693 0x04,0xB4,0x1C,0xAA,0xEC,0x6F,0xA5,0x12,0x9D,0x6F,0x34,0x65,0x77,0xA0,0xD2,0x6F,
694 0x60,0xC6,0x47,0xC2,0xDF,0x6A,0x10,0x53,0xD4,0xBA,0xF3,0xB7,0x38,0x79,0x63,0xC9,
695 0xD4,0x77,0xBC,0x54,0xE9,0x79,0x42,0xD5,0xE0,0x71,0xE7,0x9E,0x5A,0x62,0x0C,0xAD,
696 0x01,0x09,0xA8,0x9F,0x8E,0x67,0x4A,0x30,0xA4,0xB1,0x08,0xFC,0x0A,0xEA,0x7A,0x1D,
697 0x4C,0x4A,0x21,0xDE,0x00,0xD7,0x41,0x98,0x6B,0x38,0x50,0x3E,0x1F,0x25,0x06,0xE3,
698 0x6C,0xA3,0x84,0x5B,0xC1,0xED,0x47,0xDD,0xB3,0x83,0x46,0x72,0x69,0xCE,0x72,0x04,
699 0x43,0x67,0x3A,0x19,0xD9,0x0A,0xF7,0x43,0x88,0xCA,0xC7,0x31,0x34,0x21,0x4E,0x4C,
700 0xE8,0xD1,0x70,0x00,0xBD,0xB1,0xB6,0x76,0x6F,0x5B,0xF9,0xF5,0xF4,0x19,0x20,0x21,
701 0xC1,0xF0,0x11,0x36,0x66,0xAB,0x15,0xBD,0x69,0x92,0xC6,0x46,0xDE,0xDC,0xE9,0x9A,
702 0xF8,0x6C,0x15,0x29,0x15,0xA6,0x35,0x3E,0x08,0xE5,0x90,0x62,0x9F,0x86,0x56,0x83,
703 0x5D,0x60,0x0D,0x22,0x77,0xA7,0x60,0x9B,0x26,0x80,0x16,0x67,0xB4,0x46,0xBF,0x74,
704 0x55,0x92,0x5B,0x34,0xFF,0xC8,0x28,0x37,0xFF,0x14,0x62,0xFA,0xBD,0x03,0x78,0x04,
705 0x1B,0x65,0x7F,0x99,0x05,0x27,0x14,0xC0,0x06,0x4D,0x4B,0x0E,0x98,0x34,0x6A,0xB3,
706 0xA1,0xFE,0xBC,0x45,0x7D,0x52,0x50,0x0E,0x2C,0xFB,0x91,0xF5,0xFB,0x2A,0xB7,0xD9,
707 0xB8,0xB8,0x54,0x31,0x81,0x03,0x93,0x2C,0xE1,0x5C,0xB9,0x2C,0xE8,0x38,0xC0,0xA7,
708 0x58,0x18,0x92,0xC5,0x8B,0xEF,0x1E,0x33,0xA4,0xBA,0x86,0x2B,0xE9,0xEE,0xB1,0xDF,
709 0xAB,0xB8,0x48,0xDA,0x84,0xF1,0x68,0x05,0x4E,0xDE,0xB5,0x9E,0x88,0x12,0xC9,0x60,
710 0x50,0x58,0x56,0x9D,0x26,0x84,0xB6,0x1A,0xE6,0x4B,0x40,0x94,0x6D,0xE9,0x1D,0x0D,
711 0x8A,0xF9,0x2A,0xB5,0xBC,0xDB,0x06,0x8F,0x13,0x7E,0x1D,0x1C,0xC7,0xFD,0x8F,0x78,
712 0x55,0x3F,0x16,0x84,0x48,0xDA,0x1A,0xD1,0x93,0x95,0x20,0x58,0x92,0x39,0xF6,0x73,
713 0x4E,0x9E,0x7B,0x70,0xFC,0x1E,0x5B,0x20,0x48,0x96,0xB3,0x7C,0x50,0x09,0x5B,0x61,
714 0x57,0x97,0x36,0x04,0x29,0x2C,0x32,0x8E,0x93,0x4A,0x45,0xFA,0xD5,0x24,0x14,0x1A,
715 0x28,0x9C,0x1A,0x71,0xAE,0x85,0x4B,0x26,0x79,0x99,0x65,0xD0,0x07,0x98,0xED,0xC9,
716 0x1B,0x39,0x57,0x5B,0xDB,0x3D,0x87,0x69,0x66,0x9B,0x03,0x23,0x54,0x6B,0x4B,0xAC,
717 0x6E,0x7A,0x25,0x1E,0xB6,0x97,0xCF,0x1D,0x07,0xCB,0x2A,0x3E,0x85,0x02,0x93,0x31,
718 0x12,0x27,0xF0,0xA6,0x6D,0x0F,0x9A,0xB6,0xFC,0x22,0x79,0x6C,0x77,0xFD,0x3F,0xDC,
719 0x19,0xD0,0xDF,0xBD,0x9E,0xE0,0xBE,0x20,0x13,0xA3,0x0A,0x0B,0x22,0xF2,0xC8,0x6B,
720 0xA1,0xDD,0x6C,0x67,0xB3,0xFD,0x71,0xC2,0x7B,0x08,0x3B,0xF1,0x37,0xB5,0x0F,0x86,
721 0xFA,0xA9,0xE9,0x42,0xD1,0xE8,0xCD,0x05,0xEF,0xD3,0xCC,0x0B,0x70,0x51,0x5B,0x97,
722 0x06,0xC4,0x9D,0x88,0x11,0x3E,0x99,0x9F,0xBE,0x76,0x8C,0x8D,0xE6,0xBA,0xDA,0x48,
723 0xD0,0x04,0x86,0x4F,0xA9,0xC6,0xB0,0xED,0xA4,0x94,0x46,0x96,0x27,0xEE,0x9F,0xBD,
724 0xDA,0x9B,0x3D,0x11,0x80,0xD3,0x7B,0x5A,0x48,0x94,0xE5,0xCC,0x48,0xEA,0xE4,0x18,
725 0xDF,0x51,0xB3,0x02,0x57,0x20,0x4B,0x0F,0x07,0xFF,0x41,0x33,0x0F,0x6B,0x2E,0xAA,
726 0xDE,0xB2,0x56,0xF7,0xFB,0xA2,0x48,0x3C,0x97,0x1A,0x64,0x2C,0xD1,0x74,0x40,0xCF,
727 0x65,0x7F,0x14,0x08,0x59,0xC4,0x35,0xD3,0x8A,0x0F,0xFD,0x71,0x7A,0x71,0xAC,0x2D,
728 0xF3,0xFD,0x7B,0x12,0x5F,0xC0,0xBC,0x4E,0x96,0x12,0xF2,0x8E,0x41,0x84,0x01,0x0F,
729 0xED,0x7B,0xC1,0xB9,0x39,0x03,0x35,0x40,0x49,0x53,0xB8,0xB4,0x6B,0xA6,0xE7,0x0A,
730 0x14,0xBB,0x29,0x16,0xEC,0x2A,0x3A,0xD6,0x09,0xBB,0x5C,0x20,0xF8,0x09,0xFD,0x86,
731 0xC4,0x25,0x09,0x85,0x0B,0xD5,0xD8,0x51,0xB1,0xA2,0xCB,0xDC,0xC4,0xDD,0x34,0xDF,
732 0xE2,0x85,0xA9,0xCC,0x4E,0x66,0x51,0xFA,0x9C,0x4D,0xB7,0x1E,0x3E,0x49,0x34,0x9C,
733 0x21,0x66,0x07,0x44,0xB2,0xEC,0x73,0xC5,0xBB,0x27,0x9A,0xA5,0x91,0x5A,0xB9,0x9F,
734 0xBE,0xC8,0xA2,0x27,0x89,0x21,0xA7,0xEE,0x50,0x4D,0x43,0x50,0x67,0xC2,0x3B,0x7C,
735 0x20,0x0B,0x95,0x40,0xBE,0xEA,0xB5,0xD9,0x82,0xD7,0x9C,0xB5,0x21,0xAD,0xA6,0xF9,
736 0x70,0xEA,0xCD,0x04,0xDD,0x58,0x91,0x89,0xB2,0xA9,0xF9,0xB4,0x12,0xA2,0x63,0x89,
737 0x40,0x8E,0xEA,0x62,0xEE,0x0B,0x01,0x82,0x6F,0xB3,0x5E,0x5C,0x36,0xBE,0xF4,0x97,
738 0x2C,0xCF,0x96,0x7C,0x0D,0xAD,0x62,0xCE,0xD4,0x38,0xC5,0x32,0x02,0x24,0x57,0x27,
739 0xE0,0xCF,0x56,0xA5,0x72,0x6D,0x90,0x89,0x2D,0x4C,0x34,0xF6,0x1D,0xDD,0x88,0x5E,
740 0x7A,0x23,0xE3,0x6F,0x42,0xA3,0xD9,0x58,0x7E,0xE3,0x52,0x74,0x57,0x63,0xB7,0xB2,
741 0xC1,0xA3,0x30,0x92,0x2E,0xB0,0x91,0x01,0x13,0x36,0x9A,0x6A,0xA7,0x5B,0x3C,0x07,
742 0xFB,0xD8,0x1E,0x7E,0xCF,0x49,0xAB,0x3F,0xCA,0xCE,0x74,0x40,0x54,0x8D,0x83,0x61,
743 0xCA,0xC3,0x76,0x59,0x5C,0x9F,0x49,0x8A,0x7D,0xD1,0x17,0x9C,0xA4,0xDB,0xB9,0x16,
744 0x4D,0x64,0xF7,0xC7,0xF0,0x24,0xE7,0x00,0xB6,0x98,0xD5,0x8B,0x54,0xCB,0x1E,0x8B,
745 0xA2,0x2B,0x7D,0x50,0x51,0x8A,0xF0,0xEF,0x47,0xAE,0xD0,0xD6,0xA0,0x42,0x8A,0xD8,
746 0x22,0xAF,0x02,0x99,0x4A,0xE0,0x8D,0x8D,0xBF,0x11,0x05,0xA4,0xC4,0x9D,0xB3,0x89,
747 0xB4,0x4C,0xC9,0xF7,0x4D,0xC5,0x2A,0x35,0x95,0x30,0xF3,0x0E,0x2F,0xEC,0x6E,0x3A,
748 0x8B,0x05,0x76,0xED,0x1A,0x7C,0xC0,0xE7,0x22,0xCB,0x59,0xFF,0xE6,0x37,0x78,0x44,
749 0xD4,0xEE,0xAD,0xD7,0xBD,0x2E,0xB7,0x6A,0xA4,0x4E,0x0E,0xFB,0xB0,0xF5,0xCB,0x87,
750 0xCF,0xC3,0x18,0x64,0x6F,0x26,0x5C,0xD7,0x16,0xC8,0x7F,0xAB,0x29,0xC4,0xBA,0xFF,
751 0xCD,0x1C,0xE4,0x3A,0xF2,0xEB,0x6A,0x38,0xE4,0x65,0xC2,0x33,0x03,0x26,0x7D,0x9B,
752 0x7E,0x1D,0x83,0x00,0x04,0x2D,0x2B,0x5F,0xFE,0x39,0x7E,0xF1,0x3C,0xA2,0x8C,0x52,
753 0x95,0xBF,0x46,0x81,0x24,0x44,0xF8,0x10,0xC3,0x87,0x8E,0x64,0x80,0x17,0x44,0xE2,
754 0x8B,0xD1,0x3C,0x4A,0xE2,0x1F,0xA9,0xDE,0x75,0x13,0xFC,0x2E,0x86,0x0A,0x5C,0x5F,
755 0x92,0x2B,0x92,0x2D,0x2A,0xEC,0xD2,0x5C,0x82,0x6B,0x76,0x1E,0xED,0xE6,0x56,0xF7,
756 0xD2,0xDB,0x96,0x68,0x02,0x68,0x99,0x49,0xEE,0x88,0x66,0xCE,0x5D,0x08,0x88,0xA8,
757 0xB9,0x24,0xB0,0xB4,0xDC,0xA6,0xC9,0xD8,0x68,0x80,0xBF,0x6B,0x32,0x57,0x7F,0x91,
758 0x0E,0x37,0x59,0xF6,0x76,0xD2,0xC5,0x0B,0xF3,0x23,0xBF,0x38,0x52,0x0D,0x97,0x81,
759 0x17,0xBB,0x9A,0xC2,0x55,0x44,0x72,0xCE,0xEE,0xFA,0xBB,0xDA,0xAB,0xB0,0x09,0xEA,
760 0xDB,0xBF,0x45,0x95,0x07,0x88,0xD4,0xD2,0x0D,0x2E,0x15,0x31,0xBE,0x6A,0xF4,0xEF,
761 0xA3,0x7D,0x22,0x81,0x3B,0xA8,0x83,0xF9,0x42,0xE5,0x9B,0x79,0x01,0xF5,0xDC,0x19,
762 0x64,0xEB,0x47,0x67,0xAF,0xA4,0xB2,0xAE,0xF8,0xF9,0x4D,0x63,0xAD,0x54,0xE1,0x02,
763 0x56,0x89,0x4E,0x0A,0xE8,0x3E,0x03,0xFA,0x33,0x61,0x58,0x80,0x64,0x55,0x3C,0x8C,
764 0x2A,0x3D,0x70,0x3E,0xE5,0xC1,0xA7,0x75,0xFC,0x91,0x75,0x05,0x8C,0x6E,0x3A,0x74,
765 0x10,0xF1,0x30,0xE6,0xF6,0xF7,0xAB,0x6C,0xB1,0x2B,0xF0,0x2F,0x13,0x6E,0xD4,0x0A,
766 0x64,0x29,0xF8,0xBB,0xA1,0xAA,0x55,0x09,0x93,0x47,0x2F,0x8C,0x7D,0xF1,0x2D,0x81,
767 0xFE,0x78,0xFC,0xEE,0x3F,0xDD,0x49,0xDC,0x0D,0x52,0x5C,0x3B,0x8F,0x08,0xB0,0xDF,
768 0xDC,0xFC,0xBE,0x5F,0x3B,0x53,0x82,0xE2,0xBD,0x6D,0x5D,0xF2,0x8D,0xFB,0x5A,0x1D,
769 0x15,0x1B,0xE4,0xB1,0x56,0x06,0x1A,0xF8,0x9C,0xB9,0x44,0xF2,0xD9,0xF4,0xB2,0x00,
770 0x9A,0x94,0x62,0x33,0x7E,0x0A,0xB0,0x0C,0xD5,0xEF,0x8E,0xA8,0xEB,0x47,0xE9,0x20,
771 0xA8,0x68,0xEF,0x53,0xA0,0x59,0x1B,0xA0,0x2B,0xC5,0x2B,0x30,0xB6,0x5D,0xAB,0xB4,
772 0x5F,0x86,0x71,0x95,0x89,0xFC,0xC7,0x9A,0xC3,0xED,0x82,0xA0,0x3D,0x73,0xC1,0x36,
773 0x01,0x5F,0x9E,0xD7,0xE3,0xC0,0x62,0x74,0xED,0x13,0xB6,0xD6,0xD5,0x37,0x17,0xE1,
774 0x39,0xC7,0x6D,0x31,0xBA,0x02,0xAF,0xD5,0xCC,0x51,0xA8,0x09,0x3F,0x00,0x4A,0x8F,
775 0xA6,0x23,0x13,0x88,0xCD,0x1F,0x38,0x60,0xE7,0xE7,0x53,0xDC,0x65,0xE8,0x53,0x26,
776 0xBB,0xE1,0x1F,0x65,0xF0,0xAD,0x53,0x3B,0xBD,0xAD,0x97,0xAC,0xD1,0xA5,0xD0,0xE9,
777 0xEB,0xD6,0x11,0xD5,0x00,0xDF,0x72,0x9C,0xCC,0x7F,0xD3,0x67,0xA1,0x3A,0x79,0xE1,
778 0x85,0x70,0xE5,0x43,0xC9,0x28,0xA5,0x2F,0x9E,0xE7,0xFE,0xEB,0x14,0x10,0x23,0xC7,
779 0xAF,0xB1,0x24,0xC8,0xE5,0x44,0x6F,0x4C,0x04,0xEC,0xC1,0xF0,0x23,0x1C,0xF6,0xAC,
780 0xAF,0xC4,0x0E,0x2D,0x59,0x39,0x47,0xA9,0x9E,0xD9,0x2E,0x79,0xBA,0xFE,0x4F,0x12,
781 0x7F,0x63,0x7F,0x62,0x67,0x7C,0x52,0x2F,0xCA,0x8B,0x6B,0x4F,0x10,0x8F,0x14,0xC6,
782 0xA1,0x9B,0x45,0x15,0x90,0x63,0x22,0x5D,0x68,0x4B,0xCF,0xFA,0x6A,0x06,0xF0,0x26,
783 0xAC,0x6C,0x3A,0x89,0x25,0xF3,0x5E,0x90,0x06,0x93,0xB6,0x35,0x0D,0x85,0x60,0x98,
784 0xBC,0x6E,0xF2,0xA5,0x17,0x29,0x70,0xD6,0xFF,0x0C,0xD0,0xC0,0x35,0xD7,0x4A,0xFD };
787 const uint8_t Tab1_Comp[11*8] = {
788 0x70,0x49,0xD7,0xE3,0xDF,0x3C,0x96,0x03,0x2A,0x70,0x82,0xA6,0x5F,0xDE,0xCC,0x0C,
789 0x2A,0x62,0x2A,0x3E,0xA4,0x0C,0x0A,0xAB,0x4F,0x06,0x5D,0xD4,0x14,0xAA,0xE1,0xC3,
790 0x96,0xDA,0x16,0x36,0x45,0x3C,0x63,0xC2,0x97,0x71,0x87,0xAB,0xFA,0xB2,0xFC,0xD6,
791 0x8F,0x85,0xC9,0x04,0x56,0xBA,0xEB,0x3F,0x42,0x9F,0xCB,0x66,0x55,0x45,0x1C,0x96,
792 0xFF,0x4D,0x35,0xDF,0x88,0x0E,0xDC,0xC8,0x4E,0x3F,0x81,0x74,0xD8,0x77,0x4C,0x8E,
793 0x00,0xC0,0x64,0x83,0x4E,0xBB,0xF0,0xB1 };
795 unsigned short buff8[8];
796 uint8_t buff11[11+1]; // +1 to avoid func2 bug
797 int i1, i2;
798 buff11[11] = 0;
800 CommonMain_1_D2_13_15(datain, buff11);
801 for (i1 = 0; i1 < 11; i1++)
802 { buff11[i1] ^= Tab1_Comp[(loopval * 11) + i1]; }
804 for (i1 = 0; i1 < 8; i1++)
805 { buff8[i1] = CommonMain_2_D2_13_15(buff11, i1 * 11); }
807 for (i1 = 0; i1 < 8; i1++)
808 { dataout[i1] = Tab0_Comp[buff8[i1]]; }
810 i1 = 1;
811 while (i1 < 8)
813 i2 = 0 ;
814 while (i2 < 8)
816 CommonMain_3_D2_13_15(&dataout[i2], &dataout[i1 + i2], i1);
817 i2 += (i1 * 2);
819 i1 *= 2;
823 void Common_D2_13_15(uint8_t *cw0, const uint8_t *cw1, int loopval)
825 int i;
826 uint8_t buff8[8];
828 CommonMain_D2_13_15(cw1, buff8, loopval);
829 for (i = 0; i < 8; i++)
830 { cw0[i] ^= buff8[i]; }
833 void ExchangeCWs(uint8_t *cw0, uint8_t *cw1)
835 int i;
836 uint8_t b;
838 for (i = 0; i < 8; i++)
840 b = cw1[i];
841 cw1[i] = cw0[i];
842 cw0[i] = b;
847 void hdSurEncPhase1_D2_13_15(uint8_t *cws)
849 int i;
851 for (i = 0; i <= 7; i++)
853 // Possible code
854 if ((i & 1)==0)
855 Common_D2_13_15((uint8_t *) &cws[0], (uint8_t *) &cws[8], i);
856 else
857 Common_D2_13_15((uint8_t *) &cws[8], (uint8_t *) &cws[0], i);
858 // Other possible code
859 //Common_D2_13_15((uint8_t *) &cws[0], (uint8_t *) &cws[8], i);
860 //ExchangeCWs((uint8_t *) &cws[0], (uint8_t *) &cws[8]);
862 ExchangeCWs((uint8_t *) &cws[0], (uint8_t *) &cws[8]);
865 void hdSurEncPhase2_D2_13_15(uint8_t *cws)
867 int i;
869 for (i = 7; i >= 0; i--)
871 // Possible code
872 if ((i & 1)==0)
873 Common_D2_13_15((uint8_t *) &cws[8], (uint8_t *) &cws[0], i);
874 else
875 Common_D2_13_15((uint8_t *) &cws[0], (uint8_t *) &cws[8], i);
876 // Other possible code
877 //Common_D2_13_15((uint8_t *) &cws[0], (uint8_t *) &cws[8], i);
878 //ExchangeCWs((uint8_t *) &cws[0], (uint8_t *) &cws[8]);
880 ExchangeCWs((uint8_t *) &cws[8], (uint8_t *) &cws[0]);
884 static int32_t viaccess_card_init(struct s_reader *reader, ATR *newatr)
886 get_atr;
887 def_resp;
888 int32_t i;
889 uchar buf[256];
890 uchar insac[] = { 0xca, 0xac, 0x00, 0x00, 0x00 }; // select data
891 uchar insb8[] = { 0xca, 0xb8, 0x00, 0x00, 0x00 }; // read selected data
892 uchar insa4[] = { 0xca, 0xa4, 0x00, 0x00, 0x00 }; // select issuer
893 uchar insc0[] = { 0xca, 0xc0, 0x00, 0x00, 0x00 }; // read data item
894 static const uchar insFAC[] = { 0x87, 0x02, 0x00, 0x00, 0x03 }; // init FAC
895 static const uchar FacDat[] = { 0x00, 0x00, 0x28 };
896 static unsigned char ins8702_data[] = { 0x00, 0x00, 0x11};
897 static unsigned char ins8704[] = { 0x87, 0x04, 0x00, 0x00, 0x07 };
898 static unsigned char ins8706[] = { 0x87, 0x06, 0x00, 0x00, 0x04 };
901 if((atr[1] != 0x77) || ((atr[2] != 0x18) && (atr[2] != 0x11) && (atr[2] != 0x19)) || ((atr[9] != 0x68) && (atr[9] != 0x6C) && (atr[9] != 0x64)))
902 { return ERROR; }
904 write_cmd(insFAC, FacDat);
905 if(!(cta_res[cta_lr - 2] == 0x90 && cta_res[cta_lr - 1] == 0))
906 { return ERROR; }
908 if(!cs_malloc(&reader->csystem_data, sizeof(struct viaccess_data)))
909 { return ERROR; }
910 struct viaccess_data *csystem_data = reader->csystem_data;
912 write_cmd(insFAC, ins8702_data);
913 if((cta_res[cta_lr - 2] == 0x90) && (cta_res[cta_lr - 1] == 0x00))
915 write_cmd(ins8704, NULL);
916 if((cta_res[cta_lr - 2] == 0x90) && (cta_res[cta_lr - 1] == 0x00))
918 write_cmd(ins8706, NULL);
919 if((cta_res[cta_lr - 2] == 0x90) && (cta_res[cta_lr - 1] == 0x00))
921 csystem_data->last_geo.number_ecm = (cta_res[2] << 8) | (cta_res[3]);
922 rdr_log(reader, "using ecm #%x for long viaccess ecm", csystem_data->last_geo.number_ecm);
928 // switch((atr[atrsize-4]<<8)|atr[atrsize-3])
929 // {
930 // case 0x6268: ver="2.3"; break;
931 // case 0x6668: ver="2.4(?)"; break;
932 // case 0xa268:
933 // default: ver="unknown"; break;
934 // }
936 reader->caid = 0x500;
937 memset(reader->prid, 0xff, sizeof(reader->prid));
938 insac[2] = 0xa4;
939 write_cmd(insac, NULL); // request unique id
940 insb8[4] = 0x07;
941 write_cmd(insb8, NULL); // read unique id
942 memcpy(reader->hexserial, cta_res + 2, 5);
943 // rdr_log(reader, "[viaccess-reader] type: Viaccess, ver: %s serial: %llu", ver, b2ll(5, cta_res+2));
944 rdr_log_sensitive(reader, "type: Viaccess (%sstandard atr), caid: %04X, serial: {%llu}",
945 atr[9] == 0x68 ? "" : "non-", reader->caid, (unsigned long long) b2ll(5, cta_res + 2));
947 i = 0;
948 insa4[2] = 0x00;
949 write_cmd(insa4, NULL); // select issuer 0
950 buf[0] = 0;
951 while((cta_res[cta_lr - 2] == 0x90) && (cta_res[cta_lr - 1] == 0))
953 insc0[4] = 0x1a;
954 write_cmd(insc0, NULL); // show provider properties
955 cta_res[2] &= 0xF0;
956 reader->prid[i][0] = 0;
957 memcpy(&reader->prid[i][1], cta_res, 3);
958 memcpy(&csystem_data->availkeys[i][0], cta_res + 10, 16);
959 snprintf((char *)buf + strlen((char *)buf), sizeof(buf) - strlen((char *)buf), ",%06X", b2i(3, &reader->prid[i][1]));
960 //rdr_log(reader, "[viaccess-reader] buf: %s", buf);
962 insac[2] = 0xa5;
963 write_cmd(insac, NULL); // request sa
964 insb8[4] = 0x06;
965 write_cmd(insb8, NULL); // read sa
966 memcpy(&reader->sa[i][0], cta_res + 2, 4);
969 insac[2]=0xa7; write_cmd(insac, NULL); // request name
970 insb8[4]=0x02; write_cmd(insb8, NULL); // read name nano + len
971 l=cta_res[1];
972 insb8[4]=l; write_cmd(insb8, NULL); // read name
973 cta_res[l]=0;
974 rdr_log(reader, "[viaccess-reader] name: %s", cta_res);
977 insa4[2] = 0x02;
978 write_cmd(insa4, NULL); // select next issuer
979 i++;
981 reader->nprov = i;
982 rdr_log(reader, "providers: %d (%s)", reader->nprov, buf + 1);
984 get_maturity(reader);
985 if(cfg.ulparent)
987 unlock_parental(reader);
990 rdr_log(reader, "ready for requests");
991 return OK;
994 bool dcw_crc(uchar *dw)
996 int8_t i;
997 for(i = 0; i < 16; i += 4) if(dw[i + 3] != ((dw[i] + dw[i + 1] + dw[i + 2]) & 0xFF)) { return 0; }
998 return 1;
1001 static int32_t viaccess_do_ecm(struct s_reader *reader, const ECM_REQUEST *er, struct s_ecm_answer *ea)
1003 def_resp;
1004 static const unsigned char insa4[] = { 0xca, 0xa4, 0x04, 0x00, 0x03 }; // set provider id
1005 unsigned char ins88[] = { 0xca, 0x88, 0x00, 0x00, 0x00 }; // set ecm
1006 unsigned char insf8[] = { 0xca, 0xf8, 0x00, 0x00, 0x00 }; // set geographic info
1007 static const unsigned char insc0[] = { 0xca, 0xc0, 0x00, 0x00, 0x12 }; // read dcw
1008 struct viaccess_data *csystem_data = reader->csystem_data;
1010 // //XXX what is the 4th uint8_t for ??
1011 int32_t ecm88Len = MIN(MAX_ECM_SIZE - 4, SCT_LEN(er->ecm) - 4);
1012 if(ecm88Len < 1)
1014 rdr_log(reader, "ECM: Size of ECM couldn't be correctly calculated.");
1015 return ERROR;
1017 uchar ecmData[ecm88Len];
1018 memset(ecmData, 0, ecm88Len);
1019 memcpy(ecmData, er->ecm + 4, ecm88Len);
1020 uchar *ecm88Data = &ecmData[0];
1021 uint32_t provid = 0;
1022 int32_t rc = 0;
1023 int32_t hasD2 = 0;
1024 uchar hasE0 = 0;
1025 int32_t curEcm88len = 0;
1026 int32_t nanoLen = 0;
1027 uchar *nextEcm;
1028 uchar DE04[MAX_ECM_SIZE];
1029 int32_t D2KeyID = 0;
1030 int32_t curnumber_ecm = 0;
1031 //nanoD2 d2 02 0d 02 -> D2 nano, len 2
1032 // 0b, 0f, 13 -> pre AES decrypt CW
1033 // 0d, 11, 15 -> post AES decrypt CW
1035 int32_t nanoD2 = 0; // knowns D2 nanos: 0x0b ,0x0d ,0x0f ,0x11, 0x13, 0x15
1037 memset(DE04, 0, sizeof(DE04)); //fix dorcel de04 bug
1039 nextEcm = ecm88Data;
1041 while(ecm88Len > 0 && !rc)
1044 if(ecm88Data[0] == 0x00 && ecm88Data[1] == 0x00)
1046 // nano 0x00 and len 0x00 aren't valid ... something is obviously wrong with this ecm.
1047 rdr_log(reader, "ECM: Invalid ECM structure. Rejecting");
1048 return ERROR;
1051 // 80 33 nano 80 (ecm) + len (33)
1052 if(ecm88Data[0] == 0x80) // nano 80, give ecm len
1054 curEcm88len = ecm88Data[1];
1055 nextEcm = ecm88Data + curEcm88len + 2;
1056 ecm88Data += 2;
1057 ecm88Len -= 2;
1060 if(!curEcm88len) //there was no nano 80 -> simple ecm
1062 curEcm88len = ecm88Len;
1065 // d2 02 0d 02 -> D2 nano, len 2, select the AES key to be used
1066 if(ecm88Data[0] == 0xd2)
1068 // test if it needs AES decrypt
1069 if(ecm88Data[2] == 0x0b)
1071 nanoD2 = 0x0b;
1072 rdr_log_dbg(reader, D_READER, "ECM: nano D2 0x0b");
1074 if(ecm88Data[2] == 0x0d)
1076 nanoD2 = 0x0d;
1077 rdr_log_dbg(reader, D_READER, "ECM: nano D2 0x0d");
1079 if(ecm88Data[2] == 0x0f)
1081 nanoD2 = 0x0f;
1082 rdr_log_dbg(reader, D_READER, "ECM: nano D2 0x0f");
1084 if(ecm88Data[2] == 0x11)
1086 nanoD2 = 0x11;
1087 rdr_log_dbg(reader, D_READER, "ECM: nano D2 0x11");
1089 if(ecm88Data[2] == 0x13)
1091 nanoD2 = 0x13;
1092 rdr_log_dbg(reader, D_READER, "ECM: nano D2 0x13");
1094 if(ecm88Data[2] == 0x15)
1096 nanoD2 = 0x15;
1097 rdr_log_dbg(reader, D_READER, "ECM: nano D2 0x15");
1099 // use the d2 arguments to get the key # to be used
1100 int32_t len = ecm88Data[1] + 2;
1101 D2KeyID = ecm88Data[3];
1102 ecm88Data += len;
1103 ecm88Len -= len;
1104 curEcm88len -= len;
1105 hasD2 = 1;
1107 else
1108 { hasD2 = 0; }
1111 // 40 07 03 0b 00 -> nano 40, len =7 ident 030B00 (tntsat), key #0 <== we're pointing here
1112 // 09 -> use key #9
1113 // 05 67 00
1114 if((ecm88Data[0] == 0x90 || ecm88Data[0] == 0x40) && (ecm88Data[1] == 0x03 || ecm88Data[1] == 0x07))
1116 uchar ident[3], keynr;
1117 uchar *ecmf8Data = 0;
1118 int32_t ecmf8Len = 0;
1120 nanoLen = ecm88Data[1] + 2;
1121 keynr = ecm88Data[4] & 0x0F;
1123 // 40 07 03 0b 00 -> nano 40, len =7 ident 030B00 (tntsat), key #0 <== we're pointing here
1124 // 09 -> use key #9
1125 if(nanoLen > 5)
1127 curnumber_ecm = (ecm88Data[6] << 8) | (ecm88Data[7]);
1128 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);
1129 // if we have an ecm number we check it.
1130 // we can't assume that if the nano len is 5 or more we have an ecm number
1131 // as some card don't support this
1132 if(csystem_data->last_geo.number_ecm > 0)
1134 if(csystem_data->last_geo.number_ecm == curnumber_ecm && !(ecm88Data[nanoLen - 1] == 0x01))
1136 keynr = ecm88Data[5];
1137 rdr_log_dbg(reader, D_READER, "keyToUse = %02x, ECM ending with %02x", ecm88Data[5], ecm88Data[nanoLen - 1]);
1139 else
1141 if(ecm88Data[nanoLen - 1] == 0x01)
1143 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]);
1145 rdr_log_dbg(reader, D_READER, "Skip ECM ending with = %02x for ecm number (%x)", ecm88Data[nanoLen - 1], curnumber_ecm);
1146 ecm88Data = nextEcm;
1147 ecm88Len -= curEcm88len;
1148 continue; //loop to next ecm
1151 else // long ecm but we don't have an ecm number so we have to try them all.
1153 keynr = ecm88Data[5];
1154 rdr_log_dbg(reader, D_READER, "keyToUse = %02x", ecm88Data[5]);
1158 memcpy(ident, &ecm88Data[2], sizeof(ident));
1159 provid = b2i(3, ident);
1160 ident[2] &= 0xF0;
1162 if(hasD2 && reader->aes_list)
1164 // check that we have the AES key to decode the CW
1165 // if not there is no need to send the ecm to the card
1166 if(!aes_present(reader->aes_list, 0x500, (uint32_t)(provid & 0xFFFFF0) , D2KeyID))
1167 { return ERROR; }
1171 if(!chk_prov(reader, ident, keynr))
1173 rdr_log_dbg(reader, D_READER, "ECM: provider or key not found on card");
1174 snprintf(ea->msglog, MSGLOGSIZE, "provider(%02x%02x%02x) or key(%d) not found on card", ident[0], ident[1], ident[2], keynr);
1175 return ERROR;
1178 ecm88Data += nanoLen;
1179 ecm88Len -= nanoLen;
1180 curEcm88len -= nanoLen;
1182 // DE04
1183 if(ecm88Data[0] == 0xDE && ecm88Data[1] == 0x04)
1185 memcpy(DE04, &ecm88Data[0], 6);
1186 ecm88Data += 6;
1189 // E0 (seen so far in logs: E0020002 or E0022002, but not in all cases delivers invalid cw so just detect!)
1190 if(ecm88Data[0] == 0xE0 && ecm88Data[1] == 0x02)
1192 rdr_log_dbg(reader, D_READER,"[viaccess-reader] nano E0 ECM detected!");
1193 hasE0=1;
1197 if(csystem_data->last_geo.provid != provid)
1199 csystem_data->last_geo.provid = provid;
1200 csystem_data->last_geo.geo_len = 0;
1201 csystem_data->last_geo.geo[0] = 0;
1202 write_cmd(insa4, ident); // set provider
1205 // Nano D2 0x0b, 0x0f, 0x13 -> pre AES decrypt CW
1207 if(hasD2 && (nanoD2 == 0x0b|| nanoD2 == 0x0f|| nanoD2 == 0x13))
1209 uchar *ecm88DataCW = ecm88Data;
1210 int32_t cwStart = 0;
1211 //int32_t cwStartRes = 0;
1212 int32_t must_exit = 0;
1213 // find CW start
1214 while(cwStart < curEcm88len - 1 && !must_exit)
1216 if(ecm88Data[cwStart] == 0xEA && ecm88Data[cwStart + 1] == 0x10)
1218 ecm88DataCW = ecm88DataCW + cwStart + 2;
1219 must_exit = 1;
1221 cwStart++;
1223 if(nanoD2 == 0x0f)
1225 hdSurEncPhase1_D2_0F_11(ecm88DataCW);
1226 hdSurEncPhase2_D2_0F_11(ecm88DataCW);
1228 if(nanoD2 == 0x13)
1230 hdSurEncPhase1_D2_13_15(ecm88DataCW);
1233 // use AES from list to decrypt CW
1234 rdr_log_dbg(reader, D_READER, "Decoding CW : using AES key id %d for provider %06x", D2KeyID, (provid & 0xFFFFF0));
1235 if(aes_decrypt_from_list(reader->aes_list, 0x500, (uint32_t)(provid & 0xFFFFF0), D2KeyID, &ecm88DataCW[0], 16) == 0)
1236 { snprintf(ea->msglog, MSGLOGSIZE, "Missing AES key(%d)[aka E%X]",D2KeyID, D2KeyID); }
1237 if(nanoD2 == 0x0f)
1239 hdSurEncPhase1_D2_0F_11(ecm88DataCW);
1241 if(nanoD2 == 0x13)
1243 hdSurEncPhase2_D2_13_15(ecm88DataCW);
1247 while(ecm88Len > 1 && ecm88Data[0] < 0xA0)
1249 nanoLen = ecm88Data[1] + 2;
1250 if(!ecmf8Data)
1251 { ecmf8Data = (uchar *)ecm88Data; }
1252 ecmf8Len += nanoLen;
1253 ecm88Len -= nanoLen;
1254 curEcm88len -= nanoLen;
1255 ecm88Data += nanoLen;
1257 if(ecmf8Len)
1259 if(csystem_data->last_geo.geo_len != ecmf8Len ||
1260 memcmp(csystem_data->last_geo.geo, ecmf8Data, csystem_data->last_geo.geo_len))
1262 memcpy(csystem_data->last_geo.geo, ecmf8Data, ecmf8Len);
1263 csystem_data->last_geo.geo_len = ecmf8Len;
1264 insf8[3] = keynr;
1265 insf8[4] = ecmf8Len;
1266 write_cmd(insf8, ecmf8Data);
1269 ins88[2] = ecmf8Len ? 1 : 0;
1270 ins88[3] = keynr;
1271 ins88[4] = (curEcm88len > 0xFF) ? 0x00 : curEcm88len;
1273 // we should check the nano to make sure the ecm is valid
1274 // we should look for at least 1 E3 nano, 1 EA nano and the F0 signature nano
1276 // DE04
1277 if(DE04[0] == 0xDE)
1279 uint32_t l = curEcm88len - 6;
1280 if(l > MAX_ECM_SIZE || curEcm88len <= 6) //don't known if this is ok...
1282 rdr_log(reader, "ecm invalid/too long! len=%d", curEcm88len);
1283 return ERROR;
1285 memcpy(DE04 + 6, (uchar *)ecm88Data, l);
1286 write_cmd(ins88, DE04); // request dcw
1288 else
1290 write_cmd(ins88, (uchar *)ecm88Data); // request dcw
1293 write_cmd(insc0, NULL); // read dcw
1294 switch(cta_res[0])
1296 case 0xe8: // even
1297 if(cta_res[1] == 8)
1299 memcpy(ea->cw, cta_res + 2, 8);
1300 rc = 1;
1302 break;
1303 case 0xe9: // odd
1304 if(cta_res[1] == 8)
1306 memcpy(ea->cw + 8, cta_res + 2, 8);
1307 rc = 1;
1309 break;
1310 case 0xea: // complete
1311 if(cta_res[1] == 16)
1313 memcpy(ea->cw, cta_res + 2, 16);
1314 rc = 1;
1316 break;
1318 default :
1319 ecm88Data = nextEcm;
1320 ecm88Len -= curEcm88len;
1321 rdr_log_dbg(reader, D_READER, "Error: card respondend %02X %02X, trying next ECM", cta_res[0], cta_res[1]);
1322 snprintf(ea->msglog, MSGLOGSIZE, "key to use is not the current one, trying next ECM");
1325 else
1327 //ecm88Data=nextEcm;
1328 //ecm88Len-=curEcm88len;
1329 rdr_log_dbg(reader, D_READER, "ECM: Unknown ECM type");
1330 snprintf(ea->msglog, MSGLOGSIZE, "Unknown ECM type");
1331 return ERROR; /*Lets interupt the loop and exit, because we don't know this ECM type.*/
1335 // Nano D2 0d, 11, 15 -> post AES decrypt CW
1337 if(hasD2 && !dcw_crc(ea->cw) && (nanoD2 == 0x0d || nanoD2 == 0x11 || nanoD2 == 0x15 ))
1339 if(nanoD2 == 0x11)
1341 hdSurEncPhase1_D2_0F_11(ea->cw);
1342 hdSurEncPhase2_D2_0F_11(ea->cw);
1344 if(nanoD2 == 0x15)
1346 hdSurEncPhase1_D2_13_15(ea->cw);
1348 rdr_log_dbg(reader, D_READER, "Decoding CW : using AES key id %d for provider %06x", D2KeyID, (provid & 0xFFFFF0));
1349 rc = aes_decrypt_from_list(reader->aes_list, 0x500, (uint32_t)(provid & 0xFFFFF0), D2KeyID, ea->cw, 16);
1350 if(rc == 0)
1351 { snprintf(ea->msglog, MSGLOGSIZE, "Missing AES key(%d)[aka E%X]",D2KeyID, D2KeyID); }
1352 if(nanoD2 == 0x11)
1354 hdSurEncPhase1_D2_0F_11(ea->cw);
1356 if(nanoD2 == 0x15)
1358 hdSurEncPhase2_D2_13_15(ea->cw);
1362 if ( hasE0 )
1364 if ( reader->initCA28 )
1366 rdr_log_dbg(reader, D_READER, "Decrypting nano E0 encrypted cw.");
1367 uint8_t returnedcw[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
1368 memcpy(returnedcw,ea->cw,16);
1369 // Processing 3DES
1370 // Processing even cw
1371 des(returnedcw, reader->key_schedule1, 0); //decrypt
1372 des(returnedcw, reader->key_schedule2, 1); //crypt
1373 des(returnedcw, reader->key_schedule1, 0); //decrypt
1374 // Processing odd cw
1375 des(returnedcw+8, reader->key_schedule1, 0); //decrypt
1376 des(returnedcw+8, reader->key_schedule2, 1); //crypt
1377 des(returnedcw+8, reader->key_schedule1, 0); //decrypt
1379 // returning value
1380 memcpy(ea->cw,returnedcw, 16);
1382 else
1384 snprintf(ea->msglog, MSGLOGSIZE, "Viaccess nano E0 detected, no valid boxkey and deskey defined: no decoding");
1387 return (rc ? OK : ERROR);
1390 static int32_t viaccess_get_emm_type(EMM_PACKET *ep, struct s_reader *rdr)
1392 uint32_t provid = 0;
1393 rdr_log_dbg(rdr, D_EMM, "Entered viaccess_get_emm_type ep->emm[0]=%02x", ep->emm[0]);
1395 if(ep->emm[3] == 0x90 && ep->emm[4] == 0x03)
1397 provid = b2i(3, ep->emm+5);
1398 provid &=0xFFFFF0;
1399 i2b_buf(4, provid, ep->provid);
1402 switch(ep->emm[0])
1404 case 0x88:
1405 ep->type = UNIQUE;
1406 memset(ep->hexserial, 0, 8);
1407 memcpy(ep->hexserial, ep->emm + 4, 4);
1408 rdr_log_dbg(rdr, D_EMM, "UNIQUE");
1409 if(!is_network_reader(rdr))
1411 return (!memcmp(rdr->hexserial + 1, ep->hexserial, 4)); // local reader
1413 else
1415 return 1; // let server decide!
1418 case 0x8A:
1419 case 0x8B:
1420 ep->type = GLOBAL;
1421 rdr_log_dbg(rdr, D_EMM, "GLOBAL");
1422 return 1;
1424 case 0x8C:
1425 case 0x8D:
1426 ep->type = SHARED;
1427 rdr_log_dbg(rdr, D_EMM, "SHARED (part)");
1428 // We need those packets to pass otherwise we would never
1429 // be able to complete EMM reassembly
1430 return 1;
1432 case 0x8E:
1433 ep->type = SHARED;
1434 rdr_log_dbg(rdr, D_EMM, "SHARED");
1435 memset(ep->hexserial, 0, 8);
1436 memcpy(ep->hexserial, ep->emm + 3, 3);
1438 // local reader
1439 int8_t i;
1440 for(i = 0; i < rdr->nprov; i++)
1442 if(!memcmp(&rdr->prid[i][2], ep->hexserial+1, 2))
1443 { return 1; }
1445 return (!memcmp(&rdr->sa[0][0], ep->hexserial, 3));
1448 default:
1449 ep->type = UNKNOWN;
1450 rdr_log_dbg(rdr, D_EMM, "UNKNOWN");
1451 return 1;
1455 static int32_t viaccess_get_emm_filter(struct s_reader *rdr, struct s_csystem_emm_filter **emm_filters, unsigned int *filter_count)
1457 if(*emm_filters == NULL)
1459 bool network = is_network_reader(rdr);
1460 int8_t device_emm = ((rdr->deviceemm >0) ? 1 : 0); // set to 1 if device specific emms should be catched too
1462 const unsigned int max_filter_count = 4 + ((device_emm != 0 && rdr->nprov > 0) ? 1:0) + (3 * ((rdr->nprov > 0) ? (rdr->nprov - 1) : 0));
1464 if(!cs_malloc(emm_filters, max_filter_count * sizeof(struct s_csystem_emm_filter)))
1465 { return ERROR; }
1467 struct s_csystem_emm_filter *filters = *emm_filters;
1468 *filter_count = 0;
1470 int32_t idx = 0;
1471 int32_t prov;
1473 if(rdr->nprov > 0 && device_emm == 1)
1475 filters[idx].type = EMM_GLOBAL; // 8A or 8B no reassembly needed!
1476 filters[idx].enabled = 1;
1477 filters[idx].filter[0] = 0x8A;
1478 filters[idx].mask[0] = 0xFE;
1479 filters[idx].filter[3] = 0x80; // device specific emms
1480 filters[idx].mask[3] = 0x80;
1481 idx++;
1484 // shared are most important put them on top, define first since viaccess produces a lot of filters!
1485 for(prov = 0; (prov < rdr->nprov); prov++)
1487 if((rdr->prid[prov][2] &0xF0) == 0xF0) // skip this not useful provider
1489 continue;
1492 filters[idx].type = EMM_SHARED; // 8C or 8D always first part of shared, second part delivered by 8E!
1493 filters[idx].enabled = 1;
1494 filters[idx].filter[0] = 0x8C;
1495 filters[idx].mask[0] = 0xFE;
1496 if(rdr->nprov > 0)
1498 memcpy(&filters[idx].filter[4], &rdr->prid[prov][2], 2);
1499 filters[idx].mask[4] = 0xFF;
1500 filters[idx].mask[5] = 0xF0; // ignore last digit since this is key on card indicator!
1502 idx++;
1504 filters[idx].type = EMM_SHARED; // 8E second part reassembly with 8c/8d needed!
1505 filters[idx].enabled = 1;
1506 filters[idx].filter[0] = 0x8E;
1507 filters[idx].mask[0] = 0xFF;
1508 if(rdr->nprov > 0)
1510 memcpy(&filters[idx].filter[1], &rdr->sa[prov][0], 3);
1511 memset(&filters[idx].mask[1], 0xFF, 3);
1513 idx++;
1516 // globals are less important, define last since viaccess produces a lot of filters!
1517 for(prov = 0; (prov < rdr->nprov); prov++)
1519 if((rdr->prid[prov][2] &0xF0) == 0xF0) // skip this not useful provider
1521 continue;
1524 filters[idx].type = EMM_GLOBAL; // 8A or 8B no reassembly needed!
1525 filters[idx].enabled = 1;
1526 filters[idx].filter[0] = 0x8A;
1527 filters[idx].mask[0] = 0xFE;
1528 if(rdr->nprov > 0)
1530 memcpy(&filters[idx].filter[4], &rdr->prid[prov][2], 2);
1531 filters[idx].mask[4] = 0xFF;
1532 filters[idx].mask[5] = 0xF0; // ignore last digit since this is key on card indicator!
1534 else if (device_emm == 0)
1536 filters[idx].filter[3] = 0x00; // additional filter to cancel device specific emms
1537 filters[idx].mask[3] = 0x80;
1539 idx++;
1542 filters[idx].type = EMM_UNIQUE;
1543 filters[idx].enabled = 1;
1544 filters[idx].filter[0] = 0x88;
1545 filters[idx].mask[0] = 0xFF;
1546 if(!network) // network has only 3 digits out of 4
1548 memcpy(&filters[idx].filter[1], rdr->hexserial + 1, 4);
1549 memset(&filters[idx].mask[1], 0xFF, 4);
1551 else
1553 memcpy(&filters[idx].filter[1], rdr->hexserial + 1, 3);
1554 memset(&filters[idx].mask[1], 0xFF, 3);
1556 idx++;
1558 *filter_count = idx;
1561 return OK;
1564 static int32_t viaccess_do_emm(struct s_reader *reader, EMM_PACKET *ep)
1566 def_resp;
1567 static const unsigned char insa4[] = { 0xca, 0xa4, 0x04, 0x00, 0x03 }; // set provider id
1568 unsigned char insf0[] = { 0xca, 0xf0, 0x00, 0x01, 0x22 }; // set adf
1569 unsigned char insf4[] = { 0xca, 0xf4, 0x00, 0x01, 0x00 }; // set adf, encrypted
1570 unsigned char ins18[] = { 0xca, 0x18, 0x01, 0x01, 0x00 }; // set subscription
1571 unsigned char ins1c[] = { 0xca, 0x1c, 0x01, 0x01, 0x00 }; // set subscription, encrypted
1572 //static const unsigned char insc8[] = { 0xca,0xc8,0x00,0x00,0x02 }; // read extended status
1573 // static const unsigned char insc8Data[] = { 0x00,0x00 }; // data for read extended status
1574 struct viaccess_data *csystem_data = reader->csystem_data;
1576 int32_t emmdatastart = 7;
1578 if (ep->emm[1] == 0x01) // emm from cccam
1580 emmdatastart=12;
1581 ep->emm[1] = 0x70; // (& 0x0f) of this byte is length, so 0x01 would increase the length by 256
1582 ep->emm[2] -= 1;
1583 if (ep->type == SHARED || ep->type == GLOBAL) // build missing 0x90 nano from provider at serial position
1585 memcpy(ep->emm+7, ep->emm+3, 3);
1586 ep->emm[5] = 0x90;
1587 ep->emm[6] = 0x03;
1588 ep->emm[9] |= 0x01;
1589 ep->emm[10] = 0x9E;
1590 ep->emm[11] = 0x20;
1591 emmdatastart = 5;
1595 if(ep->type == UNIQUE) { emmdatastart++; }
1596 if(ep->type == GLOBAL && emmdatastart == 7) { emmdatastart -= 4; }
1597 int32_t emmLen = SCT_LEN(ep->emm) - emmdatastart;
1598 int32_t rc = 0;
1600 rdr_log_dump(reader, ep->emm, emmLen+emmdatastart, "RECEIVED EMM VIACCESS");
1602 int32_t emmUpToEnd;
1603 uchar *emmParsed = ep->emm + emmdatastart;
1604 int32_t provider_ok = 0;
1605 uint32_t emm_provid = 0;
1606 uchar keynr = 0;
1607 int32_t ins18Len = 0;
1608 uchar ins18Data[512];
1609 uchar insData[512];
1610 uchar *nano81Data = 0;
1611 uchar *nano91Data = 0;
1612 uchar *nano92Data = 0;
1613 uchar *nano9EData = 0;
1614 uchar *nanoF0Data = 0;
1615 uchar *nanoA9Data = 0;
1617 for(emmUpToEnd = emmLen; (emmParsed[1] != 0) && (emmUpToEnd > 0); emmUpToEnd -= (2 + emmParsed[1]), emmParsed += (2 + emmParsed[1]))
1619 rdr_log_dump(reader, emmParsed, emmParsed[1] + 2, "NANO");
1621 if(emmParsed[0] == 0x90 && emmParsed[1] == 0x03)
1623 /* identification of the service operator */
1625 uchar soid[3], ident[3], i;
1627 for(i = 0; i < 3; i++)
1629 soid[i] = ident[i] = emmParsed[2 + i];
1631 ident[2] &= 0xF0;
1632 emm_provid = b2i(3, ident);
1633 keynr = soid[2] & 0x0F;
1634 if(chk_prov(reader, ident, keynr))
1636 provider_ok = 1;
1638 else
1640 rdr_log(reader, "EMM: ignored since provider or key not present on card (%x, %x)", emm_provid, keynr);
1641 return SKIPPED;
1644 // check if the provider changes. If yes, set the new one. If not, don't .. card will return an error if we do.
1645 if(csystem_data->last_geo.provid != emm_provid)
1647 write_cmd(insa4, ident);
1648 if(cta_res[cta_lr - 2] != 0x90 || cta_res[cta_lr - 1] != 0x00)
1650 rdr_log_dump(reader, insa4, 5, "set provider cmd:");
1651 rdr_log_dump(reader, soid, 3, "set provider data:");
1652 rdr_log(reader, "update error: %02X %02X", cta_res[cta_lr - 2], cta_res[cta_lr - 1]);
1653 return ERROR;
1656 // as we are maybe changing the used provider, clear the cache, so the next ecm will re-select the correct one
1657 csystem_data->last_geo.provid = 0;
1658 csystem_data->last_geo.geo_len = 0;
1659 csystem_data->last_geo.geo[0] = 0;
1662 else if(emmParsed[0] == 0x9e && emmParsed[1] == 0x20)
1664 /* adf */
1666 if(!nano91Data)
1668 /* adf is not crypted, so test it */
1670 uchar custwp;
1671 uchar *afd;
1673 custwp = reader->sa[0][3];
1674 afd = (uchar *)emmParsed + 2;
1676 if(afd[31 - custwp / 8] & (1 << (custwp & 7)))
1678 rdr_log_dbg(reader, D_READER, "emm for our card %08X", b2i(4, &reader->sa[0][0]));
1680 else
1682 rdr_log_dbg(reader, D_READER, "emm not suitable for our card %08X", b2i(4, &reader->sa[0][0]));
1683 return SKIPPED;
1687 // memorize
1688 nano9EData = emmParsed;
1691 else if(emmParsed[0] == 0x81)
1693 nano81Data = emmParsed;
1695 else if(emmParsed[0] == 0x91 && emmParsed[1] == 0x08)
1697 nano91Data = emmParsed;
1699 else if(emmParsed[0] == 0x92 && emmParsed[1] == 0x08)
1701 nano92Data = emmParsed;
1703 else if(emmParsed[0] == 0xF0 && emmParsed[1] == 0x08)
1705 nanoF0Data = emmParsed;
1707 else if(emmParsed[0] == 0xD8 && emmParsed[2] == 0x45)
1709 uint8_t pos = 4 + emmParsed[3];
1710 char *tmpbuf;
1711 if(emmParsed[pos] == 0x46 && ((emmParsed[pos+1] - emmParsed[1]) == pos))
1713 if(cs_malloc(&tmpbuf, emmParsed[pos+1]))
1715 cs_strncpy(tmpbuf, (char *) emmParsed+pos+2, emmParsed[pos+1]);
1716 rdr_log(reader, "Viaccess EMM-text: %s", tmpbuf);
1717 NULLFREE(tmpbuf);
1721 else
1723 /* other nanos */
1724 show_subs(reader, emmParsed);
1725 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
1727 if(!emm_provid)
1729 rdr_log(reader, "no provid in shared emm -> skipped!");
1730 return SKIPPED;
1733 int8_t match = add_find_class(reader, emm_provid, emmParsed + 2, emmParsed[1], 0);
1735 // seems not all classes have to be present on card to accept the emm
1736 /*if(match == -1)
1738 rdr_log(reader, "shared emm provid %06X one or more classes of this emm do not match with your card -> skipped!", emm_provid);
1739 return SKIPPED;
1742 if(match == -2)
1744 rdr_log(reader, "shared emm provid %06X all classes have entitlementdate already same or newer -> skipped!", emm_provid);
1745 return SKIPPED;
1747 nanoA9Data = emmParsed;
1750 memcpy(ins18Data + ins18Len, emmParsed, emmParsed[1] + 2);
1751 ins18Len += emmParsed [1] + 2;
1755 if(!provider_ok)
1757 rdr_log_dbg(reader, D_READER, "provider not found in emm, continue anyway");
1758 // force key to 1...
1759 keynr = 1;
1760 ///return ERROR;
1763 if(!nanoF0Data)
1765 rdr_log_dump(reader, ep->emm, ep->emmlen, "can't find 0xf0 in emm...");
1766 return ERROR; // error
1769 if(nano9EData)
1771 if(!nano91Data)
1773 // set adf
1774 insf0[3] = keynr; // key
1775 insf0[4] = nano9EData[1] + 2;
1776 write_cmd(insf0, nano9EData);
1777 if(cta_res[cta_lr - 2] != 0x90 || cta_res[cta_lr - 1] != 0x00)
1779 rdr_log_dump(reader, insf0, 5, "set adf cmd:");
1780 rdr_log_dump(reader, nano9EData, insf0[4] , "set adf data:");
1781 rdr_log(reader, "update error: %02X %02X", cta_res[cta_lr - 2], cta_res[cta_lr - 1]);
1782 return ERROR;
1785 else
1787 // set adf crypte
1788 insf4[3] = keynr; // key
1789 insf4[4] = nano91Data[1] + 2 + nano9EData[1] + 2;
1790 memcpy(insData, nano91Data, nano91Data[1] + 2);
1791 memcpy(insData + nano91Data[1] + 2, nano9EData, nano9EData[1] + 2);
1792 write_cmd(insf4, insData);
1793 if((cta_res[cta_lr - 2] != 0x90 && cta_res[cta_lr - 2] != 0x91) || cta_res[cta_lr - 1] != 0x00)
1795 rdr_log_dump(reader, insf4, 5, "set adf encrypted cmd:");
1796 rdr_log_dump(reader, insData, insf4[4], "set adf encrypted data:");
1797 rdr_log(reader, "update error: %02X %02X", cta_res[cta_lr - 2], cta_res[cta_lr - 1]);
1798 return ERROR;
1803 if(!nano92Data)
1805 // send subscription
1806 ins18[2] = nano9EData ? 0x01 : 0x00; // found 9E nano ?
1807 ins18[3] = keynr; // key
1808 ins18[4] = ins18Len + nanoF0Data[1] + 2;
1809 memcpy(insData, ins18Data, ins18Len);
1810 memcpy(insData + ins18Len, nanoF0Data, nanoF0Data[1] + 2);
1811 write_cmd(ins18, insData);
1812 if((cta_res[cta_lr - 2] == 0x90 || cta_res[cta_lr - 2] == 0x91) && cta_res[cta_lr - 1] == 0x00)
1814 if(nanoA9Data)
1816 add_find_class(reader, emm_provid, nanoA9Data + 2, nanoA9Data[1], 1);
1817 rdr_log(reader, "Your subscription data was updated.");
1819 rc = 1; // written
1821 else
1823 rdr_log_dump(reader, ins18, 5, "set subscription cmd:");
1824 rdr_log_dump(reader, insData, ins18[4], "set subscription data:");
1825 if(!(cta_res[cta_lr -2] == 0x90 && cta_res[cta_lr - 1] == 0x40)) // dont throw softerror 9040 in log!
1827 rdr_log(reader, "update error: %02X %02X", cta_res[cta_lr - 2], cta_res[cta_lr - 1]);
1829 else
1831 rc = 2; // skipped
1836 else
1838 // send subscription encrypted
1840 if(!nano81Data)
1842 rdr_log_dump(reader, ep->emm, ep->emmlen, "0x92 found, but can't find 0x81 in emm...");
1843 return ERROR; // error
1846 ins1c[2] = nano9EData ? 0x01 : 0x00; // found 9E nano ?
1847 if(ep->type == UNIQUE) { ins1c[2] = 0x02; }
1848 ins1c[3] = keynr; // key
1849 ins1c[4] = nano92Data[1] + 2 + nano81Data[1] + 2 + nanoF0Data[1] + 2;
1850 memcpy(insData, nano92Data, nano92Data[1] + 2);
1851 memcpy(insData + nano92Data[1] + 2, nano81Data, nano81Data[1] + 2);
1852 memcpy(insData + nano92Data[1] + 2 + nano81Data[1] + 2, nanoF0Data, nanoF0Data[1] + 2);
1853 write_cmd(ins1c, insData);
1855 if((cta_res[cta_lr - 2] == 0x90 || cta_res[cta_lr - 2] == 0x91) &&
1856 (cta_res[cta_lr - 1] == 0x00 || cta_res[cta_lr - 1] == 0x08))
1858 rdr_log(reader, "update successfully written");
1859 rc = 1; // written
1861 rc = 1;
1862 /* don't return ERROR at this place
1863 else {
1864 if( cta_res[cta_lr-2]&0x1 )
1865 rdr_log(reader, "update not written. Data already exists or unknown address");
1867 //if( cta_res[cta_lr-2]&0x8 ) {
1868 write_cmd(insc8, NULL);
1869 if( (cta_res[cta_lr-2]==0x90 && cta_res[cta_lr-1]==0x00) ) {
1870 rdr_log(reader, "extended status %02X %02X", cta_res[0], cta_res[1]);
1873 return ERROR;
1874 } */
1879 Sub Main()
1880 Sc.Write("CA A4 04 00 03")
1882 Sc.Write("02 07 11")
1884 Sc.Write("CA F0 00 01 22")
1886 Sc.Write("9E 20")
1887 Sc.Write("10 10 08 8A 80 00 04 00 10 10 26 E8 54 80 1E 80")
1888 Sc.Write("00 01 00 00 00 00 00 50 00 00 80 02 22 00 08 50")
1890 Sc.Write("CA 18 01 01 11")
1892 Sc.Write("A9 05 34 DE 34 FF 80")
1893 Sc.Write("F0 08 1A 3E AF B5 2B EE E3 3B")
1896 End Sub
1898 return rc;
1901 static int32_t viaccess_card_info(struct s_reader *reader)
1903 def_resp;
1904 int32_t i, l;
1905 time_t now;
1906 struct tm timeinfo;
1907 uint16_t tmpdate;
1908 uchar insac[] = { 0xca, 0xac, 0x00, 0x00, 0x00 }; // select data
1909 uchar insb8[] = { 0xca, 0xb8, 0x00, 0x00, 0x00 }; // read selected data
1910 uchar insa4[] = { 0xca, 0xa4, 0x00, 0x00, 0x00 }; // select issuer
1911 uchar insc0[] = { 0xca, 0xc0, 0x00, 0x00, 0x00 }; // read data item
1912 static const uchar ins24[] = { 0xca, 0x24, 0x00, 0x00, 0x09 }; // set pin
1914 uchar cls[] = { 0x00, 0x21, 0xff, 0x9f};
1915 static const uchar pin[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04};
1916 struct viaccess_data *csystem_data = reader->csystem_data;
1918 csystem_data->last_geo.provid = 0;
1919 csystem_data->last_geo.geo_len = 0;
1920 csystem_data->last_geo.geo[0] = 0;
1922 rdr_log(reader, "card detected");
1924 cs_clear_entitlement(reader); //reset the entitlements
1926 // set pin
1927 write_cmd(ins24, pin);
1929 insac[2] = 0xa4;
1930 write_cmd(insac, NULL); // request unique id
1931 insb8[4] = 0x07;
1932 write_cmd(insb8, NULL); // read unique id
1933 rdr_log_sensitive(reader, "serial: {%llu}", (unsigned long long) b2ll(5, cta_res + 2));
1935 insa4[2] = 0x00;
1936 write_cmd(insa4, NULL); // select issuer 0
1938 for(i = 1; (cta_res[cta_lr - 2] == 0x90) && (cta_res[cta_lr - 1] == 0); i++)
1940 bool added = false;
1941 uint32_t l_provid, l_sa;
1942 uchar l_name[64];
1943 insc0[4] = 0x1a;
1944 write_cmd(insc0, NULL); // show provider properties
1945 cta_res[2] &= 0xF0;
1946 l_provid = b2i(3, cta_res);
1948 insac[2] = 0xa5;
1949 write_cmd(insac, NULL); // request sa
1950 insb8[4] = 0x06;
1951 write_cmd(insb8, NULL); // read sa
1952 l_sa = b2i(4, cta_res + 2);
1954 insac[2] = 0xa7;
1955 write_cmd(insac, NULL); // request name
1956 insb8[4] = 0x02;
1957 write_cmd(insb8, NULL); // read name nano + len
1958 l = cta_res[1];
1959 insb8[4] = l;
1960 write_cmd(insb8, NULL); // read name
1961 cta_res[l] = 0;
1962 trim((char *)cta_res);
1963 if(cta_res[0])
1964 { snprintf((char *)l_name, sizeof(l_name), ", name: %s", cta_res); }
1965 else
1966 { l_name[0] = 0; }
1968 // read GEO
1969 insac[2] = 0xa6;
1970 write_cmd(insac, NULL); // request GEO
1971 insb8[4] = 0x02;
1972 write_cmd(insb8, NULL); // read GEO nano + len
1973 l = cta_res[1];
1974 char tmp[l * 3 + 1];
1975 insb8[4] = l;
1976 write_cmd(insb8, NULL); // read geo
1977 rdr_log_sensitive(reader, "provider: %d, id: {%06X%s}, sa: {%08X}, geo: %s",
1978 i, l_provid, l_name, l_sa, (l < 4) ? "empty" : cs_hexdump(1, cta_res, l, tmp, sizeof(tmp)));
1982 // read classes subscription
1983 insac[2] = 0xa9;
1984 insac[4] = 4;
1985 if(!reader->read_old_classes)
1987 now = time(NULL) - (24*60*60);
1988 cs_gmtime_r(&now, &timeinfo);
1989 tmpdate = timeinfo.tm_mday | ((timeinfo.tm_mon + 1) << 5) | ((timeinfo.tm_year - 80) << 9);
1990 cls[0] = tmpdate >> 8;
1991 cls[1] = tmpdate & 0xff;
1993 write_cmd(insac, cls); // request class subs
1994 while((cta_res[cta_lr - 2] == 0x90) && (cta_res[cta_lr - 1] == 0))
1996 insb8[4] = 0x02;
1997 write_cmd(insb8, NULL); // read class subs nano + len
1998 if((cta_res[cta_lr - 2] == 0x90) && (cta_res[cta_lr - 1] == 0))
2000 l = cta_res[1];
2001 insb8[4] = l;
2002 write_cmd(insb8, NULL); // read class subs
2003 if((cta_res[cta_lr - 2] == 0x90) &&
2004 (cta_res[cta_lr - 1] == 0x00 || cta_res[cta_lr - 1] == 0x08))
2006 show_class(reader, NULL, l_provid, cta_res, cta_lr - 2);
2007 added = true;
2012 if(!added)
2014 // add entitlement info for provid without class
2015 cs_add_entitlement(reader, reader->caid, l_provid, 0, 0, 0, 0, 5, 1);
2018 insac[4] = 0;
2019 insa4[2] = 0x02;
2020 write_cmd(insa4, NULL); // select next provider
2022 //return ERROR;
2023 // Start process init CA 28
2024 reader->initCA28=0;
2025 int32_t lenboxkey = reader->boxkey_length;
2026 int32_t lendeskey = reader->des_key_length;
2027 if ((lenboxkey >= 4) && (lendeskey > 0))
2029 uchar ins28[] = { 0xCA, 0x28, 0x00, 0x00, 0x04 }; //Init for nanoE0 ca28
2030 ins28[4] = (uchar) lenboxkey;
2031 uchar ins28_data[4];
2032 memcpy(ins28_data, reader->boxkey, 4);
2033 write_cmd(ins28, ins28_data); // unlock card to reply on E002xxyy
2034 if((cta_res[cta_lr - 2] == 0x90) && (cta_res[cta_lr - 1] == 0))
2036 rdr_log(reader, "CA 28 initialisation successful!");
2037 // init 3DES key
2038 des_set_key(reader->des_key, reader->key_schedule1);
2039 des_set_key(reader->des_key+8, reader->key_schedule2);
2040 reader->initCA28=1;
2042 else
2044 rdr_log(reader, "CA 28 initialisation failed! CA 28 refused");
2047 //end process init CA 28
2048 return OK;
2051 static int32_t viaccess_reassemble_emm(struct s_reader *rdr, struct s_client *client, EMM_PACKET *ep)
2053 uint8_t *buffer = ep->emm;
2054 int16_t *len = &ep->emmlen;
2055 int32_t pos = 0, i;
2056 int16_t k;
2057 int32_t prov, provid = 0;
2058 struct emm_rass *r_emm = NULL;
2060 // Viaccess
2061 if(*len > 500) { return 0; }
2063 switch(buffer[0])
2065 case 0x8c:
2066 case 0x8d:
2067 // emm-s part 1
2068 provid = b2i(3, ep->emm+5); // extract provid from emm
2069 provid &= 0xFFFFF0; // last digit is dont care
2070 r_emm = find_rabuf(client, provid, (uint8_t) buffer[0], 1);
2071 if(!r_emm)
2073 cs_log("[viaccess] ERROR: Can't allocate EMM reassembly buffer.");
2074 return 0;
2076 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
2078 return 0;
2080 memset(&r_emm->emm[0], 0, sizeof(r_emm->emm)); // zero it!
2081 memcpy(&r_emm->emm[0], &buffer[0], *len); // put the fresh new shared emm
2082 r_emm->emmlen = *len; // put the emmlen indicating that this shared emm isnt being reassembled
2083 rdr_log_dump_dbg(rdr, D_EMM, r_emm->emm, r_emm->emmlen, "%s: received fresh emm-gh for provid %06X", __func__, provid);
2084 return 0;
2086 case 0x8e:
2087 // emm-s part 2
2088 for(prov = 0; prov < rdr->nprov ; prov++)
2090 if(!memcmp(&buffer[3], &rdr->sa[prov][0], 3))
2092 //matching sa found!
2093 if(is_network_reader(rdr))
2095 provid = b2i(4, ep->provid); // use provid from emm since we have nothing better!
2096 provid &= 0xFFFFF0; // last digit is dont care
2098 else
2100 provid = b2i(4, rdr->prid[prov]); // get corresponding provid from reader since there is no provid in emm payload!
2101 provid &= 0xFFFFF0; // last digit is dont care
2103 r_emm = find_rabuf(client, provid, 0, 0); // nano = dont care, the shared 8c or 8d not been written gets returned!
2104 if(!r_emm || !r_emm->emmlen)
2106 continue; // match but no emm-gh found for this provider
2108 else
2110 break; // stop searching-> emm-gh found!
2114 if(!r_emm || !r_emm->emmlen) { return 0; } // stop -> no emm-gh found!
2116 //extract nanos from emm-gh and emm-s
2117 uchar emmbuf[512];
2119 rdr_log_dbg(rdr, D_EMM, "%s: start extracting nanos", __func__);
2120 //extract from emm-gh
2121 for(i = 3; i < r_emm->emmlen; i += r_emm->emm[i + 1] + 2)
2123 //copy nano (length determined by i+1)
2124 memcpy(emmbuf + pos, r_emm->emm + i, r_emm->emm[i + 1] + 2);
2125 pos += r_emm->emm[i + 1] + 2;
2128 if(buffer[2] == 0x2c)
2130 //add 9E 20 nano + first 32 uint8_ts of emm content
2131 memcpy(emmbuf + pos, "\x9E\x20", 2);
2132 memcpy(emmbuf + pos + 2, buffer + 7, 32);
2133 pos += 34;
2135 //add F0 08 nano + 8 subsequent uint8_ts of emm content
2136 memcpy(emmbuf + pos, "\xF0\x08", 2);
2137 memcpy(emmbuf + pos + 2, buffer + 39, 8);
2138 pos += 10;
2140 else
2142 //extract from variable emm-s
2143 for(k = 7; k < (*len); k += buffer[k + 1] + 2)
2145 //copy nano (length determined by k+1)
2146 memcpy(emmbuf + pos, buffer + k, buffer[k + 1] + 2);
2147 pos += buffer[k + 1] + 2;
2151 rdr_log_dump_dbg(rdr, D_EMM, buffer, *len, "%s: %s emm-s", __func__, (buffer[2] == 0x2c) ? "fixed" : "variable");
2153 emm_sort_nanos(buffer + 7, emmbuf, pos);
2154 pos += 7;
2156 //calculate emm length and set it on position 2
2157 buffer[2] = pos - 3;
2159 rdr_log_dump_dbg(rdr, D_EMM, r_emm->emm, r_emm->emmlen, "%s: emm-gh provid %06X", __func__, provid);
2160 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;
2169 const struct s_cardsystem reader_viaccess =
2171 .desc = "viaccess",
2172 .caids = (uint16_t[]){ 0x05, 0 },
2173 .do_emm_reassembly = viaccess_reassemble_emm,
2174 .do_emm = viaccess_do_emm,
2175 .do_ecm = viaccess_do_ecm,
2176 .card_info = viaccess_card_info,
2177 .card_init = viaccess_card_init,
2178 .get_emm_type = viaccess_get_emm_type,
2179 .get_emm_filter = viaccess_get_emm_filter,
2182 #endif