source: trunk/reader-seca.c@ 4149

Last change on this file since 4149 was 4141, checked in by dingo35, 13 years ago

all: simplify debug system, add D_DVBAPI = -d128, eliminate cs_ptyp which complicates stuff unnecc

File size: 11.9 KB
Line 
1#include "globals.h"
2#include "reader-common.h"
3#include <stdlib.h>
4
5static int set_provider_info(struct s_reader * reader, int i)
6{
7 def_resp;
8 uchar ins12[] = { 0xc1, 0x12, 0x00, 0x00, 0x19 }; // get provider info
9 int year, month, day;
10 struct tm *lt;
11 time_t t;
12 int 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 lt=localtime(&t);
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 int 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 int seca_card_init(struct s_reader * reader, ATR newatr)
85{
86 get_atr;
87 def_resp;
88 char *card;
89 unsigned short pmap=0; // provider-maptable
90 unsigned long long 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 int 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[0]=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[0], 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 sprintf((char *) buf+strlen((char *)buf), ",%04lX", 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 int get_prov_index(struct s_reader * rdr, char *provid) //returns provider id or -1 if not found
145{
146 int 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 int 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 int i;
160 i=get_prov_index(reader, (char *) er->ecm+3);
161 if ((i == -1) || (reader->availkeys[i][0] == 0)) //if provider not found or expired
162 {
163 if( i == -1 )
164 snprintf( er->msglog, MSGLOGSIZE, "provider not found" );
165 else
166 snprintf( er->msglog, MSGLOGSIZE, "provider expired" );
167
168 return ERROR;
169 }
170
171 ins3c[2]=i;
172 ins3c[3]=er->ecm[7]; //key nr
173 ins3c[4]=(((er->ecm[1]&0x0f) << 8) | er->ecm[2])-0x05;
174 write_cmd(ins3c, er->ecm+8); //ecm request
175 unsigned char ins30[] = { 0xC1, 0x30, 0x00, 0x02, 0x09 };
176 unsigned char ins30data[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF };
177 /* We need to use a token */
178 if (cta_res[0] == 0x90 && cta_res[1] == 0x1a) {
179 write_cmd(ins30, ins30data);
180 write_cmd(ins3c, er->ecm+8); //ecm request
181 }
182 if ((cta_res[0] != 0x90) || (cta_res[1] != 0x00)) { snprintf( er->msglog, MSGLOGSIZE, "ins3c card response: %02x %02x", cta_res[0] , cta_res[1] ); return ERROR; }
183 write_cmd(ins3a, NULL); //get cw's
184 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!
185 memcpy(er->cw,cta_res,16);
186 return OK;
187}
188
189static int 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
190{
191 cs_debug_mask(D_EMM, "Entered seca_get_emm_type ep->emm[0]=%i",ep->emm[0]);
192 int i;
193 switch (ep->emm[0]) {
194 case 0x82:
195 ep->type = UNIQUE;
196 memset(ep->hexserial,0,8);
197 memcpy(ep->hexserial, ep->emm + 3, 6);
198 cs_debug_mask(D_EMM, "SECA EMM: UNIQUE, ep->hexserial = %s", cs_hexdump(1, ep->hexserial, 6));
199 cs_debug_mask(D_EMM, "SECA EMM: UNIQUE, rdr->hexserial = %s", cs_hexdump(1, rdr->hexserial, 6));
200 return (!memcmp (rdr->hexserial, ep->hexserial, 6));
201
202 case 0x84:
203 ep->type = SHARED;
204 memset(ep->hexserial,0,8);
205 memcpy(ep->hexserial, ep->emm + 5, 3); //dont include custom byte; this way the network also knows SA
206 i=get_prov_index(rdr, (char *) ep->emm+3);
207 cs_debug_mask(D_EMM, "SECA EMM: SHARED, ep->hexserial = %s", cs_hexdump(1, ep->hexserial, 3));
208 if (i== -1) //provider not found on this card
209 return FALSE; //do not pass this EMM
210 cs_debug_mask(D_EMM, "SECA EMM: SHARED, rdr->sa[%i] = %s", i, cs_hexdump(1, rdr->sa[i], 3));
211 return (!memcmp (rdr->sa[i], ep->hexserial, 3));
212
213 // Unknown EMM types, but allready subbmited to dev's
214 // FIXME: Drop EMM's until there are implemented
215 case 0x83:
216 /* EMM-G ?
217 83 00 74 00 00 00 00 00 C4 7B E7 54 8D 25 8D 27
218 CD 9C 87 4F B2 24 85 68 13 81 5E F1 EA AB 73 6D
219 78 A2 86 F3 C9 4E 78 55 48 21 E4 A0 0B A0 54 3B
220 5C 54 4B 01 39 1F FE C6 29 33 B8 6C 48 A0 9F 60
221 47 EB 6A FC D3 CD 4B 9A 50 F2 05 80 66 F3 82 48
222 22 EF E3 04 28 86 1D AB 82 26 9B 4D 09 B1 A8 F1
223 1D D4 50 69 44 E8 94 04 91 5F 21 A2 3C 43 BC CB
224 DD C1 90 AD 71 A7 38
225 */
226 case 0x88:
227 case 0x89:
228 // EMM-G ?
229 ep->type = UNKNOWN;
230 return FALSE;
231
232 default:
233 ep->type = UNKNOWN;
234 return TRUE;
235 }
236}
237
238static void seca_get_emm_filter(struct s_reader * rdr, uchar *filter)
239{
240 int numfilter=1;
241
242 filter[2]=UNIQUE;
243 filter[3]=0;
244
245 filter[4+0] = 0x82;
246 filter[4+0+16] = 0xFF;
247 memcpy(filter+4+1, rdr->hexserial, 6);
248 memset(filter+4+1+16, 0xFF, 6);
249
250 int prov, startpos=36;
251 for (prov=0; prov<rdr->nprov; prov++) {
252 filter[startpos++]=SHARED;
253 filter[startpos++]=0;
254
255 filter[startpos+0] = 0x84;
256 filter[startpos+0+16] = 0xFF;
257
258 memcpy(filter+startpos+1, &rdr->prid[prov][1], 2);
259 memset(filter+startpos+1+16, 0xFF, 2);
260
261 memcpy(filter+startpos+3, &rdr->sa[prov], 3);
262 memset(filter+startpos+3+16, 0xFF, 3);
263
264 numfilter++;
265 startpos+=32;
266 if (startpos>221) {
267 cs_log("seca_get_emm_filter: could not start all emm filter");
268 break;
269 }
270 }
271
272 filter[0]=0xFF;
273 filter[1]=numfilter;
274
275 return;
276}
277
278
279static int seca_do_emm(struct s_reader * reader, EMM_PACKET *ep)
280{
281 def_resp;
282 unsigned char ins40[] = { 0xc1,0x40,0x00,0x00,0x00 };
283 int i,ins40data_offset;
284 int emm_length = ((ep->emm[1] & 0x0f) << 8) + ep->emm[2];
285 char *prov_id_ptr;
286
287 cs_ddump_mask (D_EMM, ep->emm, emm_length + 3, "EMM:");
288 switch (ep->type) {
289 case SHARED:
290 ins40[3]=ep->emm[9];
291 ins40[4]= emm_length - 0x07;
292 ins40data_offset = 10;
293 prov_id_ptr = (char *)ep->emm+3;
294 break;
295
296 case UNIQUE:
297 ins40[3]=ep->emm[12];
298 ins40[4]= emm_length - 0x0A;
299 ins40data_offset = 13;
300 prov_id_ptr = (char *)ep->emm+9;
301 break;
302
303 default:
304 cs_log("[seca-reader] EMM: Congratulations, you have discovered a new EMM on SECA.");
305 cs_log("This has not been decoded yet, so send this output to authors:");
306 cs_dump (ep->emm, emm_length + 3, "EMM:");
307 return ERROR;
308 }
309
310 i=get_prov_index(reader, prov_id_ptr);
311 if (i==-1)
312 {
313 cs_log("[seca-reader] EMM: provider id not found.");
314 return ERROR;
315 }
316
317 ins40[2]=i;
318 write_cmd(ins40, ep->emm + ins40data_offset); //emm request
319 if (cta_res[0] == 0x97) {
320 cs_log("[seca-reader] EMM: Update not necessary.");
321 return OK; //Update not necessary
322 }
323 if ((cta_res[0] == 0x90) && ((cta_res[1] == 0x00) || (cta_res[1] == 0x19)))
324 if (set_provider_info(reader, i) == OK) //after successfull EMM, print new provider info
325 return OK;
326 return ERROR;
327}
328
329static int seca_card_info (struct s_reader * reader)
330{
331//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
332//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.
333//
334//This module is therefore optical only
335
336 def_resp;
337 static const unsigned char ins34[] = { 0xc1, 0x34, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00 }; //data following is provider Package Bitmap Records
338 unsigned char ins32[] = { 0xc1, 0x32, 0x00, 0x00, 0x20 }; // get PBM
339 int prov;
340
341 for (prov = 0; prov < reader->nprov; prov++) {
342 ins32[2] = prov;
343 write_cmd (ins34, ins34 + 5); //prepare card for pbm request
344 write_cmd (ins32, NULL); //pbm request
345 uchar pbm[8]; //TODO should be arrayed per prov
346 switch (cta_res[0]) {
347 case 0x04:
348 cs_ri_log (reader, "[seca-reader] no PBM for provider %i", prov + 1);
349 break;
350 case 0x83:
351 memcpy (pbm, cta_res + 1, 8);
352 cs_ri_log (reader, "[seca-reader] PBM for provider %i: %s", prov + 1, cs_hexdump (0, pbm, 8));
353 break;
354 default:
355 cs_log ("[seca-reader] ERROR: PBM returns unknown byte %02x", cta_res[0]);
356 }
357 }
358 return OK;
359}
360
361void reader_seca(struct s_cardsystem *ph)
362{
363 ph->do_emm=seca_do_emm;
364 ph->do_ecm=seca_do_ecm;
365 ph->card_info=seca_card_info;
366 ph->card_init=seca_card_init;
367 ph->get_emm_type=seca_get_emm_type;
368 ph->get_emm_filter=seca_get_emm_filter;
369 ph->caids[0]=0x01;
370 ph->desc="seca";
371}
Note: See TracBrowser for help on using the repository browser.