source: trunk/reader-videoguard1.c @ 10607

Last change on this file since 10607 was 10607, checked in by theparasol, 5 years ago

All cas systems:

  • cs_add_entitlement: extended with find only modus and some protection: only add if not found jet!

Viaccess specific: (Special thanks go again to Bit and Pr2 for their testing and logging!)

  • Separate reassembly buffers for every provid, this should fix reassembly issues if you have viaccess cards with different providers on them.
  • Extract provid from 8c/8d nano instead of provid from emmpid so they never can be mixed up with emm 8e for other provid
  • Combine with the correct provider 8c/8d emm based on the SA info in the 8e emm
  • Smarter and same filters for network and local cards
  • Smarter prio of the filters: shared on top, global at the end and skip not useful providers
  • Nano A9 provider class check to avoid 90 40 (very big thanks goes to Bit for his analysis!)
  • Property svn:eol-style set to LF
File size: 9.4 KB
Line 
1#include "globals.h"
2#ifdef READER_VIDEOGUARD
3#include "reader-common.h"
4#include "reader-videoguard-common.h"
5
6
7static int32_t vg1_do_cmd(struct s_reader *reader, const unsigned char *ins, const unsigned char *txbuff, unsigned char *rxbuff, unsigned char *cta_res)
8{
9    uint16_t cta_lr;
10    unsigned char ins2[5];
11    memcpy(ins2, ins, 5);
12    unsigned char len = 0;
13    len = ins2[4];
14
15
16
17    if(txbuff == NULL)
18    {
19        if(!write_cmd_vg(ins2, NULL) || !status_ok(cta_res + len))
20        {
21            return -1;
22        }
23        if(rxbuff != NULL)
24        {
25            memcpy(rxbuff, ins2, 5);
26            memcpy(rxbuff + 5, cta_res, len);
27            memcpy(rxbuff + 5 + len, cta_res + len, 2);
28        }
29    }
30    else
31    {
32        if(!write_cmd_vg(ins2, (uchar *) txbuff) || !status_ok(cta_res))
33        {
34            return -2;
35        }
36        if(rxbuff != NULL)
37        {
38            memcpy(rxbuff, ins2, 5);
39            memcpy(rxbuff + 5, txbuff, len);
40            memcpy(rxbuff + 5 + len, cta_res, 2);
41        }
42    }
43
44    return len;
45}
46
47static void read_tiers(struct s_reader *reader)
48{
49    struct videoguard_data *csystem_data = reader->csystem_data;
50    def_resp;
51    //  const unsigned char ins2a[5] = {  0x48, 0x2a, 0x00, 0x00, 0x00  };
52    int32_t l;
53
54    //  return; // Not working at present so just do nothing
55
56    //  l = vg1_do_cmd(reader, ins2a, NULL, NULL, cta_res);
57    //  if (l < 0 || !status_ok(cta_res + l))
58    //  {
59    //    return;
60    //  }
61    unsigned char ins76[5] = { 0x48, 0x76, 0x00, 0x00, 0x00 };
62    ins76[3] = 0x7f;
63    ins76[4] = 2;
64    if(!write_cmd_vg(ins76, NULL) || !status_ok(cta_res + 2))
65    {
66        return;
67    }
68    ins76[3] = 0;
69    ins76[4] = 0x0a;
70    int32_t num = cta_res[1];
71    int32_t i;
72
73    cs_clear_entitlement(reader); //reset the entitlements
74
75    for(i = 0; i < num; i++)
76    {
77        ins76[2] = i;
78        l = vg1_do_cmd(reader, ins76, NULL, NULL, cta_res);
79        if(l < 0 || !status_ok(cta_res + l))
80        {
81            return;
82        }
83        if(cta_res[2] == 0 && cta_res[3] == 0)
84        {
85            break;
86        }
87        uint16_t tier_id = (cta_res[2] << 8) | cta_res[3];
88        // add entitlements to list
89        struct tm timeinfo;
90        memset(&timeinfo, 0, sizeof(struct tm));
91        rev_date_calc_tm(&cta_res[4], &timeinfo, csystem_data->card_baseyear);
92        char tiername[83];
93        cs_add_entitlement(reader, reader->caid, b2ll(4, reader->prid[0]), tier_id, 0, 0, mktime(&timeinfo), 4, 1);
94        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));
95    }
96}
97
98static int32_t videoguard1_card_init(struct s_reader *reader, ATR *newatr)
99{
100
101    get_hist;
102    /* 40 B0 09 4A 50 01 4E 5A */
103    if((hist_size < 7) || (hist[1] != 0xB0) || (hist[3] != 0x4A) || (hist[4] != 0x50))
104    {
105        return ERROR;
106    }
107
108    get_atr;
109    def_resp;
110
111    if(!cs_malloc(&reader->csystem_data, sizeof(struct videoguard_data)))
112        { return ERROR; }
113    struct videoguard_data *csystem_data = reader->csystem_data;
114
115    /* set information on the card stored in reader-videoguard-common.c */
116    set_known_card_info(reader, atr, &atr_size);
117
118    if((reader->ndsversion != NDS1) && ((csystem_data->card_system_version != NDS1) || (reader->ndsversion != NDSAUTO)))
119    {
120        /* known ATR and not NDS1
121           or unknown ATR and not forced to NDS1
122           or known NDS1 ATR and forced to another NDS version
123           ... probably not NDS1 */
124        return ERROR;
125    }
126
127    rdr_log(reader, "type: %s, baseyear: %i", csystem_data->card_desc, csystem_data->card_baseyear);
128    if(reader->ndsversion == NDS1)
129    {
130        rdr_log(reader, "forced to NDS1+");
131    }
132
133    /* NDS1 Class 48 only cards only need a very basic initialisation
134       NDS1 Class 48 only cards do not respond to vg1_do_cmd(ins7416)
135       nor do they return list of valid command therefore do not even try
136       NDS1 Class 48 only cards need to be told the length as (48, ins, 00, 80, 01)
137       does not return the length */
138
139    int32_t l = 0;
140    unsigned char buff[256];
141    memset(buff, 0, sizeof(buff));
142
143    /* Try to get the boxid from the card, even if BoxID specified in the config file
144       also used to check if it is an NDS1 card as the returned information will
145       not be encrypted if it is an NDS1 card */
146
147    static const unsigned char ins36[5] = { 0x48, 0x36, 0x00, 0x00, 0x90 };
148    unsigned char boxID[4];
149    int32_t boxidOK = 0;
150    l = vg1_do_cmd(reader, ins36, NULL, buff, cta_res);
151    if(buff[7] > 0x0F)
152    {
153        rdr_log(reader, "class48 ins36: encrypted - therefore not an NDS1 card");
154        return ERROR;
155    }
156    else
157    {
158        /* skipping the initial fixed fields: cmdecho (4) + length (1) + encr/rev++ (4) */
159        int32_t i = 9;
160        int32_t gotUA = 0;
161        while(i < l)
162        {
163            if(!gotUA && buff[i] < 0xF0)      /* then we guess that the next 4 bytes is the UA */
164            {
165                gotUA = 1;
166                i += 4;
167            }
168            else
169            {
170                switch(buff[i])     /* object length vary depending on type */
171                {
172                case 0x00:      /* padding */
173                {
174                    i += 1;
175                    break;
176                }
177                case 0xEF:      /* card status */
178                {
179                    i += 3;
180                    break;
181                }
182                case 0xD1:
183                {
184                    i += 4;
185                    break;
186                }
187                case 0xDF:      /* next server contact */
188                {
189                    i += 5;
190                    break;
191                }
192                case 0xF3:      /* boxID */
193                {
194                    memcpy(&boxID, &buff[i + 1], sizeof(boxID));
195                    boxidOK = 1;
196                    i += 5;
197                    break;
198                }
199                case 0xF6:
200                {
201                    i += 6;
202                    break;
203                }
204                case 0xFC:      /* No idea seems to with with NDS1 */
205                {
206                    i += 14;
207                    break;
208                }
209                case 0x01:      /* date & time */
210                {
211                    i += 7;
212                    break;
213                }
214                case 0xFA:
215                {
216                    i += 9;
217                    break;
218                }
219                case 0x5E:
220                case 0x67:      /* signature */
221                case 0xDE:
222                case 0xE2:
223                case 0xE9:      /* tier dates */
224                case 0xF8:      /* Old PPV Event Record */
225                case 0xFD:
226                {
227                    i += buff[i + 1] + 2;   /* skip length + 2 bytes (type and length) */
228                    break;
229                }
230                default:        /* default to assume a length byte */
231                {
232                    rdr_log(reader, "class48 ins36: returned unknown type=0x%02X - parsing may fail", buff[i]);
233                    i += buff[i + 1] + 2;
234                }
235                }
236            }
237        }
238    }
239
240    // rdr_log(reader, "calculated BoxID: %02X%02X%02X%02X", boxID[0], boxID[1], boxID[2], boxID[3]);
241
242    /* the boxid is specified in the config */
243    if(reader->boxid > 0)
244    {
245        int32_t i;
246        for(i = 0; i < 4; i++)
247        {
248            boxID[i] = (reader->boxid >> (8 * (3 - i))) % 0x100;
249        }
250        // rdr_log(reader, "config BoxID: %02X%02X%02X%02X", boxID[0], boxID[1], boxID[2], boxID[3]);
251    }
252
253    if(!boxidOK)
254    {
255        rdr_log(reader, "no boxID available");
256        return ERROR;
257    }
258
259    // Send BoxID
260    static const unsigned char ins4C[5] = { 0x48, 0x4C, 0x00, 0x00, 0x09 };
261    unsigned char payload4C[9] = { 0, 0, 0, 0, 3, 0, 0, 0, 4 };
262    memcpy(payload4C, boxID, 4);
263    if(!write_cmd_vg(ins4C, payload4C) || !status_ok(cta_res + l))
264    {
265        rdr_log(reader, "class48 ins4C: sending boxid failed");
266        return ERROR;
267    }
268
269    static const unsigned char ins58[5] = { 0x48, 0x58, 0x00, 0x00, 0x17 };
270    l = vg1_do_cmd(reader, ins58, NULL, buff, cta_res);
271    if(l < 0)
272    {
273        rdr_log(reader, "class48 ins58: failed");
274        return ERROR;
275    }
276
277    memset(reader->hexserial, 0, 8);
278    memcpy(reader->hexserial + 2, cta_res + 1, 4);
279    memcpy(reader->sa, cta_res + 1, 3);
280    //  reader->caid = cta_res[24] * 0x100 + cta_res[25];
281    /* Force caid until can figure out how to get it */
282    reader->caid = 0x9 * 0x100 + 0x69;
283
284    /* we have one provider, 0x0000 */
285    reader->nprov = 1;
286    memset(reader->prid, 0x00, sizeof(reader->prid));
287
288    rdr_log_sensitive(reader, "type: VideoGuard, caid: %04X, serial: {%02X%02X%02X%02X}, BoxID: {%02X%02X%02X%02X}",
289                      reader->caid, reader->hexserial[2], reader->hexserial[3], reader->hexserial[4], reader->hexserial[5],
290                      boxID[0], boxID[1], boxID[2], boxID[3]);
291    rdr_log(reader, "ready for requests - this is in testing please send -d 255 logs");
292
293    return OK;
294}
295
296static int32_t videoguard1_do_ecm(struct s_reader *reader, const ECM_REQUEST *er, struct s_ecm_answer *ea)
297{
298    unsigned char cta_res[CTA_RES_LEN];
299    unsigned char ins40[5] = { 0x48, 0x40, 0x00, 0x80, 0xFF };
300    static const unsigned char ins54[5] = { 0x48, 0x54, 0x00, 0x00, 0x0D };
301    int32_t posECMpart2 = er->ecm[6] + 7;
302    int32_t lenECMpart2 = er->ecm[posECMpart2];
303    unsigned char tbuff[264];
304    unsigned char rbuff[264];
305    memcpy(&tbuff[0], &(er->ecm[posECMpart2 + 1]), lenECMpart2);
306    ins40[4] = lenECMpart2;
307    int32_t l;
308    l = vg1_do_cmd(reader, ins40, tbuff, NULL, cta_res);
309    if(l > 0 && status_ok(cta_res))
310    {
311        l = vg1_do_cmd(reader, ins54, NULL, rbuff, cta_res);
312        if(l > 0 && status_ok(cta_res + l))
313        {
314            if(!cw_is_valid(rbuff + 5))   //sky cards report 90 00 = ok but send cw = 00 when channel not subscribed
315            {
316                rdr_log(reader, "class48 ins54 status 90 00 but cw=00 -> channel not subscribed");
317                return ERROR;
318            }
319
320            if(er->ecm[0] & 1)
321            {
322                memset(ea->cw + 0, 0, 8);
323                memcpy(ea->cw + 8, rbuff + 5, 8);
324            }
325            else
326            {
327                memcpy(ea->cw + 0, rbuff + 5, 8);
328                memset(ea->cw + 8, 0, 8);
329            }
330            return OK;
331        }
332    }
333    rdr_log(reader, "class48 ins54 (%d) status not ok %02x %02x", l, cta_res[0], cta_res[1]);
334    return ERROR;
335}
336
337static int32_t videoguard1_do_emm(struct s_reader *reader, EMM_PACKET *ep)
338{
339    return videoguard_do_emm(reader, ep, 0x48, read_tiers, vg1_do_cmd);
340}
341
342static int32_t videoguard1_card_info(struct s_reader *reader)
343{
344    /* info is displayed in init, or when processing info */
345    struct videoguard_data *csystem_data = reader->csystem_data;
346    rdr_log(reader, "card detected");
347    rdr_log(reader, "type: %s", csystem_data->card_desc);
348    read_tiers(reader);
349    return OK;
350}
351
352const struct s_cardsystem reader_videoguard1 =
353{
354    .desc           = "videoguard1",
355    .caids          = (uint16_t[]){ 0x09, 0 },
356    .do_emm         = videoguard1_do_emm,
357    .do_ecm         = videoguard1_do_ecm,
358    .card_info      = videoguard1_card_info,
359    .card_init      = videoguard1_card_init,
360    .get_emm_type   = videoguard_get_emm_type,
361    .get_emm_filter = videoguard_get_emm_filter,
362};
363
364#endif
Note: See TracBrowser for help on using the repository browser.