source: trunk/reader-common.c@ 8377

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

cryptoworks/viaccess: Run EMM reassembly before writing EMM in the card.

Before this patch EMM reassembly was only run by the dvbapi client.

This means that any other client (via newcamd, cs378x, cccam) was
expected to perform its own EMM reassembly otherwise the card
was unable to write the EMMs that needed preprocessing (reassemblation).

This commit moves EMM reassembly where it belongs - just before the
EMM is written in the card. That simplifies client logic (no more
knowledge of EMM structure and types) and allows cards to be updated
via any network protocol as long as the client is not trying to be
smart and just sends us all EMM packets.

The changes were tested with SRG Swiss Viacess card and Digiturk
Cryptoworks card. In the both cards shared EMMs were written OK
while receiving them via cs378x protocol and tsdecrypt as client.

If a client sends already reassembled EMMs it also works.

  • Property svn:eol-style set to LF
File size: 10.3 KB
Line 
1#include "globals.h"
2
3#ifdef WITH_CARDREADER
4
5#include "module-led.h"
6#include "oscam-chk.h"
7#include "oscam-client.h"
8#include "oscam-ecm.h"
9#include "oscam-emm.h"
10#include "oscam-net.h"
11#include "oscam-time.h"
12#include "oscam-work.h"
13#include "reader-common.h"
14#include "csctapi/atr.h"
15#include "csctapi/icc_async.h"
16
17extern struct s_cardsystem cardsystems[CS_MAX_MOD];
18extern char *RDR_CD_TXT[];
19
20int32_t check_sct_len(const uchar *data, int32_t off)
21{
22 int32_t len = SCT_LEN(data);
23 if (len + off > MAX_LEN) {
24 cs_debug_mask(D_TRACE | D_READER, "check_sct_len(): smartcard section too long %d > %d", len, MAX_LEN - off);
25 len = -1;
26 }
27 return len;
28}
29
30static void reader_nullcard(struct s_reader * reader)
31{
32 memset(&reader->csystem , 0 , sizeof(reader->csystem));
33 memset(reader->hexserial, 0 , sizeof(reader->hexserial));
34 memset(reader->prid , 0xFF, sizeof(reader->prid ));
35 reader->caid=0;
36 memset(reader->availkeys, 0 , sizeof(reader->availkeys));
37 reader->acs=0;
38 reader->nprov=0;
39 reader->reassemble_emm_len=0;
40 memset(reader->reassemble_emm, 0, sizeof(reader->reassemble_emm));
41}
42
43int32_t reader_cmd2icc(struct s_reader * reader, const uchar *buf, const int32_t l, uchar * cta_res, uint16_t * p_cta_lr)
44{
45 int32_t rc;
46 *p_cta_lr=CTA_RES_LEN-1; //FIXME not sure whether this one is necessary
47 rdr_ddump_mask(reader, D_READER, buf, l, "write to cardreader");
48 rc=ICC_Async_CardWrite(reader, (uchar *)buf, (uint16_t)l, cta_res, p_cta_lr);
49 return rc;
50}
51
52#define CMD_LEN 5
53
54int32_t card_write(struct s_reader * reader, const uchar *cmd, const uchar *data, uchar *response, uint16_t * response_length)
55{
56 uchar buf[260];
57 // always copy to be able to be able to use const buffer without changing all code
58 memcpy(buf, cmd, CMD_LEN);
59
60 if (data) {
61 if (cmd[4]) memcpy(buf+CMD_LEN, data, cmd[4]);
62 return(reader_cmd2icc(reader, buf, CMD_LEN+cmd[4], response, response_length));
63 }
64 else
65 return(reader_cmd2icc(reader, buf, CMD_LEN, response, response_length));
66}
67
68static inline int reader_use_gpio(struct s_reader * reader) {
69 return reader->use_gpio && reader->detect > 4;
70}
71
72static int32_t reader_card_inserted(struct s_reader * reader)
73{
74 if (!reader_use_gpio(reader) && (reader->detect & 0x7f) > 3)
75 return 1;
76
77 int32_t card;
78 if (ICC_Async_GetStatus (reader, &card)) {
79 rdr_log(reader, "Error getting card status.");
80 return 0; //corresponds with no card inside!!
81 }
82 return (card);
83}
84
85static int32_t reader_activate_card(struct s_reader * reader, ATR * atr, uint16_t deprecated)
86{
87 int32_t i,ret;
88
89 if (reader->card_status != CARD_NEED_INIT)
90 return 0;
91
92 /* Activate card */
93 for (i=0; i<3; i++) {
94 ret = ICC_Async_Activate(reader, atr, deprecated);
95 if (!ret)
96 break;
97 rdr_log(reader, "Error activating card.");
98 led_status_card_activation_error();
99 cs_sleepms(500);
100 }
101 if (ret) return(0);
102
103// rdr_log("ATR: %s", cs_hexdump(1, atr, atr_size, tmp, sizeof(tmp)));//FIXME
104 cs_sleepms(1000);
105 return(1);
106}
107
108void cardreader_get_card_info(struct s_reader *reader)
109{
110 if ((reader->card_status == CARD_NEED_INIT) || (reader->card_status == CARD_INSERTED)) {
111 struct s_client *cl = reader->client;
112 if (cl)
113 cl->last=time((time_t*)0);
114
115 if (reader->csystem.active && reader->csystem.card_info) {
116 reader->csystem.card_info(reader);
117 }
118 }
119}
120
121static int32_t reader_get_cardsystem(struct s_reader * reader, ATR *atr)
122{
123 int32_t i;
124 for (i=0; i<CS_MAX_MOD; i++) {
125 if (cardsystems[i].card_init) {
126 if (cardsystems[i].card_init(reader, atr)) {
127 rdr_log(reader, "found card system %s", cardsystems[i].desc);
128 reader->csystem=cardsystems[i];
129 reader->csystem.active=1;
130 led_status_found_cardsystem();
131 break;
132 }
133 }
134 }
135
136 if (reader->csystem.active==0)
137 {
138 rdr_log(reader, "card system not supported");
139 led_status_unsupported_card_system();
140 }
141
142 return(reader->csystem.active);
143}
144
145void cardreader_do_reset(struct s_reader *reader)
146{
147 reader_nullcard(reader);
148 ATR atr;
149 int32_t ret = 0;
150
151 ret = ICC_Async_Reset(reader, &atr, reader_activate_card, reader_get_cardsystem);
152
153 if (ret == -1)
154 return;
155
156 if (ret == 0) {
157 uint16_t deprecated;
158 for (deprecated = reader->deprecated; deprecated < 2; deprecated++) {
159 if (!reader_activate_card(reader, &atr, deprecated)) break;
160 ret = reader_get_cardsystem(reader, &atr);
161 if (ret)
162 break;
163 if (!deprecated)
164 rdr_log(reader, "Normal mode failed, reverting to Deprecated Mode");
165 }
166 }
167
168 if (!ret)
169 {
170 reader->card_status = CARD_FAILURE;
171 rdr_log(reader, "card initializing error");
172 ICC_Async_DisplayMsg(reader, "AER");
173 led_status_card_activation_error();
174 }
175 else
176 {
177 cardreader_get_card_info(reader);
178 reader->card_status = CARD_INSERTED;
179 do_emm_from_file(reader);
180 ICC_Async_DisplayMsg(reader, "AOK");
181 ICC_Set_Transmit_Timeout(reader);
182 }
183
184 return;
185}
186
187static int32_t cardreader_device_init(struct s_reader *reader)
188{
189 int32_t rc = -1; //FIXME
190 if (ICC_Async_Device_Init(reader))
191 rdr_log(reader, "Cannot open device: %s", reader->device);
192 else
193 rc = OK;
194 return((rc!=OK) ? 2 : 0); //exit code 2 means keep retrying, exit code 0 means all OK
195}
196
197int32_t cardreader_do_checkhealth(struct s_reader * reader)
198{
199 struct s_client *cl = reader->client;
200 if (reader_card_inserted(reader)) {
201 if (reader->card_status == NO_CARD || reader->card_status == UNKNOWN) {
202 rdr_log(reader, "card detected");
203 led_status_card_detected();
204 reader->card_status = CARD_NEED_INIT;
205 add_job(cl, ACTION_READER_RESET, NULL, 0);
206 }
207 } else {
208 rdr_debug_mask(reader, D_READER, "%s: !reader_card_inserted", __func__);
209 if (reader->card_status == CARD_INSERTED || reader->card_status == CARD_NEED_INIT) {
210 rdr_log(reader, "card ejected");
211 reader_nullcard(reader);
212 if (cl) {
213 cl->lastemm = 0;
214 cl->lastecm = 0;
215 }
216 led_status_card_ejected();
217 }
218 reader->card_status = NO_CARD;
219 }
220 rdr_debug_mask(reader, D_READER, "%s: reader->card_status = %d, ret = %d", __func__,
221 reader->card_status, reader->card_status == CARD_INSERTED);
222 return reader->card_status == CARD_INSERTED;
223}
224
225// Check for card inserted or card removed on pysical reader
226void cardreader_checkhealth(struct s_client *cl, struct s_reader *rdr) {
227 if (!rdr || !rdr->enable || !rdr->active)
228 return;
229 add_job(cl, ACTION_READER_CHECK_HEALTH, NULL, 0);
230}
231
232void cardreader_reset(struct s_client *cl) {
233 add_job(cl, ACTION_READER_RESET, NULL, 0);
234}
235
236void cardreader_init_locks(void) {
237 ICC_Async_Init_Locks();
238}
239
240bool cardreader_init(struct s_reader *reader) {
241 struct s_client *client = reader->client;
242 client->typ = 'r';
243 set_localhost_ip(&client->ip);
244 while (cardreader_device_init(reader) == 2) {
245 int8_t i = 0;
246 do {
247 cs_sleepms(2000);
248 if (!ll_contains(configured_readers, reader) || !check_client(client) || reader->enable != 1)
249 return false;
250 i++;
251 } while (i < 30);
252 }
253 if (reader->mhz > 2000) {
254 rdr_log(reader, "Reader initialized (device=%s, detect=%s%s, pll max=%.2f Mhz, wanted cardmhz=%.2f Mhz",
255 reader->device,
256 reader->detect & 0x80 ? "!" : "",
257 RDR_CD_TXT[reader->detect & 0x7f],
258 (float)reader->mhz /100,
259 (float)reader->cardmhz / 100);
260 } else {
261 rdr_log(reader, "Reader initialized (device=%s, detect=%s%s, mhz=%d, cardmhz=%d)",
262 reader->device,
263 reader->detect & 0x80 ? "!" : "",
264 RDR_CD_TXT[reader->detect & 0x7f],
265 reader->mhz,
266 reader->cardmhz);
267 }
268 return true;
269}
270
271void cardreader_close(struct s_reader *reader) {
272 ICC_Async_Close(reader);
273}
274
275void reader_post_process(struct s_reader * reader)
276{
277 // some systems eg. nagra2/3 needs post process after receiving cw from card
278 // To save ECM/CW time we added this function after writing ecm answer
279 if (reader->csystem.active && reader->csystem.post_process) {
280 reader->csystem.post_process(reader);
281 }
282}
283
284int32_t cardreader_do_ecm(struct s_reader *reader, ECM_REQUEST *er, struct s_ecm_answer *ea)
285{
286 int32_t rc=-1;
287 if( (rc=cardreader_do_checkhealth(reader)) ) {
288 rdr_debug_mask(reader, D_READER, "%s: cardreader_do_checkhealth returned rc=%d", __func__, rc);
289 struct s_client *cl = reader->client;
290 if (cl) {
291 cl->last_srvid=er->srvid;
292 cl->last_caid=er->caid;
293 cl->last=time((time_t*)0);
294 }
295
296 if (reader->csystem.active && reader->csystem.do_ecm) {
297 rc=reader->csystem.do_ecm(reader, er, ea);
298 rdr_debug_mask(reader, D_READER, "%s: after csystem.do_ecm rc=%d", __func__, rc);
299 } else
300 rc=0;
301 }
302 rdr_debug_mask(reader, D_READER, "%s: ret rc=%d", __func__, rc);
303 return(rc);
304}
305
306int32_t cardreader_do_emm(struct s_reader *reader, EMM_PACKET *ep)
307{
308 int32_t rc=-1;
309
310 rc=cardreader_do_checkhealth(reader);
311 if (rc) {
312 if ((1<<(ep->emm[0] % 0x80)) & reader->b_nano)
313 return 3;
314
315 if (reader->csystem.active && reader->csystem.do_emm)
316 rc=reader->csystem.do_emm(reader, ep);
317 else
318 rc=0;
319 }
320 return(rc);
321}
322
323void cardreader_process_ecm(struct s_reader *reader, struct s_client *cl, ECM_REQUEST *er) {
324 if (ecm_ratelimit_check(reader, er, 1) != OK) {
325 rdr_debug_mask(reader, D_READER, "%s: ratelimit check failed.", __func__);
326 return; // reader_mode = 1: checkout ratelimiter in reader mode so srvid can be replaced
327 }
328 cs_ddump_mask(D_ATR, er->ecm, er->ecmlen, "ecm:");
329
330 struct timeb tps, tpe;
331 cs_ftime(&tps);
332
333 struct s_ecm_answer ea;
334 memset(&ea, 0, sizeof(struct s_ecm_answer));
335
336 int32_t rc = cardreader_do_ecm(reader, er, &ea);
337 rdr_debug_mask(reader, D_READER, "%s: cardreader_do_ecm returned rc=%d (ERROR=%d)", __func__, rc, ERROR);
338
339 ea.rc = E_FOUND; //default assume found
340 ea.rcEx = 0; //no special flag
341
342 if (rc == ERROR) {
343 char buf[32];
344 rdr_debug_mask(reader, D_READER, "Error processing ecm for caid %04X, srvid %04X, servicename: %s",
345 er->caid, er->srvid, get_servicename(cl, er->srvid, er->caid, buf));
346 ea.rc = E_NOTFOUND;
347 ea.rcEx = 0;
348 ICC_Async_DisplayMsg(reader, "Eer");
349 }
350
351 if (rc == E_CORRUPT) {
352 char buf[32];
353 rdr_debug_mask(reader, D_READER, "Error processing ecm for caid %04X, srvid %04X, servicename: %s",
354 er->caid, er->srvid, get_servicename(cl, er->srvid, er->caid, buf));
355 ea.rc = E_NOTFOUND;
356 ea.rcEx = E2_WRONG_CHKSUM; //flag it as wrong checksum
357 memcpy (ea.msglog,"Invalid ecm type for card",25);
358 }
359 cs_ftime(&tpe);
360 cl->lastecm=time((time_t*)0);
361 char ecmd5[17*3];
362 cs_hexdump(0, er->ecmd5, 16, ecmd5, sizeof(ecmd5));
363
364 rdr_debug_mask(reader, D_READER, "ecm hash: %s real time: %ld ms",
365 ecmd5, 1000 * (tpe.time - tps.time) + tpe.millitm - tps.millitm);
366
367 write_ecm_answer(reader, er, ea.rc, ea.rcEx, ea.cw, ea.msglog);
368
369 reader_post_process(reader);
370}
371
372#endif
Note: See TracBrowser for help on using the repository browser.