source: trunk/csctapi/protocol_t1.c@ 3181

Last change on this file since 3181 was 3181, checked in by dingo35, 10 years ago

Adding threadsafety FIXMEs, feel free to join checking..

File size: 8.5 KB
Line 
1//FIXME Not checked on threadsafety yet; after checking please remove this line
2/*
3 protocol_t1.c
4 Handling of ISO 7816 T=1 protocol
5
6 This file is part of the Unix driver for Towitoko smartcard readers
7 Copyright (C) 2000 Carlos Prados <cprados@yahoo.com>
8
9 This version is modified by doz21 to work in a special manner ;)
10
11 This library is free software; you can redistribute it and/or
12 modify it under the terms of the GNU Lesser General Public
13 License as published by the Free Software Foundation; either
14 version 2 of the License, or (at your option) any later version.
15
16 This library is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 Lesser General Public License for more details.
20
21 You should have received a copy of the GNU Lesser General Public
22 License along with this library; if not, write to the Free Software
23 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24*/
25
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29#include "../globals.h"
30#include "defines.h"
31#include "protocol_t1.h"
32#include "t1_block.h"
33#include "icc_async.h"
34
35/* Timings in ATR are not used in T=1 cards */
36/* #undef PROTOCOL_T1_USE_DEFAULT_TIMINGS */
37
38/*
39 * Not exported functions declaration
40 */
41
42static int Protocol_T1_SendBlock (struct s_reader *reader, T1_Block * block);
43
44static int Protocol_T1_ReceiveBlock (struct s_reader *reader, T1_Block ** block);
45
46/*
47 * Exproted funtions definition
48 */
49
50int Protocol_T1_Command (struct s_reader *reader, unsigned char * command, unsigned short command_len, unsigned char * rsp, unsigned short * lr)
51{
52 T1_Block *block;
53 BYTE *buffer, rsp_type, bytes, nr, wtx;
54 unsigned short counter;
55 int ret;
56 bool more;
57 if (command[1] == T1_BLOCK_S_IFS_REQ)
58 {
59 BYTE inf = command[3];
60
61 /* Create an IFS request S-Block */
62 block = T1_Block_NewSBlock (T1_BLOCK_S_IFS_REQ, 1, &inf);
63 cs_debug_mask (D_IFD,"Protocol: Sending block S(IFS request, %d)\n", inf);
64
65 /* Send IFSD request */
66 ret = Protocol_T1_SendBlock (reader, block);
67
68 /* Receive a block */
69 ret = Protocol_T1_ReceiveBlock (reader, &block);
70
71 if (ret == OK)
72 {
73 rsp_type = T1_Block_GetType (block);
74
75 /* Positive IFS Response S-Block received */
76 if (rsp_type == T1_BLOCK_S_IFS_RES)
77 {
78 /* Update IFSD value */
79 inf = (*T1_Block_GetInf (block));
80 cs_debug_mask (D_IFD,"Protocol: Received block S(IFS response, %d)\n", inf);
81 }
82 }
83
84 return ret;
85 }
86
87 if (command[1] == T1_BLOCK_S_RESYNCH_REQ)
88 {
89 /* Create an Resynch request S-Block */
90 block = T1_Block_NewSBlock (T1_BLOCK_S_RESYNCH_REQ, 0, NULL);
91 cs_debug_mask (D_IFD,"Protocol: Sending block S(RESYNCH request)\n");
92
93 /* Send request */
94 ret = Protocol_T1_SendBlock (reader, block);
95
96 /* Receive a block */
97 ret = Protocol_T1_ReceiveBlock (reader, &block);
98
99 if (ret == OK)
100 {
101 rsp_type = T1_Block_GetType (block);
102
103 /* Positive IFS Response S-Block received */
104 if (rsp_type == T1_BLOCK_S_RESYNCH_RES) {
105 cs_debug_mask (D_IFD,"Protocol: Received block S(RESYNCH response)\n");
106 ns = 0;
107 }
108 }
109
110 return ret;
111 }
112
113 /* Calculate the number of bytes to send */
114 counter = 0;
115 bytes = MIN (command_len, ifsc);
116
117 /* See if chaining is needed */
118 more = (command_len > ifsc);
119
120 /* Increment ns */
121 ns = (ns + 1) %2;
122
123 /* Create an I-Block */
124 block = T1_Block_NewIBlock (bytes, command, ns, more);
125 cs_debug_mask (D_IFD,"Sending block I(%d,%d)\n", ns, more);
126
127 /* Send a block */
128 call (Protocol_T1_SendBlock (reader, block));
129
130 while (more) {
131 /* Receive a block */
132 call (Protocol_T1_ReceiveBlock (reader, &block));
133 rsp_type = T1_Block_GetType (block);
134
135 /* Positive ACK R-Block received */
136 if (rsp_type == T1_BLOCK_R_OK) {
137 cs_debug_mask (D_IFD,"Protocol: Received block R(%d)\n", T1_Block_GetNR (block));
138 /* Delete block */
139 T1_Block_Delete (block);
140
141 /* Increment ns */
142 ns = (ns + 1) % 2;
143
144 /* Calculate the number of bytes to send */
145 counter += bytes;
146 bytes = MIN (command_len - counter, ifsc);
147
148 /* See if chaining is needed */
149 more = (command_len - counter > ifsc);
150
151 /* Create an I-Block */
152 block = T1_Block_NewIBlock (bytes, command + counter, ns, more);
153 cs_debug_mask (D_IFD,"Protocol: Sending block I(%d,%d)\n", ns, more);
154
155 /* Send a block */
156 call (Protocol_T1_SendBlock (reader, block));
157 }
158 else {
159 /* Delete block */
160 T1_Block_Delete (block);
161 cs_debug_mask(D_TRACE, "ERROR T1 Command %02X not implemented in SendBlock", rsp_type);
162 return ERROR;
163 }
164 }
165
166 /* Reset counter */
167 ret = OK;
168 buffer = NULL;
169 counter = 0;
170 more = TRUE;
171 wtx = 0;
172
173 while ((ret == OK) && more)
174 {
175 if (wtx > 1)
176 ICC_Async_SetTimings (reader, wtx * reader->BWT);
177
178 /* Receive a block */
179 ret = Protocol_T1_ReceiveBlock (reader, &block);
180
181 if (wtx > 1)
182 {
183 ICC_Async_SetTimings (reader, reader->BWT);
184 wtx = 0;
185 }
186
187 if (ret == OK)
188 {
189 rsp_type = T1_Block_GetType (block);
190
191 if (rsp_type == T1_BLOCK_I)
192 {
193 cs_debug_mask (D_IFD,"Protocol: Received block I(%d,%d)\n",
194 T1_Block_GetNS(block), T1_Block_GetMore (block));
195 /* Calculate nr */
196 nr = (T1_Block_GetNS (block) + 1) % 2;
197
198 /* Save inf field */
199 bytes = T1_Block_GetLen (block);
200 buffer = (BYTE *) realloc(buffer, counter + bytes);
201 memcpy (buffer + counter, T1_Block_GetInf (block), bytes);
202 counter += bytes;
203
204 /* See if chaining is requested */
205 more = T1_Block_GetMore (block);
206
207 /* Delete block */
208 T1_Block_Delete (block);
209
210 if (more)
211 {
212 /* Create an R-Block */
213 block = T1_Block_NewRBlock (T1_BLOCK_R_OK, nr);
214 cs_debug_mask (D_IFD,"Protocol: Sending block R(%d)\n", nr);
215
216 /* Send R-Block */
217 ret = Protocol_T1_SendBlock (reader, block);
218 }
219 }
220
221 /* WTX Request S-Block received */
222 else if (rsp_type == T1_BLOCK_S_WTX_REQ)
223 {
224 /* Get wtx multiplier */
225 wtx = (*T1_Block_GetInf (block));
226 cs_debug_mask (D_IFD,"Protocol: Received block S(WTX request, %d)\n", wtx);
227
228 /* Delete block */
229 T1_Block_Delete (block);
230
231 /* Create an WTX response S-Block */
232 block = T1_Block_NewSBlock (T1_BLOCK_S_WTX_RES, 1, &wtx);
233 cs_debug_mask (D_IFD,"Protocol: Sending block S(WTX response, %d)\n", wtx);
234
235 /* Send WTX response */
236 ret = Protocol_T1_SendBlock (reader, block);
237 }
238
239 else
240 {
241 cs_debug_mask(D_TRACE, "ERROR T1 Command %02X not implemented in Receive Block", rsp_type);
242 ret = ERROR;//not implemented
243 }
244 }
245 }
246
247 if (ret == OK) {
248 memcpy(rsp, buffer, counter);
249 *lr = counter;
250 }
251
252 if (buffer != NULL)
253 free (buffer);
254
255 return ret;
256}
257
258/*
259 * Not exported functions definition
260 */
261
262static int Protocol_T1_SendBlock (struct s_reader *reader, T1_Block * block)
263{
264 int ret;
265 ret = ICC_Async_Transmit (reader, block->length, block->data);
266 T1_Block_Delete(block);
267 return ret;
268}
269
270static int Protocol_T1_ReceiveBlock (struct s_reader *reader, T1_Block ** block)
271{
272 BYTE buffer[T1_BLOCK_MAX_SIZE];
273 int ret;
274
275 /* Receive four mandatory bytes */
276 if (ICC_Async_Receive (reader, 4, buffer))
277 ret = ERROR;
278 else
279 if (buffer[2] != 0x00) {
280 /* Set timings to read the remaining block */
281 ICC_Async_SetTimings (reader, reader->CWT);
282
283 /* Receive remaining bytes */
284 if (ICC_Async_Receive (reader, buffer[2], buffer + 4))
285 ret = ERROR;
286 else {
287 (*block) = T1_Block_New (buffer, buffer[2] + 4);
288 ret = OK;
289 }
290 /* Restore timings */
291 ICC_Async_SetTimings (reader, reader->BWT);
292 }
293 else {
294 ret = OK;
295 (*block) = T1_Block_New (buffer, 4);
296 }
297
298 if (ret == ERROR)
299 (*block) = NULL;
300 return ret;
301}
Note: See TracBrowser for help on using the repository browser.