source: trunk/reader-viaccess.c @ 11282

Last change on this file since 11282 was 11282, checked in by theparasol, 3 years ago

VIACCESS:

  • Entitle providers present on card that dont have any classes
  • Some code cosmetics

Tnx Pr2 for signaling this bug and necessary card details to get it fixed properly

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