source: trunk/reader-videoguard2.c @ 8960

Last change on this file since 8960 was 8960, checked in by Gorgone Impertinence, 6 years ago

revert 8951 & 8952
sorry for this !

  • Property svn:eol-style set to LF
File size: 28.5 KB
Line 
1#include "globals.h"
2#ifdef READER_VIDEOGUARD
3#include "cscrypt/md5.h"
4#include "oscam-work.h"
5#include "reader-common.h"
6#include "reader-videoguard-common.h"
7
8static void dimeno_PostProcess_Decrypt(struct s_reader *reader, unsigned char *rxbuff, unsigned char *cw)
9{
10    struct videoguard_data *csystem_data = reader->csystem_data;
11    unsigned char tag, len, len2;
12    bool valid_0x55 = 0;
13    unsigned char *body;
14    unsigned char buffer[0x10];
15    int32_t a = 0x13;
16    len2 = rxbuff[4];
17    while(a < len2 + 5 - 9)  //  +5 for 5 ins bytes, -9 (body=8 len=1) to prevent memcpy(buffer+8,body,8) from reading past rxbuff
18    {
19        tag = rxbuff[a];
20        len = rxbuff[a + 1];
21        body = rxbuff + a + 2;
22        switch(tag)
23        {
24        case 0x55:
25        {
26            if(body[0] == 0x84)     //Tag 0x56 has valid data...
27            {
28                valid_0x55 = 1;
29            }
30        }
31        break;
32        case 0x56:
33        {
34            memcpy(buffer + 8, body, 8);
35        }
36        break;
37        }
38        a += len + 2;
39    }
40    if(valid_0x55)
41    {
42        memcpy(buffer, rxbuff + 5, 8);
43        AES_decrypt(buffer, buffer, &(csystem_data->astrokey));
44        memcpy(cw + 0, buffer, 8);  // copy calculated CW in right place
45    }
46}
47
48static void do_post_dw_hash(struct s_reader *reader, unsigned char *cw, const unsigned char *ecm_header_data)
49{
50    int32_t i, ecmi, ecm_header_count;
51    unsigned char buffer[0x85]; //original 0x80 but with 0x7D mask applied +8 bytes cw it was still to small
52    unsigned char md5tmp[MD5_DIGEST_LENGTH];
53    static const uint16_t Hash3[] = {0x0123, 0x4567, 0x89AB, 0xCDEF, 0xF861, 0xCB52};
54    static const unsigned char Hash4[] = {0x0B, 0x04, 0x07, 0x08, 0x05, 0x09, 0x0B, 0x0A, 0x07, 0x02, 0x0A, 0x05, 0x04, 0x08, 0x0D, 0x0F};
55    static const uint16_t NdTabB001[0x15][0x20] =
56    {
57        {
58            0xEAF1, 0x0237, 0x29D0, 0xBAD2, 0xE9D3, 0x8BAE, 0x2D6D, 0xCD1B,
59            0x538D, 0xDE6B, 0xA634, 0xF81A, 0x18B5, 0x5087, 0x14EA, 0x672E,
60            0xF0FC, 0x055E, 0x62E5, 0xB78F, 0x5D09, 0x0003, 0xE4E8, 0x2DCE,
61            0x6BE0, 0xAC4E, 0xF485, 0x6967, 0xF28C, 0x97A0, 0x01EF, 0x0100
62        },
63        {
64            0xC539, 0xF5B9, 0x9099, 0x013A, 0xD4B9, 0x6AB5, 0xEA67, 0x7EB4,
65            0x6C30, 0x4BF0, 0xB810, 0xB0B5, 0xB76D, 0xA751, 0x1AE7, 0x14CA,
66            0x4F4F, 0x1586, 0x2608, 0x10B1, 0xE7E1, 0x48BE, 0x7DDD, 0x5ECB,
67            0xCFBF, 0x323B, 0x8B31, 0xB131, 0x0F1A, 0x664B, 0x0140, 0x0100
68        },
69        {
70            0x3C7D, 0xBDC4, 0xFEC7, 0x26A6, 0xB0A0, 0x6E55, 0xF710, 0xF9BF,
71            0x0023, 0xE81F, 0x41CA, 0xBE32, 0xB461, 0xE92D, 0xF1AF, 0x409F,
72            0xFC85, 0xFE5B, 0x7FCE, 0x17F5, 0x01AB, 0x4A46, 0xEB05, 0xA251,
73            0xDC6F, 0xF0C0, 0x10F0, 0x1D51, 0xEFAA, 0xE9BF, 0x0100, 0x0100
74        },
75        {
76            0x1819, 0x0CAA, 0x9067, 0x607A, 0x7576, 0x1CBC, 0xE51D, 0xBF77,
77            0x7EC6, 0x839E, 0xB695, 0xF096, 0xDC10, 0xCB69, 0x4654, 0x8E68,
78            0xD62D, 0x4F1A, 0x4227, 0x92AC, 0x9064, 0x6BD1, 0x1E75, 0x2747,
79            0x00DA, 0xA6A6, 0x6CF1, 0xD151, 0xBE56, 0x3E33, 0x0128, 0x0100
80        },
81        {
82            0x4091, 0x09ED, 0xD494, 0x6054, 0x1869, 0x71D5, 0xB572, 0x7BF1,
83            0xE925, 0xEE2D, 0xEEDE, 0xA13C, 0x6613, 0x9BAB, 0x122D, 0x7AE4,
84            0x5268, 0xE6C9, 0x50CB, 0x79A1, 0xF212, 0xA062, 0x6B48, 0x70B3,
85            0xF6B0, 0x06D5, 0xF8AB, 0xECF5, 0x6255, 0xEDD8, 0x79D2, 0x290A
86        },
87        {
88            0xD3CF, 0x014E, 0xACB3, 0x8F6B, 0x0F2C, 0xA5D8, 0xE8E0, 0x863D,
89            0x80D5, 0x5705, 0x658A, 0x8BC2, 0xEE46, 0xD3AE, 0x0199, 0x0100,
90            0x4A35, 0xABE4, 0xF976, 0x935A, 0xA8A5, 0xBAE9, 0x24D0, 0x71AA,
91            0xB3FE, 0x095E, 0xAB06, 0x4CD5, 0x2F0D, 0x1ACB, 0x59F3, 0x4C50
92        },
93        {
94            0xFD27, 0x0F8E, 0x191A, 0xEEE7, 0x2F49, 0x3A05, 0x3267, 0x4F88,
95            0x38AE, 0xFCE9, 0x9476, 0x18C6, 0xF961, 0x4EF0, 0x39D0, 0x42E6,
96            0xB747, 0xE625, 0xB68E, 0x5100, 0xF92A, 0x86FE, 0xE79B, 0xEE91,
97            0x21D5, 0x4C3C, 0x683D, 0x5AD1, 0x1B49, 0xF407, 0x0194, 0x0100
98        },
99        {
100            0x4BF9, 0xDC0D, 0x9478, 0x5174, 0xCB4A, 0x8A89, 0x4D6A, 0xFED8,
101            0xF123, 0xA8CD, 0xEEE7, 0xA6D1, 0xB763, 0xF5E2, 0xE085, 0x01EF,
102            0xE466, 0x9FA3, 0x2F68, 0x2190, 0x423F, 0x287F, 0x7F3F, 0x09F6,
103            0x2111, 0xA963, 0xD0BB, 0x674A, 0xBA72, 0x45F9, 0xF186, 0xB8F5
104        },
105        {
106            0x0010, 0xD1B9, 0xB164, 0x9E87, 0x1F49, 0x6950, 0x2DBF, 0x38D3,
107            0x2EB0, 0x3E8E, 0x91E6, 0xF688, 0x7E41, 0x566E, 0x01B0, 0x0100,
108            0x24A1, 0x73D8, 0xA0C3, 0xF71B, 0xA0A5, 0x2A06, 0xBA46, 0xFEC3,
109            0xDD4C, 0x52CC, 0xF9BC, 0x3B7E, 0x3812, 0x0666, 0xB74B, 0x40F8
110        },
111        {
112            0x28F2, 0x7C81, 0xFC92, 0x6FBD, 0x53D6, 0x72A3, 0xBBDF, 0xB6FC,
113            0x9CE5, 0x2331, 0xD4F6, 0xC5BB, 0xE8BB, 0x6676, 0x02D9, 0x2F0E,
114            0xD009, 0xD136, 0xCD09, 0x7551, 0x1826, 0x9D9B, 0x63EA, 0xFC63,
115            0x68CD, 0x3672, 0xCB95, 0xD28E, 0xF1CD, 0x20CA, 0x014C, 0x0100
116        },
117        {
118            0xE539, 0x55B7, 0x989D, 0x21C4, 0x463A, 0xE68F, 0xF8B5, 0xE5C5,
119            0x662B, 0x35BF, 0x3C50, 0x0131, 0xF4BF, 0x38B2, 0x41BC, 0xB829,
120            0x02B7, 0x6B8F, 0xA25C, 0xAFD2, 0xD84A, 0x2243, 0x53EB, 0xC6C9,
121            0x2E14, 0x181F, 0x8F96, 0xDF0E, 0x0D4C, 0x30F6, 0xFFE1, 0x9DDA
122        },
123        {
124            0x30B6, 0x777E, 0xDA3D, 0xAF77, 0x205E, 0xC90B, 0x856B, 0xB451,
125            0x3BCC, 0x76C2, 0x8ACF, 0xDCB1, 0xA5E5, 0xDD64, 0x0197, 0x0100,
126            0xE751, 0xB661, 0x0404, 0xDB4A, 0xE9DD, 0xA400, 0xAF26, 0x3F5E,
127            0x904B, 0xA924, 0x09E0, 0xE72B, 0x825B, 0x2C50, 0x6FD0, 0x0D52
128        },
129        {
130            0x2730, 0xC2BA, 0x9E44, 0x5815, 0xFC47, 0xB21D, 0x67B8, 0xF8B9,
131            0x047D, 0xB0AF, 0x9F14, 0x741B, 0x4668, 0xBE54, 0xDE16, 0xDB14,
132            0x7CB7, 0xF2B8, 0x0683, 0x762C, 0x09A0, 0x9507, 0x7F92, 0x022C,
133            0xBA6A, 0x7D52, 0x0AF4, 0x1BC3, 0xB46A, 0xC4FD, 0x01C2, 0x0100
134        },
135        {
136            0x7611, 0x66F3, 0xEE87, 0xEDD3, 0xC559, 0xEFD4, 0xDC59, 0xF86B,
137            0x6D1C, 0x1C85, 0x9BB1, 0x3373, 0x763F, 0x4EBE, 0x1BF3, 0x99B5,
138            0xD721, 0x978F, 0xCF5C, 0xAC51, 0x0984, 0x7462, 0x8F0C, 0x2817,
139            0x4AD9, 0xFD41, 0x6678, 0x7C85, 0xD330, 0xC9F8, 0x1D9A, 0xC622
140        },
141        {
142            0x5AE4, 0xE16A, 0x60F6, 0xFD45, 0x668C, 0x29D6, 0x0285, 0x6B92,
143            0x92C2, 0x21DE, 0x45E0, 0xEF3D, 0x8B0D, 0x02CD, 0x0198, 0x0100,
144            0x9E6D, 0x4D38, 0xDEF9, 0xE6F2, 0xF72E, 0xB313, 0x14F2, 0x390A,
145            0x2D67, 0xC71E, 0xCB69, 0x7F66, 0xD3CF, 0x7F8A, 0x81D9, 0x9DDE
146        },
147        {
148            0x85E3, 0x8F29, 0x36EB, 0xC968, 0x3696, 0x59F6, 0x7832, 0xA78B,
149            0xA1D8, 0xF5CF, 0xAB64, 0x646D, 0x7A2A, 0xBAF8, 0xAA87, 0x41C7,
150            0x5120, 0xDE78, 0x738D, 0xDC1A, 0x268D, 0x5DF8, 0xED69, 0x1C8A,
151            0xBC85, 0x3DCD, 0xAE30, 0x0F8D, 0xEC89, 0x3ABD, 0x0166, 0x0100
152        },
153        {
154            0xB8BD, 0x643B, 0x748E, 0xBD63, 0xEC6F, 0xE23A, 0x9493, 0xDD76,
155            0x0A62, 0x774F, 0xCD68, 0xA67A, 0x9A23, 0xC8A8, 0xBDE5, 0x9D1B,
156            0x2B86, 0x8B36, 0x5428, 0x1DFB, 0xCD1D, 0x0713, 0x29C2, 0x8E8E,
157            0x5207, 0xA13F, 0x6005, 0x4F5E, 0x52E0, 0xE7C8, 0x6D1C, 0x3E34
158        },
159        {
160            0x581D, 0x2BFA, 0x5E1D, 0xA891, 0x1069, 0x1DA4, 0x39A0, 0xBE45,
161            0x5B9A, 0x7333, 0x6F3E, 0x8637, 0xA550, 0xC9E9, 0x5C6C, 0x42BA,
162            0xA712, 0xC3EA, 0x3808, 0x0910, 0xAA4D, 0x5B25, 0xABCD, 0xE680,
163            0x96AD, 0x2CEC, 0x8EBB, 0xA47D, 0x1690, 0xE8FB, 0x01C8, 0x0100
164        },
165        {
166            0x73B9, 0x82BC, 0x9EBC, 0xB130, 0x0DA5, 0x8617, 0x9F7B, 0x9766,
167            0x205D, 0x752D, 0xB05C, 0x2A17, 0xA75C, 0x18EF, 0x8339, 0xFD34,
168            0x8DA2, 0x7970, 0xD0B4, 0x70F1, 0x3765, 0x7380, 0x7CAF, 0x570E,
169            0x6440, 0xBC44, 0x0743, 0x2D02, 0x0419, 0xA240, 0x2113, 0x1AD4
170        },
171        {
172            0x1EB5, 0xBBFF, 0x39B1, 0x3209, 0x705F, 0x15F4, 0xD7AD, 0x340B,
173            0xC2A6, 0x25CA, 0xF412, 0x9570, 0x0F4F, 0xE4D5, 0x1614, 0xE464,
174            0x911A, 0x0F0E, 0x07DA, 0xA929, 0x2379, 0xD988, 0x0AA6, 0x3B57,
175            0xBF63, 0x71FB, 0x72D5, 0x26CE, 0xB0AF, 0xCF45, 0x011B, 0x0100
176        },
177        {
178            0x9999, 0x98FE, 0xA108, 0x6588, 0xF90B, 0x4554, 0xFF38, 0x4642,
179            0x8F5F, 0x6CC3, 0x4E8E, 0xFF7E, 0x64C2, 0x50CA, 0x0E7F, 0xAD7D,
180            0x6AAB, 0x33C1, 0xE1F4, 0x6165, 0x7894, 0x83B9, 0x0A0C, 0x38AF,
181            0x5803, 0x18C0, 0xFA36, 0x592C, 0x4548, 0xABB8, 0x1527, 0xAEE9
182        }
183    };
184
185
186    //ecm_header_data = 01 03 b0 01 01
187    if(!cw_is_valid(cw))          //if cw is all zero, keep it that way
188    {
189        return;
190    }
191    ecm_header_count = ecm_header_data[0];
192    for(i = 0, ecmi = 1; i < ecm_header_count; i++)
193    {
194        if(ecm_header_data[ecmi + 1] != 0xb0)
195        {
196            ecmi += ecm_header_data[ecmi] + 1;
197        }
198        else
199        {
200            switch(ecm_header_data[ecmi + 2])
201            {
202                //b0 01
203            case 1:
204            {
205                uint16_t hk[8], r, j, m = 0;
206                for(r = 0; r < 6; r++)
207                    { hk[2 + r] = Hash3[r]; }
208                for(r = 0; r < 2; r++)
209                {
210                    for(j = 0; j < 0x48; j += 2)
211                    {
212                        if(r)
213                        {
214                            hk[0] = ((hk[3] & hk[5]) | ((~hk[5]) & hk[4]));
215                        }
216                        else
217                        {
218                            hk[0] = ((hk[3] & hk[4]) | ((~hk[3]) & hk[5]));
219                        }
220                        if(j < 8)
221                        {
222                            hk[0] = (hk[0] + ((cw[j + 1] << 8) | cw[j]));
223                        }
224                        if(j == 8)
225                        {
226                            hk[0] = (hk[0] + 0x80);
227                        }
228                        hk[0] = (hk[0] + hk[2] + (0xFF & NdTabB001[ecm_header_data[ecmi + 3]][m >> 1] >> ((m & 1) << 3)));
229                        hk[1] = hk[2];
230                        hk[2] = hk[3];
231                        hk[3] = hk[4];
232                        hk[4] = hk[5];
233                        hk[5] = hk[6];
234                        hk[6] = hk[7];
235                        hk[7] = hk[2] + (((hk[0] << Hash4[m & 0xF]) | (hk[0] >> (0x10 - Hash4[m & 0xF]))));
236                        m = (m + 1) & 0x3F;
237                    }
238                }
239                for(r = 0; r < 6; r++)
240                {
241                    hk[2 + r] += Hash3[r];
242                }
243                for(r = 0; r < 7; r++)
244                {
245                    cw[r] = hk[2 + (r >> 1)] >> ((r & 1) << 3);
246                }
247                cw[3] = (cw[0] + cw[1] + cw[2]) & 0xFF;
248                cw[7] = (cw[4] + cw[5] + cw[6]) & 0xFF;
249                rdr_ddump_mask(reader, D_READER, cw, 8, "Postprocessed Case 1 DW:");
250                break;
251            }
252            case 3:
253            {
254                memset(buffer, 0, sizeof(buffer));
255                memcpy(buffer, cw, 8);
256                memcpy(buffer + 8, &ecm_header_data[ecmi + 3], ecm_header_data[ecmi] & 0x7D);
257                MD5(buffer, 8 + (ecm_header_data[ecmi] & 0x7D), md5tmp);
258                memcpy(cw, md5tmp, 8);
259                rdr_ddump_mask(reader, D_READER, cw, 8, "Postprocessed Case 3 DW:");
260                break;
261            }
262            case 2:
263            {
264                /* Method 2 left out */
265                //memcpy(DW_OUTPUT, DW_INPUT, 8);
266                break;
267            }
268            }
269        }
270    }
271}
272
273
274static void vg2_read_tiers(struct s_reader *reader)
275{
276    def_resp;
277    int32_t l;
278
279    /* ins2a is not needed and causes an error on some cards eg Sky Italy 09CD
280       check if ins2a is in command table before running it
281    */
282    static const unsigned char ins2a[5] = { 0xD0, 0x2a, 0x00, 0x00, 0x00 };
283    if(cmd_exists(reader, ins2a))
284    {
285        l = do_cmd(reader, ins2a, NULL, NULL, cta_res);
286        if(l < 0 || !status_ok(cta_res + l))
287        {
288            rdr_log(reader, "classD0 ins2a: failed");
289            return;
290        }
291    }
292
293    static const unsigned char ins76007f[5] = { 0xD0, 0x76, 0x00, 0x7f, 0x02 };
294    if(!write_cmd_vg(ins76007f, NULL) || !status_ok(cta_res + 2))
295    {
296        rdr_log(reader, "classD0 ins76007f: failed");
297        return;
298    }
299    int32_t num = cta_res[1];
300
301    int32_t i;
302    unsigned char ins76[5] = { 0xD0, 0x76, 0x00, 0x00, 0x00 };
303    struct videoguard_data *csystem_data = reader->csystem_data;
304
305    // some cards start real tiers info in middle of tier info
306    // and have blank tiers between old tiers and real tiers eg 09AC
307    int32_t starttier = csystem_data->card_tierstart;
308    bool stopemptytier = 1;
309    if(!starttier)
310        { stopemptytier = 0; }
311
312    // check to see if specified start tier is blank and if blank, start at 0 and ignore blank tiers
313    ins76[2] = starttier;
314    l = do_cmd(reader, ins76, NULL, NULL, cta_res);
315    if(l < 0 || !status_ok(cta_res + l)) { return; }
316    if(cta_res[2] == 0 && cta_res[3] == 0)
317    {
318        stopemptytier = 0;
319        starttier = 0;
320    }
321
322    cs_clear_entitlement(reader); // reset the entitlements
323
324    for(i = starttier; i < num; i++)
325    {
326        ins76[2] = i;
327        l = do_cmd(reader, ins76, NULL, NULL, cta_res);
328        if(l < 0 || !status_ok(cta_res + l)) { return; }
329        if(cta_res[2] == 0 && cta_res[3] == 0 && stopemptytier) { return; }
330        if(cta_res[2] != 0 || cta_res[3] != 0)
331        {
332            char tiername[83];
333            uint16_t tier_id = (cta_res[2] << 8) | cta_res[3];
334            // add entitlements to list
335            struct tm timeinfo;
336            memset(&timeinfo, 0, sizeof(struct tm));
337            rev_date_calc_tm(&cta_res[4], &timeinfo, csystem_data->card_baseyear);
338            cs_add_entitlement(reader, reader->caid, b2ll(4, reader->prid[0]), tier_id, 0, 0, mktime(&timeinfo), 4);
339
340            if(!stopemptytier)
341            {
342                rdr_debug_mask(reader, D_READER, "tier: %04x, tier-number: 0x%02x", tier_id, i);
343            }
344            rdr_log(reader, "tier: %04x, expiry date: %04d/%02d/%02d-%02d:%02d:%02d %s", tier_id, timeinfo.tm_year + 1900, timeinfo.tm_mon + 1, timeinfo.tm_mday, timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec, get_tiername(tier_id, reader->caid, tiername));
345        }
346    }
347}
348
349static int32_t videoguard2_card_init(struct s_reader *reader, ATR *newatr)
350{
351    get_hist;
352    if((hist_size < 7) || (hist[1] != 0xB0) || (hist[4] != 0xFF) || (hist[5] != 0x4A) || (hist[6] != 0x50))
353    {
354        rdr_debug_mask(reader, D_READER, "failed history check");
355        return ERROR;
356    }
357    rdr_debug_mask(reader, D_READER, "passed history check");
358
359    get_atr;
360    def_resp;
361
362    if(!cs_malloc(&reader->csystem_data, sizeof(struct videoguard_data)))
363        { return ERROR; }
364    struct videoguard_data *csystem_data = reader->csystem_data;
365
366    /* set information on the card stored in reader-videoguard-common.c */
367    set_known_card_info(reader, atr, &atr_size);
368
369    if((reader->ndsversion != NDS2) &&
370            (((csystem_data->card_system_version != NDS2) && (csystem_data->card_system_version != NDSUNKNOWN)) ||
371             (reader->ndsversion != NDSAUTO)))
372    {
373        /* known ATR and not NDS2
374           or known NDS2 ATR and forced to another NDS version */
375        return ERROR;
376    }
377
378    rdr_debug_mask(reader, D_READER, "type: %s, baseyear: %i", csystem_data->card_desc, csystem_data->card_baseyear);
379    if(reader->ndsversion == NDS2)
380    {
381        rdr_debug_mask(reader, D_READER, "forced to NDS2");
382    }
383
384    //a non videoguard2/NDS2 card will fail on read_cmd_len(ins7401)
385    //this way unknown videoguard2/NDS2 cards will also pass this check
386
387    unsigned char ins7401[5] = { 0xD0, 0x74, 0x01, 0x00, 0x00 };
388    int32_t l;
389    if((l = read_cmd_len(reader, ins7401)) < 0)  //not a videoguard2/NDS card or communication error
390    {
391        return ERROR;
392    }
393    ins7401[4] = l;
394    if(!write_cmd_vg(ins7401, NULL) || !status_ok(cta_res + l))
395    {
396        rdr_log(reader, "classD0 ins7401: failed - cmd list not read");
397        return ERROR;
398    }
399
400    memorize_cmd_table(reader, cta_res, l);
401
402    unsigned char buff[256];
403
404    static const unsigned char ins7416[5] = { 0xD0, 0x74, 0x16, 0x00, 0x00 };
405    if(do_cmd(reader, ins7416, NULL, NULL, cta_res) < 0)
406    {
407        rdr_log(reader, "classD0 ins7416: failed");
408        return ERROR;
409    }
410
411    static const unsigned char ins02[5] = { 0xD0, 0x02, 0x00, 0x00, 0x08 };
412    // D0 02 command is not always present in command table but should be supported
413    // on most cards so do not use do_cmd()
414    if(!write_cmd_vg(ins02, NULL) || !status_ok(cta_res + 8))
415    {
416        rdr_log(reader, "Unable to get NDS ROM version.");
417    }
418    else
419    {
420        int i;
421        for(i = 0; i < 8; i++)
422        {
423            if(cta_res[i] <= 0x09)
424            {
425                cta_res[i] = cta_res[i] + 0x30;
426            }
427            else if(!isalnum(cta_res[i]))
428            {
429                cta_res[i] = '*';
430            }
431        }
432        memset(reader->rom, 0, sizeof(reader->rom));
433        memcpy(reader->rom, cta_res, 4);
434        reader->rom[4] = '-';
435        memcpy(reader->rom + 5, cta_res + 4, 4);
436
437        rdr_log(reader, "Card type:   %c%c%c%c", reader->rom[0], reader->rom[1], reader->rom[2], reader->rom[3]);
438        rdr_log(reader, "Rom version: %c%c%c%c", reader->rom[5], reader->rom[6], reader->rom[7], reader->rom[8]);
439    }
440
441
442    unsigned char boxID [4];
443
444    if(reader->boxid > 0)
445    {
446        /* the boxid is specified in the config */
447        int32_t i;
448        for(i = 0; i < 4; i++)
449        {
450            boxID[i] = (reader->boxid >> (8 * (3 - i))) % 0x100;
451        }
452    }
453    else
454    {
455        unsigned char ins36[5] = { 0xD0, 0x36, 0x00, 0x00, 0x00 };
456        static const unsigned char ins5e[5] = { 0xD0, 0x5E, 0x00, 0x0C, 0x02 };
457
458        /* we can try to get the boxid from the card */
459        int32_t boxidOK = 0;
460        l = read_cmd_len(reader, ins36);
461        if(l > 0)
462        {
463            ins36[4] = l;
464        }
465        else if(cmd_exists(reader, ins5e))
466        {
467            if(!write_cmd_vg(ins5e, NULL) || !status_ok(cta_res + 2))
468            {
469                rdr_log(reader, "classD0 ins5e: failed");
470            }
471            else
472            {
473                ins36[3] = cta_res[0];
474                ins36[4] = cta_res[1];
475            }
476        }
477        l = ins36[4];
478        if(!write_cmd_vg(ins36, NULL) || !status_ok(cta_res + l))
479        {
480            rdr_log(reader, "classD0 ins36: failed");
481            return ERROR;
482        }
483        memcpy(buff, ins36, 5);
484        memcpy(buff + 5, cta_res, l);
485        memcpy(buff + 5 + l, cta_res + l, 2);
486        if(l < 13)
487            { rdr_log(reader, "classD0 ins36: answer too int16"); }
488        else if(buff[7] > 0x0F)
489            { rdr_log(reader, "classD0 ins36: encrypted - can't parse"); }
490        else
491        {
492            /* skipping the initial fixed fields: cmdecho (4) + length (1) + encr/rev++ (4) */
493            int32_t i = 9;
494            int32_t gotUA = 0;
495            while(i < l)
496            {
497                if(!gotUA && buff[i] < 0xF0)  /* then we guess that the next 4 bytes is the UA */
498                {
499                    gotUA = 1;
500                    i += 4;
501                }
502                else switch(buff[i])      /* object length vary depending on type */
503                    {
504                    case 0x00: /* padding */
505                        i += 1;
506                        break;
507                    case 0xEF: /* card status */
508                        i += 3;
509                        break;
510                    case 0xD1:
511                        i += 4;
512                        break;
513                    case 0xDF: /* next server contact */
514                        i += 5;
515                        break;
516                    case 0xF3: /* boxID */
517                        memcpy(boxID, buff + i + 1, sizeof(boxID));
518                        boxidOK = 1;
519                        i += 5;
520                        break;
521                    case 0xF6:
522                        i += 6;
523                        break;
524                    case 0x01: /* date & time */
525                        i += 7;
526                        break;
527                    case 0xFA:
528                        i += 9;
529                        break;
530                    case 0x5E:
531                    case 0x67: /* signature */
532                    case 0xDE:
533                    case 0xE2:
534                    case 0xE9: /* tier dates */
535                    case 0xF8: /* Old PPV Event Record */
536                    case 0xFD:
537                        i += buff[i + 1] + 2; /* skip length + 2 bytes (type and length) */
538                        break;
539                    default: /* default to assume a length byte */
540                        rdr_log(reader, "classD0 ins36: returned unknown type=0x%02X - parsing may fail", buff[i]);
541                        i += buff[i + 1] + 2;
542                    }
543            }
544        }
545
546        if(!boxidOK)
547        {
548            rdr_log(reader, "no boxID available");
549            return ERROR;
550        }
551    }
552
553    static const unsigned char ins4C[5] = { 0xD0, 0x4C, 0x00, 0x00, 0x09 };
554    unsigned char payload4C[9] = { 0, 0, 0, 0, 3, 0, 0, 0, 4 };
555    memcpy(payload4C, boxID, 4);
556    if(!write_cmd_vg(ins4C, payload4C) || !status_ok(cta_res + l))
557    {
558        rdr_log(reader, "classD0 ins4C: failed - sending boxid failed");
559        return ERROR;
560    }
561
562    //int16_t int32_t SWIRDstatus = cta_res[1];
563    static const unsigned char ins58[5] = { 0xD0, 0x58, 0x00, 0x00, 0x00 };
564    l = do_cmd(reader, ins58, NULL, NULL, cta_res);
565    if(l < 0)
566    {
567        rdr_log(reader, "classD0 ins58: failed");
568        return ERROR;
569    }
570    memset(reader->hexserial, 0, 8);
571    memcpy(reader->hexserial + 2, cta_res + 3, 4);
572    memcpy(reader->sa, cta_res + 3, 3);
573    reader->caid = cta_res[24] * 0x100 + cta_res[25];
574
575    /* we have one provider, 0x0000 */
576    reader->nprov = 1;
577    memset(reader->prid, 0x00, sizeof(reader->prid));
578
579    /*
580    rdr_log(reader, "INS58 : Fuse byte=0x%02X, IRDStatus=0x%02X", cta_res[2],SWIRDstatus);
581    if (SWIRDstatus==4)  {
582    // If swMarriage=4, not married then exchange for BC Key
583    rdr_log(reader, "Card not married, exchange for BC Keys");
584     */
585
586    cCamCryptVG_SetSeed(reader);
587
588    static const unsigned char insB4[5] = { 0xD0, 0xB4, 0x00, 0x00, 0x40 };
589    unsigned char tbuff[64];
590    cCamCryptVG_GetCamKey(reader, tbuff);
591    l = do_cmd(reader, insB4, tbuff, NULL, cta_res);
592    if(l < 0 || !status_ok(cta_res))
593    {
594        rdr_log(reader, "classD0 insB4: failed");
595        return ERROR;
596    }
597
598    static const unsigned char insBC[5] = { 0xD0, 0xBC, 0x00, 0x00, 0x00 };
599    l = do_cmd(reader, insBC, NULL, NULL, cta_res);
600    if(l < 0)
601    {
602        rdr_log(reader, "classD0 insBC: failed");
603        return ERROR;
604    }
605
606    // Class D1/D3 instructions only work after this point
607
608    static const unsigned char insBE[5] = { 0xD3, 0xBE, 0x00, 0x00, 0x00 };
609    l = do_cmd(reader, insBE, NULL, NULL, cta_res);
610    if(l < 0)
611    {
612        rdr_log(reader, "classD3 insBE: failed");
613        return ERROR;
614    }
615
616    static const unsigned char ins58a[5] = { 0xD1, 0x58, 0x00, 0x00, 0x00 };
617    l = do_cmd(reader, ins58a, NULL, NULL, cta_res);
618    if(l < 0)
619    {
620        rdr_log(reader, "classD1 ins58: failed");
621        return ERROR;
622    }
623
624    static const unsigned char ins4Ca[5] = { 0xD1, 0x4C, 0x00, 0x00, 0x00 };
625    l = do_cmd(reader, ins4Ca, payload4C, NULL, cta_res);
626    if(l < 0 || !status_ok(cta_res))
627    {
628        rdr_log(reader, "classD1 ins4Ca: failed");
629        return ERROR;
630    }
631
632    if(reader->ins7E[0x1A])
633    {
634        static const uint8_t ins7E[5] = { 0xD1, 0x7E, 0x10, 0x00, 0x1A };
635        l = do_cmd(reader, ins7E, reader->ins7E, NULL, cta_res);
636        if(l < 0 || !status_ok(cta_res))
637        {
638            rdr_log(reader, "classD1 ins7E: failed");
639            return ERROR;
640        }
641    }
642
643    if(reader->ins7E11[0x01])
644    {
645        unsigned char ins742b[5] = { 0xD0, 0x74, 0x2b, 0x00, 0x00 };
646
647        l = read_cmd_len(reader, ins742b);  //get command len for ins742b
648
649        if(l < 2)
650        {
651            rdr_log(reader, "No TA1 change for this card is possible by ins7E11");
652        }
653        else
654        {
655            ins742b[4] = l;
656            bool ta1ok = 0;
657
658            if(!write_cmd_vg(ins742b, NULL) || !status_ok(cta_res + ins742b[4]))  //get supported TA1 bytes
659            {
660                rdr_log(reader, "classD0 ins742b: failed");
661                return ERROR;
662            }
663            else
664            {
665                int32_t i;
666
667                for(i = 2; i < l; i++)
668                {
669                    if(cta_res[i] == reader->ins7E11[0x00])
670                    {
671                        ta1ok = 1;
672                        break;
673                    }
674                }
675            }
676            if(ta1ok == 0)
677            {
678                rdr_log(reader, "The value %02X of ins7E11 is not supported,try one between %02X and %02X", reader->ins7E11[0x00], cta_res[2], cta_res[ins742b[4] - 1]);
679            }
680            else
681            {
682                static const uint8_t ins7E11[5] = { 0xD0, 0x7E, 0x11, 0x00, 0x01 };
683
684                reader->ins7e11_fast_reset = 0;
685
686                l = do_cmd(reader, ins7E11, reader->ins7E11, NULL, cta_res);
687
688                if(l < 0 || !status_ok(cta_res))
689                {
690                    rdr_log(reader, "classD0 ins7E11: failed");
691                    return ERROR;
692                }
693                else
694                {
695                    unsigned char TA1;
696
697                    if(ATR_GetInterfaceByte(newatr, 1, ATR_INTERFACE_BYTE_TA, &TA1) == ATR_OK)
698                    {
699                        if(TA1 != reader->ins7E11[0x00])
700                        {
701                            rdr_log(reader, "classD0 ins7E11: Scheduling card reset for TA1 change from %02X to %02X", TA1, reader->ins7E11[0x00]);
702                            reader->ins7e11_fast_reset = 1;
703#ifdef WITH_COOLAPI
704                            if(reader->typ == R_MOUSE || reader->typ == R_SC8in1 || reader->typ == R_SMART || reader->typ == R_INTERNAL)
705                            {
706#else
707                            if(reader->typ == R_MOUSE || reader->typ == R_SC8in1 || reader->typ == R_SMART)
708                            {
709#endif
710                                add_job(reader->client, ACTION_READER_RESET_FAST, NULL, 0);
711                            }
712                            else
713                            {
714                                add_job(reader->client, ACTION_READER_RESTART, NULL, 0);
715                            }
716                            return OK; // Skip the rest of the init since the card will be reset anyway
717                        }
718                    }
719                }
720            }
721        }
722    }
723
724    /* get parental lock settings */
725    static const unsigned char ins74e[5] = {0xD0, 0x74, 0x0E, 0x00, 0x00};
726    if(cmd_exists(reader, ins74e))
727    {
728        l = do_cmd(reader, ins74e, NULL, NULL, cta_res);
729        if(l < 0 || !status_ok(cta_res + l))
730        {
731            rdr_log(reader, "classD0 ins74e: failed to get parental lock settings");
732        }
733        else
734        {
735            char tmp[l > 0 ? l * 3 : 1];
736            rdr_log(reader, "parental lock setting: %s", cs_hexdump(1, cta_res + 2, l - 2, tmp, sizeof(tmp)));
737        }
738    }
739
740    /* disable parental lock */
741    static const uchar ins2e[5] = {0xD0, 0x2E, 0x00, 0x00, 0x04};
742    static const uchar payload2e[4] = {0xFF, 0xFF, 0xFF, 0xFF};
743    if(cfg.ulparent)
744    {
745        if(cmd_exists(reader, ins74e) && write_cmd_vg(ins2e, payload2e) && status_ok(cta_res + l))
746        {
747            rdr_log(reader, "parental lock disabled");
748        }
749        else
750        {
751            rdr_log(reader, "cannot disable parental lock");
752        }
753        if(cmd_exists(reader, ins74e))
754        {
755            l = do_cmd(reader, ins74e, NULL, NULL, cta_res);
756            if(l < 0 || !status_ok(cta_res + l))
757            {
758                rdr_log(reader, "classD0 ins74e: failed to get parental lock settings");
759            }
760            else
761            {
762                char tmp[l > 0 ? l * 3 : 1];
763                rdr_log(reader, "parental lock setting after disabling: %s", cs_hexdump(1, cta_res + 2, l - 2, tmp, sizeof(tmp)));
764            }
765        }
766    }
767
768    // fix for 09ac cards
769    unsigned char dimeno_magic[0x10] = {0xF9, 0xFB, 0xCD, 0x5A, 0x76, 0xB5, 0xC4, 0x5C, 0xC8, 0x2E, 0x1D, 0xE1, 0xCC, 0x5B, 0x6B, 0x02};
770    int32_t a;
771    for(a = 0; a < 4; a++)
772        { dimeno_magic[a] = dimeno_magic[a] ^ boxID[a]; }
773    AES_set_decrypt_key(dimeno_magic, 128, &(csystem_data->astrokey));
774
775    rdr_log(reader, "type: %s, caid: %04X",
776            csystem_data->card_desc,
777            reader->caid);
778    rdr_log_sensitive(reader, "serial: {%02X%02X%02X%02X}, BoxID: {%02X%02X%02X%02X}, baseyear: %i",
779                      reader->hexserial[2], reader->hexserial[3], reader->hexserial[4], reader->hexserial[5],
780                      boxID[0], boxID[1], boxID[2], boxID[3],
781                      csystem_data->card_baseyear);
782    rdr_log(reader, "ready for requests");
783
784    return OK;
785}
786
787static int32_t videoguard2_do_ecm(struct s_reader *reader, const ECM_REQUEST *er, struct s_ecm_answer *ea)
788{
789    unsigned char cta_res[CTA_RES_LEN];
790    static const char valid_ecm[] = { 0x00, 0x00, 0x01 };
791    unsigned char ins40[5] = { 0xD1, 0x40, 0x00, 0x80, 0xFF };
792    static const unsigned char ins54[5] = { 0xD3, 0x54, 0x00, 0x00, 0x00};
793    int32_t posECMpart2 = er->ecm[6] + 7;
794    int32_t lenECMpart2 = er->ecm[posECMpart2] + 1;
795    unsigned char tbuff[264], rbuff[264];
796    tbuff[0] = 0;
797
798    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
799
800    if(memcmp(&(er->ecm[3]), valid_ecm, sizeof(valid_ecm) != 0))
801    {
802        rdr_log(reader, "Not a valid ecm");
803        return ERROR;
804    }
805
806    memcpy(tbuff + 1, er->ecm + posECMpart2 + 1, lenECMpart2 - 1);
807
808    /*
809      //log parental lock byte
810      int32_t j;
811      for (j = posECMpart2+1; j < lenECMpart2+posECMpart2+1-4; j++){
812        if (er->ecm[j] == 0x02 && er->ecm[j+3] == 0x02) {
813          rdr_log(reader, "channel parental lock mask: %02X%02X, channel parental lock byte: %02X",er->ecm[j+1],er->ecm[j+2],er->ecm[j+4]);
814          break;
815        }
816      }
817
818      //log tiers
819      int32_t k;
820      char tiername[83];
821      for (k = posECMpart2+1; k < lenECMpart2+posECMpart2+1-4; k++){
822        if (er->ecm[k] == 0x03 && er->ecm[k+3] == 0x80) {
823          uint16_t vtier_id = (er->ecm[k+1] << 8) | er->ecm[k+2];
824          get_tiername(vtier_id, reader->caid, tiername);
825          rdr_log(reader, "valid tier: %04x %s",vtier_id, tiername);
826        }
827      }
828    */
829
830    int32_t new_len = lenECMpart2;
831    if(reader->fix_9993 && reader->caid == 0x919 && tbuff[1] == 0x7F)
832    {
833        tbuff[1] = 0x47;
834        tbuff[2] = 0x08;
835        memmove(tbuff + 11, tbuff + 13, new_len - 11);
836        new_len -= 2;
837    }
838    ins40[4] = new_len;
839    int32_t l;
840
841    l = do_cmd(reader, ins40, tbuff, NULL, cta_res);
842    if(l < 0 || !status_ok(cta_res))
843    {
844        rdr_log(reader, "classD0 ins40: (%d) status not ok %02x %02x", l, cta_res[0], cta_res[1]);
845        rdr_log(reader, "The card is not answering correctly! Restarting reader for safety");
846        add_job(reader->client, ACTION_READER_RESTART, NULL, 0);
847        return ERROR;
848    }
849    else
850    {
851        l = do_cmd(reader, ins54, NULL, rbuff, cta_res);
852        if(l < 0 || !status_ok(cta_res + l))
853        {
854            rdr_log(reader, "classD3 ins54: (%d) status not ok %02x %02x", l, cta_res[0], cta_res[1]);
855            rdr_log(reader, "The card is not answering correctly! Restarting reader for safety");
856            add_job(reader->client, ACTION_READER_RESTART, NULL, 0);
857            return ERROR;
858        }
859        else
860        {
861
862            // Log decrypted INS54
863            rdr_ddump_mask(reader, D_READER, rbuff, 5, "INS54:");
864            rdr_ddump_mask(reader, D_READER, rbuff + 5, rbuff[4], "Decrypted payload");
865
866            if(!cw_is_valid(rbuff + 5))  //sky cards report 90 00 = ok but send cw = 00 when channel not subscribed
867            {
868                rdr_log(reader, "classD3 ins54: status 90 00 = ok but cw=00 -> channel not subscribed ");
869                return ERROR;
870            }
871
872            // copy cw1 in place
873            memcpy(ea->cw + 0, rbuff + 5, 8);
874
875            // process cw2
876            unsigned char *payload = rbuff + 5;
877            int32_t payloadLen = rbuff[4];
878            int32_t ind = 8 + 6; // +8 for CW1, +6 for counter(?)
879
880            while(ind < payloadLen)
881            {
882                switch(payload[ind])
883                {
884                case 0x25:  // CW2
885                    //cs_dump (payload + ind, payload[ind+1]+2, "INS54 - CW2");
886                    memcpy(ea->cw + 8, &payload[ind + 3], 8);
887                    ind += payload[ind + 1] + 2;
888                    break;
889
890                default:
891                    //cs_dump (payload + ind, payload[ind+1]+2, "INS54");
892                    ind += payload[ind + 1] + 2;
893                    break;
894                }
895            }
896
897            if(new_len != lenECMpart2)
898            {
899                memcpy(ea->cw, ea->cw + 8, 8);
900                memset(ea->cw + 8, 0, 8);
901            }
902            // fix for 09ac cards
903            dimeno_PostProcess_Decrypt(reader, rbuff, ea->cw);
904
905            //test for postprocessing marker
906            int32_t posB0 = -1;
907            int32_t i;
908            for(i = 6; i < posECMpart2; i++)
909            {
910                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)))
911                {
912                    posB0 = i;
913                    break;
914                }
915            }
916            if(posB0 != -1)
917            {
918                do_post_dw_hash(reader, ea->cw + 0, &er->ecm[posB0 - 2]);
919                do_post_dw_hash(reader, ea->cw + 8, &er->ecm[posB0 - 2]);
920            }
921
922            if(reader->caid == 0x0907)    //quickfix: cw2 is not a valid cw, something went wrong before
923            {
924                memset(ea->cw + 8, 0, 8);
925                if(er->ecm[0] & 1)
926                {
927                    memcpy(ea->cw + 8, ea->cw, 8);
928                    memset(ea->cw, 0, 8);
929                }
930            }
931            else
932            {
933                if(er->ecm[0] & 1)
934                {
935                    unsigned char tmpcw[8];
936                    memcpy(tmpcw, ea->cw + 8, 8);
937                    memcpy(ea->cw + 8, ea->cw + 0, 8);
938                    memcpy(ea->cw + 0, tmpcw, 8);
939                }
940            }
941
942            return OK;
943        }
944    }
945}
946
947static int32_t videoguard2_do_emm(struct s_reader *reader, EMM_PACKET *ep)
948{
949    return videoguard_do_emm(reader, ep, 0xD1, vg2_read_tiers, do_cmd);
950}
951
952static int32_t videoguard2_card_info(struct s_reader *reader)
953{
954    /* info is displayed in init, or when processing info */
955    struct videoguard_data *csystem_data = reader->csystem_data;
956    rdr_log(reader, "card detected");
957    rdr_log(reader, "type: %s", csystem_data->card_desc);
958    if(reader->ins7e11_fast_reset != 1)
959    {
960        vg2_read_tiers(reader);
961    }
962    return OK;
963}
964
965void reader_videoguard2(struct s_cardsystem *ph)
966{
967    ph->do_emm = videoguard2_do_emm;
968    ph->do_ecm = videoguard2_do_ecm;
969    ph->card_info = videoguard2_card_info;
970    ph->card_init = videoguard2_card_init;
971    ph->get_emm_type = videoguard_get_emm_type;
972    ph->get_emm_filter = videoguard_get_emm_filter;
973    ph->caids[0] = 0x09;
974    ph->desc = "videoguard2";
975}
976#endif
977
Note: See TracBrowser for help on using the repository browser.