source: trunk/reader-viaccess.c@ 8376

Last change on this file since 8376 was 8376, checked in by gf, 9 years ago

Revert r8119 changes related to Viaccess EMM reassembly.

EMM reassembly should not know internal dvbapi client information.

The proper fix is to run reassembly on the local reader side and
remove it completely from the client side.

  • Property svn:eol-style set to LF
File size: 31.2 KB
Line 
1#include "globals.h"
2#ifdef READER_VIACCESS
3#include "oscam-aes.h"
4#include "oscam-time.h"
5#include "reader-common.h"
6
7struct via_date {
8 uint16_t day_s : 5;
9 uint16_t month_s : 4;
10 uint16_t year_s : 7;
11
12 uint16_t day_e : 5;
13 uint16_t month_e : 4;
14 uint16_t year_e : 7;
15};
16
17static void parse_via_date(const uchar *buf, struct via_date *vd, int32_t fend)
18{
19 uint16_t date;
20
21 date = (buf[0]<<8) | buf[1];
22 vd->day_s = date & 0x1f;
23 vd->month_s = (date>>5) & 0x0f;
24 vd->year_s = (date>>9) & 0x7f;
25
26 if( fend )
27 {
28 date = (buf[2]<<8) | buf[3];
29 vd->day_e = date & 0x1f;
30 vd->month_e = (date>>5) & 0x0f;
31 vd->year_e = (date>>9) & 0x7f;
32 }
33}
34
35//static void get_via_data(const uchar *b, int32_t l, time_t *start_t, time_t *end_t, uchar *cls)
36//{
37// int32_t i, j;
38// struct via_date vd;
39// struct tm tm;
40// memset(&vd, 0, sizeof(struct via_date));
41//
42// // b -> via date (4 bytes)
43// b+=4;
44// l-=4;
45//
46// j=l-1;
47// for (; j>=0; j--)
48// for (i=0; i<8; i++)
49// if (b[j] & (1 << (i&7)))
50// {
51// parse_via_date(b-4, &vd, 1);
52// *cls=(l-(j+1))*8+i;
53// }
54//
55// memset(&tm, 0, sizeof(struct tm));
56// tm.tm_year = vd.year_s + 80; //via year starts in 1980, tm_year starts in 1900
57// tm.tm_mon = vd.month_s - 1; // january is 0 in tm_mon
58// tm.tm_mday = vd.day_s;
59// *start_t = mktime(&tm);
60//
61// tm.tm_year = vd.year_e + 80;
62// tm.tm_mon = vd.month_e - 1;
63// tm.tm_mday = vd.day_e;
64// *end_t = mktime(&tm);
65//
66//}
67
68static void show_class(struct s_reader *reader, const char *p, uint32_t provid, const uchar *b, int32_t l)
69{
70 int32_t i, j;
71
72 // b -> via date (4 bytes)
73 b+=4;
74 l-=4;
75
76 j=l-1;
77 for (; j>=0; j--)
78 for (i=0; i<8; i++)
79 if (b[j] & (1 << (i&7)))
80 {
81 uchar cls;
82 struct via_date vd;
83 parse_via_date(b-4, &vd, 1);
84 cls=(l-(j+1))*8+i;
85 if (p)
86 rdr_log(reader, "%sclass: %02X, expiry date: %04d/%02d/%02d - %04d/%02d/%02d", p, cls,
87 vd.year_s+1980, vd.month_s, vd.day_s,
88 vd.year_e+1980, vd.month_e, vd.day_e);
89 else {
90 rdr_log(reader, "class: %02X, expiry date: %04d/%02d/%02d - %04d/%02d/%02d", cls,
91 vd.year_s+1980, vd.month_s, vd.day_s,
92 vd.year_e+1980, vd.month_e, vd.day_e);
93
94 time_t start_t, end_t;
95 struct tm tm;
96 //convert time:
97 memset(&tm, 0, sizeof(tm));
98 tm.tm_year = vd.year_s+80; //via year starts in 1980, tm_year starts in 1900
99 tm.tm_mon = vd.month_s-1; // january is 0 in tm_mon
100 tm.tm_mday = vd.day_s;
101 start_t = cs_timegm(&tm);
102
103 tm.tm_year = vd.year_e+80; //via year starts in 1980, tm_year starts in 1900
104 tm.tm_mon = vd.month_e-1; // january is 0 in tm_mon
105 tm.tm_mday = vd.day_e;
106 end_t = cs_timegm(&tm);
107
108 cs_add_entitlement(reader, reader->caid, provid, cls, cls, start_t, end_t, 5);
109 }
110 }
111}
112
113static void show_subs(struct s_reader * reader, const uchar *emm)
114{
115 // emm -> A9, A6, B6
116
117 switch( emm[0] )
118 {
119 case 0xA9:
120 show_class(reader, "nano A9: ", 0, emm+2, emm[1]);
121 break;
122 /*
123 {
124 int32_t i, j, byts;
125 const uchar *oemm;
126
127 oemm = emm;
128 byts = emm[1]-4;
129 emm+=6;
130
131 j=byts-1;
132 for( ; j>=0; j-- )
133 for( i=0; i<8; i++ )
134 if( emm[j] & (1 << (i&7)) )
135 {
136 uchar cls;
137 struct via_date vd;
138 parse_via_date(emm-4, &vd, 1);
139 cls=(byts-(j+1))*8+i;
140 rdr_log(reader, "%sclass %02X: expiry date: %02d/%02d/%04d - %02d/%02d/%04d",
141 fnano?"nano A9: ":"", cls,
142 vd.day_s, vd.month_s, vd.year_s+1980,
143 vd.day_e, vd.month_e, vd.year_e+1980);
144 }
145 break;
146 }
147 */
148 case 0xA6:
149 {
150 char szGeo[256];
151
152 memset(szGeo, 0, 256);
153 strncpy(szGeo, (char *)emm+2, emm[1]);
154 rdr_log(reader, "nano A6: geo %s", szGeo);
155 break;
156 }
157 case 0xB6:
158 {
159 uchar m; // modexp
160 struct via_date vd;
161
162 m=emm[emm[1]+1];
163 parse_via_date(emm+2, &vd, 0);
164 rdr_log(reader, "nano B6: modexp %d%d%d%d%d%d: %02d/%02d/%04d", (m&0x20)?1:0,
165 (m&0x10)?1:0,(m&0x08)?1:0,(m&0x04)?1:0,(m&0x02)?1:0,(m&0x01)?1:0,
166 vd.day_s, vd.month_s, vd.year_s+1980);
167 break;
168 }
169 }
170}
171
172static int32_t chk_prov(struct s_reader * reader, uchar *id, uchar keynr)
173{
174 int32_t i, j, rc;
175 for (rc=i=0; (!rc) && (i<reader->nprov); i++)
176 if(!memcmp(&reader->prid[i][1], id, 3))
177 for (j=0; (!rc) && (j<16); j++)
178 if (reader->availkeys[i][j]==keynr)
179 rc=1;
180 return(rc);
181}
182
183static int32_t unlock_parental(struct s_reader * reader)
184{
185 /* disabling parental lock. assuming pin "0000" if no pin code is provided in the config */
186
187 static const uchar inDPL[] = {0xca, 0x24, 0x02, 0x00, 0x09};
188 uchar cmDPL[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F};
189 def_resp;
190
191 if (strcmp(reader->pincode, "none")) {
192 rdr_log(reader, "Using PIN %s",reader->pincode);
193 // the pin need to be coded in bcd, so we need to convert from ascii to bcd, so '1234' -> 0x12 0x34
194 cmDPL[6]=((reader->pincode[0]-0x30)<<4) | ((reader->pincode[1]-0x30) & 0x0f);
195 cmDPL[7]=((reader->pincode[2]-0x30)<<4) | ((reader->pincode[3]-0x30) & 0x0f);
196 }
197 else {
198 rdr_log(reader, "Using PIN 0000!");
199 }
200 write_cmd(inDPL,cmDPL);
201 if( !(cta_res[cta_lr-2]==0x90 && cta_res[cta_lr-1]==0) ) {
202 if (strcmp(reader->pincode, "none")) {
203 rdr_log(reader, "Can't disable parental lock. Wrong PIN? OSCam used %s!",reader->pincode);
204 }
205 else {
206 rdr_log(reader, "Can't disable parental lock. Wrong PIN? OSCam used 0000!");
207 }
208 }
209 else
210 rdr_log(reader, "Parental lock disabled");
211
212 return 0;
213}
214
215static int32_t viaccess_card_init(struct s_reader * reader, ATR *newatr)
216{
217 get_atr;
218 def_resp;
219 int32_t i;
220 uchar buf[256];
221 uchar insac[] = { 0xca, 0xac, 0x00, 0x00, 0x00 }; // select data
222 uchar insb8[] = { 0xca, 0xb8, 0x00, 0x00, 0x00 }; // read selected data
223 uchar insa4[] = { 0xca, 0xa4, 0x00, 0x00, 0x00 }; // select issuer
224 uchar insc0[] = { 0xca, 0xc0, 0x00, 0x00, 0x00 }; // read data item
225 static const uchar insFAC[] = { 0x87, 0x02, 0x00, 0x00, 0x03 }; // init FAC
226 static const uchar FacDat[] = { 0x00, 0x00, 0x28 };
227 static unsigned char ins8702_data[] = { 0x00, 0x00, 0x11};
228 static unsigned char ins8704[] = { 0x87, 0x04, 0x00, 0x00, 0x07 };
229 static unsigned char ins8706[] = { 0x87, 0x06, 0x00, 0x00, 0x04 };
230
231
232 if ((atr[1]!=0x77) || ((atr[2]!=0x18) && (atr[2]!=0x11) && (atr[2]!=0x19)) || ((atr[9]!=0x68) && (atr[9]!=0x6C)))
233 return ERROR;
234
235 write_cmd(insFAC, FacDat);
236 if( !(cta_res[cta_lr-2]==0x90 && cta_res[cta_lr-1]==0) )
237 return ERROR;
238
239 memset(&reader->last_geo, 0, sizeof(reader->last_geo));
240 write_cmd(insFAC, ins8702_data);
241 if ((cta_res[cta_lr-2]==0x90) && (cta_res[cta_lr-1]==0x00)) {
242 write_cmd(ins8704, NULL);
243 if ((cta_res[cta_lr-2]==0x90) && (cta_res[cta_lr-1]==0x00)) {
244 write_cmd(ins8706, NULL);
245 if ((cta_res[cta_lr-2]==0x90) && (cta_res[cta_lr-1]==0x00)) {
246 reader->last_geo.number_ecm =(cta_res[2]<<8) | (cta_res[3]);
247 rdr_log(reader, "using ecm #%x for long viaccess ecm",reader->last_geo.number_ecm);
248 }
249 }
250 }
251
252
253 // switch((atr[atrsize-4]<<8)|atr[atrsize-3])
254 // {
255 // case 0x6268: ver="2.3"; break;
256 // case 0x6668: ver="2.4(?)"; break;
257 // case 0xa268:
258 // default: ver="unknown"; break;
259 // }
260
261 reader->caid=0x500;
262 memset(reader->prid, 0xff, sizeof(reader->prid));
263 insac[2]=0xa4; write_cmd(insac, NULL); // request unique id
264 insb8[4]=0x07; write_cmd(insb8, NULL); // read unique id
265 memcpy(reader->hexserial, cta_res+2, 5);
266 // rdr_log(reader, "[viaccess-reader] type: Viaccess, ver: %s serial: %llu", ver, b2ll(5, cta_res+2));
267 rdr_log_sensitive(reader, "type: Viaccess (%sstandard atr), caid: %04X, serial: {%llu}",
268 atr[9]==0x68?"":"non-",reader->caid, (unsigned long long) b2ll(5, cta_res+2));
269
270 i=0;
271 insa4[2]=0x00; write_cmd(insa4, NULL); // select issuer 0
272 buf[0]=0;
273 while((cta_res[cta_lr-2]==0x90) && (cta_res[cta_lr-1]==0))
274 {
275 insc0[4]=0x1a; write_cmd(insc0, NULL); // show provider properties
276 cta_res[2]&=0xF0;
277 reader->prid[i][0]=0;
278 memcpy(&reader->prid[i][1], cta_res, 3);
279 memcpy(&reader->availkeys[i][0], cta_res+10, 16);
280 snprintf((char *)buf+strlen((char *)buf), sizeof(buf)-strlen((char *)buf), ",%06X", b2i(3, &reader->prid[i][1]));
281 //rdr_log(reader, "[viaccess-reader] buf: %s", buf);
282
283 insac[2]=0xa5; write_cmd(insac, NULL); // request sa
284 insb8[4]=0x06; write_cmd(insb8, NULL); // read sa
285 memcpy(&reader->sa[i][0], cta_res+2, 4);
286
287 /*
288 insac[2]=0xa7; write_cmd(insac, NULL); // request name
289 insb8[4]=0x02; write_cmd(insb8, NULL); // read name nano + len
290 l=cta_res[1];
291 insb8[4]=l; write_cmd(insb8, NULL); // read name
292 cta_res[l]=0;
293 rdr_log(reader, "[viaccess-reader] name: %s", cta_res);
294 */
295
296 insa4[2]=0x02;
297 write_cmd(insa4, NULL); // select next issuer
298 i++;
299 }
300 reader->nprov=i;
301 rdr_log(reader, "providers: %d (%s)", reader->nprov, buf+1);
302
303 if (cfg.ulparent)
304 unlock_parental(reader);
305
306 rdr_log(reader, "ready for requests");
307 return OK;
308}
309
310bool dcw_crc(uchar *dw){
311 int8_t i;
312 for(i=0;i<16;i+=4) if(dw[i+3]!=((dw[i]+dw[i+1]+dw[i+2])& 0xFF))return 0;
313 return 1;
314}
315
316static int32_t viaccess_do_ecm(struct s_reader * reader, const ECM_REQUEST *er, struct s_ecm_answer *ea)
317{
318 def_resp;
319 static const unsigned char insa4[] = { 0xca,0xa4,0x04,0x00,0x03 }; // set provider id
320 unsigned char ins88[] = { 0xca,0x88,0x00,0x00,0x00 }; // set ecm
321 unsigned char insf8[] = { 0xca,0xf8,0x00,0x00,0x00 }; // set geographic info
322 static const unsigned char insc0[] = { 0xca,0xc0,0x00,0x00,0x12 }; // read dcw
323
324 // //XXX what is the 4th byte for ??
325 int32_t ecm88Len = MIN(MAX_ECM_SIZE-4, SCT_LEN(er->ecm)-4);
326 if(ecm88Len < 1){
327 rdr_log(reader, "ECM: Size of ECM couldn't be correctly calculated.");
328 return ERROR;
329 }
330 uchar ecmData[ecm88Len];
331 memset(ecmData, 0, ecm88Len);
332 memcpy(ecmData, er->ecm+4, ecm88Len);
333 uchar *ecm88Data = &ecmData[0];
334 uint32_t provid=0;
335 int32_t rc=0;
336 int32_t hasD2 = 0;
337 int32_t curEcm88len=0;
338 int32_t nanoLen=0;
339 uchar *nextEcm;
340 uchar DE04[256];
341 int32_t D2KeyID=0;
342 int32_t curnumber_ecm=0;
343 //nanoD2 d2 02 0d 02 -> D2 nano, len 2
344 // 0d -> post AES decrypt CW
345 // 0b -> pre AES decrypt CW
346 int32_t nanoD2 = 0; // 0x0b = 1 0x0d = 2
347
348 memset(DE04, 0, sizeof(DE04)); //fix dorcel de04 bug
349
350 nextEcm=ecm88Data;
351
352
353
354 while (ecm88Len>0 && !rc) {
355
356 if(ecm88Data[0] ==0x00 && ecm88Data[1] == 0x00) {
357 // nano 0x00 and len 0x00 aren't valid ... something is obviously wrong with this ecm.
358 rdr_log(reader, "ECM: Invalid ECM structure. Rejecting");
359 return ERROR;
360 }
361
362 // 80 33 nano 80 (ecm) + len (33)
363 if(ecm88Data[0]==0x80) { // nano 80, give ecm len
364 curEcm88len=ecm88Data[1];
365 nextEcm=ecm88Data+curEcm88len+2;
366 ecm88Data += 2;
367 ecm88Len -= 2;
368 }
369
370 if(!curEcm88len) { //there was no nano 80 -> simple ecm
371 curEcm88len=ecm88Len;
372 }
373
374 // d2 02 0d 02 -> D2 nano, len 2, select the AES key to be used
375 if(ecm88Data[0]==0xd2) {
376 // test if need post or pre AES decrypt
377 if(ecm88Data[2]==0x0b)
378 {
379 nanoD2 = 1;
380 rdr_debug_mask(reader, D_READER, "ECM: nano D2 0x0b");
381 }
382 if(ecm88Data[2]==0x0d)
383 {
384 nanoD2 = 2;
385 rdr_debug_mask(reader, D_READER, "ECM: nano D2 0x0d");
386 }
387 // use the d2 arguments to get the key # to be used
388 int32_t len = ecm88Data[1] + 2;
389 D2KeyID=ecm88Data[3];
390 ecm88Data += len;
391 ecm88Len -= len;
392 curEcm88len -=len;
393 hasD2 = 1;
394 }
395 else
396 hasD2 = 0;
397
398
399 // 40 07 03 0b 00 -> nano 40, len =7 ident 030B00 (tntsat), key #0 <== we're pointing here
400 // 09 -> use key #9
401 // 05 67 00
402 if ((ecm88Data[0]==0x90 || ecm88Data[0]==0x40) && (ecm88Data[1]==0x03 || ecm88Data[1]==0x07 ) )
403 {
404 uchar ident[3], keynr;
405 uchar *ecmf8Data=0;
406 int32_t ecmf8Len=0;
407
408 nanoLen=ecm88Data[1] + 2;
409 keynr=ecm88Data[4]&0x0F;
410
411 // 40 07 03 0b 00 -> nano 40, len =7 ident 030B00 (tntsat), key #0 <== we're pointing here
412 // 09 -> use key #9
413 if(nanoLen>5) {
414 curnumber_ecm =(ecm88Data[6]<<8) | (ecm88Data[7]);
415 rdr_debug_mask(reader, D_READER, "checking if the ecm number (%x) match the card one (%x)",curnumber_ecm,reader->last_geo.number_ecm);
416 // if we have an ecm number we check it.
417 // we can't assume that if the nano len is 5 or more we have an ecm number
418 // as some card don't support this
419 if( reader->last_geo.number_ecm > 0 ) {
420 if (reader->last_geo.number_ecm == curnumber_ecm && !( ecm88Data[nanoLen-1] == 0x01 && (ecm88Data[2] == 0x03 && ecm88Data[3] == 0x0B && ecm88Data[4] == 0x00 ) )) {
421 keynr=ecm88Data[5];
422 rdr_debug_mask(reader, D_READER, "keyToUse = %02x, ECM ending with %02x",ecm88Data[5], ecm88Data[nanoLen-1]);
423 } else {
424 if( ecm88Data[nanoLen-1] == 0x01 && (ecm88Data[2] == 0x03 && ecm88Data[3] == 0x0B && ecm88Data[4] == 0x00 ) )
425 {
426 rdr_debug_mask(reader, D_READER, "Skip ECM ending with = %02x for ecm number (%x) for provider %02x%02x%02x",ecm88Data[nanoLen-1], curnumber_ecm, ecm88Data[2], ecm88Data[3], ecm88Data[4]);
427 }
428 rdr_debug_mask(reader, D_READER, "Skip ECM ending with = %02x for ecm number (%x)",ecm88Data[nanoLen-1], curnumber_ecm);
429 ecm88Data=nextEcm;
430 ecm88Len-=curEcm88len;
431 continue; //loop to next ecm
432 }
433 }
434 else { // long ecm but we don't have an ecm number so we have to try them all.
435 keynr=ecm88Data[5];
436 rdr_debug_mask(reader, D_READER, "keyToUse = %02x",ecm88Data[5]);
437 }
438 }
439
440 memcpy (ident, &ecm88Data[2], sizeof(ident));
441 provid = b2i(3, ident);
442 ident[2]&=0xF0;
443
444 if(hasD2 && reader->aes_list) {
445 // check that we have the AES key to decode the CW
446 // if not there is no need to send the ecm to the card
447 if(!aes_present(reader->aes_list, 0x500, (uint32_t) (provid & 0xFFFFF0) , D2KeyID))
448 return ERROR;
449 }
450
451
452 if (!chk_prov(reader, ident, keynr))
453 {
454 rdr_debug_mask(reader, D_READER, "ECM: provider or key not found on card");
455 snprintf( ea->msglog, MSGLOGSIZE, "provider(%02x%02x%02x) or key(%d) not found on card", ident[0],ident[1],ident[2], keynr );
456 return ERROR;
457 }
458
459 ecm88Data+=nanoLen;
460 ecm88Len-=nanoLen;
461 curEcm88len-=nanoLen;
462
463 // DE04
464 if (ecm88Data[0]==0xDE && ecm88Data[1]==0x04)
465 {
466 memcpy (DE04, &ecm88Data[0], 6);
467 ecm88Data+=6;
468 }
469 //
470
471 if( reader->last_geo.provid != provid )
472 {
473 reader->last_geo.provid = provid;
474 reader->last_geo.geo_len = 0;
475 reader->last_geo.geo[0] = 0;
476 write_cmd(insa4, ident); // set provider
477 }
478
479 //Nano D2 0x0b Pre AES decrypt CW
480 if ( hasD2 && nanoD2 == 1)
481 {
482 uchar *ecm88DataCW = ecm88Data;
483 int32_t cwStart = 0;
484 //int32_t cwStartRes = 0;
485 int32_t must_exit = 0;
486 // find CW start
487 while(cwStart < curEcm88len -1 && !must_exit)
488 {
489 if(ecm88Data[cwStart] == 0xEA && ecm88Data[cwStart+1] == 0x10)
490 {
491 ecm88DataCW = ecm88DataCW + cwStart + 2;
492 must_exit = 1;
493 }
494 cwStart++;
495 }
496 // use AES from list to decrypt CW
497 rdr_debug_mask(reader, D_READER, "Decoding CW : using AES key id %d for provider %06x",D2KeyID, (provid & 0xFFFFF0));
498 if (aes_decrypt_from_list(reader->aes_list,0x500, (uint32_t) (provid & 0xFFFFF0), D2KeyID, &ecm88DataCW[0], 16) == 0)
499 snprintf( ea->msglog, MSGLOGSIZE, "AES Decrypt : key id %d not found for CAID %04X , provider %06x", D2KeyID, 0x500, (provid & 0xFFFFF0) );
500 }
501
502 while(ecm88Len>1 && ecm88Data[0]<0xA0)
503 {
504 nanoLen=ecm88Data[1]+2;
505 if (!ecmf8Data)
506 ecmf8Data=(uchar *)ecm88Data;
507 ecmf8Len+=nanoLen;
508 ecm88Len-=nanoLen;
509 curEcm88len-=nanoLen;
510 ecm88Data+=nanoLen;
511 }
512 if(ecmf8Len)
513 {
514 if( reader->last_geo.geo_len!=ecmf8Len ||
515 memcmp(reader->last_geo.geo, ecmf8Data, reader->last_geo.geo_len))
516 {
517 memcpy(reader->last_geo.geo, ecmf8Data, ecmf8Len);
518 reader->last_geo.geo_len= ecmf8Len;
519 insf8[3]=keynr;
520 insf8[4]=ecmf8Len;
521 write_cmd(insf8, ecmf8Data);
522 }
523 }
524 ins88[2]=ecmf8Len?1:0;
525 ins88[3]=keynr;
526 ins88[4]= curEcm88len;
527 //
528 // we should check the nano to make sure the ecm is valid
529 // we should look for at least 1 E3 nano, 1 EA nano and the F0 signature nano
530 //
531 // DE04
532 if (DE04[0]==0xDE)
533 {
534 uint32_t l = curEcm88len-6;
535 if (l > 256 || curEcm88len <= 6) { //don't known if this is ok...
536 rdr_log(reader, "ecm invalid/too long! len=%d", curEcm88len);
537 return ERROR;
538 }
539 memcpy(DE04+6, (uchar *)ecm88Data, l);
540 write_cmd(ins88, DE04); // request dcw
541 }
542 else
543 {
544 write_cmd(ins88, (uchar *)ecm88Data); // request dcw
545 }
546 //
547 write_cmd(insc0, NULL); // read dcw
548 switch(cta_res[0])
549 {
550 case 0xe8: // even
551 if(cta_res[1]==8) { memcpy(ea->cw,cta_res+2,8); rc=1; }
552 break;
553 case 0xe9: // odd
554 if(cta_res[1]==8) { memcpy(ea->cw+8,cta_res+2,8); rc=1; }
555 break;
556 case 0xea: // complete
557 if(cta_res[1]==16) { memcpy(ea->cw,cta_res+2,16); rc=1; }
558 break;
559 default :
560 ecm88Data=nextEcm;
561 ecm88Len-=curEcm88len;
562 rdr_debug_mask(reader, D_READER, "ECM: key to use is not the current one, trying next ECM");
563 snprintf( ea->msglog, MSGLOGSIZE, "key to use is not the current one, trying next ECM" );
564 }
565 }
566 else {
567 //ecm88Data=nextEcm;
568 //ecm88Len-=curEcm88len;
569 rdr_debug_mask(reader, D_READER, "ECM: Unknown ECM type");
570 snprintf( ea->msglog, MSGLOGSIZE, "Unknown ECM type" );
571 return ERROR; /*Lets interupt the loop and exit, because we don't know this ECM type.*/
572 }
573 }
574
575 if ( hasD2 && !dcw_crc(ea->cw) && nanoD2 == 2) {
576 rdr_debug_mask(reader, D_READER, "Decoding CW : using AES key id %d for provider %06x",D2KeyID, (provid & 0xFFFFF0));
577 rc=aes_decrypt_from_list(reader->aes_list,0x500, (uint32_t) (provid & 0xFFFFF0), D2KeyID,ea->cw, 16);
578 if( rc == 0 )
579 snprintf( ea->msglog, MSGLOGSIZE, "AES Decrypt : key id %d not found for CAID %04X , provider %06x", D2KeyID, 0x500, (provid & 0xFFFFF0) );
580 }
581
582 return(rc?OK:ERROR);
583}
584
585static int32_t viaccess_get_emm_type(EMM_PACKET *ep, struct s_reader * rdr)
586{
587 uint32_t provid=0;
588 rdr_debug_mask(rdr, D_EMM, "Entered viaccess_get_emm_type ep->emm[0]=%02x",ep->emm[0]);
589
590 if (ep->emm[3] == 0x90 && ep->emm[4] == 0x03) {
591 provid = ep->emm[5] << 16 | ep->emm[6] << 8 | (ep->emm[7] & 0xFE);
592 i2b_buf(4, provid, ep->provid);
593 }
594
595 switch (ep->emm[0]) {
596case 0x88:
597 ep->type=UNIQUE;
598 memset(ep->hexserial, 0, 8);
599 memcpy(ep->hexserial, ep->emm + 4, 4);
600 rdr_debug_mask(rdr, D_EMM, "UNIQUE");
601 return(!memcmp(rdr->hexserial + 1, ep->hexserial, 4));
602
603case 0x8A:
604case 0x8B:
605 ep->type=GLOBAL;
606 rdr_debug_mask(rdr, D_EMM, "GLOBAL");
607 return 1;
608
609case 0x8C:
610case 0x8D:
611 ep->type=SHARED;
612 rdr_debug_mask(rdr, D_EMM, "SHARED (part)");
613 return 0;
614
615case 0x8E:
616 ep->type=SHARED;
617 memset(ep->hexserial, 0, 8);
618 memcpy(ep->hexserial, ep->emm + 3, 3);
619 rdr_debug_mask(rdr, D_EMM, "SHARED");
620
621 //check for provider as serial (cccam only?)
622 int8_t i;
623 for (i=0;i<rdr->nprov;i++) {
624 if (!memcmp(&rdr->prid[i][1], ep->hexserial, 3))
625 return 1;
626 }
627 return(!memcmp(&rdr->sa[0][0], ep->hexserial, 3));
628
629default:
630 ep->type = UNKNOWN;
631 rdr_debug_mask(rdr, D_EMM, "UNKNOWN");
632 return 1;
633 }
634}
635
636static void viaccess_get_emm_filter(struct s_reader * rdr, uchar *filter)
637{
638 int32_t idx = 2;
639
640 filter[0]=0xFF;
641 filter[1]=0;
642
643 filter[idx++]=EMM_GLOBAL;
644 filter[idx++]=0;
645 filter[idx+0] = 0x8D;
646 filter[idx+0+16] = 0xFE;
647 //filter[idx+6] = 0xA0; // FIXME: dummy, flood client with EMM's
648 //filter[idx+6+16] = 0xF0;
649 filter[1]++;
650 idx += 32;
651
652 filter[idx++]=EMM_SHARED;
653 filter[idx++]=0;
654 filter[idx+0] = 0x8E;
655 filter[idx+0+16] = 0xFF;
656 memcpy(filter+idx+1, &rdr->sa[0][0], 3);
657 memset(filter+idx+1+16, 0xFF, 3);
658 filter[1]++;
659 idx += 32;
660
661 filter[idx++]=EMM_UNIQUE;
662 filter[idx++]=0;
663 filter[idx+0] = 0x88;
664 filter[idx+0+16] = 0xFF;
665 memcpy(filter+idx+1, rdr->hexserial + 1, 4);
666 memset(filter+idx+1+16, 0xFF, 4);
667 filter[1]++;
668
669 return;
670}
671
672static int32_t viaccess_do_emm(struct s_reader * reader, EMM_PACKET *ep)
673{
674 def_resp;
675 static const unsigned char insa4[] = { 0xca,0xa4,0x04,0x00,0x03 }; // set provider id
676 unsigned char insf0[] = { 0xca,0xf0,0x00,0x01,0x22 }; // set adf
677 unsigned char insf4[] = { 0xca,0xf4,0x00,0x01,0x00 }; // set adf, encrypted
678 unsigned char ins18[] = { 0xca,0x18,0x01,0x01,0x00 }; // set subscription
679 unsigned char ins1c[] = { 0xca,0x1c,0x01,0x01,0x00 }; // set subscription, encrypted
680 //static const unsigned char insc8[] = { 0xca,0xc8,0x00,0x00,0x02 }; // read extended status
681 // static const unsigned char insc8Data[] = { 0x00,0x00 }; // data for read extended status
682
683 int32_t emmdatastart=7;
684
685
686 if (ep->type == UNIQUE) emmdatastart++;
687 int32_t emmLen=SCT_LEN(ep->emm)-emmdatastart;
688 int32_t rc=0;
689
690 ///cs_dump(ep->emm, emmLen+emmdatastart, "RECEIVED EMM VIACCESS");
691
692 int32_t emmUpToEnd;
693 uchar *emmParsed = ep->emm+emmdatastart;
694 int32_t provider_ok = 0;
695 uint32_t emm_provid;
696 uchar keynr = 0;
697 int32_t ins18Len = 0;
698 uchar ins18Data[512];
699 uchar insData[512];
700 uchar *nano81Data = 0;
701 uchar *nano91Data = 0;
702 uchar *nano92Data = 0;
703 uchar *nano9EData = 0;
704 uchar *nanoF0Data = 0;
705
706 for (emmUpToEnd=emmLen; (emmParsed[1] != 0) && (emmUpToEnd > 0); emmUpToEnd -= (2 + emmParsed[1]), emmParsed += (2 + emmParsed[1])) {
707 ///cs_dump (emmParsed, emmParsed[1] + 2, "NANO");
708
709 if (emmParsed[0]==0x90 && emmParsed[1]==0x03) {
710 /* identification of the service operator */
711
712 uchar soid[3], ident[3], i;
713
714 for (i=0; i<3; i++) {
715 soid[i]=ident[i]=emmParsed[2+i];
716 }
717 ident[2]&=0xF0;
718 emm_provid=b2i(3, ident);
719 keynr=soid[2]&0x0F;
720 if (chk_prov(reader, ident, keynr)) {
721 provider_ok = 1;
722 } else {
723 rdr_log(reader, "EMM: provider or key not found on card (%x, %x)", emm_provid, keynr);
724 return ERROR;
725 }
726
727 // check if the provider changes. If yes, set the new one. If not, don't .. card will return an error if we do.
728 if( reader->last_geo.provid != emm_provid ) {
729 write_cmd(insa4, ident);
730 if( cta_res[cta_lr-2]!=0x90 || cta_res[cta_lr-1]!=0x00 ) {
731 cs_dump(insa4, 5, "set provider cmd:");
732 cs_dump(soid, 3, "set provider data:");
733 rdr_log(reader, "update error: %02X %02X", cta_res[cta_lr-2], cta_res[cta_lr-1]);
734 return ERROR;
735 }
736 }
737 // as we are maybe changing the used provider, clear the cache, so the next ecm will re-select the correct one
738 reader->last_geo.provid = 0;
739 reader->last_geo.geo_len = 0;
740 reader->last_geo.geo[0] = 0;
741
742 }
743 else if (emmParsed[0]==0x9e && emmParsed[1]==0x20) {
744 /* adf */
745
746 if (!nano91Data) {
747 /* adf is not crypted, so test it */
748
749 uchar custwp;
750 uchar *afd;
751
752 custwp=reader->sa[0][3];
753 afd=(uchar*)emmParsed+2;
754
755 if( afd[31-custwp/8] & (1 << (custwp & 7)) )
756 rdr_debug_mask(reader, D_READER, "emm for our card %08X", b2i(4, &reader->sa[0][0]));
757 else
758 return SKIPPED;
759 }
760
761 // memorize
762 nano9EData = emmParsed;
763
764 } else if (emmParsed[0]==0x81) {
765 nano81Data = emmParsed;
766 } else if (emmParsed[0]==0x91 && emmParsed[1]==0x08) {
767 nano91Data = emmParsed;
768 } else if (emmParsed[0]==0x92 && emmParsed[1]==0x08) {
769 nano92Data = emmParsed;
770 } else if (emmParsed[0]==0xF0 && emmParsed[1]==0x08) {
771 nanoF0Data = emmParsed;
772 } else {
773 /* other nanos */
774 show_subs(reader, emmParsed);
775
776 memcpy(ins18Data+ins18Len, emmParsed, emmParsed[1] + 2);
777 ins18Len += emmParsed [1] + 2;
778 }
779 }
780
781 if (!provider_ok) {
782 rdr_debug_mask(reader, D_READER, "provider not found in emm, continue anyway");
783 // force key to 1...
784 keynr = 1;
785 ///return ERROR;
786 }
787
788 if (!nanoF0Data) {
789 cs_dump(ep->emm, ep->emmlen, "can't find 0xf0 in emm...");
790 return ERROR; // error
791 }
792
793 if (nano9EData) {
794 if (!nano91Data) {
795 // set adf
796 insf0[3] = keynr; // key
797 insf0[4] = nano9EData[1] + 2;
798 write_cmd(insf0, nano9EData);
799 if( cta_res[cta_lr-2]!=0x90 || cta_res[cta_lr-1]!=0x00 ) {
800 cs_dump(insf0, 5, "set adf cmd:");
801 cs_dump(nano9EData, insf0[4] , "set adf data:");
802 rdr_log(reader, "update error: %02X %02X", cta_res[cta_lr-2], cta_res[cta_lr-1]);
803 return ERROR;
804 }
805 } else {
806 // set adf crypte
807 insf4[3] = keynr; // key
808 insf4[4] = nano91Data[1] + 2 + nano9EData[1] + 2;
809 memcpy (insData, nano91Data, nano91Data[1] + 2);
810 memcpy (insData + nano91Data[1] + 2, nano9EData, nano9EData[1] + 2);
811 write_cmd(insf4, insData);
812 if(( cta_res[cta_lr-2]!=0x90 && cta_res[cta_lr-2]!=0x91) || cta_res[cta_lr-1]!=0x00 ) {
813 cs_dump(insf4, 5, "set adf encrypted cmd:");
814 cs_dump(insData, insf4[4], "set adf encrypted data:");
815 rdr_log(reader, "update error: %02X %02X", cta_res[cta_lr-2], cta_res[cta_lr-1]);
816 return ERROR;
817 }
818 }
819 }
820
821 if (!nano92Data) {
822 // send subscription
823 ins18[2] = nano9EData ? 0x01: 0x00; // found 9E nano ?
824 ins18[3] = keynr; // key
825 ins18[4] = ins18Len + nanoF0Data[1] + 2;
826 memcpy (insData, ins18Data, ins18Len);
827 memcpy (insData + ins18Len, nanoF0Data, nanoF0Data[1] + 2);
828 write_cmd(ins18, insData);
829 if( (cta_res[cta_lr-2]==0x90 || cta_res[cta_lr-2]==0x91) && cta_res[cta_lr-1]==0x00 ) {
830 rdr_debug_mask(reader, D_READER, "update successfully written");
831 rc=1; // written
832 } else {
833 cs_dump(ins18, 5, "set subscription cmd:");
834 cs_dump(insData, ins18[4], "set subscription data:");
835 rdr_log(reader, "update error: %02X %02X", cta_res[cta_lr-2], cta_res[cta_lr-1]);
836 }
837
838 } else {
839 // send subscription encrypted
840
841 if (!nano81Data) {
842 cs_dump(ep->emm, ep->emmlen, "0x92 found, but can't find 0x81 in emm...");
843 return ERROR; // error
844 }
845
846 ins1c[2] = nano9EData ? 0x01: 0x00; // found 9E nano ?
847 if (ep->type == UNIQUE) ins1c[2] = 0x02;
848 ins1c[3] = keynr; // key
849 ins1c[4] = nano92Data[1] + 2 + nano81Data[1] + 2 + nanoF0Data[1] + 2;
850 memcpy (insData, nano92Data, nano92Data[1] + 2);
851 memcpy (insData + nano92Data[1] + 2, nano81Data, nano81Data[1] + 2);
852 memcpy (insData + nano92Data[1] + 2 + nano81Data[1] + 2, nanoF0Data, nanoF0Data[1] + 2);
853 write_cmd(ins1c, insData);
854
855 if( (cta_res[cta_lr-2]==0x90 || cta_res[cta_lr-2]==0x91) &&
856 (cta_res[cta_lr-1]==0x00 || cta_res[cta_lr-1]==0x08) ) {
857 rdr_log(reader, "update successfully written");
858 rc=1; // written
859 }
860 rc=1;
861 /* don't return ERROR at this place
862 else {
863 if( cta_res[cta_lr-2]&0x1 )
864 rdr_log(reader, "update not written. Data already exists or unknown address");
865
866 //if( cta_res[cta_lr-2]&0x8 ) {
867 write_cmd(insc8, NULL);
868 if( (cta_res[cta_lr-2]==0x90 && cta_res[cta_lr-1]==0x00) ) {
869 rdr_log(reader, "extended status %02X %02X", cta_res[0], cta_res[1]);
870 }
871 //}
872 return ERROR;
873 } */
874
875 }
876
877 /*
878 Sub Main()
879 Sc.Write("CA A4 04 00 03")
880 RX
881 Sc.Write("02 07 11")
882 RX
883 Sc.Write("CA F0 00 01 22")
884 RX
885 Sc.Write("9E 20")
886 Sc.Write("10 10 08 8A 80 00 04 00 10 10 26 E8 54 80 1E 80")
887 Sc.Write("00 01 00 00 00 00 00 50 00 00 80 02 22 00 08 50")
888 RX
889 Sc.Write("CA 18 01 01 11")
890 RX
891 Sc.Write("A9 05 34 DE 34 FF 80")
892 Sc.Write("F0 08 1A 3E AF B5 2B EE E3 3B")
893 RX
894
895 End Sub
896 */
897 return rc;
898}
899
900static int32_t viaccess_card_info(struct s_reader * reader)
901{
902 def_resp;
903 int32_t i, l;
904 uchar insac[] = { 0xca, 0xac, 0x00, 0x00, 0x00 }; // select data
905 uchar insb8[] = { 0xca, 0xb8, 0x00, 0x00, 0x00 }; // read selected data
906 uchar insa4[] = { 0xca, 0xa4, 0x00, 0x00, 0x00 }; // select issuer
907 uchar insc0[] = { 0xca, 0xc0, 0x00, 0x00, 0x00 }; // read data item
908 static const uchar ins24[] = { 0xca, 0x24, 0x00, 0x00, 0x09 }; // set pin
909
910 static const uchar cls[] = { 0x00, 0x21, 0xff, 0x9f};
911 static const uchar pin[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04};
912
913 reader->last_geo.provid = 0;
914 reader->last_geo.geo_len = 0;
915 reader->last_geo.geo[0] = 0;
916
917 rdr_log(reader, "card detected");
918
919 cs_clear_entitlement(reader); //reset the entitlements
920
921 // set pin
922 write_cmd(ins24, pin);
923
924 insac[2]=0xa4; write_cmd(insac, NULL); // request unique id
925 insb8[4]=0x07; write_cmd(insb8, NULL); // read unique id
926 rdr_log_sensitive(reader, "serial: {%llu}", (unsigned long long) b2ll(5, cta_res+2));
927
928 insa4[2]=0x00; write_cmd(insa4, NULL); // select issuer 0
929 for (i=1; (cta_res[cta_lr-2]==0x90) && (cta_res[cta_lr-1]==0); i++)
930 {
931 uint32_t l_provid, l_sa;
932 uchar l_name[64];
933 insc0[4]=0x1a; write_cmd(insc0, NULL); // show provider properties
934 cta_res[2]&=0xF0;
935 l_provid=b2i(3, cta_res);
936
937 insac[2]=0xa5; write_cmd(insac, NULL); // request sa
938 insb8[4]=0x06; write_cmd(insb8, NULL); // read sa
939 l_sa=b2i(4, cta_res+2);
940
941 insac[2]=0xa7; write_cmd(insac, NULL); // request name
942 insb8[4]=0x02; write_cmd(insb8, NULL); // read name nano + len
943 l=cta_res[1];
944 insb8[4]=l; write_cmd(insb8, NULL); // read name
945 cta_res[l]=0;
946 trim((char *)cta_res);
947 if (cta_res[0])
948 snprintf((char *)l_name, sizeof(l_name), ", name: %s", cta_res);
949 else
950 l_name[0]=0;
951
952 // read GEO
953 insac[2]=0xa6; write_cmd(insac, NULL); // request GEO
954 insb8[4]=0x02; write_cmd(insb8, NULL); // read GEO nano + len
955 l=cta_res[1];
956 char tmp[l*3+1];
957 insb8[4]=l; write_cmd(insb8, NULL); // read geo
958 rdr_log_sensitive(reader, "provider: %d, id: {%06X%s}, sa: {%08X}, geo: %s",
959 i, l_provid, l_name, l_sa, (l<4) ? "empty" : cs_hexdump(1, cta_res, l, tmp, sizeof(tmp)));
960
961 // read classes subscription
962 insac[2]=0xa9; insac[4]=4;
963 write_cmd(insac, cls); // request class subs
964 while( (cta_res[cta_lr-2]==0x90) && (cta_res[cta_lr-1]==0) )
965 {
966 insb8[4]=0x02; write_cmd(insb8, NULL); // read class subs nano + len
967 if( (cta_res[cta_lr-2]==0x90) && (cta_res[cta_lr-1]==0) )
968 {
969 l=cta_res[1];
970 insb8[4]=l; write_cmd(insb8, NULL); // read class subs
971 if( (cta_res[cta_lr-2]==0x90) &&
972 (cta_res[cta_lr-1]==0x00 || cta_res[cta_lr-1]==0x08) )
973 {
974 show_class(reader, NULL, l_provid, cta_res, cta_lr-2);
975 }
976 }
977 }
978
979 insac[4]=0;
980 insa4[2]=0x02;
981 write_cmd(insa4, NULL); // select next provider
982 }
983 //return ERROR;
984 return OK;
985}
986
987#ifdef HAVE_DVBAPI
988void dvbapi_sort_nanos(unsigned char *dest, const unsigned char *src, int32_t len);
989
990int32_t viaccess_reassemble_emm(uchar *buffer, uint32_t *len) {
991 static uchar emm_global[512];
992 static int32_t emm_global_len = 0;
993
994 int32_t pos=0, i;
995 uint32_t k;
996
997 // Viaccess
998 if (*len>500) return 0;
999
1000 switch(buffer[0]) {
1001 case 0x8c:
1002 case 0x8d:
1003 // emm-s part 1
1004 if (!memcmp(emm_global, buffer, *len))
1005 return 0;
1006
1007 // copy first part of the emm-s
1008 memcpy(emm_global, buffer, *len);
1009 emm_global_len=*len;
1010 //cs_ddump_mask(D_READER, buffer, len, "viaccess global emm:");
1011 return 0;
1012
1013 case 0x8e:
1014 // emm-s part 2
1015 if (!emm_global_len) return 0;
1016
1017 //extract nanos from emm-gh and emm-s
1018 uchar emmbuf[512];
1019
1020 cs_debug_mask(D_DVBAPI, "[viaccess] %s: start extracting nanos", __func__);
1021 //extract from emm-gh
1022 for (i=3; i<emm_global_len; i+=emm_global[i+1]+2) {
1023 //copy nano (length determined by i+1)
1024 memcpy(emmbuf+pos, emm_global+i, emm_global[i+1]+2);
1025 pos+=emm_global[i+1]+2;
1026 }
1027
1028 if (buffer[2]==0x2c) {
1029 //add 9E 20 nano + first 32 bytes of emm content
1030 memcpy(emmbuf+pos, "\x9E\x20", 2);
1031 memcpy(emmbuf+pos+2, buffer+7, 32);
1032 pos+=34;
1033
1034 //add F0 08 nano + 8 subsequent bytes of emm content
1035 memcpy(emmbuf+pos, "\xF0\x08", 2);
1036 memcpy(emmbuf+pos+2, buffer+39, 8);
1037 pos+=10;
1038 } else {
1039 //extract from variable emm-s
1040 for (k=7; k<(*len); k+=buffer[k+1]+2) {
1041 //copy nano (length determined by k+1)
1042 memcpy(emmbuf+pos, buffer+k, buffer[k+1]+2);
1043 pos+=buffer[k+1]+2;
1044 }
1045 }
1046
1047 cs_ddump_mask(D_DVBAPI, buffer, *len, "[viaccess] %s: %s emm-s", __func__, (buffer[2]==0x2c) ? "fixed" : "variable");
1048
1049 dvbapi_sort_nanos(buffer+7, emmbuf, pos);
1050 pos+=7;
1051
1052 //calculate emm length and set it on position 2
1053 buffer[2]=pos-3;
1054
1055 cs_ddump_mask(D_DVBAPI, emm_global, emm_global_len, "[viaccess] %s: emm-gh", __func__);
1056 cs_ddump_mask(D_DVBAPI, buffer, pos, "[viaccess] %s: assembled emm", __func__);
1057
1058 *len=pos;
1059 break;
1060 }
1061 return 1;
1062}
1063#endif
1064
1065void reader_viaccess(struct s_cardsystem *ph)
1066{
1067 ph->do_emm=viaccess_do_emm;
1068 ph->do_ecm=viaccess_do_ecm;
1069 ph->card_info=viaccess_card_info;
1070 ph->card_init=viaccess_card_init;
1071 ph->get_emm_type=viaccess_get_emm_type;
1072 ph->get_emm_filter=viaccess_get_emm_filter;
1073 ph->caids[0]=0x05;
1074 ph->desc="viaccess";
1075}
1076#endif
Note: See TracBrowser for help on using the repository browser.