source: trunk/csctapi/protocol_t1.c@ 1286

Last change on this file since 1286 was 1286, checked in by dingo35, 11 years ago

Move T1 timing aspects to pps.c and fix selected_protocol error

File size: 8.8 KB
Line 
1/*
2 protocol_t1.c
3 Handling of ISO 7816 T=1 protocol
4
5 This file is part of the Unix driver for Towitoko smartcard readers
6 Copyright (C) 2000 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 "defines.h"
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29#include "protocol_t1.h"
30#include "t1_block.h"
31
32/*
33 * Not exported functions declaration
34 */
35
36static int
37Protocol_T1_SendBlock (T1_Block * block);
38
39static int
40Protocol_T1_ReceiveBlock (T1_Block ** block);
41
42static int
43Protocol_T1_UpdateBWT (unsigned short bwt);
44
45/*
46 * Exproted funtions definition
47 */
48
49int
50Protocol_T1_Command (APDU_Cmd * cmd, APDU_Rsp ** rsp)
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 (APDU_Cmd_Ins(cmd) == T1_BLOCK_S_IFS_REQ)
58 {
59 BYTE inf = APDU_Cmd_P2(cmd);
60
61 /* Create an IFS request S-Block */
62 block = T1_Block_NewSBlock (T1_BLOCK_S_IFS_REQ, 1, &inf);
63
64#ifdef DEBUG_PROTOCOL
65 printf ("Protocol: Sending block S(IFS request, %d)\n", inf);
66#endif
67 /* Send IFSD request */
68 ret = Protocol_T1_SendBlock (block);
69
70 /* Delete block */
71 T1_Block_Delete (block);
72
73 /* Receive a block */
74 ret = Protocol_T1_ReceiveBlock (&block);
75
76 if (ret == PROTOCOL_T1_OK)
77 {
78 rsp_type = T1_Block_GetType (block);
79
80 /* Positive IFS Response S-Block received */
81 if (rsp_type == T1_BLOCK_S_IFS_RES)
82 {
83 /* Update IFSD value */
84 inf = (*T1_Block_GetInf (block));
85 ifsd = inf;
86#ifdef DEBUG_PROTOCOL
87 printf ("Protocol: Received block S(IFS response, %d)\n", inf);
88#endif
89 }
90 }
91
92 return ret;
93 }
94
95 /* Calculate the number of bytes to send */
96 counter = 0;
97 bytes = MIN (APDU_Cmd_RawLen (cmd), ifsc);
98
99 /* See if chaining is needed */
100 more = (APDU_Cmd_RawLen (cmd) > ifsc);
101
102 /* Increment ns */
103 ns = (ns + 1) %2;
104
105 /* Create an I-Block */
106 block = T1_Block_NewIBlock (bytes, APDU_Cmd_Raw (cmd), ns, more);
107
108#ifdef DEBUG_PROTOCOL
109 printf ("Sending block I(%d,%d)\n", ns, more);
110#endif
111
112 /* Send a block */
113 ret = Protocol_T1_SendBlock (block);
114
115 /* Delete I-block */
116 T1_Block_Delete (block);
117
118 while ((ret == PROTOCOL_T1_OK) && more)
119 {
120 /* Receive a block */
121 ret = Protocol_T1_ReceiveBlock (&block);
122
123 if (ret == PROTOCOL_T1_OK)
124 {
125 rsp_type = T1_Block_GetType (block);
126
127 /* Positive ACK R-Block received */
128 if (rsp_type == T1_BLOCK_R_OK)
129 {
130#ifdef DEBUG_PROTOCOL
131 printf ("Protocol: Received block R(%d)\n", T1_Block_GetNR (block));
132#endif
133 /* Delete block */
134 T1_Block_Delete (block);
135
136 /* Increment ns */
137 ns = (ns + 1) % 2;
138
139 /* Calculate the number of bytes to send */
140 counter += bytes;
141 bytes = MIN (APDU_Cmd_RawLen (cmd) - counter, ifsc);
142
143 /* See if chaining is needed */
144 more = (APDU_Cmd_RawLen (cmd) - counter > ifsc);
145
146 /* Create an I-Block */
147 block =
148 T1_Block_NewIBlock (bytes, APDU_Cmd_Raw (cmd) + counter,
149 ns, more);
150#ifdef DEBUG_PROTOCOL
151 printf ("Protocol: Sending block I(%d,%d)\n", ns, more);
152#endif
153 /* Send a block */
154 ret = Protocol_T1_SendBlock (block);
155
156 /* Delete I-block */
157 T1_Block_Delete (block);
158 }
159
160 else
161 {
162 /* Delete block */
163 T1_Block_Delete (block);
164
165 ret = PROTOCOL_T1_NOT_IMPLEMENTED;
166 }
167 }
168
169 else
170 {
171 ret = PROTOCOL_T1_NOT_IMPLEMENTED;
172 }
173 }
174
175 /* Reset counter */
176 buffer = NULL;
177 counter = 0;
178 more = TRUE;
179 wtx = 0;
180
181 while ((ret == PROTOCOL_T1_OK) && more)
182 {
183 if (wtx > 1)
184 Protocol_T1_UpdateBWT (wtx * (bwt));
185
186 /* Receive a block */
187 ret = Protocol_T1_ReceiveBlock (&block);
188
189 if (wtx > 1)
190 {
191 Protocol_T1_UpdateBWT (bwt);
192 wtx = 0;
193 }
194
195 if (ret == PROTOCOL_T1_OK)
196 {
197 rsp_type = T1_Block_GetType (block);
198
199 if (rsp_type == T1_BLOCK_I)
200 {
201#ifdef DEBUG_PROTOCOL
202 printf ("Protocol: Received block I(%d,%d)\n",
203 T1_Block_GetNS(block), T1_Block_GetMore (block));
204#endif
205 /* Calculate nr */
206 nr = (T1_Block_GetNS (block) + 1) % 2;
207
208 /* Save inf field */
209 bytes = T1_Block_GetLen (block);
210 buffer = (BYTE *) realloc(buffer, counter + bytes);
211 memcpy (buffer + counter, T1_Block_GetInf (block), bytes);
212 counter += bytes;
213
214 /* See if chaining is requested */
215 more = T1_Block_GetMore (block);
216
217 /* Delete block */
218 T1_Block_Delete (block);
219
220 if (more)
221 {
222 /* Create an R-Block */
223 block = T1_Block_NewRBlock (T1_BLOCK_R_OK, nr);
224#ifdef DEBUG_PROTOCOL
225 printf ("Protocol: Sending block R(%d)\n", nr);
226#endif
227 /* Send R-Block */
228 ret = Protocol_T1_SendBlock (block);
229
230 /* Delete I-block */
231 T1_Block_Delete (block);
232 }
233 }
234
235 /* WTX Request S-Block received */
236 else if (rsp_type == T1_BLOCK_S_WTX_REQ)
237 {
238 /* Get wtx multiplier */
239 wtx = (*T1_Block_GetInf (block));
240#ifdef DEBUG_PROTOCOL
241 printf ("Protocol: Received block S(WTX request, %d)\n", wtx);
242#endif
243 /* Delete block */
244 T1_Block_Delete (block);
245
246 /* Create an WTX response S-Block */
247 block = T1_Block_NewSBlock (T1_BLOCK_S_WTX_RES, 1, &wtx);
248#ifdef DEBUG_PROTOCOL
249 printf ("Protocol: Sending block S(WTX response, %d)\n", wtx);
250#endif
251 /* Send WTX response */
252 ret = Protocol_T1_SendBlock (block);
253
254 /* Delete block */
255 T1_Block_Delete (block);
256 }
257
258 else
259 {
260 ret = PROTOCOL_T1_NOT_IMPLEMENTED;
261 }
262 }
263 }
264
265 if (ret == PROTOCOL_T1_OK)
266 (*rsp) = APDU_Rsp_New (buffer, counter);
267
268 if (buffer != NULL)
269 free (buffer);
270
271 return ret;
272}
273
274/*
275 * Not exported functions definition
276 */
277
278static int
279Protocol_T1_SendBlock (T1_Block * block)
280{
281 BYTE *buffer;
282 int length, ret;
283
284 {
285 /* Send T=1 block */
286 buffer = T1_Block_Raw (block);
287 length = T1_Block_RawLen (block);
288
289 if (ICC_Async_Transmit (length, buffer) != ICC_ASYNC_OK)
290 {
291 ret = PROTOCOL_T1_ICC_ERROR;
292 }
293
294 else
295 ret = PROTOCOL_T1_OK;
296 }
297
298 return ret;
299}
300
301static int
302Protocol_T1_ReceiveBlock (T1_Block ** block)
303{
304 BYTE buffer[T1_BLOCK_MAX_SIZE];
305 int ret;
306
307 /* Receive four mandatory bytes */
308 if (ICC_Async_Receive (4, buffer) != ICC_ASYNC_OK)
309 {
310 ret = PROTOCOL_T1_ICC_ERROR;
311 (*block) = NULL;
312 }
313
314 else
315 {
316 if (buffer[2] != 0x00)
317 {
318 /* Set timings to read the remaining block */
319 Protocol_T1_UpdateBWT (cwt);
320
321 /* Receive remaining bytes */
322 if (ICC_Async_Receive (buffer[2], buffer + 4) !=
323 ICC_ASYNC_OK)
324 {
325 (*block) = NULL;
326 ret = PROTOCOL_T1_ICC_ERROR;
327 }
328
329 else
330 {
331 (*block) = T1_Block_New (buffer, buffer[2] + 4);
332 ret = PROTOCOL_T1_OK;
333 }
334
335 /* Restore timings */
336 Protocol_T1_UpdateBWT (bwt);
337 }
338 else
339 {
340 ret = PROTOCOL_T1_OK;
341 (*block) = T1_Block_New (buffer, 4);
342 }
343 }
344
345 return ret;
346}
347
348static int
349Protocol_T1_UpdateBWT (unsigned short bwt)
350{
351 icc_timings.block_timeout = bwt;
352 ICC_Async_SetTimings ();
353
354 return PROTOCOL_T1_OK;
355}
Note: See TracBrowser for help on using the repository browser.