source: trunk/reader-conax.c @ 5375

Last change on this file since 5375 was 5359, checked in by Admin, 8 years ago

Fix #1894: Don't add messages about sending the pin to the card to the entitlements info.

File size: 9.2 KB
Line 
1#include "globals.h"
2#include "reader-common.h"
3
4static char *chid_date(const uchar *ptr, char *buf, int32_t l)
5{
6  if (buf)
7  {
8    snprintf(buf, l, "%04d/%02d/%02d",
9              1990+(ptr[1]>>4)+(((ptr[0]>>5)&7)*10), ptr[1]&0xf, ptr[0]&0x1f);
10  }
11  return(buf);
12}
13
14static int32_t read_record(struct s_reader * reader, const uchar *cmd, const uchar *data, uchar * cta_res)
15{
16  uint16_t cta_lr;
17  uchar insCA[] = {0xDD, 0xCA, 0x00, 0x00, 0x00};
18
19  write_cmd(cmd, data);     // select record
20  if (cta_res[0]!=0x98)
21    return(-1);
22   
23  insCA[4]=cta_res[1];      // get len
24  write_cmd(insCA, NULL);   // read record
25  if ((cta_res[cta_lr-2]!=0x90) || (cta_res[cta_lr-1]))
26    return(-1);
27  return(cta_lr-2);
28}
29
30static int32_t conax_card_init(struct s_reader * reader, ATR newatr)
31{
32  unsigned char cta_res[CTA_RES_LEN];
33  int32_t i, j, n;
34  static const uchar ins26[] = {0xDD, 0x26, 0x00, 0x00, 0x03, 0x10, 0x01, 0x40};
35  uchar ins82[] = {0xDD, 0x82, 0x00, 0x00, 0x11, 0x11, 0x0f, 0x01, 0xb0, 0x0f, 0xff, \
36                   0xff, 0xfb, 0x00, 0x00, 0x09, 0x04, 0x0b, 0x00, 0xe0, 0x30, 0x2b };
37
38  uchar cardver=0;
39
40  get_hist;
41  if ((hist_size < 4) || (memcmp(hist,"0B00",4)))
42    return ERROR;
43
44  reader->caid=0xB00;
45
46  if ((n=read_record(reader, ins26, ins26+5, cta_res))<=0) return ERROR;   // read caid, card-version
47
48  for (i=0; i<n; i+=cta_res[i+1]+2)
49    switch(cta_res[i])
50    {
51      case 0x20: cardver=cta_res[i+2]; break;
52      case 0x28: reader->caid=(cta_res[i+2]<<8)|cta_res[i+3];
53    }
54
55  // Ins82 command needs to use the correct CAID reported in nano 0x28
56  ins82[17]=(reader->caid>>8)&0xFF;
57  ins82[18]=(reader->caid)&0xFF;
58
59  if ((n=read_record(reader, ins82, ins82+5, cta_res))<=0) return ERROR; // read serial
60
61  for (j=0, i=2; i<n; i+=cta_res[i+1]+2)
62    switch(cta_res[i])
63    {
64      case 0x23:
65        if (cta_res[i+5] != 0x00) {
66          memcpy(reader->hexserial, &cta_res[i+3], 6);
67        }
68        else {
69          memcpy(reader->sa[j], &cta_res[i+5], 4);
70          j++;
71        }
72        break;
73    }
74
75  // we have one provider, 0x0000
76  reader->nprov = 1;
77  memset(reader->prid, 0x00, sizeof(reader->prid));
78
79  cs_ri_log(reader, "type: Conax, caid: %04X, serial: %llu, hex serial: %02x%02x%02x%02x, card: v%d",
80         reader->caid, b2ll(6, reader->hexserial), reader->hexserial[2], 
81         reader->hexserial[3], reader->hexserial[4], reader->hexserial[5], cardver);
82
83  cs_ri_log(reader, "Providers: %d", reader->nprov);
84
85  for (j=0; j<reader->nprov; j++)
86  {
87    cs_ri_log(reader, "Provider: %d  Provider-Id: %06X", j+1, b2ll(4, reader->prid[j]));
88    cs_ri_log(reader, "Provider: %d  SharedAddress: %08X", j+1, b2ll(4, reader->sa[j]));
89  }
90
91  return OK;
92}
93
94static int32_t conax_send_pin(struct s_reader * reader)
95{
96  def_resp;
97  unsigned char insPIN[] = { 0xDD,0xC8,0x00,0x00,0x07,0x1D,0x05,0x01,0x00,0x00,0x00,0x00 }; //Last four are the Pin-Code
98  memcpy(insPIN+8,reader->pincode,4);
99
100  write_cmd(insPIN, insPIN+5);
101  cs_debug_mask(D_READER, "Sent pincode to card.");
102
103  return OK;
104}
105
106
107static int32_t conax_do_ecm(struct s_reader * reader, ECM_REQUEST *er)
108{
109  def_resp;
110  int32_t i,j,n, rc=0;
111  unsigned char insA2[]  = { 0xDD,0xA2,0x00,0x00,0x00 };
112  unsigned char insCA[]  = { 0xDD,0xCA,0x00,0x00,0x00 };
113
114  unsigned char buf[256];
115
116  if ((n=check_sct_len(er->ecm, 3))<0)
117    return ERROR;
118
119  buf[0]=0x14;
120  buf[1]=n+1;
121  buf[2]=0;
122
123  memcpy(buf+3, er->ecm, n);
124  insA2[4]=n+3;
125
126  write_cmd(insA2, buf);  // write Header + ECM
127
128  while ((cta_res[cta_lr-2]==0x98) &&   // Antwort
129  ((insCA[4]=cta_res[cta_lr-1])>0) && (insCA[4]!=0xFF))
130  {
131    write_cmd(insCA, NULL);  //Codeword auslesen
132
133    if ((cta_res[cta_lr-2]==0x98) ||
134    ((cta_res[cta_lr-2]==0x90) ))
135    {
136      for(i=0; i<cta_lr-2; i+=cta_res[i+1]+2)
137      {
138        switch (cta_res[i])
139        {
140          case 0x25:
141            if ( (cta_res[i+1]>=0xD) && !((n=cta_res[i+4])&0xFE) )
142            {
143            rc|=(1<<n);
144            memcpy(er->cw+(n<<3), cta_res+i+7, 8);
145            }
146            break;
147          case 0x31:
148            if ( (cta_res[i+1]==0x02  && cta_res[i+2]==0x00  && cta_res[i+3]==0x00) || \
149            (cta_res[i+1]==0x02  && cta_res[i+2]==0x40  && cta_res[i+3]==0x00) )
150              break;
151            else if (strcmp(reader->pincode, "none"))
152            {
153              conax_send_pin(reader);
154              write_cmd(insA2, buf);  // write Header + ECM
155
156              while ((cta_res[cta_lr-2]==0x98) &&   // Antwort
157                      ((insCA[4]=cta_res[cta_lr-1])>0) && (insCA[4]!=0xFF))
158              {
159                write_cmd(insCA, NULL);  //Codeword auslesen
160
161                if ((cta_res[cta_lr-2]==0x98) ||
162                    ((cta_res[cta_lr-2]==0x90) && (!cta_res[cta_lr-1])))
163                {
164                  for(j=0;j<cta_lr-2; j+=cta_res[j+1]+2)
165                    if ((cta_res[j]==0x25) &&       // access: is cw
166                        (cta_res[j+1]>=0xD) &&      // 0xD: 5 header + 8 cw
167                        !((n=cta_res[j+4])&0xFE))   // cw idx must be 0 or 1
168                    {
169                      rc|=(1<<n);
170                      memcpy(er->cw+(n<<3), cta_res+j+7, 8);
171                    }
172                }
173              }
174            }
175            break;
176        }
177      }
178    }
179  }
180  if (rc==3)
181    return OK;
182  else
183    return ERROR;
184}
185
186static int32_t conax_get_emm_type(EMM_PACKET *ep, struct s_reader * rdr)
187{
188    int32_t i, ok = 0;
189
190    cs_debug_mask(D_EMM, "Entered conax_get_emm_type ep->emm[2]=%02x", ep->emm[2]);
191
192    for (i = 0; i < rdr->nprov; i++) {
193        ok = (!memcmp(&ep->emm[6], rdr->sa[i], 4));
194        if (ok) break;
195    }
196
197    if (ok) {
198        ep->type = SHARED;
199        memset(ep->hexserial, 0, 8);
200        memcpy(ep->hexserial, &ep->emm[6], 4);
201        cs_debug_mask(D_EMM, "CONAX EMM: SHARED, ep->hexserial = %s", cs_hexdump(1, ep->hexserial, 8));
202        return TRUE;
203    }
204    else {
205        if (!memcmp(&ep->emm[6], rdr->hexserial+2, 4)) {
206            ep->type = UNIQUE;
207            memset(ep->hexserial, 0, 8);
208            memcpy(ep->hexserial+2, &ep->emm[6], 4);
209            cs_debug_mask(D_EMM, "CONAX EMM: UNIQUE, ep->hexserial = %s", cs_hexdump(1, ep->hexserial, 8));
210            return TRUE;
211        }
212        else {
213            ep->type = GLOBAL;
214            cs_debug_mask(D_EMM, "CONAX EMM: GLOBAL");
215            memset(ep->hexserial, 0, 8);
216            return TRUE;
217        }
218    }
219}
220
221static void conax_get_emm_filter(struct s_reader * rdr, uchar *filter)
222{
223    int32_t idx = 2;
224
225    filter[0]=0xFF; //header
226    filter[1]=0;        //filter count
227
228    filter[idx++]=EMM_GLOBAL;
229    filter[idx++]=1; // FIXME: dont see any conax global EMM yet
230    filter[idx+0]    = 0x82;
231    filter[idx+0+16] = 0xFF;
232    filter[idx+8]    = 0x70;
233    filter[idx+8+16] = 0xFF;
234    filter[1]++;
235    idx += 32;
236
237    filter[idx++]=EMM_SHARED;
238    filter[idx++]=0;
239    filter[idx+0]    = 0x82;
240    filter[idx+0+16] = 0xFF;
241    filter[idx+8]    = 0x70;
242    filter[idx+8+16] = 0xFF;
243    memcpy(filter+idx+4, rdr->sa[0], 4);
244    memset(filter+idx+4+16, 0xFF, 4);
245    filter[1]++;
246    idx += 32;
247
248    filter[idx++]=EMM_UNIQUE;
249    filter[idx++]=0;
250    filter[idx+0]    = 0x82;
251    filter[idx+0+16] = 0xFF;
252    filter[idx+8]    = 0x70;
253    filter[idx+8+16] = 0xFF;
254    memcpy(filter+idx+4, rdr->hexserial + 2, 4);
255    memset(filter+idx+4+16, 0xFF, 4);
256    filter[1]++;
257    idx += 32;
258
259    return;
260}
261
262static int32_t conax_do_emm(struct s_reader * reader, EMM_PACKET *ep)
263{
264  def_resp;
265  unsigned char insEMM[] = { 0xDD,0x84,0x00,0x00,0x00 };
266  unsigned char buf[255];
267  int32_t rc=0;
268
269  const int32_t l = ep->emm[2];
270
271  insEMM[4]=l+5;
272  buf[0]=0x12;
273  buf[1]=l+3;
274  memcpy(buf+2, ep->emm, buf[1]);
275  write_cmd(insEMM, buf);
276
277  rc=((cta_res[0]==0x90)&&(cta_res[1]==0x00));
278
279  if (rc)
280    return OK;
281  else
282    return ERROR;
283}
284
285static int32_t conax_card_info(struct s_reader * reader)
286{
287  def_resp;
288  int32_t type, i, j, k, n=0;
289  uint16_t provid;
290  char provname[32], pdate[32];
291  static const uchar insC6[] = {0xDD, 0xC6, 0x00, 0x00, 0x03, 0x1C, 0x01, 0x00};
292  static const uchar ins26[] = {0xDD, 0x26, 0x00, 0x00, 0x03, 0x1C, 0x01, 0x01};
293  uchar insCA[] = {0xDD, 0xCA, 0x00, 0x00, 0x00};
294  char *txt[] = { "Package", "PPV-Event" };
295  static const uchar *cmd[] = { insC6, ins26 };
296
297  for (type=0; type<2; type++)
298  {
299    n=0;
300    write_cmd(cmd[type], cmd[type]+5);
301    while (cta_res[cta_lr-2]==0x98)
302    {
303      insCA[4]=cta_res[cta_lr-1];       // get len
304      write_cmd(insCA, NULL);       // read
305      if ((cta_res[cta_lr-2]==0x90) || (cta_res[cta_lr-2]==0x98))
306      {
307        for (j=0; j<cta_lr-2; j+=cta_res[j+1]+2)
308        {
309          provid=(cta_res[j+2+type]<<8) | cta_res[j+3+type];
310          for (k=0, i=j+4+type; (i<j+cta_res[j+1]) && (k<2); i+=cta_res[i+1]+2)
311          {
312            int32_t l;
313            switch(cta_res[i])
314            {
315              case 0x01: l=(cta_res[i+1]<(sizeof(provname)-1)) ?
316                           cta_res[i+1] : sizeof(provname)-1;
317                         memcpy(provname, cta_res+i+2, l);
318                         provname[l]='\0';
319                         break;
320              case 0x30: chid_date(cta_res+i+2, pdate+(k++<<4), 15);
321                         break;
322            }
323          }
324          cs_ri_log(reader, "%s: %d, id: %04X, date: %s - %s, name: %s",
325                    txt[type], ++n, provid, pdate, pdate+16, trim(provname));
326        }
327      }
328    }
329  }
330  cs_log("[conax-reader] ready for requests");
331  return OK;
332}
333
334void reader_conax(struct s_cardsystem *ph) 
335{
336    ph->do_emm=conax_do_emm;
337    ph->do_ecm=conax_do_ecm;
338    ph->card_info=conax_card_info;
339    ph->card_init=conax_card_init;
340    ph->get_emm_type=conax_get_emm_type;
341    ph->get_emm_filter=conax_get_emm_filter;
342    ph->caids[0]=0x0B;
343    ph->desc="conax";
344}
Note: See TracBrowser for help on using the repository browser.