source: trunk/reader-seca.c@ 3181

Last change on this file since 3181 was 3181, checked in by dingo35, 10 years ago

Adding threadsafety FIXMEs, feel free to join checking..

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