source: trunk/reader-viaccess.c @ 11200

Last change on this file since 11200 was 11200, checked in by theparasol, 4 years ago

VIACCESS:

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