source: trunk/reader-seca.c @ 5375

Last change on this file since 5375 was 5306, checked in by neoen, 8 years ago

Seca ECMs using OP Key xE are sent to reader even if privider is expired

File size: 12.5 KB
Line 
1#include "globals.h"
2#include "reader-common.h"
3#include <stdlib.h>
4
5static int32_t set_provider_info(struct s_reader * reader, int32_t i)
6{
7  def_resp;
8  uchar ins12[] = { 0xc1, 0x12, 0x00, 0x00, 0x19 }; // get provider info
9  int32_t year, month, day;
10  struct tm lt;
11  time_t t;
12  int32_t valid=0;//0=false, 1=true
13  char l_name[16+8+1]=", name: ";
14
15  ins12[2]=i;//select provider
16  write_cmd(ins12, NULL); // show provider properties
17 
18  if ((cta_res[25] != 0x90) || (cta_res[26] != 0x00)) return ERROR;
19  reader->prid[i][0]=0;
20  reader->prid[i][1]=0;//blanken high byte provider code
21  memcpy(&reader->prid[i][2], cta_res, 2);
22 
23  year = (cta_res[22]>>1) + 1990;
24  month = ((cta_res[22]&0x1)<< 3) | (cta_res[23] >>5);
25  day = (cta_res[23]&0x1f);
26  t=time(NULL);
27  localtime_r(&t, &lt);
28  if (lt.tm_year + 1900 != year)
29     valid = (lt.tm_year + 1900 < year);
30  else if (lt.tm_mon + 1 != month)
31     valid = (lt.tm_mon + 1 < month);
32  else if (lt.tm_mday != day)
33     valid = (lt.tm_mday < day);
34
35  memcpy(l_name+8, cta_res+2, 16);
36  l_name[sizeof(l_name)-1]=0;
37  trim(l_name+8);
38  l_name[0]=(l_name[8]) ? ',' : 0;
39  reader->availkeys[i][0]=valid; //misusing availkeys to register validity of provider
40  cs_ri_log (reader, "[seca-reader] provider: %d, valid: %i%s, expiry date: %4d/%02d/%02d",
41         i+1, valid,l_name, year, month, day);
42  memcpy(&reader->sa[i][0], cta_res+18, 4);
43  if (valid==1) //if not expired
44    cs_ri_log (reader, "[seca-reader] SA: %s", cs_hexdump(0, cta_res+18, 4));
45  return OK;
46}
47
48static int32_t unlock_parental(struct s_reader * reader)
49{
50    // Unlock parental control
51    // c1 30 00 01 09
52    // 00 00 00 00 00 00 00 00 ff
53    static const uchar ins30[] = { 0xc1, 0x30, 0x00, 0x01, 0x09 };
54    static uchar ins30data[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff };
55
56    def_resp;
57
58    if (strcmp(reader->pincode, "none")) {
59        cs_log("[seca-reader] Using PIN %s",reader->pincode);
60        // the pin need to be coded in bcd, so we need to convert from ascii to bcd, so '1234' -> 0x12 0x34
61        ins30data[6]=((reader->pincode[0]-0x30)<<4) | ((reader->pincode[1]-0x30) & 0x0f);
62        ins30data[7]=((reader->pincode[2]-0x30)<<4) | ((reader->pincode[3]-0x30) & 0x0f);
63    }
64    else {
65        cs_log("[seca-reader] Using PIN 0000!");
66    }
67
68    write_cmd(ins30, ins30data); 
69    if( !(cta_res[cta_lr-2]==0x90 && cta_res[cta_lr-1]==0) ) {
70        if (strcmp(reader->pincode, "none")) {
71            cs_log("[seca-reader] Can't disable parental lock. Wrong PIN? OSCam used %s!",reader->pincode);
72        }
73        else {
74            cs_log("[seca-reader] Can't disable parental lock. Wrong PIN? OSCam used 0000!");
75        }
76    }
77    else
78        cs_log("[seca-reader] Parental lock disabled");
79   
80    cs_debug_mask(D_READER, "[seca-reader] ins30_answer: %02x%02x",cta_res[0], cta_res[1]);
81    return 0;
82}
83
84static int32_t seca_card_init(struct s_reader * reader, ATR newatr)
85{
86    get_atr;
87    def_resp;
88    char *card;
89    uint16_t pmap=0;    // provider-maptable
90    uint64_t serial ;
91  uchar buf[256];
92  static const uchar ins0e[] = { 0xc1, 0x0e, 0x00, 0x00, 0x08 }; // get serial number (UA)
93  static const uchar ins16[] = { 0xc1, 0x16, 0x00, 0x00, 0x07 }; // get nr. of prividers
94  int32_t i;
95
96
97  buf[0]=0x00;
98  if ((atr[10]!=0x0e) || (atr[11]!=0x6c) || (atr[12]!=0xb6) || (atr[13]!=0xd6)) return ERROR;
99  switch(atr[7]<<8|atr[8])
100  {
101    case 0x5084: card="Generic"; break;
102    case 0x5384: card="Philips"; break;
103    case 0x5130:
104    case 0x5430:
105    case 0x5760: card="Thompson"; break;
106    case 0x5284:
107    case 0x5842:
108    case 0x6060: card="Siemens"; break;
109    case 0x7070: card="Canal+ NL"; break;
110    default:     card="Unknown"; break;
111  }
112  reader->caid=0x0100;
113  memset(reader->prid, 0xff, sizeof(reader->prid));
114  write_cmd(ins0e, NULL); // read unique id
115  memcpy(reader->hexserial, cta_res+2, 6);
116  serial = b2ll(5, cta_res+3) ;
117  cs_ri_log (reader, "type: SECA, caid: %04X, serial: %llu, card: %s v%d.%d",
118         reader->caid, serial, card, atr[9]&0x0F, atr[9]>>4);
119  write_cmd(ins16, NULL); // read nr of providers
120  pmap=cta_res[2]<<8|cta_res[3];
121  for (reader->nprov=0, i=pmap; i; i>>=1)
122    reader->nprov+=i&1;
123 
124  for (i=0; i<16; i++)
125    if (pmap&(1<<i))
126    {
127      if (set_provider_info(reader, i) == ERROR)
128        return ERROR;
129      else
130    snprintf((char *) buf+strlen((char *)buf), sizeof(buf)-strlen((char *)buf), ",%04X", b2i(2, &reader->prid[i][2])); 
131    }
132
133  cs_ri_log (reader, "providers: %d (%s)", reader->nprov, buf+1);
134// Unlock parental control
135  if( cfg.ulparent != 0 ){
136    unlock_parental(reader);
137  }else {
138      cs_ri_log (reader, "[seca-reader] parental locked");
139  } 
140  cs_log("[seca-reader] ready for requests");
141  return OK;
142}
143
144static int32_t get_prov_index(struct s_reader * rdr, uint8_t *provid)   //returns provider id or -1 if not found
145{
146  int32_t prov;
147  for (prov=0; prov<rdr->nprov; prov++) //search for provider index
148    if (!memcmp(provid, &rdr->prid[prov][2], 2))
149      return(prov);
150  return(-1);
151}
152   
153
154static int32_t seca_do_ecm(struct s_reader * reader, ECM_REQUEST *er)
155{
156  def_resp;
157  unsigned char ins3c[] = { 0xc1,0x3c,0x00,0x00,0x00 }; // coding cw
158  unsigned char ins3a[] = { 0xc1,0x3a,0x00,0x00,0x10 }; // decoding cw
159  int32_t i;
160
161  if ((i = get_prov_index(reader, er->ecm+3)) == -1) // if provider not found
162  {
163     snprintf( er->msglog, MSGLOGSIZE, "provider not found" );
164     return ERROR;
165  }
166
167  if ((er->ecm[7] & 0x0F) != 0x0E && reader->availkeys[i][0] == 0) // if expired and not using OP Key 0E
168  {
169     snprintf( er->msglog, MSGLOGSIZE, "provider expired" );
170     return ERROR;
171  }
172
173  ins3c[2]=i;
174  ins3c[3]=er->ecm[7]; //key nr
175  ins3c[4]=(((er->ecm[1]&0x0f) << 8) | er->ecm[2])-0x05;
176    int32_t try = 1;
177    int32_t ret;
178  do {
179    if (try > 1)
180      snprintf( er->msglog, MSGLOGSIZE, "ins3c try nr %i", try);
181    write_cmd(ins3c, er->ecm+8); //ecm request
182    unsigned char ins30[] = { 0xC1, 0x30, 0x00, 0x02, 0x09 };
183    unsigned char ins30data[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF };
184    /* We need to use a token */
185    if (cta_res[0] == 0x90 && cta_res[1] == 0x1a) {
186      write_cmd(ins30, ins30data);
187      write_cmd(ins3c, er->ecm+8); //ecm request
188    }
189    ret = ((cta_res[0] != 0x90) || (cta_res[1] != 0x00));
190    if ((cta_res[0] == 0x93) && (cta_res[1] == 0x02)) {
191      snprintf( er->msglog, MSGLOGSIZE, "%s unsubscribed", reader->label);
192      break;
193    }
194    if (ret)
195      snprintf( er->msglog, MSGLOGSIZE, "%s ins3c card res: %02x %02x", reader->label, cta_res[0] , cta_res[1] );
196    try++;
197  } while ((try < 3) && (ret));
198  if (ret)
199    return ERROR;
200 
201  write_cmd(ins3a, NULL); //get cw's
202  if ((cta_res[16] != 0x90) || (cta_res[17] != 0x00)) { snprintf( er->msglog, MSGLOGSIZE, "ins3a card response: %02x %02x", cta_res[16] , cta_res[17] ); return ERROR; };//exit if response is not 90 00 //TODO: if response is 9027 ppv mode is possible!
203  memcpy(er->cw,cta_res,16);
204  return OK;
205}
206
207static int32_t seca_get_emm_type(EMM_PACKET *ep, struct s_reader * rdr) //returns TRUE if shared emm matches SA, unique emm matches serial, or global or unknown
208{
209    cs_debug_mask(D_EMM, "Entered seca_get_emm_type ep->emm[0]=%i",ep->emm[0]);
210    int32_t i;
211    switch (ep->emm[0]) {
212        case 0x82:
213            ep->type = UNIQUE;
214            memset(ep->hexserial,0,8);
215            memcpy(ep->hexserial, ep->emm + 3, 6);
216            cs_debug_mask(D_EMM, "SECA EMM: UNIQUE, ep->hexserial = %s", cs_hexdump(1, ep->hexserial, 6)); 
217            cs_debug_mask(D_EMM, "SECA EMM: UNIQUE, rdr->hexserial = %s", cs_hexdump(1, rdr->hexserial, 6)); 
218            return (!memcmp (rdr->hexserial, ep->hexserial, 6));
219
220        case 0x84:
221            ep->type = SHARED;
222            memset(ep->hexserial,0,8);
223            memcpy(ep->hexserial, ep->emm + 5, 3); //dont include custom byte; this way the network also knows SA
224            i=get_prov_index(rdr, ep->emm+3);
225            cs_debug_mask(D_EMM, "SECA EMM: SHARED, ep->hexserial = %s", cs_hexdump(1, ep->hexserial, 3)); 
226            if (i== -1) //provider not found on this card
227                return FALSE; //do not pass this EMM
228            cs_debug_mask(D_EMM, "SECA EMM: SHARED, rdr->sa[%i] = %s", i, cs_hexdump(1, rdr->sa[i], 3)); 
229            return (!memcmp (rdr->sa[i], ep->hexserial, 3));
230
231        // Unknown EMM types, but allready subbmited to dev's
232        // FIXME: Drop EMM's until there are implemented
233        case 0x83:
234        /*  EMM-G ?
235            83 00 74 00 00 00 00 00 C4 7B E7 54 8D 25 8D 27
236            CD 9C 87 4F B2 24 85 68 13 81 5E F1 EA AB 73 6D
237            78 A2 86 F3 C9 4E 78 55 48 21 E4 A0 0B A0 54 3B
238            5C 54 4B 01 39 1F FE C6 29 33 B8 6C 48 A0 9F 60
239            47 EB 6A FC D3 CD 4B 9A 50 F2 05 80 66 F3 82 48
240            22 EF E3 04 28 86 1D AB 82 26 9B 4D 09 B1 A8 F1
241            1D D4 50 69 44 E8 94 04 91 5F 21 A2 3C 43 BC CB
242            DD C1 90 AD 71 A7 38
243        */ 
244        case 0x88:
245        case 0x89:
246        //  EMM-G ?
247            ep->type = UNKNOWN;
248            return FALSE;
249
250        default:
251            ep->type = UNKNOWN;
252            return TRUE;
253    }
254}
255
256static void seca_get_emm_filter(struct s_reader * rdr, uchar *filter)
257{
258    int32_t idx = 2;
259
260    filter[0]=0xFF;
261    filter[1]=0;
262
263    filter[idx++]=EMM_UNIQUE;
264    filter[idx++]=0;
265    filter[idx+0]    = 0x82;
266    filter[idx+0+16] = 0xFF;
267    memcpy(filter+idx+1, rdr->hexserial, 6);
268    memset(filter+idx+1+16, 0xFF, 6);
269    filter[1]++;
270    idx += 32;
271
272    int32_t prov;
273    for (prov=0; prov<rdr->nprov; prov++) {
274        filter[idx++]=EMM_SHARED;
275        filter[idx++]=0;
276        filter[idx+0]    = 0x84;
277        filter[idx+0+16] = 0xFF;
278        memcpy(filter+idx+1, &rdr->prid[prov][2], 2);
279        memset(filter+idx+1+16, 0xFF, 2);
280        memcpy(filter+idx+3, &rdr->sa[prov], 3);
281        memset(filter+idx+3+16, 0xFF, 3);
282        filter[1]++;
283        idx += 32;
284        if (filter[1]>=10) {
285            cs_log("seca_get_emm_filter: could not start all emm filter");
286            break;
287        }
288    }
289
290    return;
291}
292
293   
294static int32_t seca_do_emm(struct s_reader * reader, EMM_PACKET *ep)
295{
296  def_resp;
297  unsigned char ins40[] = { 0xc1,0x40,0x00,0x00,0x00 };
298  int32_t i,ins40data_offset;
299  int32_t emm_length = ((ep->emm[1] & 0x0f) << 8) + ep->emm[2];
300  uint8_t *prov_id_ptr;
301
302  cs_ddump_mask (D_EMM, ep->emm, emm_length + 3, "EMM:");
303  switch (ep->type) {
304        case SHARED:
305            ins40[3]=ep->emm[9];
306            ins40[4]= emm_length - 0x07;
307            ins40data_offset = 10;
308            prov_id_ptr = ep->emm+3;
309            break;
310
311        case UNIQUE:   
312            ins40[3]=ep->emm[12];
313            ins40[4]= emm_length - 0x0A;
314            ins40data_offset = 13;
315            prov_id_ptr = ep->emm+9;
316            break;
317
318        default:
319                cs_log("[seca-reader] EMM: Congratulations, you have discovered a new EMM on SECA.");
320            cs_log("This has not been decoded yet, so send this output to authors:");
321            cs_dump (ep->emm, emm_length + 3, "EMM:");
322            return ERROR;
323  }
324
325  i=get_prov_index(reader, prov_id_ptr);
326  if (i==-1) 
327  {
328      cs_log("[seca-reader] EMM: provider id not found.");
329    return ERROR;
330  }
331
332  ins40[2]=(ep->emm[ins40data_offset-2] & 0xF0) | (i & 0x0F);
333  write_cmd(ins40, ep->emm + ins40data_offset); //emm request
334  if (cta_res[0] == 0x97) {
335     if (!(cta_res[1] & 4)) // date updated
336        set_provider_info(reader, i);
337     else
338        cs_log("[seca-reader] EMM: Update not necessary.");
339     return OK; //Update not necessary
340  }
341  if ((cta_res[0] == 0x90) && ((cta_res[1] == 0x00) || (cta_res[1] == 0x19)))
342    if (set_provider_info(reader, i) == OK) //after successfull EMM, print32_t new provider info
343      return OK;
344  return ERROR;
345}
346
347static int32_t seca_card_info (struct s_reader * reader)
348{
349//SECA Package BitMap records (PBM) can be used to determine whether the channel is part of the package that the SECA card can decrypt. This module reads the PBM
350//from the SECA card. It cannot be used to check the channel, because this information seems to reside in the CA-descriptor, which seems not to be passed on through servers like camd, newcamd, radegast etc.
351//
352//This module is therefore optical only
353
354  def_resp;
355  static const unsigned char ins34[] = { 0xc1, 0x34, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00 };              //data following is provider Package Bitmap Records
356  unsigned char ins32[] = { 0xc1, 0x32, 0x00, 0x00, 0x20 };             // get PBM
357  int32_t prov;
358
359  for (prov = 0; prov < reader->nprov; prov++) {
360    ins32[2] = prov;
361    write_cmd (ins34, ins34 + 5);   //prepare card for pbm request
362    write_cmd (ins32, NULL);    //pbm request
363    uchar pbm[8];       //TODO should be arrayed per prov
364    switch (cta_res[0]) {
365    case 0x04:
366      cs_ri_log (reader, "[seca-reader] no PBM for provider %i", prov + 1);
367      break;
368    case 0x83:
369      memcpy (pbm, cta_res + 1, 8);
370      cs_ri_log (reader, "[seca-reader] PBM for provider %i: %s", prov + 1, cs_hexdump (0, pbm, 8));
371      break;
372    default:
373      cs_log ("[seca-reader] ERROR: PBM returns unknown byte %02x", cta_res[0]);
374    }
375  }
376  return OK;
377}
378
379void reader_seca(struct s_cardsystem *ph) 
380{
381    ph->do_emm=seca_do_emm;
382    ph->do_ecm=seca_do_ecm;
383    ph->card_info=seca_card_info;
384    ph->card_init=seca_card_init;
385    ph->get_emm_type=seca_get_emm_type;
386    ph->get_emm_filter=seca_get_emm_filter;
387    ph->caids[0]=0x01;
388    ph->desc="seca";
389}
Note: See TracBrowser for help on using the repository browser.