source: trunk/reader-viaccess.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: 24.3 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
5struct via_date {
6 ushort day_s : 5;
7 ushort month_s : 4;
8 ushort year_s : 7;
9
10 ushort day_e : 5;
11 ushort month_e : 4;
12 ushort year_e : 7;
13};
14
15static void parse_via_date(const uchar *buf, struct via_date *vd, int fend)
16{
17 ushort date;
18
19 date = (buf[0]<<8) | buf[1];
20 vd->day_s = date & 0x1f;
21 vd->month_s = (date>>5) & 0x0f;
22 vd->year_s = (date>>9) & 0x7f;
23
24 if( fend )
25 {
26 date = (buf[2]<<8) | buf[3];
27 vd->day_e = date & 0x1f;
28 vd->month_e = (date>>5) & 0x0f;
29 vd->year_e = (date>>9) & 0x7f;
30 }
31}
32
33static void show_class(struct s_reader * reader, const char *p, const uchar *b, int l)
34{
35 int i, j;
36
37 // b -> via date (4 bytes)
38 b+=4;
39 l-=4;
40
41 j=l-1;
42 for (; j>=0; j--)
43 for (i=0; i<8; i++)
44 if (b[j] & (1 << (i&7)))
45 {
46 uchar cls;
47 struct via_date vd;
48 parse_via_date(b-4, &vd, 1);
49 cls=(l-(j+1))*8+i;
50 if (p)
51 cs_log("%sclass: %02X, expiry date: %04d/%02d/%02d - %04d/%02d/%02d", p, cls,
52 vd.year_s+1980, vd.month_s, vd.day_s,
53 vd.year_e+1980, vd.month_e, vd.day_e);
54 else
55 cs_ri_log(reader, "class: %02X, expiry date: %04d/%02d/%02d - %04d/%02d/%02d", cls,
56 vd.year_s+1980, vd.month_s, vd.day_s,
57 vd.year_e+1980, vd.month_e, vd.day_e);
58 }
59}
60
61static void show_subs(struct s_reader * reader, const uchar *emm)
62{
63 // emm -> A9, A6, B6
64
65 switch( emm[0] )
66 {
67 case 0xA9:
68 show_class(reader, "nano A9: ", emm+2, emm[1]);
69 break;
70/*
71 {
72 int i, j, byts;
73 const uchar *oemm;
74
75 oemm = emm;
76 byts = emm[1]-4;
77 emm+=6;
78
79 j=byts-1;
80 for( ; j>=0; j-- )
81 for( i=0; i<8; i++ )
82 if( emm[j] & (1 << (i&7)) )
83 {
84 uchar cls;
85 struct via_date vd;
86 parse_via_date(emm-4, &vd, 1);
87 cls=(byts-(j+1))*8+i;
88 cs_log("%sclass %02X: expiry date: %02d/%02d/%04d - %02d/%02d/%04d",
89 fnano?"nano A9: ":"", cls,
90 vd.day_s, vd.month_s, vd.year_s+1980,
91 vd.day_e, vd.month_e, vd.year_e+1980);
92 }
93 break;
94 }
95*/
96 case 0xA6:
97 {
98 char szGeo[256];
99
100 memset(szGeo, 0, 256);
101 strncpy(szGeo, (char *)emm+2, emm[1]);
102 cs_log("[viaccess-reader] nano A6: geo %s", szGeo);
103 break;
104 }
105 case 0xB6:
106 {
107 uchar m; // modexp
108 struct via_date vd;
109
110 m=emm[emm[1]+1];
111 parse_via_date(emm+2, &vd, 0);
112 cs_log("[viaccess-reader] nano B6: modexp %d%d%d%d%d%d: %02d/%02d/%04d", (m&0x20)?1:0,
113 (m&0x10)?1:0,(m&0x08)?1:0,(m&0x04)?1:0,(m&0x02)?1:0,(m&0x01)?1:0,
114 vd.day_s, vd.month_s, vd.year_s+1980);
115 break;
116 }
117 }
118}
119
120static int chk_prov(struct s_reader * reader, uchar *id, uchar keynr)
121{
122 int i, j, rc;
123 for (rc=i=0; (!rc) && (i<reader->nprov); i++)
124 if(!memcmp(&reader->prid[i][1], id, 3))
125 for (j=0; (!rc) && (j<16); j++)
126 if (reader->availkeys[i][j]==keynr)
127 rc=1;
128 return(rc);
129}
130
131int viaccess_card_init(struct s_reader * reader, ATR newatr)
132{
133 get_atr;
134 def_resp;
135 int i;
136 uchar buf[256];
137 uchar insac[] = { 0xca, 0xac, 0x00, 0x00, 0x00 }; // select data
138 uchar insb8[] = { 0xca, 0xb8, 0x00, 0x00, 0x00 }; // read selected data
139 uchar insa4[] = { 0xca, 0xa4, 0x00, 0x00, 0x00 }; // select issuer
140 uchar insc0[] = { 0xca, 0xc0, 0x00, 0x00, 0x00 }; // read data item
141
142 static const uchar insFAC[] = { 0x87, 0x02, 0x00, 0x00, 0x03 }; // init FAC
143 static const uchar FacDat[] = { 0x00, 0x00, 0x28 };
144
145 if ((atr[0]!=0x3f) || (atr[1]!=0x77) || ((atr[2]!=0x18) && (atr[2]!=0x11) && (atr[2]!=0x19)) || (atr[9]!=0x68)) return ERROR;
146
147 write_cmd(insFAC, FacDat);
148 if( !(cta_res[cta_lr-2]==0x90 && cta_res[cta_lr-1]==0) )
149 return ERROR;
150
151// switch((atr[atrsize-4]<<8)|atr[atrsize-3])
152// {
153// case 0x6268: ver="2.3"; break;
154// case 0x6668: ver="2.4(?)"; break;
155// case 0xa268:
156// default: ver="unknown"; break;
157// }
158
159 reader->caid[0]=0x500;
160 memset(reader->prid, 0xff, sizeof(reader->prid));
161 insac[2]=0xa4; write_cmd(insac, NULL); // request unique id
162 insb8[4]=0x07; write_cmd(insb8, NULL); // read unique id
163 memcpy(reader->hexserial, cta_res+2, 5);
164// cs_log("[viaccess-reader] type: Viaccess, ver: %s serial: %llu", ver, b2ll(5, cta_res+2));
165 cs_ri_log(reader, "type: Viaccess (%sstandard atr), caid: %04X, serial: %llu",
166 atr[9]==0x68?"":"non-",reader->caid[0], b2ll(5, cta_res+2));
167
168 i=0;
169 insa4[2]=0x00; write_cmd(insa4, NULL); // select issuer 0
170 buf[0]=0;
171 while((cta_res[cta_lr-2]==0x90) && (cta_res[cta_lr-1]==0))
172 {
173 insc0[4]=0x1a; write_cmd(insc0, NULL); // show provider properties
174 cta_res[2]&=0xF0;
175 reader->prid[i][0]=0;
176 memcpy(&reader->prid[i][1], cta_res, 3);
177 memcpy(&reader->availkeys[i][0], cta_res+10, 16);
178 sprintf((char *)buf+strlen((char *)buf), ",%06lX", b2i(3, &reader->prid[i][1]));
179//cs_log("[viaccess-reader] buf: %s", buf);
180
181 insac[2]=0xa5; write_cmd(insac, NULL); // request sa
182 insb8[4]=0x06; write_cmd(insb8, NULL); // read sa
183 memcpy(&reader->sa[i][0], cta_res+2, 4);
184
185/*
186 insac[2]=0xa7; write_cmd(insac, NULL); // request name
187 insb8[4]=0x02; write_cmd(insb8, NULL); // read name nano + len
188 l=cta_res[1];
189 insb8[4]=l; write_cmd(insb8, NULL); // read name
190 cta_res[l]=0;
191cs_log("[viaccess-reader] name: %s", cta_res);
192*/
193
194 insa4[2]=0x02;
195 write_cmd(insa4, NULL); // select next issuer
196 i++;
197 }
198 reader->nprov=i;
199 cs_ri_log(reader, "providers: %d (%s)", reader->nprov, buf+1);
200
201 /* init the maybe existing aes key */
202 aes_set_key((char *)reader->aes_key);
203
204 /* disabling parental lock. assuming pin "0000" */
205 if (cfg->ulparent) {
206 static const uchar inDPL[] = {0xca, 0x24, 0x02, 0x00, 0x09};
207 static const uchar cmDPL[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F};
208 write_cmd(inDPL,cmDPL);
209 if( !(cta_res[cta_lr-2]==0x90 && cta_res[cta_lr-1]==0) )
210 cs_log("[viaccess-reader] Can't disable parental lock. Wrong PIN? I assumed 0000!");
211 else
212 cs_log("[viaccess-reader] Parental lock disabled");
213 }
214
215 cs_log("[viaccess-reader] ready for requests");
216 memset(&reader->last_geo, 0, sizeof(reader->last_geo));
217 return OK;
218}
219
220int viaccess_do_ecm(struct s_reader * reader, ECM_REQUEST *er)
221{
222 def_resp;
223 static const unsigned char insa4[] = { 0xca,0xa4,0x04,0x00,0x03 }; // set provider id
224 unsigned char ins88[] = { 0xca,0x88,0x00,0x00,0x00 }; // set ecm
225 unsigned char insf8[] = { 0xca,0xf8,0x00,0x00,0x00 }; // set geographic info
226 static const unsigned char insc0[] = { 0xca,0xc0,0x00,0x00,0x12 }; // read dcw
227
228 const uchar *ecm88Data=er->ecm+4; //XXX what is the 4th byte for ??
229 int ecm88Len=SCT_LEN(er->ecm)-4;
230 ulong provid=0;
231 int rc=0;
232 int hasD2 = 0;
233 int curEcm88len=0;
234 int nanoLen=0;
235 const uchar *nextEcm;
236 uchar keyToUse=0;
237 uchar DE04[256];
238 int D2KeyID=0;
239 memset(DE04, 0, sizeof(DE04)); //fix dorcel de04 bug
240
241 nextEcm=ecm88Data;
242
243 while (ecm88Len && !rc) {
244
245 if(ecm88Data[0] ==0x00 && ecm88Data[1] == 0x00) {
246 // nano 0x00 and len 0x00 aren't valid ... something is obviously wrong with this ecm.
247 cs_log("[viaccess-reader] ECM: Invalid ECM structure. Rejecting");
248 return ERROR;
249 }
250
251 // 80 33 nano 80 (ecm) + len (33)
252 if(ecm88Data[0]==0x80) { // nano 80, give ecm len
253 curEcm88len=ecm88Data[1];
254 nextEcm=ecm88Data+curEcm88len+2;
255 ecm88Data += 2;
256 ecm88Len -= 2;
257 }
258
259 if(!curEcm88len) { //there was no nano 80 -> simple ecm
260 curEcm88len=ecm88Len;
261 }
262
263 // d2 02 0d 02 -> D2 nano, len 2, select the AES key to be used
264 if(ecm88Data[0]==0xd2) {
265 // use the d2 arguments to get the key # to be used
266 int len = ecm88Data[1] + 2;
267 D2KeyID=ecm88Data[3];
268 ecm88Data += len;
269 ecm88Len -= len;
270 curEcm88len -=len;
271 hasD2 = 1;
272 }
273 else
274 hasD2 = 0;
275
276 // 40 07 03 0b 00 -> nano 40, len =7 ident 030B00 (tntsat), key #0 <== we're pointing here
277 // 09 -> use key #9
278 // 05 67 00
279 if ((ecm88Data[0]==0x90 || ecm88Data[0]==0x40) && (ecm88Data[1]==0x03 || ecm88Data[1]==0x07 ) )
280 {
281 uchar ident[3], keynr;
282 //uchar buff[256]; // MAX_LEN
283 uchar *ecmf8Data=0;
284 int ecmf8Len=0;
285
286 nanoLen=ecm88Data[1] + 2;
287
288 memcpy (ident, &ecm88Data[2], sizeof(ident));
289 provid = b2i(3, ident);
290 ident[2]&=0xF0;
291
292 if(hasD2 && reader->aes_list) {
293 // check that we have the AES key to decode the CW
294 // if not there is no need to send the ecm to the card
295 if(!aes_present(reader->aes_list, 0x500, (uint32) provid, D2KeyID))
296 return ERROR;
297 }
298
299 keynr=ecm88Data[4]&0x0F;
300 // 40 07 03 0b 00 -> nano 40, len =7 ident 030B00 (tntsat), key #0 <== we're pointing here
301 // 09 -> use key #9
302 if(nanoLen>5) {
303 keyToUse=ecm88Data[5];
304 keynr=keyToUse;
305 cs_debug("keyToUse = %d",keyToUse);
306 }
307
308 if (!chk_prov(reader, ident, keynr))
309 {
310 cs_debug("[viaccess-reader] ECM: provider or key not found on card");
311 snprintf( er->msglog, MSGLOGSIZE, "provider(%02x%02x%02x) or key(%d) not found on card", ident[0],ident[1],ident[2], keynr );
312 return ERROR;
313 }
314
315 ecm88Data+=nanoLen;
316 ecm88Len-=nanoLen;
317 curEcm88len-=nanoLen;
318
319 // DE04
320 if (ecm88Data[0]==0xDE && ecm88Data[1]==0x04)
321 {
322 memcpy (DE04, &ecm88Data[0], 6);
323 ecm88Data+=6;
324 }
325 //
326
327 if( reader->last_geo.provid != provid )
328 {
329 reader->last_geo.provid = provid;
330 reader->last_geo.geo_len = 0;
331 reader->last_geo.geo[0] = 0;
332 write_cmd(insa4, ident); // set provider
333 }
334
335 while(ecm88Len>0 && ecm88Data[0]<0xA0)
336 {
337 int nanoLen=ecm88Data[1]+2;
338 if (!ecmf8Data)
339 ecmf8Data=(uchar *)ecm88Data;
340 ecmf8Len+=nanoLen;
341 ecm88Len-=nanoLen;
342 curEcm88len-=nanoLen;
343 ecm88Data+=nanoLen;
344 }
345 if(ecmf8Len)
346 {
347 if( reader->last_geo.geo_len!=ecmf8Len ||
348 memcmp(reader->last_geo.geo, ecmf8Data, reader->last_geo.geo_len))
349 {
350 memcpy(reader->last_geo.geo, ecmf8Data, ecmf8Len);
351 reader->last_geo.geo_len= ecmf8Len;
352 insf8[3]=keynr;
353 insf8[4]=ecmf8Len;
354 write_cmd(insf8, ecmf8Data);
355 }
356 }
357 ins88[2]=ecmf8Len?1:0;
358 ins88[3]=keynr;
359 ins88[4]= curEcm88len;
360 //
361 // we should check the nano to make sure the ecm is valid
362 // we should look for at least 1 E3 nano, 1 EA nano and the F0 signature nano
363 //
364 // DE04
365 if (DE04[0]==0xDE)
366 {
367 memcpy(DE04+6, (uchar *)ecm88Data, curEcm88len-6);
368 write_cmd(ins88, DE04); // request dcw
369 }
370 else
371 {
372 write_cmd(ins88, (uchar *)ecm88Data); // request dcw
373 }
374 //
375 write_cmd(insc0, NULL); // read dcw
376 switch(cta_res[0])
377 {
378 case 0xe8: // even
379 if(cta_res[1]==8) { memcpy(er->cw,cta_res+2,8); rc=1; }
380 break;
381 case 0xe9: // odd
382 if(cta_res[1]==8) { memcpy(er->cw+8,cta_res+2,8); rc=1; }
383 break;
384 case 0xea: // complete
385 if(cta_res[1]==16) { memcpy(er->cw,cta_res+2,16); rc=1; }
386 break;
387 default :
388 ecm88Data=nextEcm;
389 ecm88Len-=curEcm88len;
390 cs_debug("[viaccess-reader] ECM: key to use is not the current one, trying next ECM");
391 snprintf( er->msglog, MSGLOGSIZE, "key to use is not the current one, trying next ECM" );
392 }
393 }
394 else {
395 ecm88Data=nextEcm;
396 ecm88Len-=curEcm88len;
397 cs_debug("[viaccess-reader] ECM: Unknown ECM type");
398 snprintf( er->msglog, MSGLOGSIZE, "Unknown ECM type" );
399 }
400 }
401
402 if (hasD2) {
403 if(reader->aes_list) {
404 cs_debug("Decoding CW : using AES key id %d for provider %06x",D2KeyID,provid);
405 rc=aes_decrypt_from_list(reader->aes_list,0x500, (uint32) provid, D2KeyID,er->cw, 16);
406 if( rc == 0 )
407 snprintf( er->msglog, MSGLOGSIZE, "AES Decrypt : key id %d not found for CAID %04X , provider %06lx", D2KeyID, 0x500, provid );
408 }
409 else
410 aes_decrypt(er->cw, 16);
411 }
412
413 return(rc?OK:ERROR);
414}
415
416int viaccess_get_emm_type(EMM_PACKET *ep, struct s_reader * rdr)
417{
418 cs_debug_mask(D_EMM, "Entered viaccess_get_emm_type ep->emm[0]=%02x",ep->emm[0]);
419
420 switch (ep->emm[0]) {
421 case 0x88:
422 ep->type=UNIQUE;
423 memset(ep->hexserial, 0, 8);
424 memcpy(ep->hexserial, ep->emm + 3, 3);
425 cs_debug_mask(D_EMM, "VIACCESS EMM: UNIQUE");
426 return(!memcmp(rdr->hexserial + 1, ep->hexserial, 4));
427
428 case 0x8A:
429 case 0x8B:
430 ep->type=GLOBAL;
431 cs_debug_mask(D_EMM, "VIACCESS EMM: GLOBAL");
432 return TRUE;
433
434 case 0x8C:
435 case 0x8D:
436 ep->type=SHARED;
437 cs_debug_mask(D_EMM, "VIACCESS EMM: SHARED (part)");
438 return FALSE;
439
440 case 0x8E:
441 ep->type=SHARED;
442 memset(ep->hexserial, 0, 8);
443 memcpy(ep->hexserial, ep->emm + 3, 3);
444 cs_debug_mask(D_EMM, "VIACCESS EMM: SHARED");
445 return(!memcmp(&rdr->sa[0][0], ep->hexserial, 3));
446
447 default:
448 ep->type = UNKNOWN;
449 cs_debug_mask(D_EMM, "VIACCESS EMM: UNKNOWN");
450 return TRUE;
451 }
452}
453
454void viaccess_get_emm_filter(struct s_reader * rdr, uchar *filter)
455{
456 filter[0]=0xFF;
457 filter[1]=3;
458
459 filter[2]=GLOBAL;
460 filter[3]=0;
461
462 filter[4+0] = 0x8D;
463 filter[4+0+16] = 0xFE;
464 //filter[4+6] = 0xA0; // FIXME: dummy, flood client with EMM's
465 //filter[4+6+16] = 0xF0;
466
467
468 filter[36]=SHARED;
469 filter[37]=0;
470
471 filter[38+0] = 0x8E;
472 filter[38+0+16] = 0xFF;
473 memcpy(filter+38+1, &rdr->sa[0][0], 3);
474 memset(filter+38+1+16, 0xFF, 3);
475
476
477 filter[70]=UNIQUE;
478 filter[71]=0;
479
480 filter[72+0] = 0x88;
481 filter[72+0+16] = 0xFF;
482 memcpy(filter+72+1, rdr->hexserial + 1, 4);
483 memset(filter+72+1+16, 0xFF, 4);
484
485 return;
486}
487
488int viaccess_do_emm(struct s_reader * reader, EMM_PACKET *ep)
489{
490 def_resp;
491 static const unsigned char insa4[] = { 0xca,0xa4,0x04,0x00,0x03 }; // set provider id
492 unsigned char insf0[] = { 0xca,0xf0,0x00,0x01,0x22 }; // set adf
493 unsigned char insf4[] = { 0xca,0xf4,0x00,0x01,0x00 }; // set adf, encrypted
494 unsigned char ins18[] = { 0xca,0x18,0x01,0x01,0x00 }; // set subscription
495 unsigned char ins1c[] = { 0xca,0x1c,0x01,0x01,0x00 }; // set subscription, encrypted
496 static const unsigned char insc8[] = { 0xca,0xc8,0x00,0x00,0x02 }; // read extended status
497 static const unsigned char insc8Data[] = { 0x00,0x00 }; // data for read extended status
498
499 int emmLen=SCT_LEN(ep->emm)-7;
500 int rc=0;
501
502 ///cs_dump(ep->emm, emmLen+7, "RECEIVED EMM VIACCESS");
503
504 int emmUpToEnd;
505 uchar *emmParsed = ep->emm+7;
506 int provider_ok = 0;
507 uchar keynr = 0;
508 int ins18Len = 0;
509 uchar ins18Data[512];
510 uchar insData[512];
511 uchar *nano81Data = 0;
512 uchar *nano91Data = 0;
513 uchar *nano92Data = 0;
514 uchar *nano9EData = 0;
515 uchar *nanoF0Data = 0;
516
517 for (emmUpToEnd=emmLen; (emmParsed[1] != 0) && (emmUpToEnd > 0); emmUpToEnd -= (2 + emmParsed[1]), emmParsed += (2 + emmParsed[1])) {
518 ///cs_dump (emmParsed, emmParsed[1] + 2, "NANO");
519
520 if (emmParsed[0]==0x90 && emmParsed[1]==0x03) {
521 /* identification of the service operator */
522
523 uchar soid[3], ident[3], i;
524
525 for (i=0; i<3; i++) {
526 soid[i]=ident[i]=emmParsed[2+i];
527 }
528 ident[2]&=0xF0;
529 keynr=soid[2]&0x0F;
530 if (chk_prov(reader, ident, keynr)) {
531 provider_ok = 1;
532 } else {
533 cs_debug("[viaccess-reader] EMM: provider or key not found on card (%x, %x)", ident, keynr);
534 cs_log("[viaccess-reader] EMM: provider or key not found on card (%x, %x)", ident, keynr);
535 return ERROR;
536 }
537
538 // as we are maybe changing the used provider, clear the cache, so the next ecm will re-select the correct one
539 memset(&reader->last_geo, 0, sizeof(reader->last_geo));
540
541 // set provider
542 write_cmd(insa4, soid);
543 if( cta_res[cta_lr-2]!=0x90 || cta_res[cta_lr-1]!=0x00 ) {
544 cs_dump(insa4, 5, "set provider cmd:");
545 cs_dump(soid, 3, "set provider data:");
546 cs_log("[viaccess-reader] update error: %02X %02X", cta_res[cta_lr-2], cta_res[cta_lr-1]);
547 return ERROR;
548 }
549 } else if (emmParsed[0]==0x9e && emmParsed[1]==0x20) {
550 /* adf */
551
552 if (!nano91Data) {
553 /* adf is not crypted, so test it */
554
555 uchar custwp;
556 uchar *afd;
557
558 custwp=reader->sa[0][3];
559 afd=(uchar*)emmParsed+2;
560
561 if( afd[31-custwp/8] & (1 << (custwp & 7)) )
562 cs_debug("[viaccess-reader] emm for our card %08X", b2i(4, &reader->sa[0][0]));
563 else
564 return SKIPPED;
565 }
566
567 // memorize
568 nano9EData = emmParsed;
569
570 } else if (emmParsed[0]==0x81) {
571 nano81Data = emmParsed;
572 } else if (emmParsed[0]==0x91 && emmParsed[1]==0x08) {
573 nano91Data = emmParsed;
574 } else if (emmParsed[0]==0x92 && emmParsed[1]==0x08) {
575 nano92Data = emmParsed;
576 } else if (emmParsed[0]==0xF0 && emmParsed[1]==0x08) {
577 nanoF0Data = emmParsed;
578 } else if (emmParsed[0]==0x1D && emmParsed[0]==0x01 && emmParsed[0]==0x01) {
579 /* from cccam... skip it... */
580 } else {
581 /* other nanos */
582 show_subs(reader, emmParsed);
583
584 memcpy(ins18Data+ins18Len, emmParsed, emmParsed[1] + 2);
585 ins18Len += emmParsed [1] + 2;
586 }
587 }
588
589 if (!provider_ok) {
590 cs_debug("[viaccess-reader] provider not found in emm, continue anyway");
591 // force key to 1...
592 keynr = 1;
593 ///return ERROR;
594 }
595
596 if (!nanoF0Data) {
597 cs_dump(ep->emm, ep->l, "can't find 0xf0 in emm...");
598 return ERROR; // error
599 }
600
601 if (nano9EData) {
602 if (!nano91Data) {
603 // set adf
604 insf0[3] = keynr; // key
605 write_cmd(insf0, nano9EData);
606 if( cta_res[cta_lr-2]!=0x90 || cta_res[cta_lr-1]!=0x00 ) {
607 cs_dump(insf0, 5, "set adf cmd:");
608 cs_dump(nano9EData, 0x22, "set adf data:");
609 cs_log("[viaccess-reader] update error: %02X %02X", cta_res[cta_lr-2], cta_res[cta_lr-1]);
610 return ERROR;
611 }
612 } else {
613 // set adf crypte
614 insf4[3] = keynr; // key
615 insf4[4] = nano91Data[1] + 2 + nano9EData[1] + 2;
616 memcpy (insData, nano91Data, nano91Data[1] + 2);
617 memcpy (insData + nano91Data[1] + 2, nano9EData, nano9EData[1] + 2);
618 write_cmd(insf4, insData);
619 if(( cta_res[cta_lr-2]!=0x90 && cta_res[cta_lr-2]!=0x91) || cta_res[cta_lr-1]!=0x00 ) {
620 cs_dump(insf4, 5, "set adf encrypted cmd:");
621 cs_dump(insData, insf4[4], "set adf encrypted data:");
622 cs_log("[viaccess-reader] update error: %02X %02X", cta_res[cta_lr-2], cta_res[cta_lr-1]);
623 return ERROR;
624 }
625 }
626 }
627
628 if (!nano92Data) {
629 // send subscription
630 ins18[4] = ins18Len + nanoF0Data[1] + 2;
631 memcpy (insData, ins18Data, ins18Len);
632 memcpy (insData + ins18Len, nanoF0Data, nanoF0Data[1] + 2);
633 write_cmd(ins18, insData);
634 if( (cta_res[cta_lr-2]==0x90 || cta_res[cta_lr-2]==0x91) && cta_res[cta_lr-1]==0x00 ) {
635 cs_debug("[viaccess-reader] update successfully written");
636 rc=1; // written
637 } else {
638 cs_dump(ins18, 5, "set subscription cmd:");
639 cs_dump(insData, ins18[4], "set subscription data:");
640 cs_log("[viaccess-reader] update error: %02X %02X", cta_res[cta_lr-2], cta_res[cta_lr-1]);
641 }
642
643 } else {
644 // send subscription encrypted
645
646 if (!nano81Data) {
647 cs_dump(ep->emm, ep->l, "0x92 found, but can't find 0x81 in emm...");
648 return ERROR; // error
649 }
650
651 ins1c[3] = keynr; // key
652 ins1c[4] = nano92Data[1] + 2 + nano81Data[1] + 2 + nanoF0Data[1] + 2;
653 memcpy (insData, nano92Data, nano92Data[1] + 2);
654 memcpy (insData + nano92Data[1] + 2, nano81Data, nano81Data[1] + 2);
655 memcpy (insData + nano92Data[1] + 2 + nano81Data[1] + 2, nanoF0Data, nanoF0Data[1] + 2);
656 write_cmd(ins1c, insData);
657 if( (cta_res[cta_lr-2]!=0x90 && cta_res[cta_lr-2]!=0x91) || cta_res[cta_lr-1]!=0x00 ) {
658 /* maybe a 2nd level status, so read it */
659 ///cs_dump(ins1c, 5, "set subscription encrypted cmd:");
660 ///cs_dump(insData, ins1c[4], "set subscription encrypted data:");
661 ///cs_log("[viaccess-reader] update error: %02X %02X", cta_res[cta_lr-2], cta_res[cta_lr-1]);
662
663 write_cmd(insc8, insc8Data);
664 if( cta_res[0] != 0x00 || cta_res[1] != 00 || cta_res[cta_lr-2]!=0x90 || cta_res[cta_lr-1]!=0x00 ) {
665 ///cs_dump(cta_res, cta_lr, "extended status error:");
666 return ERROR;
667 } else {
668 cs_debug("[viaccess-reader] update successfully written (with extended status OK)");
669 rc=1; // written
670 }
671 } else {
672 cs_debug("[viaccess-reader] update successfully written");
673 rc=1; // written
674 }
675 }
676
677 /*
678 Sub Main()
679 Sc.Write("CA A4 04 00 03")
680 RX
681 Sc.Write("02 07 11")
682 RX
683 Sc.Write("CA F0 00 01 22")
684 RX
685 Sc.Write("9E 20")
686 Sc.Write("10 10 08 8A 80 00 04 00 10 10 26 E8 54 80 1E 80")
687 Sc.Write("00 01 00 00 00 00 00 50 00 00 80 02 22 00 08 50")
688 RX
689 Sc.Write("CA 18 01 01 11")
690 RX
691 Sc.Write("A9 05 34 DE 34 FF 80")
692 Sc.Write("F0 08 1A 3E AF B5 2B EE E3 3B")
693 RX
694
695 End Sub
696*/
697 return rc;
698}
699
700int viaccess_card_info(struct s_reader * reader)
701{
702 def_resp;
703 int i, l, scls, show_cls;
704 uchar insac[] = { 0xca, 0xac, 0x00, 0x00, 0x00 }; // select data
705 uchar insb8[] = { 0xca, 0xb8, 0x00, 0x00, 0x00 }; // read selected data
706 uchar insa4[] = { 0xca, 0xa4, 0x00, 0x00, 0x00 }; // select issuer
707 uchar insc0[] = { 0xca, 0xc0, 0x00, 0x00, 0x00 }; // read data item
708 static const uchar ins24[] = { 0xca, 0x24, 0x00, 0x00, 0x09 }; // set pin
709
710 static const uchar cls[] = { 0x00, 0x21, 0xff, 0x9f};
711 static const uchar pin[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04};
712
713 show_cls=reader->show_cls;
714 memset(&reader->last_geo, 0, sizeof(reader->last_geo));
715
716 cs_log("[viaccess-reader] card detected");
717
718 // set pin
719 write_cmd(ins24, pin);
720
721 insac[2]=0xa4; write_cmd(insac, NULL); // request unique id
722 insb8[4]=0x07; write_cmd(insb8, NULL); // read unique id
723 cs_log("[viaccess-reader] serial: %llu", b2ll(5, cta_res+2));
724
725 scls=0;
726 insa4[2]=0x00; write_cmd(insa4, NULL); // select issuer 0
727 for (i=1; (cta_res[cta_lr-2]==0x90) && (cta_res[cta_lr-1]==0); i++)
728 {
729 ulong l_provid, l_sa;
730 uchar l_name[64];
731 insc0[4]=0x1a; write_cmd(insc0, NULL); // show provider properties
732 cta_res[2]&=0xF0;
733 l_provid=b2i(3, cta_res);
734
735 insac[2]=0xa5; write_cmd(insac, NULL); // request sa
736 insb8[4]=0x06; write_cmd(insb8, NULL); // read sa
737 l_sa=b2i(4, cta_res+2);
738
739 insac[2]=0xa7; write_cmd(insac, NULL); // request name
740 insb8[4]=0x02; write_cmd(insb8, NULL); // read name nano + len
741 l=cta_res[1];
742 insb8[4]=l; write_cmd(insb8, NULL); // read name
743 cta_res[l]=0;
744 trim((char *)cta_res);
745 if (cta_res[0])
746 snprintf((char *)l_name, sizeof(l_name), ", name: %s", cta_res);
747 else
748 l_name[0]=0;
749
750 // read GEO
751 insac[2]=0xa6; write_cmd(insac, NULL); // request GEO
752 insb8[4]=0x02; write_cmd(insb8, NULL); // read GEO nano + len
753 l=cta_res[1];
754 insb8[4]=l; write_cmd(insb8, NULL); // read geo
755 cs_ri_log(reader, "provider: %d, id: %06X%s, sa: %08X, geo: %s",
756 i, l_provid, l_name, l_sa, (l<4) ? "empty" : cs_hexdump(1, cta_res, l));
757
758 // read classes subscription
759 insac[2]=0xa9; insac[4]=4;
760 write_cmd(insac, cls); // request class subs
761 scls=0;
762 while( (cta_res[cta_lr-2]==0x90) && (cta_res[cta_lr-1]==0) )
763 {
764 insb8[4]=0x02; write_cmd(insb8, NULL); // read class subs nano + len
765 if( (cta_res[cta_lr-2]==0x90) && (cta_res[cta_lr-1]==0) )
766 {
767 int fshow;
768 l=cta_res[1];
769 //fshow=(client[cs_idx].dbglvl==D_DUMP)?1:(scls < show_cls)?1:0;
770 fshow=(scls<show_cls);
771 insb8[4]=l; write_cmd(insb8, NULL); // read class subs
772 if( (cta_res[cta_lr-2]==0x90) && (fshow) &&
773 (cta_res[cta_lr-1]==0x00 || cta_res[cta_lr-1]==0x08) )
774 {
775 show_class(reader, NULL, cta_res, cta_lr-2);
776 scls++;
777 }
778 }
779 }
780
781 insac[4]=0;
782 insa4[2]=0x02;
783 write_cmd(insa4, NULL); // select next provider
784 }
785 //return ERROR;
786 return OK;
787}
788
789void reader_viaccess(struct s_cardsystem *ph)
790{
791 ph->do_emm=viaccess_do_emm;
792 ph->do_ecm=viaccess_do_ecm;
793 ph->card_info=viaccess_card_info;
794 ph->card_init=viaccess_card_init;
795 ph->get_emm_type=viaccess_get_emm_type;
796 ph->caids[0]=0x05;
797}
Note: See TracBrowser for help on using the repository browser.