4 #include "oscam-time.h"
6 #include "reader-common.h"
7 #include "cscrypt/des.h"
8 #include "oscam-work.h"
20 struct geo_cache last_geo
;
21 uint8_t availkeys
[CS_MAXPROV
][16];
35 static void parse_via_date(const uint8_t *buf
, struct via_date
*vd
, int32_t fend
)
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;
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
)
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)
72 if(add
&& e
->provid
== provid
&& e
->emm
[0] == nano
)
83 if(!cs_malloc(&e
, sizeof(struct emm_rass
)))
89 ll_append(client
->ra_buf
, e
);
93 static void show_class(struct s_reader
*reader
, const char *p
, uint32_t provid
, const uint8_t *b
, int32_t l
)
97 // b -> via date (4 uint8_ts)
104 for(i
= 0; i
< 8; i
++)
106 if(b
[j
] & (1 << (i
& 7)))
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
);
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
);
126 time_t start_t
, end_t
;
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)
156 for(i
= 0; i
< 8; i
++)
158 if(b
[j
] & (1 << (i
& 7)))
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
);
171 rdr_log(reader
, "provid %06X has matching class %02X", provid
, cls
);
174 parse_via_date(b
- 4, &vd
, 1);
175 time_t start_t
, end_t
;
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
)
194 rdr_log(reader
, "class %02X provid %06X has already this daterange or newer entitled", cls
, provid
);
211 return 1; // emmdate is fresh!
214 static void show_subs(struct s_reader
*reader
, const uint8_t *emm
)
220 show_class(reader
, "nano A9: ", 1, emm
+ 2, emm
[1]);
228 memset(szGeo
, 0, 256);
229 cs_strncpy(szGeo
, (char *)emm
+ 2, emm
[1]);
230 rdr_log(reader
, "nano A6: geo %s", szGeo
);
240 parse_via_date(emm
+ 2, &vd
, 0);
241 rdr_log(reader
, "nano B6: modexp %d%d%d%d%d%d: %02d/%02d/%04d",
248 vd
.day_s
, vd
.month_s
, vd
.year_s
+ 1980);
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
;
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
)
275 static int32_t get_maturity(struct s_reader
*reader
)
277 /* retrieve maturity rating on the card */
281 uint8_t insac
[] = { 0xca, 0xac, 0x00, 0x00, 0x00 }; // select data
282 uint8_t insb8
[] = { 0xca, 0xb8, 0x00, 0x00, 0x00 }; // read selected data
285 write_cmd(insac
, NULL
); // request maturity rating
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
);
300 rdr_log(reader
, "Maturity level [%X]=no age limit", reader
->maturity
);
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 };
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);
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
);
334 rdr_log(reader
, "Can't disable parental lock. Wrong PIN? OSCam used 0000!");
339 rdr_log(reader
, "Parental lock disabled");
340 get_maturity(reader
);
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;
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
]);
544 for(i1
= 0; i1
<= 3; ++i1
)
546 for(i2
= 0; i2
<= 3; ++i2
)
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
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
]];
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
)
591 for(i
= 0; i
<= 7; ++i
)
593 Buffer
[i
] = hdSurEncCryptLookup_D2_0F_11(CWb
[i
], AddrInd
);
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);
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 };
633 for (i1
= 0; i1
< 11; i1
++)
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
;
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
)
658 unsigned long bb1
, bb2
;
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);
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
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
]];
842 CommonMain_3_D2_13_15(&dataout
[i2
], &dataout
[i1
+ i2
], i1
);
849 void Common_D2_13_15(uint8_t *cw0
, const uint8_t *cw1
, int loopval
)
854 CommonMain_D2_13_15(cw1
, buff8
, loopval
);
855 for (i
= 0; i
< 8; i
++)
861 void ExchangeCWs(uint8_t *cw0
, uint8_t *cw1
)
866 for (i
= 0; i
< 8; i
++)
875 void hdSurEncPhase1_D2_13_15(uint8_t *cws
)
879 for (i
= 0; i
<= 7; i
++)
884 Common_D2_13_15((uint8_t *) &cws
[0], (uint8_t *) &cws
[8], i
);
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
)
898 for (i
= 7; i
>= 0; i
--)
903 Common_D2_13_15((uint8_t *) &cws
[8], (uint8_t *) &cws
[0], i
);
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
)
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)))
935 write_cmd(insFAC
, FacDat
);
936 if(!(cta_res
[cta_lr
- 2] == 0x90 && cta_res
[cta_lr
- 1] == 0))
941 if(!cs_malloc(&reader
->csystem_data
, sizeof(struct viaccess_data
)))
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
));
966 write_cmd(insac
, NULL
); // request unique id
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));
976 write_cmd(insa4
, NULL
); // select issuer 0
978 while((cta_res
[cta_lr
- 2] == 0x90) && (cta_res
[cta_lr
- 1] == 0))
981 write_cmd(insc0
, NULL
); // show provider properties
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);
990 write_cmd(insac
, NULL
); // request sa
992 write_cmd(insb8
, NULL
); // read sa
993 memcpy(&reader
->sa
[i
][0], cta_res
+ 2, 4);
996 write_cmd(insa4
, NULL
); // select next issuer
1000 rdr_log(reader
, "providers: %d (%s)", reader
->nprov
, buf
+ 1);
1002 get_maturity(reader
);
1005 unlock_parental(reader
);
1008 rdr_log(reader
, "ready for requests");
1012 bool dcw_crc(uint8_t *dw
)
1015 for(i
= 0; i
< 16; i
+= 4) if(dw
[i
+ 3] != ((dw
[i
] + dw
[i
+ 1] + dw
[i
+ 2]) & 0xFF)) { return 0; }
1019 static int32_t viaccess_do_ecm(struct s_reader
*reader
, const ECM_REQUEST
*er
, struct s_ecm_answer
*ea
)
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);
1032 rdr_log(reader
, "ECM: Size of ECM couldn't be correctly calculated.");
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;
1043 int32_t curEcm88len
= 0;
1044 int32_t nanoLen
= 0;
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");
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;
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)
1090 rdr_log_dbg(reader
, D_READER
, "ECM: nano D2 0x0b");
1093 if(ecm88Data
[2] == 0x0d)
1096 rdr_log_dbg(reader
, D_READER
, "ECM: nano D2 0x0d");
1099 if(ecm88Data
[2] == 0x0f)
1102 rdr_log_dbg(reader
, D_READER
, "ECM: nano D2 0x0f");
1105 if(ecm88Data
[2] == 0x11)
1108 rdr_log_dbg(reader
, D_READER
, "ECM: nano D2 0x11");
1111 if(ecm88Data
[2] == 0x13)
1114 rdr_log_dbg(reader
, D_READER
, "ECM: nano D2 0x13");
1117 if(ecm88Data
[2] == 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];
1136 // 40 07 03 0b 00 -> nano 40, len =7 ident 030B00 (tntsat), key #0 <== we're pointing here
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
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]);
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
);
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
))
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
);
1205 ecm88Data
+= nanoLen
;
1206 ecm88Len
-= nanoLen
;
1207 curEcm88len
-= nanoLen
;
1210 if(ecm88Data
[0] == 0xDE && ecm88Data
[1] == 0x04)
1212 memcpy(DE04
, &ecm88Data
[0], 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!");
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;
1239 while(cwStart
< curEcm88len
- 1 && !must_exit
)
1241 if(ecm88Data
[cwStart
] == 0xEA && ecm88Data
[cwStart
+ 1] == 0x10)
1243 ecm88DataCW
= ecm88DataCW
+ cwStart
+ 2;
1251 hdSurEncPhase1_D2_0F_11(ecm88DataCW
);
1252 hdSurEncPhase2_D2_0F_11(ecm88DataCW
);
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
);
1269 hdSurEncPhase1_D2_0F_11(ecm88DataCW
);
1274 hdSurEncPhase2_D2_13_15(ecm88DataCW
);
1278 while(ecm88Len
> 1 && ecm88Data
[0] < 0xA0)
1280 nanoLen
= ecm88Data
[1] + 2;
1283 ecmf8Data
= (uint8_t *)ecm88Data
;
1285 ecmf8Len
+= nanoLen
;
1286 ecm88Len
-= nanoLen
;
1287 curEcm88len
-= nanoLen
;
1288 ecm88Data
+= nanoLen
;
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
;
1298 insf8
[4] = ecmf8Len
;
1299 write_cmd(insf8
, ecmf8Data
);
1302 ins88
[2] = ecmf8Len
? 1 : 0;
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
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
);
1318 memcpy(DE04
+ 6, (uint8_t *)ecm88Data
, l
);
1319 write_cmd(ins88
, DE04
); // request dcw
1323 write_cmd(ins88
, (uint8_t *)ecm88Data
); // request dcw
1326 write_cmd(insc0
, NULL
); // read dcw
1332 memcpy(ea
->cw
, cta_res
+ 2, 8);
1339 memcpy(ea
->cw
+ 8, cta_res
+ 2, 8);
1343 case 0xea: // complete
1344 if(cta_res
[1] == 16)
1346 memcpy(ea
->cw
, cta_res
+ 2, 16);
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");
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))
1373 hdSurEncPhase1_D2_0F_11(ea
->cw
);
1374 hdSurEncPhase2_D2_0F_11(ea
->cw
);
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);
1386 snprintf(ea
->msglog
, MSGLOGSIZE
, "Missing AES key(%d)[aka E%X]",D2KeyID
, D2KeyID
);
1391 hdSurEncPhase1_D2_0F_11(ea
->cw
);
1396 hdSurEncPhase2_D2_13_15(ea
->cw
);
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);
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
1420 memcpy(ea
->cw
,returnedcw
, 16);
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);
1439 i2b_buf(4, provid
, ep
->provid
);
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
1455 return 1; // let server decide!
1461 rdr_log_dbg(rdr
, D_EMM
, "GLOBAL");
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
1474 rdr_log_dbg(rdr
, D_EMM
, "SHARED");
1475 memset(ep
->hexserial
, 0, 8);
1476 memcpy(ep
->hexserial
, ep
->emm
+ 3, 3);
1480 for(i
= 0; i
< rdr
->nprov
; i
++)
1482 if(!memcmp(&rdr
->prid
[i
][2], ep
->hexserial
+1, 2))
1486 return (!memcmp(&rdr
->sa
[0][0], ep
->hexserial
, 3));
1491 rdr_log_dbg(rdr
, D_EMM
, "UNKNOWN");
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
)))
1509 struct s_csystem_emm_filter
*filters
= *emm_filters
;
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;
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
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;
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!
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;
1552 memcpy(&filters
[idx
].filter
[1], &rdr
->sa
[prov
][0], 3);
1553 memset(&filters
[idx
].mask
[1], 0xFF, 3);
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
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;
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;
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);
1595 memcpy(&filters
[idx
].filter
[1], rdr
->hexserial
+ 1, 3);
1596 memset(&filters
[idx
].mask
[1], 0xFF, 3);
1600 *filter_count
= idx
;
1606 static int32_t viaccess_do_emm(struct s_reader
*reader
, EMM_PACKET
*ep
)
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
1621 ep
->emm
[1] = 0x70; // (& 0x0f) of this byte is length, so 0x01 would increase the length by 256
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);
1635 if(ep
->type
== UNIQUE
)
1640 if(ep
->type
== GLOBAL
&& emmdatastart
== 7)
1645 int32_t emmLen
= SCT_LEN(ep
->emm
) - emmdatastart
;
1648 rdr_log_dump(reader
, ep
->emm
, emmLen
+ emmdatastart
, "RECEIVED EMM VIACCESS");
1651 uint8_t *emmParsed
= ep
->emm
+ emmdatastart
;
1652 int32_t provider_ok
= 0;
1653 uint32_t emm_provid
= 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
];
1680 emm_provid
= b2i(3, ident
);
1681 keynr
= soid
[2] & 0x0F;
1683 if(chk_prov(reader
, ident
, keynr
))
1689 rdr_log(reader
, "EMM: ignored since provider or key not present on card (%x, %x)", emm_provid
, keynr
);
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]);
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)
1717 /* adf is not crypted, so test it */
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]));
1731 rdr_log_dbg(reader
, D_READER
, "emm not suitable for our card %08X", b2i(4, &reader
->sa
[0][0]));
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];
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
);
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
1778 rdr_log(reader
, "no provid in shared emm -> skipped!");
1781 int8_t match
= add_find_class(reader
, emm_provid
, emmParsed
+ 2, emmParsed
[1], 0);
1785 rdr_log(reader
, "shared emm provid %06X all classes have entitlementdate already same or newer -> skipped!", emm_provid
);
1788 nanoA9Data
= emmParsed
;
1791 memcpy(ins18Data
+ ins18Len
, emmParsed
, emmParsed
[1] + 2);
1792 ins18Len
+= emmParsed
[1] + 2;
1798 rdr_log_dbg(reader
, D_READER
, "provider not found in emm, continue anyway");
1799 // force key to 1...
1806 rdr_log_dump(reader
, ep
->emm
, ep
->emmlen
, "can't find 0xf0 in emm...");
1807 return ERROR
; // error
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]);
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]);
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)
1859 add_find_class(reader
, emm_provid
, nanoA9Data
+ 2, nanoA9Data
[1], 1);
1860 rdr_log(reader
, "Your subscription data was updated.");
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]);
1882 // send subscription encrypted
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
)
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");
1914 static int32_t viaccess_card_info(struct s_reader
*reader
)
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
1940 write_cmd(ins24
, pin
);
1943 write_cmd(insac
, NULL
); // request unique id
1945 write_cmd(insb8
, NULL
); // read unique id
1946 rdr_log_sensitive(reader
, "serial: {%llu}", (unsigned long long) b2ll(5, cta_res
+ 2));
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
++)
1954 uint32_t l_provid
, l_sa
;
1957 write_cmd(insc0
, NULL
); // show provider properties
1959 l_provid
= b2i(3, cta_res
);
1962 write_cmd(insac
, NULL
); // request sa
1964 write_cmd(insb8
, NULL
); // read sa
1965 l_sa
= b2i(4, cta_res
+ 2);
1968 write_cmd(insac
, NULL
); // request name
1970 write_cmd(insb8
, NULL
); // read name nano + len
1973 write_cmd(insb8
, NULL
); // read name
1975 trim((char *)cta_res
);
1979 snprintf((char *)l_name
, sizeof(l_name
), ", name: %.55s", cta_res
);
1988 write_cmd(insac
, NULL
); // request GEO
1990 write_cmd(insb8
, NULL
); // read GEO nano + len
1992 char tmp
[l
* 3 + 1];
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
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))
2013 write_cmd(insb8
, NULL
); // read class subs nano + len
2014 if((cta_res
[cta_lr
- 2] == 0x90) && (cta_res
[cta_lr
- 1] == 0))
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);
2029 // add entitlement info for provid without class
2030 cs_add_entitlement(reader
, reader
->caid
, l_provid
, 0, 0, 0, 0, 5, 1);
2035 write_cmd(insa4
, NULL
); // select next provider
2038 // Start process init CA 28
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!");
2054 des_set_key(reader
->des_key
, reader
->key_schedule1
);
2055 des_set_key(reader
->des_key
+8, reader
->key_schedule2
);
2060 rdr_log(reader
, "CA 28 initialisation failed! CA 28 refused");
2063 //end process init CA 28
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
;
2073 int32_t prov
, provid
= 0;
2074 struct emm_rass
*r_emm
= NULL
;
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);
2093 cs_log("[viaccess] ERROR: Can't allocate EMM reassembly buffer.");
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
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
);
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
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
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);
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);
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
);
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__
);
2190 r_emm
->emmlen
= 0; // mark this shared 8c or 8d as being used for reassembly and send to reader!
2196 const struct s_cardsystem reader_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
,