source: trunk/reader-viaccess.c

Last change on this file was 11492, checked in by Gorgone Impertinence, 10 months ago

eliminate build warnings by using the integrated function

cs_strncpy instead of strncpy

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