Initial commit
[platform/upstream/ccid.git] / src / towitoko / pps.c
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 library is free software; you can redistribute it and/or
9     modify it under the terms of the GNU Lesser General Public
10     License as published by the Free Software Foundation; either
11     version 2 of the License, or (at your option) any later version.
12
13     This library is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16     Lesser General Public License for more details.
17
18         You should have received a copy of the GNU Lesser General Public License
19         along with this library; if not, write to the Free Software Foundation,
20         Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22
23 #include "pps.h"
24 #include "atr.h"
25 #ifdef HAVE_STDLIB_H
26 #include <stdlib.h>
27 #endif
28 #ifdef HAVE_STRING_H
29 #include <string.h>
30 #endif
31 #include <ifdhandler.h>
32
33 #include "commands.h"
34 #include "defs.h"
35 #include "debug.h"
36
37 /*
38  * Not exported funtions declaration
39  */
40
41 static int PPS_Match (BYTE * request, unsigned len_request, BYTE * reply, unsigned len_reply);
42
43 static unsigned PPS_GetLength (BYTE * block);
44
45 static BYTE PPS_GetPCK (BYTE * block, unsigned length);
46
47 int
48 PPS_Exchange (int lun, BYTE * params, unsigned *length, unsigned char *pps1)
49 {
50   BYTE confirm[PPS_MAX_LENGTH];
51   unsigned len_request, len_confirm;
52   int ret;
53
54   len_request = PPS_GetLength (params);
55   params[len_request - 1] = PPS_GetPCK(params, len_request - 1);
56
57   DEBUG_XXD ("PPS: Sending request: ", params, len_request);
58
59   /* Send PPS request */
60   if (CCID_Transmit (lun, len_request, params, isCharLevel(lun) ? 4 : 0, 0)
61         != IFD_SUCCESS)
62     return PPS_ICC_ERROR;
63
64   /* Get PPS confirm */
65   len_confirm = sizeof(confirm);
66   if (CCID_Receive (lun, &len_confirm, confirm, NULL) != IFD_SUCCESS)
67     return PPS_ICC_ERROR;
68
69   DEBUG_XXD ("PPS: Receiving confirm: ", confirm, len_confirm);
70
71   if (!PPS_Match (params, len_request, confirm, len_confirm))
72     ret = PPS_HANDSAKE_ERROR;
73   else
74     ret = PPS_OK;
75
76   *pps1 = 0x11; /* default TA1 */
77
78   /* if PPS1 is echoed */
79   if (PPS_HAS_PPS1 (params) && PPS_HAS_PPS1 (confirm))
80       *pps1 = confirm[2];
81
82   /* Copy PPS handsake */
83   memcpy (params, confirm, len_confirm);
84   (*length) = len_confirm;
85
86   return ret;
87 }
88
89 static int
90 PPS_Match (BYTE * request, unsigned len_request, BYTE * confirm, unsigned len_confirm)
91 {
92   /* See if the reply differs from request */
93   if ((len_request == len_confirm) &&   /* same length */
94       memcmp (request, confirm, len_request))   /* different contents */
95         return FALSE;
96
97   if (len_request < len_confirm)        /* confirm longer than request */
98     return FALSE;
99
100   /* See if the card specifies other than default FI and D */
101   if ((PPS_HAS_PPS1 (confirm)) && (confirm[2] != request[2]))
102     return FALSE;
103
104   return TRUE;
105 }
106
107 static unsigned
108 PPS_GetLength (BYTE * block)
109 {
110   unsigned length = 3;
111
112   if (PPS_HAS_PPS1 (block))
113     length++;
114
115   if (PPS_HAS_PPS2 (block))
116     length++;
117
118   if (PPS_HAS_PPS3 (block))
119     length++;
120
121   return length;
122 }
123
124 static BYTE
125 PPS_GetPCK (BYTE * block, unsigned length)
126 {
127   BYTE pck;
128   unsigned i;
129
130   pck = block[0];
131   for (i = 1; i < length; i++)
132     pck ^= block[i];
133
134   return pck;
135 }
136