source: branches/smartreader/csctapi/pps.c@ 1186

Last change on this file since 1186 was 1186, checked in by rorothetroll, 12 years ago

resync with trunk. Old smartreader code is gone (and will soon be gone from trunk). I'm restarting from trunk to do a clean implementation of the samrtreader support using libusb.

File size: 16.3 KB
Line 
1/*
2 pps.c
3 Protocol Parameters Selection
4
5 This file is part of the Unix driver for Towitoko smartcard readers
6 Copyright (C) 2000 2001 Carlos Prados <cprados@yahoo.com>
7
8 This version is modified by doz21 to work in a special manner ;)
9
10 This library is free software; you can redistribute it and/or
11 modify it under the terms of the GNU Lesser General Public
12 License as published by the Free Software Foundation; either
13 version 2 of the License, or (at your option) any later version.
14
15 This library is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Lesser General Public License for more details.
19
20 You should have received a copy of the GNU Lesser General Public
21 License along with this library; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23*/
24
25#include "pps.h"
26#include "atr.h"
27#include "protocol_t0.h"
28#include "protocol_t1.h"
29#include <stdlib.h>
30#include <stdio.h>
31#include <string.h>
32#include "ifd.h"
33
34/*
35 * Not exported constants definition
36 */
37
38#define PPS_DEFAULT_PROTOCOL 0x00
39
40/*
41 * Not exported macros definition
42 */
43
44#define PPS_HAS_PPS1(block) ((block[1] & 0x10) == 0x10)
45#define PPS_HAS_PPS2(block) ((block[1] & 0x20) == 0x20)
46#define PPS_HAS_PPS3(block) ((block[1] & 0x40) == 0x40)
47
48/*
49 * Not exported funtions declaration
50 */
51
52static int PPS_Exchange (PPS * pps, BYTE * params, unsigned *length);
53
54static bool PPS_Match (BYTE * request, unsigned len_request, BYTE * reply, unsigned len_reply);
55
56static unsigned PPS_GetLength (BYTE * block);
57
58static int PPS_InitICC (PPS * pps);
59
60static int PPS_InitProtocol (PPS * pps, int protocol_selected);
61
62static BYTE PPS_GetPCK (BYTE * block, unsigned length);
63
64/*
65 * Exported functions definition
66 */
67
68PPS * PPS_New (ICC_Async * icc)
69{
70 PPS *pps;
71
72 pps = (PPS *) malloc (sizeof (PPS));
73
74 if (pps != NULL)
75 {
76 pps->icc = icc;
77 pps->protocol = NULL;
78 pps->parameters.t = PPS_DEFAULT_PROTOCOL;
79 pps->parameters.FI = ATR_DEFAULT_FI;
80 pps->parameters.d = ATR_DEFAULT_D;
81 pps->parameters.n = ATR_DEFAULT_N;
82 }
83
84 return pps;
85}
86
87int PPS_Perform (PPS * pps, BYTE * params, unsigned *length)
88{
89 //Performs PPS Exchange on command when *length >0
90 //If unsuccesfull, or when length <= 0
91 //Gets parametes from ATR
92 //If necessary perform PPS session
93 //
94 //Output is pps->params.FI,n,d,t set with correct values
95 //and switched SC-device conform these values to correct baudrate
96 //
97 //We need to store FI instread of F, because SCI_DEV works with FI
98 //and it is easier to overclock then
99 //also from FI -> F is easy, other way around not
100
101 ATR *atr;
102 int ret;
103 bool PPS_success;
104
105 /* Perform PPS Exchange if requested by command */
106 if ((*length) > 0)
107 {
108 ret = PPS_Exchange (pps, params, length);
109
110 /* Get parameters from PPS handsake */
111 if (ret == PPS_OK)
112 {
113 pps->parameters.t = params[1] & 0x0F;
114
115 if (PPS_HAS_PPS1 (params))
116 {
117 pps->parameters.FI = (params[2] >> 4);
118 pps->parameters.d = atr_d_table[(params[2] & 0x0F)];
119 }
120
121/*
122 ret = PPS_InitICC(pps);
123
124 if (ret != PPS_OK)
125 return ret;
126*/
127 }
128/*
129 else
130 {
131 return ret;
132 }
133*/
134 }
135 PPS_success = PPS_OK;
136 int protocol_selected = 0; //stores which TAi,TBi etc. bytes must be used 0 means not set
137 atr = ICC_Async_GetAtr (pps->icc);
138 if ((*length) <= 0 || !PPS_success) // If not by command, or PPS Exchange by command failed: Try PPS Exchange by ATR or Get parameters from ATR
139 {
140 int numprot = atr->pn;//number of protocol lines in ATR
141 BYTE tx;
142 cs_debug("ATR reports smartcard supports %i protocols:",numprot);
143 int i,point;
144 char txt[50];
145 bool OffersT[3]; //T14 stored as T2
146 for (i = 0; i <= 2; i++)
147 OffersT[i] = FALSE;
148 for (i=1; i<= numprot; i++) {
149 sprintf(txt,"Protocol %01i: ",i);
150 point = 12;
151 if (ATR_GetInterfaceByte (atr, i, ATR_INTERFACE_BYTE_TA, &tx) == ATR_OK) {
152 sprintf((char *)txt+point,"TA%i=%02X ",i,tx);
153 point +=7;
154 }
155 if (ATR_GetInterfaceByte (atr, i, ATR_INTERFACE_BYTE_TB, &tx) == ATR_OK) {
156 sprintf((char *)txt+point,"TB%i=%02X ",i,tx);
157 point +=7;
158 }
159 if (ATR_GetInterfaceByte (atr, i, ATR_INTERFACE_BYTE_TC, &tx) == ATR_OK) {
160 sprintf((char *)txt+point,"TC%i=%02X ",i,tx);
161 point +=7;
162 }
163 if (ATR_GetInterfaceByte (atr, i, ATR_INTERFACE_BYTE_TD, &tx) == ATR_OK) {
164 sprintf((char *)txt+point,"TD%i=%02X ",i,tx);
165 point +=7;
166 tx &= 0X0F;
167 sprintf((char *)txt+point,"(T%i)",tx);
168 if (tx == 14)
169 OffersT[2] = TRUE;
170 else
171 OffersT[tx] = TRUE;
172 }
173 else {
174 sprintf((char *)txt+point,"no TD%i means T0",i);
175 OffersT[0] = TRUE;
176 }
177 cs_debug("%s",txt);
178 }
179
180 int numprottype = 0;
181 for (i = 0; i <= 2; i++)
182 if (OffersT[i])
183 numprottype ++;
184 cs_debug("%i protocol types detected. Historical bytes: %s",numprottype, cs_hexdump(1,atr->hb,atr->hbn));
185
186//If more than one protocol type and/or TA1 parameter values other than the default values and/or N equeal to 255 is/are indicated in the answer to reset, the card shall know unambiguously, after having sent the answer to reset, which protocol type or/and transmission parameter values (FI, D, N) will be used. Consequently a selection of the protocol type and/or the transmission parameters values shall be specified.
187 ATR_GetParameter (atr, ATR_PARAMETER_N, &(pps->parameters.n));
188 ATR_GetProtocolType(atr,1,&(pps->parameters.t)); //get protocol from TD1
189 BYTE TA2;
190 bool SpecificMode = (ATR_GetInterfaceByte (atr, 2, ATR_INTERFACE_BYTE_TA, &TA2) == ATR_OK); //if TA2 present, specific mode, else negotiable mode
191 if (SpecificMode) {
192 pps->parameters.t = TA2 & 0x0F;
193 if ((TA2 & 0x10) != 0x10) { //bit 5 set to 0 means F and D explicitly defined in interface characters
194 BYTE TA1;
195 if (ATR_GetInterfaceByte (atr, 1 , ATR_INTERFACE_BYTE_TA, &TA1) == ATR_OK) {
196 pps->parameters.FI = TA1 >> 4;
197 ATR_GetParameter (atr, ATR_PARAMETER_D, &(pps->parameters.d));
198 }
199 else {
200 pps->parameters.FI = ATR_DEFAULT_FI;
201 pps->parameters.d = ATR_DEFAULT_D;
202 }
203 }
204 else {
205 cs_log("Specific mode: speed 'implicitly defined', not sure how to proceed, assuming default values");
206 pps->parameters.FI = ATR_DEFAULT_FI;
207 pps->parameters.d = ATR_DEFAULT_D;
208 }
209 cs_debug("Specific mode: T%i, F=%.0f, D=%.6f, N=%.0f\n", pps->parameters.t, (double) atr_f_table[pps->parameters.FI], pps->parameters.d, pps->parameters.n);
210 }
211 else { //negotiable mode
212
213 bool NeedsPTS = ((pps->parameters.t != 14) && (numprottype > 1 || (atr->ib[0][ATR_INTERFACE_BYTE_TA].present == TRUE && atr->ib[0][ATR_INTERFACE_BYTE_TA].value != 0x11) || pps->parameters.n == 255)); //needs PTS according to ISO 7816 , SCI gets stuck on our PTS
214 if (NeedsPTS) {
215 // PTSS PTS0 PTS1 PTS2 PTS3 PCK
216 // PTSS PTS0 PTS1 PCK
217 BYTE req[] = { 0xFF, 0x10, 0x00, 0x00 }; //we currently do not support PTS2, standard guardtimes
218
219 int p;
220 for (p=1; p<=numprot; p++) {
221 ATR_GetProtocolType(atr,p,&(pps->parameters.t));
222 req[1]=0x10 | pps->parameters.t; //PTS0 always flags PTS1 to be sent always
223 if (ATR_GetInterfaceByte (atr, p, ATR_INTERFACE_BYTE_TA, &req[2]) != ATR_OK) //PTS1
224 req[2] = 0x11; //defaults FI and DI to 1
225 //req[3]=PPS_GetPCK(req,sizeof(req)-1); will be set by PPS_Exchange
226 unsigned int len = sizeof(req);
227 ret = PPS_Exchange (pps, req, &len);
228 if (ret == PPS_OK) {
229 pps->parameters.FI = req[2] >> 4;
230 BYTE DI = req[2] & 0x0F;
231 pps->parameters.d = (double) (atr_d_table[DI]);
232 PPS_success = TRUE;
233 protocol_selected = p;
234 cs_debug("PTS Succesfull, selected protocol %i: T%i, F=%.0f, D=%.6f, N=%.0f\n", protocol_selected, pps->parameters.t, (double) atr_f_table[pps->parameters.FI], pps->parameters.d, pps->parameters.n);
235 break;
236 }
237 else
238 cs_ddump(req,4,"PTS Failure for protocol %i, response:",p);
239 }
240 }
241
242 //FIXME Currently InitICC sets baudrate to 9600 for all T14 cards (=no switching);
243 //When for SCI, T14 protocol, TA1 is obeyed, this goes OK for mosts devices, but somehow on DM7025 Sky S02 card goes wrong when setting ETU (ok on DM800/DM8000)
244 if (!PPS_success) {//last PPS not succesfull
245 BYTE TA1;
246 if (ATR_GetInterfaceByte (atr, 1 , ATR_INTERFACE_BYTE_TA, &TA1) == ATR_OK) {
247 pps->parameters.FI = TA1 >> 4;
248 ATR_GetParameter (atr, ATR_PARAMETER_D, &(pps->parameters.d));
249 }
250 else { //do not obey TA1
251 pps->parameters.FI = ATR_DEFAULT_FI;
252 pps->parameters.d = ATR_DEFAULT_D;
253 }
254 ATR_GetProtocolType (atr, 1, &(pps->parameters.t));
255 protocol_selected = 1;
256
257 if (NeedsPTS) {
258 if ((pps->parameters.d == 32) || (pps->parameters.d == 12) || (pps->parameters.d == 20))
259 pps->parameters.d = 0; //behave conform "old" atr_d_table; viaccess cards that fail PTS need this
260 }
261 /////Here all non-ISO behaviour
262 /////End all non-ISO behaviour
263
264 cs_debug("No PTS %s, selected protocol 1: T%i, F=%.0f, D=%.6f, N=%.0f\n", NeedsPTS?"happened":"needed", pps->parameters.t, (double) atr_f_table[pps->parameters.FI], pps->parameters.d, pps->parameters.n);
265 }
266 }//end negotiable mode
267 }//end length<0
268
269 //make sure no zero values
270 double F = (double) atr_f_table[pps->parameters.FI];
271 if (!F) {
272 pps->parameters.FI = ATR_DEFAULT_FI;
273 cs_log("Warning: F=0 is invalid, forcing FI=%d", pps->parameters.FI);
274 }
275 if (!pps->parameters.d) {
276 pps->parameters.d = ATR_DEFAULT_D;
277 cs_log("Warning: D=0 is invalid, forcing D=%.0f",pps->parameters.d);
278 }
279
280 pps->icc->protocol_type = pps->parameters.t;
281
282#ifdef DEBUG_PROTOCOL
283 printf("PPS: T=%i, F=%.0f, D=%.6f, N=%.0f\n",
284 pps->parameters.t,
285 F,
286 pps->parameters.d,
287 pps->parameters.n);
288#endif
289
290 ret = PPS_InitICC(pps);
291
292 if (ret != PPS_OK)
293 return ret;
294
295 /* Initialize selected protocol with selected parameters */
296 if (pps->parameters.t == 1)
297 ret = PPS_InitProtocol (pps, 3); //FIXME in practice most T1 cards carry timing parameters in TA3, TB3 and TC3
298 else
299 ret = PPS_InitProtocol (pps, 2); //FIXME T0 cards carry timing parameters in TC2
300
301 return ret;
302}
303
304void * PPS_GetProtocol (PPS * pps)
305{
306 return pps->protocol;
307}
308
309PPS_ProtocolParameters *PPS_GetProtocolParameters (PPS * pps)
310{
311 /* User must Remember not to reference this struct after removing PPS */
312 return &(pps->parameters);
313}
314
315void PPS_Delete (PPS * pps)
316{
317 free (pps);
318}
319
320/*
321 * Not exported funtions definition
322 */
323
324static int PPS_Exchange (PPS * pps, BYTE * params, unsigned *length)
325{
326 BYTE confirm[PPS_MAX_LENGTH];
327 unsigned len_request, len_confirm;
328 int ret;
329#ifdef DEBUG_PROTOCOL
330 int i;
331#endif
332
333 len_request = PPS_GetLength (params);
334 params[len_request - 1] = PPS_GetPCK(params, len_request - 1);
335
336#ifdef DEBUG_PROTOCOL
337 printf ("PPS: Sending request: ");
338 for (i = 0; i < len_request; i++)
339 printf ("%X ", params[i]);
340 printf ("\n");
341#endif
342
343 cs_debug("PTS: Sending request: %s", cs_hexdump(1, params, len_request));
344
345 /* Send PPS request */
346#ifdef COOL
347 //unsigned char ptsAck[10];
348 //u_int8 ptsLen = len_request;
349 unsigned short int ptsLen = len_request;
350 int Status = cnxt_smc_start_pps(handle, params, confirm, &ptsLen, TRUE);
351 printf ("cnxt_smc_start_pps Status=%i\n", Status);
352 len_confirm = ptsLen;
353#ifdef DEBUG_PROTOCOL
354 printf("COOL: confirm: \n");
355 for (i = 0; i < ptsLen; i++)
356 printf ("%02X", confirm[i]);
357 printf ("\n");
358 fflush(stdout);
359 printf("COOL: req: \n");
360 for (i = 0; i < len_request; i++)
361 printf ("%02X", params[i]);
362 printf ("\n");
363 fflush(stdout);
364#endif
365 if (Status)
366 return PPS_HANDSAKE_ERROR;
367#else
368 if (ICC_Async_Transmit (pps->icc, len_request, params) != ICC_ASYNC_OK)
369 return PPS_ICC_ERROR;
370
371 /* Get PPS confirm */
372 if (ICC_Async_Receive (pps->icc, 2, confirm) != ICC_ASYNC_OK)
373 return PPS_ICC_ERROR;
374
375 len_confirm = PPS_GetLength (confirm);
376
377 if (ICC_Async_Receive (pps->icc, len_confirm - 2, confirm + 2) != ICC_ASYNC_OK)
378 return PPS_ICC_ERROR;
379
380#ifdef DEBUG_PROTOCOL
381 printf ("PPS: Receivig confirm: ");
382 for (i = 0; i < len_confirm; i++)
383 printf ("%X ", confirm[i]);
384 printf ("\n");
385#endif
386
387 cs_debug("PTS: Receiving confirm: %s", cs_hexdump(1, confirm, len_confirm));
388
389 if (!PPS_Match (params, len_request, confirm, len_confirm))
390 ret = PPS_HANDSAKE_ERROR;
391 else
392 ret = PPS_OK;
393#endif
394
395 /* Copy PPS handsake */
396 memcpy (params, confirm, len_confirm);
397 (*length) = len_confirm;
398
399 return ret;
400}
401
402static bool PPS_Match (BYTE * request, unsigned len_request, BYTE * confirm, unsigned len_confirm)
403{
404 /* See if the reply differs from request */
405 if ((len_request != len_confirm) || (memcmp (request, confirm, len_request)))
406 {
407 /* See if the card specifies other than default FI and D */
408 //if ((PPS_HAS_PPS1 (confirm)) && (confirm[2] != request[2]))
409 return FALSE;
410 }
411
412 return TRUE;
413}
414
415static unsigned PPS_GetLength (BYTE * block)
416{
417 unsigned length = 3;
418
419 if (PPS_HAS_PPS1 (block))
420 length++;
421
422 if (PPS_HAS_PPS2 (block))
423 length++;
424
425 if (PPS_HAS_PPS3 (block))
426 length++;
427
428 return length;
429}
430
431static int PPS_InitICC (PPS * pps)
432{
433#ifdef SCI_DEV
434#include <sys/ioctl.h>
435#include "sci_global.h"
436#include "sci_ioctl.h"
437 if(pps->icc->ifd->io->com==RTYP_SCI)
438 {
439 int n;
440 SCI_PARAMETERS params;
441 //memset(&params,0,sizeof(SCI_PARAMETERS));
442 if (ioctl(pps->icc->ifd->io->fd, IOCTL_GET_PARAMETERS, &params) < 0 )
443 return PPS_ICC_ERROR;
444
445 ATR *atr = ICC_Async_GetAtr (pps->icc);
446
447 params.T = pps->parameters.t;
448 params.fs = atr_fs_table[pps->parameters.FI] / 1000000;
449 double F = (double) atr_f_table[pps->parameters.FI];
450 //for Irdeto T14 cards, do not set ETU
451 if (!(atr->hbn >= 6 && !memcmp(atr->hb, "IRDETO", 6) && params.T == 14))
452 params.ETU = F / pps->parameters.d;
453 if (pps->parameters.n == 255) //only for T0 or also for T1?
454 params.EGT = 0;
455 else
456 params.EGT = pps->parameters.n;
457
458 double a;
459 ATR_GetParameter(atr, ATR_PARAMETER_P, &a);
460 params.P=(unsigned char)a;
461 ATR_GetParameter(atr, ATR_PARAMETER_I, &a);
462 params.I=(unsigned char)a;
463
464 cs_debug("Setting T=%d fs=%lu mhz ETU=%d WWT=%d CWT=%d BWT=%d EGT=%d clock=%d check=%d P=%d I=%d U=%d", (int)params.T, params.fs, (int)params.ETU, (int)params.WWT, (int)params.CWT, (int)params.BWT, (int)params.EGT, (int)params.clock_stop_polarity, (int)params.check, (int)params.P, (int)params.I, (int)params.U);
465
466 if (ioctl(pps->icc->ifd->io->fd, IOCTL_SET_PARAMETERS, &params)!=0)
467 return PPS_ICC_ERROR;
468
469 }
470 else
471#elif COOL
472 if(pps->icc->ifd->io->com==RTYP_SCI) {
473 int mhz = atr_fs_table[pps->parameters.FI] / 10000;
474 if (!Cool_SetBaudrate(mhz))
475 return PPS_ICC_ERROR;
476#ifdef DEBUG_PROTOCOL
477 printf("Coolstream: set clock to %i * 10kHz\n", mhz);
478#endif
479 return PPS_OK;
480 }
481 else
482#endif
483 {
484 unsigned long baudrate;
485 double F = (double) atr_f_table[pps->parameters.FI];
486 if (pps->parameters.t == 14)
487 baudrate = 9600;
488 else
489 baudrate = pps->parameters.d * ICC_Async_GetClockRate (pps->icc) / F;
490
491#ifdef DEBUG_PROTOCOL
492 printf ("PPS: Baudrate = %d\n", (int)baudrate);
493#endif
494
495
496 if (ICC_Async_SetBaudrate (pps->icc, baudrate) != ICC_ASYNC_OK)
497 return PPS_ICC_ERROR;
498
499 return PPS_OK;
500 }
501}
502
503static int PPS_InitProtocol (PPS * pps, int selected_protocol)
504{
505 int ret;
506
507 if (pps->parameters.t == ATR_PROTOCOL_TYPE_T0)
508 {
509 pps->protocol = Protocol_T0_New ();
510
511 if ((pps->protocol) != NULL)
512 {
513 ret = Protocol_T0_Init ((Protocol_T0 *) pps->protocol, (ICC_Async *) pps->icc, &(pps->parameters), selected_protocol);
514
515 if (ret != PROTOCOL_T0_OK)
516 {
517 Protocol_T0_Delete ((Protocol_T0 *) pps->protocol);
518 pps->protocol = NULL;
519 return PPS_PROTOCOL_ERROR;
520 }
521
522 return PPS_OK;
523 }
524 }
525 else if (pps->parameters.t == ATR_PROTOCOL_TYPE_T1)
526 {
527 pps->protocol = Protocol_T1_New ();
528
529 if (pps->protocol != NULL)
530 {
531 ret = Protocol_T1_Init ((Protocol_T1 *) pps->protocol, (ICC_Async *) pps->icc, selected_protocol);
532
533 if (ret != PROTOCOL_T1_OK)
534 {
535 Protocol_T1_Delete ((Protocol_T1 *) pps->protocol);
536 pps->protocol = NULL;
537 return PPS_PROTOCOL_ERROR;
538 }
539
540 return PPS_OK;
541 }
542 }
543 else if (pps->parameters.t == ATR_PROTOCOL_TYPE_T14)
544 {
545 pps->protocol = Protocol_T14_New ();
546
547 if ((pps->protocol) != NULL)
548 {
549 ret = Protocol_T14_Init ((Protocol_T14 *) pps->protocol, (ICC_Async *) pps->icc, &(pps->parameters), selected_protocol);
550
551 if (ret != PROTOCOL_T14_OK)
552 {
553 Protocol_T14_Delete ((Protocol_T14 *) pps->protocol);
554 pps->protocol = NULL;
555 return PPS_PROTOCOL_ERROR;
556 }
557
558 return PPS_OK;
559 }
560 }
561 else
562 {
563 pps->protocol = NULL;
564 }
565
566 return PPS_PROTOCOL_ERROR;
567}
568
569static BYTE PPS_GetPCK (BYTE * block, unsigned length)
570{
571 BYTE pck;
572 unsigned i;
573
574 pck = block[0];
575 for (i = 1; i < length; i++)
576 pck ^= block[i];
577
578 return pck;
579}
Note: See TracBrowser for help on using the repository browser.