source: trunk/reader-videoguard2.c

Last change on this file was 11572, checked in by felixka, 3 months ago
  • fix for BSkyB 0963
  • fix ticket #4764
  • Property svn:eol-style set to LF
File size: 45.2 KB
Line 
1#include "globals.h"
2#ifdef READER_VIDEOGUARD
3#include "cscrypt/md5.h"
4#include "cscrypt/des.h"
5#include "oscam-work.h"
6#include "reader-common.h"
7#include "reader-videoguard-common.h"
8
9
10static void do_post_dw_hash(struct s_reader *reader, uint8_t *cw, const uint8_t *ecm_header_data)
11{
12    int32_t i, ecmi, ecm_header_count;
13    uint8_t buffer[0x85]; // original 0x80 but with 0x7D mask applied +8 bytes cw it was still to small
14    uint8_t md5tmp[MD5_DIGEST_LENGTH];
15
16    static const uint16_t Hash3[] = { 0x0123, 0x4567, 0x89AB, 0xCDEF, 0xF861, 0xCB52 };
17    static const uint8_t Hash4[] = { 0x0B, 0x04, 0x07, 0x08, 0x05, 0x09, 0x0B, 0x0A,
18                                     0x07, 0x02, 0x0A, 0x05, 0x04, 0x08, 0x0D, 0x0F };
19
20    static const uint16_t NdTabB001[0x15][0x20] =
21    {
22        {
23            0xEAF1, 0x0237, 0x29D0, 0xBAD2, 0xE9D3, 0x8BAE, 0x2D6D, 0xCD1B,
24            0x538D, 0xDE6B, 0xA634, 0xF81A, 0x18B5, 0x5087, 0x14EA, 0x672E,
25            0xF0FC, 0x055E, 0x62E5, 0xB78F, 0x5D09, 0x0003, 0xE4E8, 0x2DCE,
26            0x6BE0, 0xAC4E, 0xF485, 0x6967, 0xF28C, 0x97A0, 0x01EF, 0x0100
27        },
28        {
29            0xC539, 0xF5B9, 0x9099, 0x013A, 0xD4B9, 0x6AB5, 0xEA67, 0x7EB4,
30            0x6C30, 0x4BF0, 0xB810, 0xB0B5, 0xB76D, 0xA751, 0x1AE7, 0x14CA,
31            0x4F4F, 0x1586, 0x2608, 0x10B1, 0xE7E1, 0x48BE, 0x7DDD, 0x5ECB,
32            0xCFBF, 0x323B, 0x8B31, 0xB131, 0x0F1A, 0x664B, 0x0140, 0x0100
33        },
34        {
35            0x3C7D, 0xBDC4, 0xFEC7, 0x26A6, 0xB0A0, 0x6E55, 0xF710, 0xF9BF,
36            0x0023, 0xE81F, 0x41CA, 0xBE32, 0xB461, 0xE92D, 0xF1AF, 0x409F,
37            0xFC85, 0xFE5B, 0x7FCE, 0x17F5, 0x01AB, 0x4A46, 0xEB05, 0xA251,
38            0xDC6F, 0xF0C0, 0x10F0, 0x1D51, 0xEFAA, 0xE9BF, 0x0100, 0x0100
39        },
40        {
41            0x1819, 0x0CAA, 0x9067, 0x607A, 0x7576, 0x1CBC, 0xE51D, 0xBF77,
42            0x7EC6, 0x839E, 0xB695, 0xF096, 0xDC10, 0xCB69, 0x4654, 0x8E68,
43            0xD62D, 0x4F1A, 0x4227, 0x92AC, 0x9064, 0x6BD1, 0x1E75, 0x2747,
44            0x00DA, 0xA6A6, 0x6CF1, 0xD151, 0xBE56, 0x3E33, 0x0128, 0x0100
45        },
46        {
47            0x4091, 0x09ED, 0xD494, 0x6054, 0x1869, 0x71D5, 0xB572, 0x7BF1,
48            0xE925, 0xEE2D, 0xEEDE, 0xA13C, 0x6613, 0x9BAB, 0x122D, 0x7AE4,
49            0x5268, 0xE6C9, 0x50CB, 0x79A1, 0xF212, 0xA062, 0x6B48, 0x70B3,
50            0xF6B0, 0x06D5, 0xF8AB, 0xECF5, 0x6255, 0xEDD8, 0x79D2, 0x290A
51        },
52        {
53            0xD3CF, 0x014E, 0xACB3, 0x8F6B, 0x0F2C, 0xA5D8, 0xE8E0, 0x863D,
54            0x80D5, 0x5705, 0x658A, 0x8BC2, 0xEE46, 0xD3AE, 0x0199, 0x0100,
55            0x4A35, 0xABE4, 0xF976, 0x935A, 0xA8A5, 0xBAE9, 0x24D0, 0x71AA,
56            0xB3FE, 0x095E, 0xAB06, 0x4CD5, 0x2F0D, 0x1ACB, 0x59F3, 0x4C50
57        },
58        {
59            0xFD27, 0x0F8E, 0x191A, 0xEEE7, 0x2F49, 0x3A05, 0x3267, 0x4F88,
60            0x38AE, 0xFCE9, 0x9476, 0x18C6, 0xF961, 0x4EF0, 0x39D0, 0x42E6,
61            0xB747, 0xE625, 0xB68E, 0x5100, 0xF92A, 0x86FE, 0xE79B, 0xEE91,
62            0x21D5, 0x4C3C, 0x683D, 0x5AD1, 0x1B49, 0xF407, 0x0194, 0x0100
63        },
64        {
65            0x4BF9, 0xDC0D, 0x9478, 0x5174, 0xCB4A, 0x8A89, 0x4D6A, 0xFED8,
66            0xF123, 0xA8CD, 0xEEE7, 0xA6D1, 0xB763, 0xF5E2, 0xE085, 0x01EF,
67            0xE466, 0x9FA3, 0x2F68, 0x2190, 0x423F, 0x287F, 0x7F3F, 0x09F6,
68            0x2111, 0xA963, 0xD0BB, 0x674A, 0xBA72, 0x45F9, 0xF186, 0xB8F5
69        },
70        {
71            0x0010, 0xD1B9, 0xB164, 0x9E87, 0x1F49, 0x6950, 0x2DBF, 0x38D3,
72            0x2EB0, 0x3E8E, 0x91E6, 0xF688, 0x7E41, 0x566E, 0x01B0, 0x0100,
73            0x24A1, 0x73D8, 0xA0C3, 0xF71B, 0xA0A5, 0x2A06, 0xBA46, 0xFEC3,
74            0xDD4C, 0x52CC, 0xF9BC, 0x3B7E, 0x3812, 0x0666, 0xB74B, 0x40F8
75        },
76        {
77            0x28F2, 0x7C81, 0xFC92, 0x6FBD, 0x53D6, 0x72A3, 0xBBDF, 0xB6FC,
78            0x9CE5, 0x2331, 0xD4F6, 0xC5BB, 0xE8BB, 0x6676, 0x02D9, 0x2F0E,
79            0xD009, 0xD136, 0xCD09, 0x7551, 0x1826, 0x9D9B, 0x63EA, 0xFC63,
80            0x68CD, 0x3672, 0xCB95, 0xD28E, 0xF1CD, 0x20CA, 0x014C, 0x0100
81        },
82        {
83            0xE539, 0x55B7, 0x989D, 0x21C4, 0x463A, 0xE68F, 0xF8B5, 0xE5C5,
84            0x662B, 0x35BF, 0x3C50, 0x0131, 0xF4BF, 0x38B2, 0x41BC, 0xB829,
85            0x02B7, 0x6B8F, 0xA25C, 0xAFD2, 0xD84A, 0x2243, 0x53EB, 0xC6C9,
86            0x2E14, 0x181F, 0x8F96, 0xDF0E, 0x0D4C, 0x30F6, 0xFFE1, 0x9DDA
87        },
88        {
89            0x30B6, 0x777E, 0xDA3D, 0xAF77, 0x205E, 0xC90B, 0x856B, 0xB451,
90            0x3BCC, 0x76C2, 0x8ACF, 0xDCB1, 0xA5E5, 0xDD64, 0x0197, 0x0100,
91            0xE751, 0xB661, 0x0404, 0xDB4A, 0xE9DD, 0xA400, 0xAF26, 0x3F5E,
92            0x904B, 0xA924, 0x09E0, 0xE72B, 0x825B, 0x2C50, 0x6FD0, 0x0D52
93        },
94        {
95            0x2730, 0xC2BA, 0x9E44, 0x5815, 0xFC47, 0xB21D, 0x67B8, 0xF8B9,
96            0x047D, 0xB0AF, 0x9F14, 0x741B, 0x4668, 0xBE54, 0xDE16, 0xDB14,
97            0x7CB7, 0xF2B8, 0x0683, 0x762C, 0x09A0, 0x9507, 0x7F92, 0x022C,
98            0xBA6A, 0x7D52, 0x0AF4, 0x1BC3, 0xB46A, 0xC4FD, 0x01C2, 0x0100
99        },
100        {
101            0x7611, 0x66F3, 0xEE87, 0xEDD3, 0xC559, 0xEFD4, 0xDC59, 0xF86B,
102            0x6D1C, 0x1C85, 0x9BB1, 0x3373, 0x763F, 0x4EBE, 0x1BF3, 0x99B5,
103            0xD721, 0x978F, 0xCF5C, 0xAC51, 0x0984, 0x7462, 0x8F0C, 0x2817,
104            0x4AD9, 0xFD41, 0x6678, 0x7C85, 0xD330, 0xC9F8, 0x1D9A, 0xC622
105        },
106        {
107            0x5AE4, 0xE16A, 0x60F6, 0xFD45, 0x668C, 0x29D6, 0x0285, 0x6B92,
108            0x92C2, 0x21DE, 0x45E0, 0xEF3D, 0x8B0D, 0x02CD, 0x0198, 0x0100,
109            0x9E6D, 0x4D38, 0xDEF9, 0xE6F2, 0xF72E, 0xB313, 0x14F2, 0x390A,
110            0x2D67, 0xC71E, 0xCB69, 0x7F66, 0xD3CF, 0x7F8A, 0x81D9, 0x9DDE
111        },
112        {
113            0x85E3, 0x8F29, 0x36EB, 0xC968, 0x3696, 0x59F6, 0x7832, 0xA78B,
114            0xA1D8, 0xF5CF, 0xAB64, 0x646D, 0x7A2A, 0xBAF8, 0xAA87, 0x41C7,
115            0x5120, 0xDE78, 0x738D, 0xDC1A, 0x268D, 0x5DF8, 0xED69, 0x1C8A,
116            0xBC85, 0x3DCD, 0xAE30, 0x0F8D, 0xEC89, 0x3ABD, 0x0166, 0x0100
117        },
118        {
119            0xB8BD, 0x643B, 0x748E, 0xBD63, 0xEC6F, 0xE23A, 0x9493, 0xDD76,
120            0x0A62, 0x774F, 0xCD68, 0xA67A, 0x9A23, 0xC8A8, 0xBDE5, 0x9D1B,
121            0x2B86, 0x8B36, 0x5428, 0x1DFB, 0xCD1D, 0x0713, 0x29C2, 0x8E8E,
122            0x5207, 0xA13F, 0x6005, 0x4F5E, 0x52E0, 0xE7C8, 0x6D1C, 0x3E34
123        },
124        {
125            0x581D, 0x2BFA, 0x5E1D, 0xA891, 0x1069, 0x1DA4, 0x39A0, 0xBE45,
126            0x5B9A, 0x7333, 0x6F3E, 0x8637, 0xA550, 0xC9E9, 0x5C6C, 0x42BA,
127            0xA712, 0xC3EA, 0x3808, 0x0910, 0xAA4D, 0x5B25, 0xABCD, 0xE680,
128            0x96AD, 0x2CEC, 0x8EBB, 0xA47D, 0x1690, 0xE8FB, 0x01C8, 0x0100
129        },
130        {
131            0x73B9, 0x82BC, 0x9EBC, 0xB130, 0x0DA5, 0x8617, 0x9F7B, 0x9766,
132            0x205D, 0x752D, 0xB05C, 0x2A17, 0xA75C, 0x18EF, 0x8339, 0xFD34,
133            0x8DA2, 0x7970, 0xD0B4, 0x70F1, 0x3765, 0x7380, 0x7CAF, 0x570E,
134            0x6440, 0xBC44, 0x0743, 0x2D02, 0x0419, 0xA240, 0x2113, 0x1AD4
135        },
136        {
137            0x1EB5, 0xBBFF, 0x39B1, 0x3209, 0x705F, 0x15F4, 0xD7AD, 0x340B,
138            0xC2A6, 0x25CA, 0xF412, 0x9570, 0x0F4F, 0xE4D5, 0x1614, 0xE464,
139            0x911A, 0x0F0E, 0x07DA, 0xA929, 0x2379, 0xD988, 0x0AA6, 0x3B57,
140            0xBF63, 0x71FB, 0x72D5, 0x26CE, 0xB0AF, 0xCF45, 0x011B, 0x0100
141        },
142        {
143            0x9999, 0x98FE, 0xA108, 0x6588, 0xF90B, 0x4554, 0xFF38, 0x4642,
144            0x8F5F, 0x6CC3, 0x4E8E, 0xFF7E, 0x64C2, 0x50CA, 0x0E7F, 0xAD7D,
145            0x6AAB, 0x33C1, 0xE1F4, 0x6165, 0x7894, 0x83B9, 0x0A0C, 0x38AF,
146            0x5803, 0x18C0, 0xFA36, 0x592C, 0x4548, 0xABB8, 0x1527, 0xAEE9
147        }
148    };
149
150    //ecm_header_data = 01 03 b0 01 01
151    if(!cw_is_valid(cw)) // if cw is all zero, keep it that way
152    {
153        return;
154    }
155
156    ecm_header_count = ecm_header_data[0];
157    for(i = 0, ecmi = 1; i < ecm_header_count; i++)
158    {
159        if(ecm_header_data[ecmi + 1] != 0xb0)
160        {
161            ecmi += ecm_header_data[ecmi] + 1;
162        }
163        else
164        {
165            switch(ecm_header_data[ecmi + 2])
166            {
167                case 1: // b0 01
168                {
169                    uint16_t hk[8], r, j, m = 0;
170                    for(r = 0; r < 6; r++)
171                    {
172                        hk[2 + r] = Hash3[r];
173                    }
174
175                    for(r = 0; r < 2; r++)
176                    {
177                        for(j = 0; j < 0x48; j += 2)
178                        {
179                            if(r)
180                            {
181                                hk[0] = ((hk[3] & hk[5]) | ((~hk[5]) & hk[4]));
182                            }
183                            else
184                            {
185                                hk[0] = ((hk[3] & hk[4]) | ((~hk[3]) & hk[5]));
186                            }
187
188                            if(j < 8)
189                            {
190                                hk[0] = (hk[0] + ((cw[j + 1] << 8) | cw[j]));
191                            }
192
193                            if(j == 8)
194                            {
195                                hk[0] = (hk[0] + 0x80);
196                            }
197
198                            hk[0] = (hk[0] + hk[2] + (0xFF & NdTabB001[ecm_header_data[ecmi + 3]][m >> 1] >> ((m & 1) << 3)));
199                            hk[1] = hk[2];
200                            hk[2] = hk[3];
201                            hk[3] = hk[4];
202                            hk[4] = hk[5];
203                            hk[5] = hk[6];
204                            hk[6] = hk[7];
205                            hk[7] = hk[2] + (((hk[0] << Hash4[m & 0xF]) | (hk[0] >> (0x10 - Hash4[m & 0xF]))));
206                            m = (m + 1) & 0x3F;
207                        }
208                    }
209
210                    for(r = 0; r < 6; r++)
211                    {
212                        hk[2 + r] += Hash3[r];
213                    }
214
215                    for(r = 0; r < 7; r++)
216                    {
217                        cw[r] = hk[2 + (r >> 1)] >> ((r & 1) << 3);
218                    }
219
220                    cw[3] = (cw[0] + cw[1] + cw[2]) & 0xFF;
221                    cw[7] = (cw[4] + cw[5] + cw[6]) & 0xFF;
222                    rdr_log_dump_dbg(reader, D_READER, cw, 8, "Postprocessed Case 1 DW:");
223                    break;
224                }
225
226                case 3:
227                {
228                    memset(buffer, 0, sizeof(buffer));
229                    memcpy(buffer, cw, 8);
230                    memcpy(buffer + 8, &ecm_header_data[ecmi + 3], ecm_header_data[ecmi] & 0x7D);
231                    MD5(buffer, 8 + (ecm_header_data[ecmi] & 0x7D), md5tmp);
232                    memcpy(cw, md5tmp, 8);
233                    rdr_log_dump_dbg(reader, D_READER, cw, 8, "Postprocessed Case 3 DW:");
234                    break;
235                }
236
237                case 2:
238                {
239                    // Method 2 left out
240                    //memcpy(DW_OUTPUT, DW_INPUT, 8);
241                    break;
242                }
243            }
244        }
245    }
246}
247
248static void vg2_read_tiers(struct s_reader *reader)
249{
250    uint8_t cta_res[CTA_RES_LEN];
251    struct videoguard_data *csystem_data = reader->csystem_data;
252
253    if(reader->readtiers == 1)
254    {
255        uint8_t ins707f[5] = { 0xD1, 0x70, 0x00, 0x7f, 0x02 };
256        if(do_cmd(reader, ins707f, NULL, NULL, cta_res) < 0)
257        {
258            rdr_log(reader, "classD1 ins707f: failed to get number of classes supported");
259        }
260        else
261        {
262            cs_clear_entitlement(reader);
263            rdr_log(reader, "------------------------------------------------------------------");
264            rdr_log(reader, "|- class -|-- tier --|----- valid to ------|--- package name ----|");
265            rdr_log(reader, "+---------+----------+---------------------+---------------------+");
266
267            if((reader->VgFuse & 5) == 0)
268            {
269                rdr_log(reader, "|------- This card is not active, so no package available! ------|");
270            }
271
272            uint32_t TierClass, ClassSupported;
273            ClassSupported = cta_res[1];
274            uint8_t ins70[5] = { 0xD1, 0x70, 0x00, 0x00, 0x00 };
275
276            for(TierClass = 0; TierClass < ClassSupported; TierClass++)
277            {
278                ins70[2] = TierClass;
279                if(do_cmd(reader, ins70, NULL, NULL, cta_res) < 0)
280                {
281                    rdr_log(reader, "classD1 ins70: failed to get tiers for class %02X", TierClass);
282                }
283                else
284                {
285                    char tiername[83];
286                    uint32_t word;
287                    uint32_t bitnum;
288                    uint32_t tier_id;
289                    struct tm timeinfo;
290                    memset(&timeinfo, 0, sizeof(struct tm));
291                    time_t start_t = 0, end_t;
292
293                    if(cta_res[1] > 0x23)
294                    {
295                        rev_date_calc_tm(&cta_res[38], &timeinfo, csystem_data->card_baseyear);
296                        start_t = mktime(&timeinfo);
297                    }
298
299                    rev_date_calc_tm(&cta_res[34], &timeinfo, csystem_data->card_baseyear);
300                    end_t = mktime(&timeinfo);
301
302                    for(word = 0; word < 32; word += 2)
303                    {
304                        for (bitnum = 0; bitnum < 8; bitnum++)
305                        {
306                            if((cta_res[word + 2] >> bitnum) & 1)
307                            {
308                                tier_id = 0;
309                                tier_id = ((TierClass << 8) + (word << 3) + bitnum);
310                                cs_add_entitlement(reader, reader->caid, b2ll(4, reader->prid[0]), tier_id, TierClass, start_t, end_t, 4, 1);
311                                rdr_log(reader, "|-- %02x ---|-- %04x --| %04d/%02d/%02d-%02d:%02d:%02d | %s",
312                                    TierClass,
313                                    tier_id,
314                                    timeinfo.tm_year + 1900,
315                                    timeinfo.tm_mon + 1,
316                                    timeinfo.tm_mday,
317                                    timeinfo.tm_hour,
318                                    timeinfo.tm_min,
319                                    timeinfo.tm_sec,
320                                    get_tiername(tier_id, reader->caid, tiername));
321                            }
322
323                            if((cta_res[word + 1 + 2] >> bitnum) & 1)
324                            {
325                                tier_id = 0;
326                                tier_id = ((TierClass << 8) + (word << 3) + bitnum + 8);
327                                cs_add_entitlement(reader, reader->caid, b2ll(4, reader->prid[0]), tier_id, TierClass, start_t, end_t, 4, 1);
328                                rdr_log(reader, "|-- %02x ---|-- %04x --| %04d/%02d/%02d-%02d:%02d:%02d | %s",
329                                    TierClass,
330                                    tier_id,
331                                    timeinfo.tm_year + 1900,
332                                    timeinfo.tm_mon + 1,
333                                    timeinfo.tm_mday,
334                                    timeinfo.tm_hour,
335                                    timeinfo.tm_min,
336                                    timeinfo.tm_sec,
337                                    get_tiername(tier_id, reader->caid, tiername));
338                            }
339                        }
340                    }
341                }
342            }
343        }
344        rdr_log(reader, "------------------------------------------------------from-ins70--");
345    }
346    else if(reader->readtiers == 2)
347    {
348        int32_t l;
349        // ins2a is not needed and causes an error on some cards eg Sky Italy 09CD
350        // check if ins2a is in command table before running it
351
352        static const uint8_t ins2a[5] = { 0xD1, 0x2a, 0x00, 0x00, 0x00 };
353        if(cmd_exists(reader, ins2a))
354        {
355            l = do_cmd(reader, ins2a, NULL, NULL, cta_res);
356            if(l < 0 || !status_ok(cta_res + l))
357            {
358                rdr_log(reader, "classD1 ins2a: failed");
359                return;
360            }
361        }
362
363        static const uint8_t ins76007f[5] = { 0xD1, 0x76, 0x00, 0x7f, 0x02 };
364        l = do_cmd(reader, ins76007f, NULL, NULL, cta_res);
365        if(l < 0 || !status_ok(cta_res + 2))
366        {
367            rdr_log(reader, "classD1 ins76007f: failed");
368            return;
369        }
370        int32_t num = cta_res[1];
371
372        int32_t i;
373        uint8_t ins76[5] = { 0xD1, 0x76, 0x00, 0x00, 0x00 };
374
375        // some cards start real tiers info in middle of tier info
376        // and have blank tiers between old tiers and real tiers eg 09AC
377        int32_t starttier = csystem_data->card_tierstart;
378        bool stopemptytier = 1;
379        if(!starttier)
380        {
381            stopemptytier = 0;
382        }
383
384        // check to see if specified start tier is blank and if blank, start at 0 and ignore blank tiers
385        ins76[2] = starttier;
386        l = do_cmd(reader, ins76, NULL, NULL, cta_res);
387        if(l < 0 || !status_ok(cta_res + l))
388        {
389            return;
390        }
391
392        if(cta_res[2] == 0 && cta_res[3] == 0)
393        {
394            stopemptytier = 0;
395            starttier = 0;
396        }
397
398        cs_clear_entitlement(reader); // reset the entitlements
399        rdr_log(reader, "------------------------------------------------------------------");
400        rdr_log(reader, "|- class -|-- tier --|----- valid to ------|--- package name ----|");
401        rdr_log(reader, "+---------+----------+---------------------+---------------------+");
402        if((reader->VgFuse&5) == 0)
403        {
404            rdr_log(reader, "|------- This card is not active, so no package available! ------|");
405        }
406
407        for(i = starttier; i < num; i++)
408        {
409            ins76[2] = i;
410            l = do_cmd(reader, ins76, NULL, NULL, cta_res);
411
412            if(l < 0 || !status_ok(cta_res + l))
413            {
414                return;
415            }
416
417            if(cta_res[2] == 0 && cta_res[3] == 0 && stopemptytier)
418            {
419                return;
420            }
421
422            if(cta_res[2] != 0 || cta_res[3] != 0)
423            {
424                char tiername[83];
425                uint16_t tier_id = (cta_res[2] << 8) | cta_res[3];
426                // add entitlements to list
427                struct tm timeinfo;
428                memset(&timeinfo, 0, sizeof(struct tm));
429                rev_date_calc_tm(&cta_res[4], &timeinfo, csystem_data->card_baseyear);
430                cs_add_entitlement(reader, reader->caid, b2ll(4, reader->prid[0]), tier_id, 0, 0, mktime(&timeinfo), 4, 1);
431
432                if(!stopemptytier)
433                {
434                    rdr_log_dbg(reader, D_READER, "tier: %04x, tier-number: 0x%02x", tier_id, i);
435                }
436                rdr_log(reader, "|-- %02x ---|-- %04x --| %04d/%02d/%02d-%02d:%02d:%02d | %s",
437                    cta_res[2],
438                    tier_id,
439                    timeinfo.tm_year + 1900,
440                    timeinfo.tm_mon + 1,
441                    timeinfo.tm_mday,
442                    timeinfo.tm_hour,
443                    timeinfo.tm_min,
444                    timeinfo.tm_sec,
445                    get_tiername(tier_id, reader->caid, tiername));
446            }
447        }
448        rdr_log(reader, "------------------------------------------------------from-ins76--");
449    }
450    else if(reader->readtiers == 0)
451    {
452        rdr_log(reader, "------------------------------------------------------------------");
453        rdr_log(reader, "|--- The reading of the tiers is disabled by the configuration --|");
454        rdr_log(reader, "------------------------------------------------------------------");
455    }
456}
457
458void videoguard2_poll_status(struct s_reader *reader)
459{
460    const time_t poll_interval = 12; // less is better
461    time_t now = time(0);
462    int32_t i;
463
464    if(now >= reader->last_poll + poll_interval)
465    {
466        static const uint8_t ins5C[5] = { 0xD1, 0x5C, 0x00, 0x00, 0x04 };
467        uint8_t cta_res[CTA_RES_LEN];
468        int32_t l;
469        l = do_cmd(reader, ins5C, NULL, NULL, cta_res);
470
471        if(l < 0 || !status_ok(cta_res + l))
472        {
473            rdr_log(reader, "classD1 ins5C: failed");
474        }
475        else
476        {
477            switch (cta_res[1])
478            {
479                case 0x14: // loc_43C250
480                {
481                    static const uint8_t ins4Ca[5] = { 0xD1, 0x4C, 0x00, 0x00, 0x00 };
482                    l = do_cmd(reader, ins4Ca, reader->payload4C, NULL, cta_res);
483
484                    if(l < 0 || !status_ok(cta_res))
485                    {
486                        rdr_log(reader, "classD1 ins4Ca: failed");
487                    }
488
489                    if(reader->ins7E[0x1A])
490                    {
491                        static const uint8_t ins7E[5] = { 0xD1, 0x7E, 0x10, 0x00, 0x1A };
492                        l = do_cmd(reader, ins7E, reader->ins7E, NULL, cta_res);
493
494                        if(l < 0 || !status_ok(cta_res))
495                        {
496                            rdr_log(reader, "classD1 ins7E: failed");
497                        }
498                    }
499
500                    if(reader->ins2e06[4])
501                    {
502                        static const uint8_t ins2e06[5] = { 0xD1, 0x2E, 0x06, 0x00, 0x04 };
503                        l = do_cmd(reader, ins2e06, reader->ins2e06, NULL, cta_res);
504                        if(l < 0 || !status_ok(cta_res))
505                        {
506                            rdr_log(reader, "classD1 ins2E: failed");
507                        }
508                    }
509
510                    static const uint8_t ins58a[5] = { 0xD1, 0x58, 0x00, 0x00, 0x00 };
511                    if((do_cmd(reader, ins58a, NULL, NULL, cta_res) < 0))
512                    {
513                        rdr_log(reader, "classD1 ins58: failed");
514                    }
515
516                    reader->VgFuse = cta_res[2];
517                    static const uint8_t ins7403a[5] = { 0xD1, 0x74, 0x03, 0x00, 0x00 };
518
519                    if((do_cmd(reader, ins7403a, NULL, NULL, cta_res) < 0))
520                    {
521                        rdr_log(reader, "classD1 ins7403a: failed");
522                    }
523                    else
524                    {
525                        if(((cta_res[2] >> 5) & 1))
526                        {
527                            static const uint8_t ins7423[5] = { 0xD3, 0x74, 0x23, 0x00, 0x00 };
528                            if(do_cmd(reader, ins7423, NULL, NULL, cta_res) < 0)
529                            {
530                                rdr_log(reader, "classD1 ins7423: failed");
531                            }
532                        }
533                    }
534                    break;
535                }
536
537                case 0xB: // .text:000000000043C050
538                {
539                    uint8_t ins5E[5] = { 0xD1,0x5E,0x00,0x00,0x00 };
540                    ins5E[2] = cta_res[2];
541                    ins5E[3] = cta_res[1];
542                    ins5E[4] = cta_res[3];
543                    l = do_cmd(reader, ins5E, NULL, NULL, cta_res);
544
545                    if(l < 0 || !status_ok(cta_res + l))
546                    {
547                        rdr_log(reader, "Ins5E: failed");
548                    }
549
550                    uint8_t ins78[5] = { 0xD1, 0x78, 0x00, 0x00, 0x18 };
551                    ins78[2] = cta_res[0];
552                    l = do_cmd(reader, ins78, NULL, NULL, cta_res);
553
554                    if(l < 0 || !status_ok(cta_res + l))
555                    {
556                        rdr_log(reader, "classD1 ins78: failed");
557                    }
558
559                    uint8_t ins32[5] = { 0xD1, 0x32, 0x00, 0x00, 0x01 };
560                    const uint8_t payload32[1] = { 0x25 };
561                    l = do_cmd(reader, ins32, payload32, NULL, cta_res);
562
563                    if(l < 0 || !status_ok(cta_res + l))
564                    {
565                        rdr_log(reader, "classD1 ins32: failed");
566                    }
567                    break;
568                }
569
570                case 0x0C: // loc_43C13F
571                {
572                    uint8_t ins5E[5] = { 0xD1,0x5E,0x00,0x00,0x00 };
573                    ins5E[2] = cta_res[2];
574                    ins5E[3] = cta_res[1];
575                    ins5E[4] = cta_res[3];
576                    l = do_cmd(reader, ins5E, NULL, NULL, cta_res);
577
578                    if(l < 0 || !status_ok(cta_res + l))
579                    {
580                        rdr_log(reader, "Ins5E: failed");
581                    }
582                    else
583                    {
584                        uint8_t ins36[5] = { 0xD1, 0x36, 0x00, 0x00, 0x00 };
585                        ins36[4] = cta_res[1];
586
587                        for (i = 0; i <= cta_res[0]; i++)
588                        {
589                            ins36[3] = i;
590                            l = do_cmd(reader, ins36, NULL, NULL, cta_res);
591
592                            if(l < 0 || !status_ok(cta_res + l))
593                            {
594                                rdr_log(reader, "Ins36: failed");
595                            }
596                        }
597                    }
598                    break;
599                }
600
601                case 0x10: // loc_43C203
602                {
603                    uint8_t ins7411[5] = { 0xD3,0x74,0x11,0x00,0x00 };
604                    l = read_cmd_len(reader, ins7411);
605                    ins7411[4] = l + 0x10;
606                    l = do_cmd(reader, ins7411, NULL, NULL, cta_res);
607
608                    if(l < 0 || !status_ok(cta_res))
609                    {
610                        rdr_log(reader, "classD3 ins7411: failed");
611                    }
612                    break;
613                }
614
615                case 0x00: // normal state
616                {
617                    break;
618                }
619
620                default:
621                {
622                    rdr_log(reader, "unknown ins5C state: %02X %02X %02X %02X",
623                            cta_res[0], cta_res[1], cta_res[2], cta_res[3]);
624                    break;
625                }
626            }
627        }
628        reader->last_poll = now;
629    }
630}
631
632static int32_t videoguard2_card_init(struct s_reader *reader, ATR *newatr)
633{
634    get_hist;
635    if((hist_size < 7) || (hist[1] != 0xB0) || (hist[4] != 0xFF) || (hist[5] != 0x4A) || (hist[6] != 0x50))
636    {
637        rdr_log_dbg(reader, D_READER, "failed history check");
638        return ERROR;
639    }
640    rdr_log_dbg(reader, D_READER, "passed history check");
641
642    get_atr;
643    def_resp;
644
645    if(!cs_malloc(&reader->csystem_data, sizeof(struct videoguard_data)))
646    {
647        return ERROR;
648    }
649    struct videoguard_data *csystem_data = reader->csystem_data;
650
651    // set information on the card stored in reader-videoguard-common.c
652    set_known_card_info(reader, atr, &atr_size);
653
654    if((reader->ndsversion != NDS2) && (((csystem_data->card_system_version != NDS2)
655        && (csystem_data->card_system_version != NDSUNKNOWN)) || (reader->ndsversion != NDSAUTO)))
656    {
657        /* known ATR and not NDS2
658           or known NDS2 ATR and forced to another NDS version */
659        return ERROR;
660    }
661
662    rdr_log_dbg(reader, D_READER, "type: %s, baseyear: %i", csystem_data->card_desc, csystem_data->card_baseyear);
663    if(reader->ndsversion == NDS2)
664    {
665        rdr_log_dbg(reader, D_READER, "forced to NDS2");
666    }
667
668    // a non videoguard2/NDS2 card will fail on read_cmd_len(ins7401)
669    // this way unknown videoguard2/NDS2 cards will also pass this check
670
671    uint8_t ins7401[5] = { 0xD0, 0x74, 0x01, 0x00, 0x00 };
672    int32_t l;
673    if((l = read_cmd_len(reader, ins7401)) < 0) // not a videoguard2/NDS card or communication error
674    {
675        return ERROR;
676    }
677
678    ins7401[4] = l;
679    if(!write_cmd_vg(ins7401, NULL) || !status_ok(cta_res + l))
680    {
681        rdr_log(reader, "classD0 ins7401: failed - cmd list not read");
682        return ERROR;
683    }
684
685    memorize_cmd_table(reader, cta_res, l);
686
687    uint8_t buff[256];
688    static const uint8_t ins02[5] = { 0xD0, 0x02, 0x00, 0x00, 0x08 };
689
690    // D0 02 command is not always present in command table but should be supported
691    // on most cards so do not use do_cmd()
692    if(!write_cmd_vg(ins02, NULL) || !status_ok(cta_res + 8))
693    {
694        rdr_log(reader, "Unable to get NDS ROM version.");
695    }
696    else
697    {
698        int i;
699        for(i = 0; i < 8; i++)
700        {
701            if(cta_res[i] <= 0x09)
702            {
703                cta_res[i] = cta_res[i] + 0x30;
704            }
705            else if(!isalnum(cta_res[i]))
706            {
707                cta_res[i] = '*';
708            }
709        }
710        memset(reader->rom, 0, sizeof(reader->rom));
711        memcpy(reader->rom, cta_res, 4);
712        reader->rom[4] = '-';
713        memcpy(reader->rom + 5, cta_res + 4, 4);
714
715        rdr_log(reader, "Card type:   %c%c%c%c", reader->rom[0], reader->rom[1], reader->rom[2], reader->rom[3]);
716        rdr_log(reader, "Rom version: %c%c%c%c", reader->rom[5], reader->rom[6], reader->rom[7], reader->rom[8]);
717    }
718
719    // get Vg credit on card
720    uint8_t ins7404[5] = { 0xD0, 0x74, 0x04, 0x00, 0x00 };
721    if((l = read_cmd_len(reader, ins7404)) > 0) // get command len for ins7404
722    {
723        ins7404[4] = l;
724        if(!write_cmd_vg(ins7404, NULL) || !status_ok(cta_res + l))
725        {
726            rdr_log(reader, "classD0 ins7404: failed");
727        }
728        else
729        {
730            if(cta_res[0] == 0x15)
731            {
732                reader->VgCredit = ((cta_res[8] << 8) + cta_res[9]) / 100;
733                rdr_log(reader, "Credit available on card: %i euro", reader->VgCredit);
734            }
735        }
736    }
737    else // case V13
738    {
739        rdr_log(reader, "Unable to get smartcard credit");
740    }
741
742    static const uint8_t ins7416[5] = { 0xD0, 0x74, 0x16, 0x00, 0x00 };
743
744    if(do_cmd(reader, ins7416, NULL, NULL, cta_res) < 0)
745    {
746        rdr_log(reader, "classD0 ins7416: failed");
747        return ERROR;
748    }
749    uint8_t boxID [4];
750
751    if(reader->boxid > 0)
752    {
753        // the boxid is specified in the config
754        int32_t i;
755        for(i = 0; i < 4; i++)
756        {
757            boxID[i] = (reader->boxid >> (8 * (3 - i))) % 0x100;
758        }
759    }
760    else
761    {
762        uint8_t ins36[5] = { 0xD0, 0x36, 0x00, 0x00, 0x00 };
763        static const uint8_t ins5e[5] = { 0xD0, 0x5E, 0x00, 0x0C, 0x02 };
764
765        // we can try to get the boxid from the card
766        int32_t boxidOK = 0;
767        l = read_cmd_len(reader, ins36);
768        if(l > 0)
769        {
770            ins36[4] = l;
771        }
772        else if(cmd_exists(reader, ins5e))
773        {
774            if(!write_cmd_vg(ins5e, NULL) || !status_ok(cta_res + 2))
775            {
776                rdr_log(reader, "classD0 ins5e: failed");
777            }
778            else
779            {
780                ins36[3] = cta_res[0];
781                ins36[4] = cta_res[1];
782            }
783        }
784
785        l = ins36[4];
786        if(!write_cmd_vg(ins36, NULL) || !status_ok(cta_res + l))
787        {
788            rdr_log(reader, "classD0 ins36: failed");
789            return ERROR;
790        }
791
792        memcpy(buff, ins36, 5);
793        memcpy(buff + 5, cta_res, l);
794        memcpy(buff + 5 + l, cta_res + l, 2);
795
796        if(l < 13)
797        {
798            rdr_log(reader, "classD0 ins36: answer too int16");
799        }
800        else if(buff[7] > 0x0F)
801        {
802            rdr_log(reader, "classD0 ins36: encrypted - can't parse");
803        }
804        else
805        {
806            // skipping the initial fixed fields: cmdecho (4) + length (1) + encr/rev++ (4)
807            int32_t i = 9;
808            int32_t gotUA = 0;
809            while(i < l)
810            {
811                if(!gotUA && buff[i] < 0xF0) // then we guess that the next 4 bytes is the UA
812                {
813                    gotUA = 1;
814                    i += 4;
815                }
816                else
817                {
818                    switch(buff[i]) // object length vary depending on type
819                    {
820                        case 0x00: // padding
821                            i += 1;
822                            break;
823
824                        case 0xEF: // card status
825                            i += 3;
826                            break;
827
828                        case 0xD1:
829                            i += 4;
830                            break;
831
832                        case 0xDF: // next server contact
833                            i += 5;
834                            break;
835
836                        case 0xF3: // boxID
837                            memcpy(boxID, buff + i + 1, sizeof(boxID));
838                            boxidOK = 1;
839                            i += 5;
840                            break;
841
842                        case 0xF6:
843                            i += 6;
844                            break;
845
846                        case 0x01: // date & time
847                            i += 7;
848                            break;
849
850                        case 0xFA:
851                            i += 9;
852                            break;
853
854                        case 0x5E:
855                        case 0x67: // signature
856                        case 0xDE:
857                        case 0xE2:
858                        case 0xE9: // tier dates
859                        case 0xF8: // Old PPV Event Record
860                        case 0xFD:
861                            i += buff[i + 1] + 2; // skip length + 2 bytes (type and length)
862                            break;
863
864                        default: // default to assume a length byte
865                            rdr_log(reader, "classD0 ins36: returned unknown type=0x%02X - parsing may fail", buff[i]);
866                            i += buff[i + 1] + 2;
867                    }
868                }
869            }
870        }
871
872        if(!boxidOK)
873        {
874            rdr_log(reader, "no boxID available");
875            return ERROR;
876        }
877    }
878
879    uint8_t ins4C[5] = { 0xD0, 0x4C, 0x00, 0x00, 0x09 };
880    uint8_t len4c = 0, mode = 0;
881    uint8_t payload4C[0xF] = { 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
882
883    if(cmd_table_get_info(reader, ins4C, &len4c, &mode))
884    {
885        ins4C[4] = len4c; // don't mind if payload is > of ins len, it will be cutted after write_cmd_vg()
886        if(len4c > 9)
887        {
888            rdr_log_dbg(reader, D_READER, "extended ins4C detected");
889        }
890    }
891    memcpy(payload4C, boxID, 4);
892    if(!write_cmd_vg(ins4C, payload4C))
893    {
894        rdr_log(reader, "classD0 ins4C: failed - sending boxid failed");
895        return ERROR;
896    }
897
898    int d37423_ok = 0;
899    static const uint8_t ins7403[5] = { 0xD0, 0x74, 0x03, 0x00, 0x00 }; // taken from v13 boot log
900    if(do_cmd(reader, ins7403, NULL, NULL, cta_res) < 0)
901    {
902        rdr_log(reader, "classD0 ins7403: failed");
903    }
904    else
905    {
906        d37423_ok = (cta_res[2] >> 5) & 1;
907    }
908
909    if(reader->ins7E11[0x01]) // the position of the ins7E is taken from v13 log
910    {
911        uint8_t ins742b[5] = { 0xD0, 0x74, 0x2b, 0x00, 0x00 };
912        l = read_cmd_len(reader, ins742b); // get command len for ins742b
913
914        if(l < 2)
915        {
916            rdr_log(reader, "No TA1 change for this card is possible by ins7E11");
917        }
918        else
919        {
920            ins742b[4] = l;
921            bool ta1ok = 0;
922            if(!write_cmd_vg(ins742b, NULL) || !status_ok(cta_res + ins742b[4])) // get supported TA1 bytes
923            {
924                rdr_log(reader, "classD0 ins742b: failed");
925                return ERROR;
926            }
927            else
928            {
929                int32_t i;
930                for(i = 2; i < l; i++)
931                {
932                    if(cta_res[i] == reader->ins7E11[0x00])
933                    {
934                        ta1ok = 1;
935                        break;
936                    }
937                }
938            }
939
940            if(ta1ok == 0)
941            {
942                rdr_log(reader, "The value %02X of ins7E11 is not supported,try one between %02X and %02X",
943                        reader->ins7E11[0x00], cta_res[2], cta_res[ins742b[4] - 1]);
944            }
945            else
946            {
947                static const uint8_t ins7E11[5] = { 0xD0, 0x7E, 0x11, 0x00, 0x01 };
948                reader->ins7e11_fast_reset = 0;
949                l = do_cmd(reader, ins7E11, reader->ins7E11, NULL, cta_res);
950
951                if(l < 0 || !status_ok(cta_res))
952                {
953                    rdr_log(reader, "classD0 ins7E11: failed");
954                    return ERROR;
955                }
956                else
957                {
958                    uint8_t TA1;
959                    if(ATR_GetInterfaceByte(newatr, 1, ATR_INTERFACE_BYTE_TA, &TA1) == ATR_OK)
960                    {
961                        if(TA1 != reader->ins7E11[0x00])
962                        {
963                            rdr_log(reader, "classD0 ins7E11: Scheduling card reset for TA1 change from %02X to %02X", TA1, reader->ins7E11[0x00]);
964                            reader->ins7e11_fast_reset = 1;
965
966#if defined(WITH_COOLAPI) || defined(WITH_COOLAPI2)
967                            if(reader->typ == R_MOUSE || reader->typ == R_SC8in1 || reader->typ == R_SMART || reader->typ == R_INTERNAL)
968                            {
969#else
970                            if(reader->typ == R_MOUSE || reader->typ == R_SC8in1 || reader->typ == R_SMART)
971                            {
972#endif
973                                add_job(reader->client, ACTION_READER_RESET_FAST, NULL, 0);
974                            }
975                            else
976                            {
977                                add_job(reader->client, ACTION_READER_RESTART, NULL, 0);
978                            }
979                            return OK; // Skip the rest of the init since the card will be reset anyway
980                        }
981                    }
982                }
983            }
984        }
985    }
986
987    //int16_t int32_t SWIRDstatus = cta_res[1];
988    static const uint8_t ins58[5] = { 0xD0, 0x58, 0x00, 0x00, 0x00 };
989    l = do_cmd(reader, ins58, NULL, NULL, cta_res);
990
991    if(l < 0)
992    {
993        rdr_log(reader, "classD0 ins58: failed");
994        return ERROR;
995    }
996
997    memset(reader->hexserial, 0, 8);
998    memcpy(reader->hexserial + 2, cta_res + 3, 4);
999    memcpy(reader->sa, cta_res + 3, 3);
1000    reader->caid = cta_res[24] * 0x100 + cta_res[25];
1001    reader->VgFuse = cta_res[2];
1002    rdr_log(reader, "FuseByte: %02X", reader->VgFuse);
1003    memset(reader->VgRegionC, 0, 8);
1004    memcpy(reader->VgRegionC, cta_res + 60, 8);
1005
1006    rdr_log(reader, "Region Code: %c%c%c%c%c%c%c%c",
1007            reader->VgRegionC[0], reader->VgRegionC[1],
1008            reader->VgRegionC[2], reader->VgRegionC[3],
1009            reader->VgRegionC[4], reader->VgRegionC[5],
1010            reader->VgRegionC[6], reader->VgRegionC[7]);
1011
1012    memset(reader->VgCountryC, 0, 3);
1013    memcpy(reader->VgCountryC, cta_res + 55, 3);
1014    rdr_log(reader, "Country Code: %c%c%c", reader->VgCountryC[0], reader->VgCountryC[1], reader->VgCountryC[2]);
1015
1016    // we have one provider, 0x0000
1017    reader->nprov = 1;
1018    memset(reader->prid, 0x00, sizeof(reader->prid));
1019
1020    cCamCryptVG_SetSeed(reader);
1021
1022    static const uint8_t insB4[5] = { 0xD0, 0xB4, 0x00, 0x00, 0x40 };
1023    uint16_t tbuff[32];
1024    cCamCryptVG_GetCamKey(reader, tbuff);
1025    l = do_cmd(reader, insB4, (uint8_t *)tbuff, NULL, cta_res);
1026    if(l < 0 || !status_ok(cta_res))
1027    {
1028        rdr_log(reader, "classD0 insB4: failed");
1029        return ERROR;
1030    }
1031
1032    static const uint8_t insBC[5] = { 0xD0, 0xBC, 0x00, 0x00, 0x00 };
1033    l = do_cmd(reader, insBC, NULL, NULL, cta_res);
1034    if(l < 0)
1035    {
1036        rdr_log(reader, "classD0 insBC: failed");
1037        return ERROR;
1038    }
1039
1040    // Class D1/D3 instructions only work after this point
1041
1042    static const uint8_t insBE[5] = { 0xD3, 0xBE, 0x00, 0x00, 0x00 };
1043    l = do_cmd(reader, insBE, NULL, NULL, cta_res);
1044    if(l < 0)
1045    {
1046        rdr_log(reader, "classD3 insBE: failed");
1047        return ERROR;
1048    }
1049
1050    static const uint8_t ins58a[5] = { 0xD1, 0x58, 0x00, 0x00, 0x00 };
1051    l = do_cmd(reader, ins58a, NULL, NULL, cta_res);
1052    if(l < 0)
1053    {
1054        rdr_log(reader, "classD1 ins58: failed");
1055        return ERROR;
1056    }
1057
1058    // new ins74 present at boot
1059    if(d37423_ok) // from ins7403 answer
1060    {
1061        static const uint8_t ins7423[5] = { 0xD3, 0x74, 0x23, 0x00, 0x00 };
1062        if(do_cmd(reader, ins7423, NULL, NULL, cta_res) < 0)
1063        {
1064            rdr_log(reader, "classD1 ins7423: failed");
1065        }
1066    }
1067/*
1068    static const uint8_t ins742A[5] = { 0xD1, 0x74, 0x2A, 0x00, 0x00 };
1069    if(do_cmd(reader, ins742A, NULL, NULL, cta_res) < 0)
1070    {
1071        rdr_log(reader, "classD1 ins742A: failed");
1072    }
1073
1074    static const uint8_t ins741C[5] = { 0xD1, 0x74, 0x1C, 0x00, 0x00 };
1075    if(do_cmd(reader, ins741C, NULL, NULL, cta_res) < 0)
1076    {
1077        rdr_log(reader, "classD1 ins741C: failed");
1078    }
1079*/
1080    static const uint8_t ins4Ca[5] = { 0xD1, 0x4C, 0x00, 0x00, 0x00 };
1081
1082    payload4C[4] = 0x83;
1083
1084    l = do_cmd(reader, ins4Ca, payload4C, NULL, cta_res);
1085    if(l < 0 || !status_ok(cta_res))
1086    {
1087        rdr_log(reader, "classD1 ins4Ca: failed");
1088        return ERROR;
1089    }
1090    memcpy(reader->payload4C, payload4C, 0xF);
1091
1092    if(reader->ins7E[0x1A])
1093    {
1094        static const uint8_t ins7E[5] = { 0xD1, 0x7E, 0x10, 0x00, 0x1A };
1095        l = do_cmd(reader, ins7E, reader->ins7E, NULL, cta_res);
1096        if(l < 0 || !status_ok(cta_res))
1097        {
1098            rdr_log(reader, "classD1 ins7E: failed");
1099            return ERROR;
1100        }
1101    }
1102
1103    // get PIN settings
1104    static const uint8_t ins7411[5] = { 0xD1, 0x74, 0x11, 0x00, 0x00 };
1105    uint8_t payload2e4[4];
1106    if(do_cmd(reader, ins7411, NULL, NULL, cta_res) < 0)
1107    {
1108        rdr_log(reader, "classD1 ins7411: unable to get PIN");
1109        return ERROR;
1110    }
1111    else
1112    {
1113        memset(payload2e4, 0, 4);
1114        memcpy(payload2e4, cta_res + 2, 4);
1115        reader->VgPin = (cta_res[4] << 8) + cta_res[5];
1116        rdr_log(reader, "Pincode read: %04hu", reader->VgPin);
1117    }
1118
1119    // get PCB(content rating) settings
1120    static const uint8_t ins74e[5] = { 0xD1, 0x74, 0x0E, 0x00, 0x00 };
1121    if(do_cmd(reader, ins74e, NULL, NULL, cta_res) < 0)
1122    {
1123        rdr_log(reader, "classD1 ins74e: failed to get PCB settings");
1124    }
1125    else
1126    {
1127        rdr_log(reader, "PCB settings: %X %X %X %X", cta_res[2], cta_res[3], cta_res[4], cta_res[5]);
1128    }
1129
1130    // send PIN
1131    static const uint8_t ins2epin[5] = { 0xD1, 0x2E, 0x04, 0x00, 0x04 };
1132    if(cfg.ulparent)
1133    {
1134        l = do_cmd(reader, ins2epin, payload2e4, NULL, cta_res);
1135        if(l < 0 || !status_ok(cta_res))
1136        {
1137            rdr_log(reader, "classD1 ins2E: failed");
1138            rdr_log(reader, "Cannot disable parental control");
1139            return ERROR;
1140        }
1141        else
1142        {
1143            rdr_log(reader, "Parental control disabled");
1144        }
1145    }
1146
1147    // send check control for pin, needed on some cards
1148    // the presence and the value of payloads is provider's dependent*/
1149    if(reader->ins2e06[4])
1150    {
1151        static const uint8_t ins2e06[5] = { 0xD1, 0x2E, 0x06, 0x00, 0x04 };
1152        l = do_cmd(reader, ins2e06, reader->ins2e06, NULL, cta_res);
1153        if(l < 0 || !status_ok(cta_res))
1154        {
1155            rdr_log(reader, "classD1 ins2E: failed");
1156            return ERROR;
1157        }
1158    }
1159
1160    // fix for 09ac cards
1161    uint8_t dimeno_magic[0x10] = { 0xF9, 0xFB, 0xCD, 0x5A, 0x76, 0xB5, 0xC4, 0x5C,
1162                                   0xC8, 0x2E, 0x1D, 0xE1, 0xCC, 0x5B, 0x6B, 0x02 };
1163
1164    int32_t a;
1165    for(a = 0; a < 4; a++)
1166    {
1167        dimeno_magic[a] = dimeno_magic[a] ^ boxID[a];
1168    }
1169
1170    AES_set_decrypt_key(dimeno_magic, 128, &(csystem_data->astrokey));
1171
1172    rdr_log(reader, "type: %s, caid: %04X", csystem_data->card_desc, reader->caid);
1173    rdr_log_sensitive(reader, "serial: {%02X%02X%02X%02X}, BoxID: {%02X%02X%02X%02X}, baseyear: %i",
1174        reader->hexserial[2],
1175        reader->hexserial[3],
1176        reader->hexserial[4],
1177        reader->hexserial[5],
1178        boxID[0],
1179        boxID[1],
1180        boxID[2],
1181        boxID[3],
1182        csystem_data->card_baseyear);
1183
1184    rdr_log(reader, "ready for requests");
1185
1186    return OK;
1187}
1188
1189static int32_t videoguard2_do_ecm(struct s_reader *reader, const ECM_REQUEST *er, struct s_ecm_answer *ea)
1190{
1191    uint8_t cta_res[CTA_RES_LEN];
1192    static const char valid_ecm[] = { 0x00, 0x00, 0x01 };
1193    uint8_t ins40[5] = { 0xD1, 0x40, 0x00, 0x80, 0xFF };
1194    static const uint8_t ins54[5] = { 0xD3, 0x54, 0x00, 0x00, 0x00};
1195    int32_t posECMpart2 = er->ecm[6] + 7;
1196    int32_t lenECMpart2 = er->ecm[posECMpart2] + 1;
1197    uint8_t tbuff[264], rbuff[264];
1198    const uint8_t *EcmIrdHeader = er->ecm + 5;
1199    tbuff[0] = 0;
1200
1201    memset(ea->cw + 0, 0, 16); // set cw to 0 so client will know it is invalid unless it is overwritten with a valid cw
1202    int32_t chk;
1203    chk = checksum_ok(EcmIrdHeader);
1204
1205    if((memcmp(&(er->ecm[3]), valid_ecm, sizeof(valid_ecm)) != 0) || (chk == 0))
1206    {
1207        rdr_log(reader, "Not a valid ecm");
1208        return E_CORRUPT;
1209    }
1210    memcpy(tbuff + 1, er->ecm + posECMpart2 + 1, lenECMpart2 - 1);
1211
1212    int32_t new_len = lenECMpart2;
1213    if(reader->fix_9993 && reader->caid == 0x919 && tbuff[1] == 0x7F)
1214    {
1215        tbuff[1] = 0x47;
1216        tbuff[2] = 0x08;
1217        memmove(tbuff + 11, tbuff + 13, new_len - 11);
1218        new_len -= 2;
1219    }
1220
1221    ins40[4] = new_len;
1222    int32_t l;
1223    l = do_cmd(reader, ins40, tbuff, NULL, cta_res);
1224
1225    if(l < 0 || !status_ok(cta_res))
1226    {
1227        rdr_log(reader, "classD1 ins40: (%d) status not ok %02x %02x", l, cta_res[0], cta_res[1]);
1228        rdr_log(reader, "The card is not answering correctly! Restarting reader for safety");
1229        add_job(reader->client, ACTION_READER_RESTART, NULL, 0);
1230        return ERROR;
1231    }
1232    else
1233    {
1234        l = do_cmd(reader, ins54, NULL, rbuff, cta_res);
1235        if(l < 0 || !status_ok(cta_res + l))
1236        {
1237            rdr_log(reader, "classD3 ins54: (%d) status not ok %02x %02x", l, cta_res[0], cta_res[1]);
1238            rdr_log(reader, "The card is not answering correctly! Restarting reader for safety");
1239            add_job(reader->client, ACTION_READER_RESTART, NULL, 0);
1240            return ERROR;
1241        }
1242        else
1243        {
1244            struct videoguard_data *csystem_data = reader->csystem_data;
1245            uint8_t *payload = rbuff + 5;
1246            uint8_t buff_0F[6] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
1247            uint8_t buff_56[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
1248            uint8_t buff_55[1] = { 0x00 };
1249            uint8_t tag, t_len;
1250            uint8_t *t_body;
1251            int32_t payloadLen = rbuff[4];
1252            int32_t ind = 8 + 6; // +8 (CW1), +2 (cw checksum) + 2 (tier used) +2 (result byte)
1253
1254            while(ind < payloadLen)
1255            {
1256                tag = payload[ind];
1257                t_len = payload[ind + 1]; // len of the tag
1258                t_body = payload + ind + 2; // body of the tag
1259
1260                switch(tag)
1261                {
1262                    case 0x0F: // Debug ecm info
1263                        if(t_len > 6)
1264                        {
1265                            t_len = 6;
1266                        }
1267                        memcpy(buff_0F, t_body, t_len);
1268                        break;
1269
1270                    case 0x25: // CW2 tag
1271                        memcpy(ea->cw + 8, t_body +1, 8);
1272                        break;
1273
1274                    case 0x55: // cw crypt info tag
1275                        memcpy(buff_55, t_body, 1 );
1276                        break;
1277
1278                    case 0x56: // tag data for astro
1279                        memcpy(buff_56, t_body, 8);
1280                        break;
1281
1282                    default:
1283                        break;
1284                }
1285                ind += t_len + 2;
1286            }
1287
1288            if(12 < payloadLen)
1289            {
1290                ea->tier = b2i(2, &payload[10]);
1291            }
1292
1293            memcpy(reader->VgLastPayload, buff_0F, 6);
1294
1295            int32_t test_0F = 1;
1296            if(!cw_is_valid(rbuff + 5)) // sky cards report 90 00 = ok but send cw = 00 when something goes wrong :(
1297            {
1298                if(buff_0F[0] & 1) // case 0f_0x 01 xx xx xx xx xx
1299                {
1300                    rdr_log(reader, "classD3 ins54: no cw --> Bad/wrong ECM");
1301                    test_0F = 0;
1302                }
1303
1304                if(buff_0F[1] & 1) // case 0f_0x xx 01 xx xx xx xx
1305                {
1306                    rdr_log(reader, "classD3 ins54: no cw --> Card appears in error");
1307                    test_0F = 0;
1308                }
1309
1310                if((buff_0F[0] >> 1) & 1) // case 0f_0x 02 xx xx xx xx xx
1311                {
1312                    rdr_log(reader, "classD3 ins54: no cw --> Card isn't active");
1313                    test_0F = 0;
1314                }
1315                else // These Messages are only nessensary if the Card is active
1316                {
1317                    if((buff_0F[1] >> 4) & 1) // case 0f_0x xx 10 xx xx xx xx
1318                    {
1319                        rdr_log(reader, "classD3 ins54: no cw --> Card needs pairing/extra data");
1320                        if((reader->caid == 0x98C || reader->caid == 0x98D) && (buff_0F[5] == 0)){ //case 0f_0x xx 10 xx xx xx 00
1321                            rdr_log(reader, "classD3 ins54: no cw --> unassigned Boxid");
1322                        }
1323                        test_0F = 0;
1324                    }
1325
1326                    if((buff_0F[1] >> 5) & 1) // case 0f_0x xx 20 xx xx xx xx
1327                    {
1328                        rdr_log(reader, "classD3 ins54: no cw --> No tier found"); //check this
1329                        test_0F = 0;
1330                    }
1331
1332                    if((buff_0F[2] >> 5) & 1) // case 0f_0x xx xx 20 xx xx xx
1333                    {
1334                        rdr_log(reader, "classD3 ins54: no cw --> Tier expired");
1335                        test_0F = 0;
1336                    }
1337
1338                    if((buff_0F[1] >> 6) & 1) // case 0f_0x xx 40 xx xx xx xx
1339                    {
1340                        rdr_log(reader, "classD3 ins54: no cw --> Card needs pin");
1341                        test_0F = 0;
1342                    }
1343
1344                    if((reader->caid == 0x98C || reader->caid == 0x98D) && ((buff_0F[5] >> 3) & 1)) //case 0f_0x xx xx xx xx xx XX = binary xxxx1xxx
1345                    {
1346                        rdr_log(reader, "classD3 ins54: no cw --> CW-overcrypt%s is required! (Debug-ECM-Info: 0F_06 %02X %02X %02X %02X %02X %02X)",
1347                                (((buff_0F[5] >> 1) & 1) ? " (and assignment)" : ""), buff_0F[0], buff_0F[1], buff_0F[2], buff_0F[3], buff_0F[4], buff_0F[5]); //case 0f_0x xx xx xx xx xx XX = binary xxxx1x?x
1348                    }
1349                }
1350
1351                if(test_0F) // case unknown error
1352                {
1353                    rdr_log(reader, "classD3 ins54: status 90 00 = ok but cw=00 tag 0F: %02X %02X %02X %02X %02X %02X, please report to the developers with decrypted ins54",
1354                            buff_0F[0], buff_0F[1], buff_0F[2], buff_0F[3], buff_0F[4], buff_0F[5]);
1355                }
1356                return ERROR;
1357            }
1358
1359            // copy cw1 in place
1360            memcpy(ea->cw + 0, rbuff + 5, 8);
1361
1362            // case 55_01 xx where bit0==1, CW is crypted
1363            if(buff_55[0] & 1)
1364            {
1365                if((buff_55[0] >> 3) & 1) //case 55_01 xx where bit3==1, CW-Overcrypt may not required
1366                {
1367                    rdr_log_dbg(reader, D_READER, "classD3 ins54: Tag55_01 = %02X, CW-overcrypt may not required", buff_55[0]);
1368                }
1369                if(~((buff_55[0] >> 2) & 1)) //case 55_01 xx where bit2==0, no AES overcrypt
1370                {
1371                    if((buff_55[0] >> 1) & 1) //case 55_01 xx where bit1==1, unique Pairing
1372                    {
1373                        rdr_log_dbg(reader, D_READER, "classD3 ins54: CW is crypted, trying to decrypt unique pairing mode 0x%02X", buff_55[0]);
1374                        if(er->ecm[0] & 1){ //log crypted CW
1375                            rdr_log_dbg(reader, D_READER, "crypted CW is: 0000000000000000%02X%02X%02X%02X%02X%02X%02X%02X", ea->cw[0], ea->cw[1], ea->cw[2], ea->cw[3], ea->cw[4], ea->cw[5], ea->cw[6], ea->cw[7]);
1376                        } else {
1377                            rdr_log_dbg(reader, D_READER, "crypted CW is: %02X%02X%02X%02X%02X%02X%02X%02X0000000000000000", ea->cw[0], ea->cw[1], ea->cw[2], ea->cw[3], ea->cw[4], ea->cw[5], ea->cw[6], ea->cw[7]);
1378                        }
1379                        if((reader->k1_unique[16] == 0x08) || (reader->k1_unique[16] == 0x10)) //check k1 for unique pairing mode is DES(8 bytes) or 3DES(16 bytes) long
1380                        {
1381                            if(reader->k1_unique[16] == 0x08){
1382                                rdr_log_dbg(reader, D_READER, "use k1(DES) for CW decryption in unique pairing mode");
1383                                des_ecb_decrypt(ea->cw, reader->k1_unique, 0x08);
1384                            }
1385                            else
1386                            {
1387                                rdr_log_dbg(reader, D_READER, "use k1(3DES) for CW decryption in unique pairing mode");
1388                                des_ecb3_decrypt(ea->cw, reader->k1_unique);
1389                            }
1390                            if(er->ecm[0] & 1){ //log decrypted CW
1391                                rdr_log_dbg(reader, D_READER, "decrypted CW is: 0000000000000000%02X%02X%02X%02X%02X%02X%02X%02X", ea->cw[0], ea->cw[1], ea->cw[2], ea->cw[3], ea->cw[4], ea->cw[5], ea->cw[6], ea->cw[7]);
1392                            } else {
1393                                rdr_log_dbg(reader, D_READER, "decrypted CW is: %02X%02X%02X%02X%02X%02X%02X%02X0000000000000000", ea->cw[0], ea->cw[1], ea->cw[2], ea->cw[3], ea->cw[4], ea->cw[5], ea->cw[6], ea->cw[7]);
1394                            }
1395                        }
1396                        else
1397                        {
1398                            rdr_log_dbg(reader, D_READER, "k1 for unique pairing mode is not set");
1399                            return ERROR;
1400                        }
1401                    }
1402                    else //case 55_01 xx where bit1==0, generic Pairing
1403                    {
1404                        rdr_log_dbg(reader, D_READER, "classD3 ins54: CW is crypted, trying to decrypt generic pairing mode 0x%02X", buff_55[0]);
1405                        if(er->ecm[0] & 1){ //log crypted CW
1406                            rdr_log_dbg(reader, D_READER, "crypted CW is: 0000000000000000%02X%02X%02X%02X%02X%02X%02X%02X", ea->cw[0], ea->cw[1], ea->cw[2], ea->cw[3], ea->cw[4], ea->cw[5], ea->cw[6], ea->cw[7]);
1407                        } else {
1408                            rdr_log_dbg(reader, D_READER, "crypted CW is: %02X%02X%02X%02X%02X%02X%02X%02X0000000000000000", ea->cw[0], ea->cw[1], ea->cw[2], ea->cw[3], ea->cw[4], ea->cw[5], ea->cw[6], ea->cw[7]);
1409                        }
1410                        if((reader->k1_generic[16] == 0x08) || (reader->k1_generic[16] == 0x10)) //check k1 for generic pairing mode is DES(8 bytes) or 3DES(16 bytes) long
1411                        {
1412                            if(reader->k1_generic[16] == 0x08){
1413                                rdr_log_dbg(reader, D_READER, "use k1(DES) for CW decryption in generic pairing mode");
1414                                des_ecb_decrypt(ea->cw, reader->k1_generic, 0x08);
1415                            }
1416                            else
1417                            {
1418                                rdr_log_dbg(reader, D_READER, "use k1(3DES) for CW decryption in generic pairing mode");
1419                                des_ecb3_decrypt(ea->cw, reader->k1_generic);
1420                            }
1421                            if(er->ecm[0] & 1){ //log decrypted CW
1422                                rdr_log_dbg(reader, D_READER, "decrypted CW is: 0000000000000000%02X%02X%02X%02X%02X%02X%02X%02X", ea->cw[0], ea->cw[1], ea->cw[2], ea->cw[3], ea->cw[4], ea->cw[5], ea->cw[6], ea->cw[7]);
1423                            } else {
1424                                rdr_log_dbg(reader, D_READER, "decrypted CW is: %02X%02X%02X%02X%02X%02X%02X%02X0000000000000000", ea->cw[0], ea->cw[1], ea->cw[2], ea->cw[3], ea->cw[4], ea->cw[5], ea->cw[6], ea->cw[7]);
1425                            }
1426                        }
1427                        else
1428                        {
1429                            rdr_log_dbg(reader, D_READER, "k1 for generic pairing mode is not set");
1430                            return ERROR;
1431                        }
1432                    }
1433                }
1434                else //unkown pairing mode or AES overcrypt
1435                {
1436                    rdr_log_dbg(reader, D_READER, "classD3 ins54: CW is crypted, unknown pairing mode 0x%02X, AES overcrypt?", buff_55[0]);
1437                    if(er->ecm[0] & 1){ //log crypted CW
1438                        rdr_log_dbg(reader, D_READER, "crypted CW is: 0000000000000000%02X%02X%02X%02X%02X%02X%02X%02X", ea->cw[0], ea->cw[1], ea->cw[2], ea->cw[3], ea->cw[4], ea->cw[5], ea->cw[6], ea->cw[7]);
1439                    } else {
1440                        rdr_log_dbg(reader, D_READER, "crypted CW is: %02X%02X%02X%02X%02X%02X%02X%02X0000000000000000", ea->cw[0], ea->cw[1], ea->cw[2], ea->cw[3], ea->cw[4], ea->cw[5], ea->cw[6], ea->cw[7]);
1441                    }
1442                    return ERROR;
1443                }
1444            }
1445
1446            // case 55_01 xx where bit2==1, old dimeno_PostProcess_Decrypt(reader, rbuff, ea->cw);
1447            if((buff_55[0] >> 2) & 1)
1448            {
1449                uint8_t buffer[0x10];
1450                memcpy(buffer, rbuff + 5, 8);
1451                memcpy(buffer + 8, buff_56, 8);
1452                AES_decrypt(buffer, buffer, &(csystem_data->astrokey));
1453                memcpy(ea->cw + 0, buffer, 8); // copy calculated CW in right place
1454            }
1455
1456            if(new_len != lenECMpart2)
1457            {
1458                memcpy(ea->cw, ea->cw + 8, 8);
1459                memset(ea->cw + 8, 0, 8);
1460            }
1461
1462            // test for postprocessing marker
1463            int32_t posB0 = -1;
1464            int32_t i;
1465            for(i = 6; i < posECMpart2; i++)
1466            {
1467                if(er->ecm[i - 3] == 0x80 && er->ecm[i] == 0xB0 && ((er->ecm[i + 1] == 0x01) || (er->ecm[i + 1] == 0x02) || (er->ecm[i + 1] == 0x03)))
1468                {
1469                    posB0 = i;
1470                    break;
1471                }
1472            }
1473
1474            if(posB0 != -1 && (reader->caid == 0x919 || reader->caid == 0x93B || reader->caid == 0x9CD || reader->caid == 0x9C1))
1475            {
1476                do_post_dw_hash(reader, ea->cw + 0, &er->ecm[posB0 - 2]);
1477                do_post_dw_hash(reader, ea->cw + 8, &er->ecm[posB0 - 2]);
1478            }
1479
1480            if(reader->caid == 0x0907) // quickfix: cw2 is not a valid cw, something went wrong before
1481            {
1482                memset(ea->cw + 8, 0, 8);
1483                if(er->ecm[0] & 1)
1484                {
1485                    memcpy(ea->cw + 8, ea->cw, 8);
1486                    memset(ea->cw, 0, 8);
1487                }
1488            }
1489            else
1490            {
1491                if(er->ecm[0] & 1)
1492                {
1493                    uint8_t tmpcw[8];
1494                    memcpy(tmpcw, ea->cw + 8, 8);
1495                    memcpy(ea->cw + 8, ea->cw + 0, 8);
1496                    memcpy(ea->cw + 0, tmpcw, 8);
1497                }
1498            }
1499
1500            return OK;
1501        }
1502    }
1503}
1504
1505static int32_t videoguard2_do_emm(struct s_reader *reader, EMM_PACKET *ep)
1506{
1507    return videoguard_do_emm(reader, ep, 0xD1, vg2_read_tiers, do_cmd);
1508}
1509
1510static int32_t videoguard2_card_info(struct s_reader *reader)
1511{
1512    // info is displayed in init, or when processing info
1513    struct videoguard_data *csystem_data = reader->csystem_data;
1514    rdr_log(reader, "card detected");
1515    rdr_log(reader, "type: %s", csystem_data->card_desc);
1516
1517    if(reader->ins7e11_fast_reset != 1)
1518    {
1519        vg2_read_tiers(reader);
1520    }
1521    return OK;
1522}
1523
1524static void videoguard2_card_done(struct s_reader *reader)
1525{
1526    struct videoguard_data *csystem_data = reader->csystem_data;
1527    if(csystem_data)
1528    {
1529        NULLFREE(csystem_data->cmd_table);
1530    }
1531}
1532
1533const struct s_cardsystem reader_videoguard2 =
1534{
1535    .desc           = "videoguard2",
1536    .caids          = (uint16_t[]){ 0x09, 0 },
1537    .do_emm         = videoguard2_do_emm,
1538    .do_ecm         = videoguard2_do_ecm,
1539    .card_info      = videoguard2_card_info,
1540    .card_init      = videoguard2_card_init,
1541    .poll_status    = videoguard2_poll_status,
1542    .card_done      = videoguard2_card_done,
1543    .get_emm_type   = videoguard_get_emm_type,
1544    .get_emm_filter = videoguard_get_emm_filter,
1545};
1546
1547#endif
Note: See TracBrowser for help on using the repository browser.