1 | #include "globals.h"
|
---|
2 | #ifdef READER_CONAX
|
---|
3 | #include "cscrypt/bn.h"
|
---|
4 | #include "reader-common.h"
|
---|
5 | #include "cscrypt/des.h"
|
---|
6 |
|
---|
7 | static int32_t CWPK_CNX(struct s_reader *reader,uint8_t *msg)
|
---|
8 | {
|
---|
9 | int32_t ret = 0;
|
---|
10 |
|
---|
11 | uint8_t CWp1[8];
|
---|
12 | uint8_t CWp2[8];
|
---|
13 | uint8_t CWs1[8];
|
---|
14 | uint8_t CWs2[8];
|
---|
15 |
|
---|
16 | CWp1[0] = msg[7];
|
---|
17 | CWp1[1] = msg[8];
|
---|
18 | CWp1[2] = msg[9];
|
---|
19 | CWp1[3] = msg[10];
|
---|
20 | CWp1[4] = msg[11];
|
---|
21 | CWp1[5] = msg[12];
|
---|
22 | CWp1[6] = msg[13];
|
---|
23 | CWp1[7] = msg[14];
|
---|
24 |
|
---|
25 | CWp2[0] = msg[22];
|
---|
26 | CWp2[1] = msg[23];
|
---|
27 | CWp2[2] = msg[24];
|
---|
28 | CWp2[3] = msg[25];
|
---|
29 | CWp2[4] = msg[26];
|
---|
30 | CWp2[5] = msg[27];
|
---|
31 | CWp2[6] = msg[28];
|
---|
32 | CWp2[7] = msg[29];
|
---|
33 |
|
---|
34 | des_ecb3_decrypt(CWp1,reader->cwpk_mod);
|
---|
35 | des_ecb3_decrypt(CWp2,reader->cwpk_mod);
|
---|
36 | CWs1[0] = CWp1[4];
|
---|
37 | CWs1[1] = CWp1[5];
|
---|
38 | CWs1[2] = CWp1[6];
|
---|
39 | CWs1[3] = CWp1[7];
|
---|
40 | CWs1[4] = CWp1[0];
|
---|
41 | CWs1[5] = CWp1[1];
|
---|
42 | CWs1[6] = CWp1[2];
|
---|
43 | CWs1[7] = CWp1[3];
|
---|
44 |
|
---|
45 | CWs2[0] = CWp2[4];
|
---|
46 | CWs2[1] = CWp2[5];
|
---|
47 | CWs2[2] = CWp2[6];
|
---|
48 | CWs2[3] = CWp2[7];
|
---|
49 | CWs2[4] = CWp2[0];
|
---|
50 | CWs2[5] = CWp2[1];
|
---|
51 | CWs2[6] = CWp2[2];
|
---|
52 | CWs2[7] = CWp2[3];
|
---|
53 |
|
---|
54 | int chkok = 1;
|
---|
55 | if(((CWs1[0] + CWs1[1] + CWs1[2]) & 0xFF) != CWs1[3])
|
---|
56 | {
|
---|
57 | chkok = 0;
|
---|
58 | rdr_log(reader, "CW0 checksum error [0]");
|
---|
59 | }
|
---|
60 | if(((CWs1[4] + CWs1[5] + CWs1[6]) & 0xFF) != CWs1[7])
|
---|
61 | {
|
---|
62 | chkok = 0;
|
---|
63 | rdr_log(reader, "CW0 checksum error [1]");
|
---|
64 | }
|
---|
65 | if(((CWs2[0] + CWs2[1] + CWs2[2]) & 0xFF) != CWs2[3])
|
---|
66 | {
|
---|
67 | chkok = 0;
|
---|
68 | rdr_log(reader, "CW1 checksum error [0]");
|
---|
69 | }
|
---|
70 | if(((CWs2[4] + CWs2[5] + CWs2[6]) & 0xFF) != CWs2[7])
|
---|
71 | {
|
---|
72 | chkok = 0;
|
---|
73 | rdr_log(reader, "CW1 checksum error [1]");
|
---|
74 | }
|
---|
75 |
|
---|
76 | if(chkok == 1)
|
---|
77 | {
|
---|
78 | memcpy(&msg[7],CWs1,0x08);
|
---|
79 | memcpy(&msg[22],CWs2,0x08);
|
---|
80 |
|
---|
81 | ret = 0;
|
---|
82 | }
|
---|
83 | if(chkok != 1)
|
---|
84 | {
|
---|
85 | ret = -8;
|
---|
86 | }
|
---|
87 |
|
---|
88 | return ret;
|
---|
89 | }
|
---|
90 |
|
---|
91 | static int32_t RSA_CNX(struct s_reader *reader, uint8_t *msg, uint8_t *mod, uint8_t *exp, uint32_t cta_lr, uint32_t modbytes, uint32_t expbytes)
|
---|
92 | {
|
---|
93 | int32_t ret = 0;
|
---|
94 | uint32_t n = 0, pre_size = 0, size = 0;
|
---|
95 | BN_CTX *ctx;
|
---|
96 | BIGNUM *bn_mod, *bn_exp, *bn_data, *bn_res;
|
---|
97 | uint8_t data[64];
|
---|
98 |
|
---|
99 | /*prefix size*/
|
---|
100 | pre_size = 2 + 4 + msg[5];
|
---|
101 |
|
---|
102 | /*size of data to decryption*/
|
---|
103 | if(msg[1] > (pre_size - 2))
|
---|
104 | { size = msg[1] - pre_size + 2; }
|
---|
105 |
|
---|
106 | if(cta_lr > (pre_size + size) && size >= modbytes && size < 128)
|
---|
107 | {
|
---|
108 | ctx = BN_CTX_new();
|
---|
109 |
|
---|
110 | if(ctx == NULL)
|
---|
111 | {
|
---|
112 | rdr_log_dbg(reader, D_READER, "RSA Error in RSA_CNX");
|
---|
113 | }
|
---|
114 |
|
---|
115 | BN_CTX_start(ctx);
|
---|
116 | bn_mod = BN_CTX_get(ctx);
|
---|
117 | bn_exp = BN_CTX_get(ctx);
|
---|
118 | bn_data = BN_CTX_get(ctx);
|
---|
119 | bn_res = BN_CTX_get(ctx);
|
---|
120 |
|
---|
121 | /*RSA first round*/
|
---|
122 | BN_bin2bn(mod, modbytes, bn_mod); // rsa modulus
|
---|
123 | BN_bin2bn(exp, expbytes, bn_exp); // exponent
|
---|
124 | BN_bin2bn(msg + pre_size, modbytes, bn_data);
|
---|
125 | BN_mod_exp(bn_res, bn_data, bn_exp, bn_mod, ctx);
|
---|
126 |
|
---|
127 | n = BN_bn2bin(bn_res, data);
|
---|
128 |
|
---|
129 | size -= modbytes; // 3
|
---|
130 | pre_size += modbytes;
|
---|
131 |
|
---|
132 | /*Check if second round is needed*/
|
---|
133 | if(0 < size)
|
---|
134 | {
|
---|
135 | /*check if length of data from first RSA round will be enough to padding rest of data*/
|
---|
136 | if((n + size) >= modbytes)
|
---|
137 | {
|
---|
138 | /*RSA second round*/
|
---|
139 | /*move the remaining data at the beginning of the buffer*/
|
---|
140 | memcpy(msg, msg + pre_size, size);
|
---|
141 | /*padding buffer with data from first round*/
|
---|
142 | memcpy(msg + size, data + (n - (modbytes - size)), modbytes - size);
|
---|
143 |
|
---|
144 | BN_bin2bn(msg, modbytes, bn_data);
|
---|
145 | BN_mod_exp(bn_res, bn_data, bn_exp, bn_mod, ctx);
|
---|
146 | n = BN_bn2bin(bn_res, data);
|
---|
147 | if(0x25 != data[0])
|
---|
148 | { ret = -1; } /*RSA key is probably wrong*/
|
---|
149 | }
|
---|
150 | else
|
---|
151 | { ret = -3; } /*wrong size of data for second round*/
|
---|
152 | }
|
---|
153 |
|
---|
154 | if(0 == ret)
|
---|
155 | { memcpy(msg, data, n); }
|
---|
156 |
|
---|
157 | BN_CTX_end(ctx);
|
---|
158 | BN_CTX_free(ctx);
|
---|
159 | }
|
---|
160 | else
|
---|
161 | { ret = -2; } /*wrong size of data*/
|
---|
162 |
|
---|
163 | return ret;
|
---|
164 | }
|
---|
165 |
|
---|
166 | static time_t chid_date(const uint8_t *ptr, char *buf, int32_t l)
|
---|
167 | {
|
---|
168 | time_t rc = 0;
|
---|
169 | struct tm timeinfo;
|
---|
170 | memset(&timeinfo, 0, sizeof(struct tm));
|
---|
171 |
|
---|
172 | if(buf)
|
---|
173 | {
|
---|
174 | timeinfo.tm_year = 90 + (ptr[1] >> 4) + (((ptr[0] >> 5) & 7) * 10);
|
---|
175 | timeinfo.tm_mon = (ptr[1] & 0xf) - 1;
|
---|
176 | timeinfo.tm_mday = ptr[0] & 0x1f;
|
---|
177 | timeinfo.tm_isdst = -1;
|
---|
178 | rc = mktime(&timeinfo);
|
---|
179 | strftime(buf, l, "%Y/%m/%d", &timeinfo);
|
---|
180 | }
|
---|
181 | return (rc);
|
---|
182 | }
|
---|
183 |
|
---|
184 | static int32_t read_record(struct s_reader *reader, const uint8_t *cmd, const uint8_t *data, uint8_t *cta_res)
|
---|
185 | {
|
---|
186 | uint16_t cta_lr;
|
---|
187 | uint8_t insCA[] = { 0xDD, 0xCA, 0x00, 0x00, 0x00 };
|
---|
188 |
|
---|
189 | write_cmd(cmd, data); // select record
|
---|
190 | if(cta_res[0] != 0x98)
|
---|
191 | { return (-1); }
|
---|
192 |
|
---|
193 | insCA[4] = cta_res[1]; // get len
|
---|
194 | write_cmd(insCA, NULL); // read record
|
---|
195 |
|
---|
196 | if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1]))
|
---|
197 | { return (-1); }
|
---|
198 |
|
---|
199 | return (cta_lr - 2);
|
---|
200 | }
|
---|
201 |
|
---|
202 | static int32_t check_pairing(struct s_reader *reader, const uint8_t *cmd, const uint8_t *data, uint8_t *cta_res)
|
---|
203 | {
|
---|
204 | uint16_t cta_lr;
|
---|
205 |
|
---|
206 | if(reader->cwpk_mod_length)
|
---|
207 | {
|
---|
208 | write_cmd(cmd, data);
|
---|
209 | rdr_log(reader, "CWPK Pairing is active");
|
---|
210 | }
|
---|
211 | else if(reader->rsa_mod_length)
|
---|
212 | {
|
---|
213 | rdr_log(reader, "RSA Pairing is active");
|
---|
214 | }
|
---|
215 | else
|
---|
216 | {
|
---|
217 | rdr_log(reader, "Pairing is not active");
|
---|
218 | }
|
---|
219 | return OK;
|
---|
220 | }
|
---|
221 |
|
---|
222 | static uint8_t PairingECMRotation(struct s_reader *reader, const ECM_REQUEST *er, int32_t n)
|
---|
223 | {
|
---|
224 | uint8_t cta_res[CTA_RES_LEN] = { 0x00 };
|
---|
225 | uint8_t ins26[] = { 0xDD, 0x26, 0x00, 0x00, 0x03, 0x10, 0x01, 0x00 };
|
---|
226 | uint8_t cnxcurrecm = 0;
|
---|
227 |
|
---|
228 | if(0x0 != reader->rsa_mod[0] && n > 3 &&
|
---|
229 | 0x54 == er->ecm[n - 3] &&
|
---|
230 | 0x02 == er->ecm[n - 2] &&
|
---|
231 | 0x00 == er->ecm[n - 1])
|
---|
232 | {
|
---|
233 | cnxcurrecm = 1;
|
---|
234 | }
|
---|
235 |
|
---|
236 | if((0 == reader->cnxlastecm) != (0 == cnxcurrecm))
|
---|
237 | {
|
---|
238 | if(0 == cnxcurrecm) // not paired
|
---|
239 | { ins26[7] = 0x30; }
|
---|
240 | else
|
---|
241 | { ins26[7] = 0x40; }
|
---|
242 |
|
---|
243 | if(read_record(reader, ins26, ins26 + 5, cta_res) <= 0)
|
---|
244 | { rdr_log(reader, "PairingECMRotation - ERROR"); }
|
---|
245 | }
|
---|
246 | reader->cnxlastecm = cnxcurrecm;
|
---|
247 | return cnxcurrecm;
|
---|
248 | }
|
---|
249 |
|
---|
250 | static int32_t conax_card_init(struct s_reader *reader, ATR *newatr)
|
---|
251 | {
|
---|
252 | uint8_t cta_res[CTA_RES_LEN];
|
---|
253 | int32_t i, j, n;
|
---|
254 | static const uint8_t ins26[] = { 0xDD, 0x26, 0x00, 0x00, 0x03, 0x10, 0x01, 0x40 };
|
---|
255 | static const uint8_t inscp[] = { 0xDD, 0x26, 0x00, 0x00, 0x04, 0x6C, 0x02, 0x10,0x00 };
|
---|
256 | uint8_t ins82[] = { 0xDD, 0x82, 0x00, 0x00, 0x11, 0x11, 0x0f, 0x01, 0xb0, 0x0f, 0xff,
|
---|
257 | 0xff, 0xfb, 0x00, 0x00, 0x09, 0x04, 0x0b, 0x00, 0xe0, 0x30, 0x2b };
|
---|
258 |
|
---|
259 | uint8_t cardver = 0;
|
---|
260 |
|
---|
261 | get_hist;
|
---|
262 | if((hist_size < 4) || (memcmp(hist, "0B00", 4)))
|
---|
263 | { return ERROR; }
|
---|
264 |
|
---|
265 | reader->caid = 0xB00;
|
---|
266 |
|
---|
267 | if((n = read_record(reader, ins26, ins26 + 5, cta_res)) <= 0) { return ERROR; } // read caid, card-version
|
---|
268 |
|
---|
269 | for(i = 0; i < n; i += cta_res[i + 1] + 2)
|
---|
270 | {
|
---|
271 | switch(cta_res[i])
|
---|
272 | {
|
---|
273 | case 0x20:
|
---|
274 | cardver = cta_res[i + 2];
|
---|
275 | break;
|
---|
276 |
|
---|
277 | case 0x28:
|
---|
278 | reader->caid = (cta_res[i + 2] << 8) | cta_res[i + 3];
|
---|
279 | }
|
---|
280 | }
|
---|
281 |
|
---|
282 | // Ins82 command needs to use the correct CAID reported in nano 0x28
|
---|
283 | ins82[17] = (reader->caid >> 8) & 0xFF;
|
---|
284 | ins82[18] = (reader->caid) & 0xFF;
|
---|
285 |
|
---|
286 | if((n = read_record(reader, ins82, ins82 + 5, cta_res)) <= 0) { return ERROR; } // read serial
|
---|
287 |
|
---|
288 | reader->nprov = 0;
|
---|
289 |
|
---|
290 | for(j = 0, i = 2; i < n; i += cta_res[i + 1] + 2)
|
---|
291 | {
|
---|
292 | switch(cta_res[i])
|
---|
293 | {
|
---|
294 | case 0x23:
|
---|
295 | if(cta_res[i + 5] != 0x00)
|
---|
296 | {
|
---|
297 | memcpy(reader->hexserial, &cta_res[i + 3], 6);
|
---|
298 | }
|
---|
299 | else
|
---|
300 | {
|
---|
301 | memcpy(reader->sa[j], &cta_res[i + 5], 4);
|
---|
302 | j++;
|
---|
303 | reader->nprov++;
|
---|
304 | }
|
---|
305 | break;
|
---|
306 | }
|
---|
307 | }
|
---|
308 |
|
---|
309 | memset(reader->prid, 0x00, sizeof(reader->prid));
|
---|
310 |
|
---|
311 | rdr_log_sensitive(reader, "type: Conax, caid: %04X, serial: {%llu}, hex serial: {%02x%02x%02x%02x}, card: v%d",
|
---|
312 | reader->caid, (unsigned long long) b2ll(6, reader->hexserial), reader->hexserial[2],
|
---|
313 | reader->hexserial[3], reader->hexserial[4], reader->hexserial[5], cardver);
|
---|
314 |
|
---|
315 | rdr_log(reader, "Providers: %d", reader->nprov);
|
---|
316 |
|
---|
317 | for(j = 0; j < reader->nprov; j++)
|
---|
318 | {
|
---|
319 | rdr_log(reader, "Provider: %d Provider-Id: %06X", j + 1, b2i(4, reader->prid[j]));
|
---|
320 | rdr_log_sensitive(reader, "Provider: %d SharedAddress: {%08X}", j + 1, b2i(4, reader->sa[j]));
|
---|
321 | }
|
---|
322 | check_pairing(reader, inscp, inscp + 5, cta_res);
|
---|
323 |
|
---|
324 | return OK;
|
---|
325 | }
|
---|
326 |
|
---|
327 | static int32_t conax_send_pin(struct s_reader *reader)
|
---|
328 | {
|
---|
329 | def_resp;
|
---|
330 | uint8_t insPIN[] = { 0xDD, 0xC8, 0x00, 0x00, 0x07, 0x1D, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00 }; // Last four are the Pin-Code
|
---|
331 | memcpy(insPIN + 8, reader->pincode, 4);
|
---|
332 |
|
---|
333 | write_cmd(insPIN, insPIN + 5);
|
---|
334 | rdr_log_dbg(reader, D_READER, "Sent pincode to card.");
|
---|
335 |
|
---|
336 | return OK;
|
---|
337 | }
|
---|
338 |
|
---|
339 | static int32_t conax_do_ecm(struct s_reader *reader, const ECM_REQUEST *er, struct s_ecm_answer *ea)
|
---|
340 | {
|
---|
341 | def_resp;
|
---|
342 | int32_t i, j, n, num_dw = 0, rc = 0;
|
---|
343 | uint8_t insA2[] = { 0xDD, 0xA2, 0x00, 0x00, 0x00 };
|
---|
344 | uint8_t insCA[] = { 0xDD, 0xCA, 0x00, 0x00, 0x00 };
|
---|
345 |
|
---|
346 | uint8_t exp[] = { 0x01, 0x00, 0x01 };
|
---|
347 | uint8_t buf[256];
|
---|
348 |
|
---|
349 | char ppp = 0x00;
|
---|
350 |
|
---|
351 | if((n = check_sct_len(er->ecm, 3)) < 0)
|
---|
352 | { return ERROR; }
|
---|
353 |
|
---|
354 | buf[0] = 0x14;
|
---|
355 | buf[1] = n + 1;
|
---|
356 |
|
---|
357 | if(reader->cwpk_mod_length)
|
---|
358 | {
|
---|
359 | buf[2] = 4;
|
---|
360 | ppp = 0x01;
|
---|
361 | }
|
---|
362 | else if(0x0 != reader->rsa_mod[0])
|
---|
363 | {
|
---|
364 | if(0x0 != PairingECMRotation(reader, er, n))
|
---|
365 | {
|
---|
366 | buf[2] = 2;
|
---|
367 | ppp = 0x03;
|
---|
368 | }
|
---|
369 | else
|
---|
370 | {
|
---|
371 | buf[2] = 0;
|
---|
372 | ppp = 0x02;
|
---|
373 | }
|
---|
374 | }
|
---|
375 | else
|
---|
376 | {
|
---|
377 | buf[2] = 0;
|
---|
378 | ppp = 0x02;
|
---|
379 | }
|
---|
380 |
|
---|
381 | memcpy(buf + 3, er->ecm, n);
|
---|
382 | insA2[4] = n + 3;
|
---|
383 |
|
---|
384 | write_cmd(insA2, buf); // write Header + ECM
|
---|
385 |
|
---|
386 | while((cta_res[cta_lr - 2] == 0x98) && // Antwort
|
---|
387 | ((insCA[4] = cta_res[cta_lr - 1]) > 0) && (insCA[4] != 0xFF))
|
---|
388 | {
|
---|
389 | write_cmd(insCA, NULL); // Codeword auslesen
|
---|
390 |
|
---|
391 | if((cta_res[cta_lr - 2] == 0x98) || ((cta_res[cta_lr - 2] == 0x90)))
|
---|
392 | {
|
---|
393 | /*checks if answer is encrypted with RSA algo and decrypts it if needed*/
|
---|
394 | if(0x81 == cta_res[0] && 2 == cta_res[2] >> 5 && 0x03 == ppp) /*81 XX 5X*/
|
---|
395 | {
|
---|
396 | if(0x00 == cta_res[cta_lr - 1])
|
---|
397 | { rc = RSA_CNX(reader, cta_res, reader->rsa_mod, exp, cta_lr, 64u, 3u); }
|
---|
398 | else
|
---|
399 | { rc = -4; } /*card has no right to decode this channel*/
|
---|
400 | }
|
---|
401 | else if(0x01 == ppp)
|
---|
402 | {
|
---|
403 | if(0x00 == cta_res[cta_lr - 1])
|
---|
404 | {
|
---|
405 | /*trying to decode using CWPK*/
|
---|
406 | rc = CWPK_CNX(reader, cta_res); /*enabled when no loging needed*/
|
---|
407 | }
|
---|
408 | else
|
---|
409 | {
|
---|
410 | rc = -4;
|
---|
411 | }
|
---|
412 | }
|
---|
413 |
|
---|
414 | if(0 == rc)
|
---|
415 | {
|
---|
416 | for(i = 0; i < cta_lr - 2 && num_dw < 2; i += cta_res[i + 1] + 2)
|
---|
417 | {
|
---|
418 | switch(cta_res[i])
|
---|
419 | {
|
---|
420 | case 0x25:
|
---|
421 | if((cta_res[i + 1] >= 0xD) && !((n = cta_res[i + 4]) & 0xFE))
|
---|
422 | {
|
---|
423 | rc |= (1 << n);
|
---|
424 | memcpy(ea->cw + (n << 3), cta_res + i + 7, 8);
|
---|
425 | ++num_dw;
|
---|
426 | }
|
---|
427 | break;
|
---|
428 |
|
---|
429 | case 0x31:
|
---|
430 | if((cta_res[i + 1] == 0x02 && cta_res[i + 2] == 0x00 && cta_res[i + 3] == 0x00) || \
|
---|
431 | (cta_res[i + 1] == 0x02 && cta_res[i + 2] == 0x40 && cta_res[i + 3] == 0x00))
|
---|
432 | { break; }
|
---|
433 | else if(strcmp(reader->pincode, "none"))
|
---|
434 | {
|
---|
435 | conax_send_pin(reader);
|
---|
436 | write_cmd(insA2, buf); // write Header + ECM
|
---|
437 |
|
---|
438 | while((cta_res[cta_lr - 2] == 0x98) && // Antwort
|
---|
439 | ((insCA[4] = cta_res[cta_lr - 1]) > 0) && (insCA[4] != 0xFF))
|
---|
440 | {
|
---|
441 | write_cmd(insCA, NULL); // Codeword auslesen
|
---|
442 |
|
---|
443 | if((cta_res[cta_lr - 2] == 0x98) ||
|
---|
444 | ((cta_res[cta_lr - 2] == 0x90) && (!cta_res[cta_lr - 1])))
|
---|
445 | {
|
---|
446 | for(j = 0; j < cta_lr - 2; j += cta_res[j + 1] + 2)
|
---|
447 | {
|
---|
448 | if((cta_res[j] == 0x25) && // access: is cw
|
---|
449 | (cta_res[j + 1] >= 0xD) && // 0xD: 5 header + 8 cw
|
---|
450 | !((n = cta_res[j + 4]) & 0xFE)) // cw idx must be 0 or 1
|
---|
451 | {
|
---|
452 | rc |= (1 << n);
|
---|
453 | memcpy(ea->cw + (n << 3), cta_res + j + 7, 8);
|
---|
454 | ++num_dw;
|
---|
455 | }
|
---|
456 | }
|
---|
457 | }
|
---|
458 | }
|
---|
459 | }
|
---|
460 | break;
|
---|
461 | }
|
---|
462 | }
|
---|
463 | }
|
---|
464 | }
|
---|
465 | }
|
---|
466 |
|
---|
467 | switch(rc)
|
---|
468 | {
|
---|
469 | case -1:
|
---|
470 | rdr_log(reader, "conax decode ECM problem - RSA key is probably faulty");
|
---|
471 | break;
|
---|
472 |
|
---|
473 | case -2:
|
---|
474 | rdr_log(reader, "conax RSA pairing - wrong size of data");
|
---|
475 | break;
|
---|
476 |
|
---|
477 | case -3:
|
---|
478 | rdr_log(reader, "conax RSA pairing- wrong size of data for second round");
|
---|
479 | /* fallthrough */
|
---|
480 |
|
---|
481 | case -4:
|
---|
482 | rdr_log(reader, "card has no right to decode this channel");
|
---|
483 | break;
|
---|
484 |
|
---|
485 | case -8:
|
---|
486 | rdr_log(reader, "CWPK is faulty");
|
---|
487 | break;
|
---|
488 | }
|
---|
489 |
|
---|
490 | /* answer 9011 - conax smart card need reset */
|
---|
491 | if(2 <= cta_lr && 0x90 == cta_res[cta_lr - 2] && 0x11 == cta_res[cta_lr - 1])
|
---|
492 | {
|
---|
493 | rdr_log(reader, "conax card hangs - reset is required");
|
---|
494 | reader->card_status = UNKNOWN;
|
---|
495 | }
|
---|
496 |
|
---|
497 | if(rc == 3)
|
---|
498 | { return OK; }
|
---|
499 | else
|
---|
500 | { return ERROR; }
|
---|
501 | }
|
---|
502 |
|
---|
503 | static int32_t conax_get_emm_type(EMM_PACKET *ep, struct s_reader *rdr)
|
---|
504 | {
|
---|
505 | int32_t i, ok = 0;
|
---|
506 | char tmp_dbg[17];
|
---|
507 |
|
---|
508 | rdr_log_dbg(rdr, D_EMM, "Entered conax_get_emm_type ep->emm[2]=%02x", ep->emm[2]);
|
---|
509 |
|
---|
510 | for(i = 0; i < rdr->nprov; i++)
|
---|
511 | {
|
---|
512 | ok = (!memcmp(&ep->emm[6], rdr->sa[i], 4));
|
---|
513 | if(ok) { break; }
|
---|
514 | }
|
---|
515 |
|
---|
516 | if(ok)
|
---|
517 | {
|
---|
518 | ep->type = SHARED;
|
---|
519 | memset(ep->hexserial, 0, 8);
|
---|
520 | memcpy(ep->hexserial, &ep->emm[6], 4);
|
---|
521 | rdr_log_dbg_sensitive(rdr, D_EMM, "SHARED, ep->hexserial = {%s}",
|
---|
522 | cs_hexdump(1, ep->hexserial, 8, tmp_dbg, sizeof(tmp_dbg)));
|
---|
523 | return 1;
|
---|
524 | }
|
---|
525 | else
|
---|
526 | {
|
---|
527 | if(!memcmp(&ep->emm[6], rdr->hexserial + 2, 4))
|
---|
528 | {
|
---|
529 | ep->type = UNIQUE;
|
---|
530 | memset(ep->hexserial, 0, 8);
|
---|
531 | memcpy(ep->hexserial + 2, &ep->emm[6], 4);
|
---|
532 | rdr_log_dbg_sensitive(rdr, D_EMM, "UNIQUE, ep->hexserial = {%s}",
|
---|
533 | cs_hexdump(1, ep->hexserial, 8, tmp_dbg, sizeof(tmp_dbg)));
|
---|
534 | return 1;
|
---|
535 | }
|
---|
536 | else
|
---|
537 | {
|
---|
538 | ep->type = GLOBAL;
|
---|
539 | rdr_log_dbg(rdr, D_EMM, "GLOBAL");
|
---|
540 | memset(ep->hexserial, 0, 8);
|
---|
541 | return 1;
|
---|
542 | }
|
---|
543 | }
|
---|
544 | }
|
---|
545 |
|
---|
546 | static int32_t conax_get_emm_filter(struct s_reader *rdr, struct s_csystem_emm_filter **emm_filters, unsigned int *filter_count)
|
---|
547 | {
|
---|
548 | if(*emm_filters == NULL)
|
---|
549 | {
|
---|
550 | const unsigned int max_filter_count = 2 + rdr->nprov;
|
---|
551 | if(!cs_malloc(emm_filters, max_filter_count * sizeof(struct s_csystem_emm_filter)))
|
---|
552 | { return ERROR; }
|
---|
553 |
|
---|
554 | struct s_csystem_emm_filter *filters = *emm_filters;
|
---|
555 | *filter_count = 0;
|
---|
556 |
|
---|
557 | int idx = 0, prov;
|
---|
558 |
|
---|
559 | filters[idx].type = EMM_GLOBAL;
|
---|
560 | filters[idx].enabled = 0; // FIXME: dont see any conax global EMM yet
|
---|
561 | filters[idx].filter[0] = 0x82;
|
---|
562 | filters[idx].mask[0] = 0xFF;
|
---|
563 | filters[idx].filter[8] = 0x70;
|
---|
564 | filters[idx].mask[8] = 0xFF;
|
---|
565 | idx++;
|
---|
566 |
|
---|
567 | for(prov = 0; prov < rdr->nprov; prov++)
|
---|
568 | {
|
---|
569 | filters[idx].type = EMM_SHARED;
|
---|
570 | filters[idx].enabled = 1;
|
---|
571 | filters[idx].filter[0] = 0x82;
|
---|
572 | filters[idx].mask[0] = 0xFF;
|
---|
573 | memcpy(&filters[idx].filter[4], rdr->sa[prov], 4);
|
---|
574 | memset(&filters[idx].mask[4], 0xFF, 4);
|
---|
575 | idx++;
|
---|
576 | }
|
---|
577 |
|
---|
578 | filters[idx].type = EMM_UNIQUE;
|
---|
579 | filters[idx].enabled = 1;
|
---|
580 | filters[idx].filter[0] = 0x82;
|
---|
581 | filters[idx].mask[0] = 0xFF;
|
---|
582 | memcpy(&filters[idx].filter[4], rdr->hexserial + 2, 4);
|
---|
583 | memset(&filters[idx].mask[4], 0xFF, 4);
|
---|
584 | idx++;
|
---|
585 |
|
---|
586 | *filter_count = idx;
|
---|
587 | }
|
---|
588 |
|
---|
589 | return OK;
|
---|
590 | }
|
---|
591 |
|
---|
592 | static int32_t conax_do_emm(struct s_reader *reader, EMM_PACKET *ep)
|
---|
593 | {
|
---|
594 | def_resp;
|
---|
595 | uint8_t insCA[] = { 0xDD, 0xCA, 0x00, 0x00, 0x00 };
|
---|
596 | uint8_t insEMM[] = { 0xDD, 0x84, 0x00, 0x00, 0x00 };
|
---|
597 | uint8_t buf[255];
|
---|
598 | int32_t rc = 0;
|
---|
599 |
|
---|
600 | const int32_t l = ep->emm[2];
|
---|
601 |
|
---|
602 | insEMM[4] = l + 5;
|
---|
603 | buf[0] = 0x12;
|
---|
604 | buf[1] = l + 3;
|
---|
605 | memcpy(buf + 2, ep->emm, buf[1]);
|
---|
606 | write_cmd(insEMM, buf);
|
---|
607 |
|
---|
608 | if(cta_res[0] == 0x98)
|
---|
609 | {
|
---|
610 | insCA[4] = cta_res[1];
|
---|
611 | write_cmd(insCA, NULL);
|
---|
612 | }
|
---|
613 |
|
---|
614 | rc = ((cta_res[0] == 0x90) && (cta_res[1] == 0x00));
|
---|
615 |
|
---|
616 | if(rc)
|
---|
617 | { return OK; }
|
---|
618 | else
|
---|
619 | { return ERROR; }
|
---|
620 | }
|
---|
621 |
|
---|
622 | static int32_t conax_card_info(struct s_reader *reader)
|
---|
623 | {
|
---|
624 | def_resp;
|
---|
625 | int32_t type, i, j, k = 0, n = 0, l;
|
---|
626 | uint16_t provid = 0;
|
---|
627 | char provname[32], pdate[32], chid[32];
|
---|
628 | static const uint8_t insC6[] = { 0xDD, 0xC6, 0x00, 0x00, 0x03, 0x1C, 0x01, 0x00 };
|
---|
629 | static const uint8_t ins26[] = { 0xDD, 0x26, 0x00, 0x00, 0x03, 0x1C, 0x01, 0x01 };
|
---|
630 | uint8_t insCA[] = { 0xDD, 0xCA, 0x00, 0x00, 0x00 };
|
---|
631 | char *txt[] = { "Package", "PPV-Event" };
|
---|
632 | static const uint8_t *cmd[] = { insC6, ins26 };
|
---|
633 | time_t start_t = 0, end_t = 0;
|
---|
634 | uint32_t cxclass = 0;
|
---|
635 |
|
---|
636 | cs_clear_entitlement(reader); // reset the entitlements
|
---|
637 |
|
---|
638 | for(type = 0; type < 2; type++)
|
---|
639 | {
|
---|
640 | n = 0;
|
---|
641 | write_cmd(cmd[type], cmd[type] + 5);
|
---|
642 | while(cta_res[cta_lr - 2] == 0x98)
|
---|
643 | {
|
---|
644 | insCA[4] = cta_res[cta_lr - 1]; // get len
|
---|
645 | write_cmd(insCA, NULL); // read
|
---|
646 |
|
---|
647 | if((cta_res[cta_lr - 2] == 0x90) || (cta_res[cta_lr - 2] == 0x98))
|
---|
648 | {
|
---|
649 | for(j = 0; j < cta_lr - 2; j += cta_res[j + 1] + 2)
|
---|
650 | {
|
---|
651 | provid = (cta_res[j + 2 + type] << 8) | cta_res[j + 3 + type];
|
---|
652 | chid[0] = '\0';
|
---|
653 |
|
---|
654 | for(k = 0, i = j + 4 + type; (i < j + cta_res[j + 1]); i += cta_res[i + 1] + 2)
|
---|
655 | {
|
---|
656 | switch(cta_res[i])
|
---|
657 | {
|
---|
658 | case 0x01:
|
---|
659 | l = (cta_res[i + 1] < (sizeof(provname) - 1)) ? cta_res[i + 1] : sizeof(provname) - 1;
|
---|
660 | memcpy(provname, cta_res + i + 2, l);
|
---|
661 | provname[l] = '\0';
|
---|
662 | break;
|
---|
663 |
|
---|
664 | case 0x30:
|
---|
665 | if(k > 1)
|
---|
666 | {
|
---|
667 | rdr_log(reader, "%s: %d, id: %04X%s, date: %s - %s, name: %s",
|
---|
668 | txt[type], ++n, provid, chid, pdate, pdate + 16, trim(provname));
|
---|
669 |
|
---|
670 | // add entitlements to list
|
---|
671 | cs_add_entitlement(reader, reader->caid, b2ll(4, reader->prid[0]),
|
---|
672 | provid, cxclass, start_t, end_t, type + 1, 1);
|
---|
673 |
|
---|
674 | k = 0;
|
---|
675 | chid[0] = '\0';
|
---|
676 | }
|
---|
677 | if(k == 0) { start_t = chid_date(cta_res + i + 2, pdate, 15); }
|
---|
678 | else { end_t = chid_date(cta_res + i + 2, pdate + 16, 15) /* add 23:59:59 here: */ + 0x1517F; }
|
---|
679 | ++k;
|
---|
680 | break;
|
---|
681 |
|
---|
682 | case 0x20: // Provider classes
|
---|
683 | case 0x90: // (?) not sure what this is, saw it once in log
|
---|
684 | snprintf(chid, sizeof(chid), ", classes: %02X%02X%02X%02X",
|
---|
685 | cta_res[i + 2], cta_res[i + 3], cta_res[i + 4] , cta_res[i + 5]);
|
---|
686 | cxclass = b2ll(4, &cta_res[i + 2]);
|
---|
687 | break;
|
---|
688 | }
|
---|
689 | }
|
---|
690 | rdr_log(reader, "%s: %d, id: %04X%s, date: %s - %s, name: %s",
|
---|
691 | txt[type], ++n, provid, chid, pdate, pdate + 16, trim(provname));
|
---|
692 |
|
---|
693 | // add entitlements to list
|
---|
694 | cs_add_entitlement(reader, reader->caid, b2ll(4, reader->prid[0]),
|
---|
695 | provid, cxclass, start_t, end_t, type + 1, 1);
|
---|
696 | }
|
---|
697 | }
|
---|
698 | }
|
---|
699 | }
|
---|
700 | rdr_log(reader, "ready for requests");
|
---|
701 | return OK;
|
---|
702 | }
|
---|
703 |
|
---|
704 | const struct s_cardsystem reader_conax =
|
---|
705 | {
|
---|
706 | .desc = "conax",
|
---|
707 | .caids = (uint16_t[]){ 0x0B, 0 },
|
---|
708 | .do_emm = conax_do_emm,
|
---|
709 | .do_ecm = conax_do_ecm,
|
---|
710 | .card_info = conax_card_info,
|
---|
711 | .card_init = conax_card_init,
|
---|
712 | .get_emm_type = conax_get_emm_type,
|
---|
713 | .get_emm_filter = conax_get_emm_filter,
|
---|
714 | };
|
---|
715 |
|
---|
716 | #endif
|
---|