source: trunk/csctapi/apdu.c@ 1

Last change on this file since 1 was 1, checked in by root, 14 years ago

initial import

File size: 7.2 KB
Line 
1/*
2 apdu.c
3 ISO 7816-4 Application Layer PDU's handling
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 "defines.h"
26#include "apdu.h"
27#include <stdlib.h>
28#include <string.h>
29
30/*
31 * Not exported constants definiton
32 */
33
34#define APDU_MIN_CMD_SIZE 4 /* Min command size */
35#define APDU_MIN_RSP_SIZE 2 /* Min response size */
36#define APDU_CMD_HEADER_SIZE 4 /* Size of the header */
37
38/*
39 * Exported functions definition
40 */
41
42APDU_Cmd * APDU_Cmd_New (BYTE * data, unsigned long length)
43{
44 APDU_Cmd *apdu;
45
46 if ((length > APDU_MAX_CMD_SIZE))
47 return NULL;
48
49 apdu = (APDU_Cmd *) malloc (sizeof (APDU_Cmd));
50
51 if (apdu != NULL)
52 {
53 apdu->length = MAX (APDU_MIN_CMD_SIZE, length);
54 apdu->command = (BYTE *) calloc (apdu->length, sizeof (BYTE));
55
56 if (apdu->command != NULL)
57 {
58 memcpy (apdu->command, data, length);
59 if (length < apdu->length)
60 memset (apdu->command + length, 0, apdu->length - length);
61 }
62 else
63 {
64 free (apdu);
65 apdu = NULL;
66 }
67 }
68
69 return apdu;
70}
71
72void APDU_Cmd_Delete (APDU_Cmd * apdu)
73{
74 free (apdu->command);
75 free (apdu);
76}
77
78int APDU_Cmd_Case (APDU_Cmd * apdu)
79{
80 BYTE B1;
81 unsigned short B2B3;
82 unsigned long L;
83 int res;
84
85 /* Calculate length of body */
86 L = MAX(apdu->length - 4, 0);
87
88 /* Case 1 */
89 if (L == 0)
90 {
91 res = APDU_CASE_1;
92 }
93 else
94 {
95 /* Get first byte of body */
96 B1 = apdu->command[4];
97
98 if ((B1 != 0) && (L == B1 + 1))
99 res = APDU_CASE_2S;
100 else if (L == 1)
101 res = APDU_CASE_3S;
102 else if ((B1 != 0) && (L == B1 + 2))
103 res = APDU_CASE_4S;
104 else if ((B1 == 0) && (L>2))
105 {
106 /* Get second and third byte of body */
107 B2B3 = (((unsigned short)(apdu->command[5]) << 8) | apdu->command[6]);
108
109 if ((B2B3 != 0) && (L == B2B3 + 3))
110 res = APDU_CASE_2E;
111 else if (L == 3)
112 res = APDU_CASE_3E;
113 else if ((B2B3 != 0) && (L == B2B3 + 5))
114 res = APDU_CASE_4E;
115 else
116 res = APDU_MALFORMED;
117 }
118 else
119 {
120 res = APDU_MALFORMED;
121 }
122 }
123
124 return res;
125}
126
127BYTE APDU_Cmd_Cla (APDU_Cmd * apdu)
128{
129 return apdu->command[0];
130}
131
132BYTE APDU_Cmd_Ins (APDU_Cmd * apdu)
133{
134 return apdu->command[1];
135}
136
137BYTE APDU_Cmd_P1 (APDU_Cmd * apdu)
138{
139 return apdu->command[2];
140}
141
142BYTE APDU_Cmd_P2 (APDU_Cmd * apdu)
143{
144 return apdu->command[3];
145}
146
147unsigned long APDU_Cmd_Lc (APDU_Cmd * apdu)
148{
149 int c;
150 unsigned long res;
151
152 c = APDU_Cmd_Case (apdu);
153
154 if ((c == APDU_CASE_1) || (c == APDU_CASE_3S) || (c == APDU_CASE_3E))
155 res = 0;
156 else if ((c == APDU_CASE_2S) || (c == APDU_CASE_4S))
157 res = apdu->command[4];
158 else if ((c == APDU_CASE_2E) || (c == APDU_CASE_4E))
159 res = (((unsigned long)(apdu->command[5]) << 8) | apdu->command[6]);
160 else
161 res = 0;
162
163 return res;
164}
165
166unsigned long APDU_Cmd_Le (APDU_Cmd * apdu)
167{
168 int c;
169 unsigned long res;
170
171 c = APDU_Cmd_Case (apdu);
172
173 if ((c == APDU_CASE_1) || (c == APDU_CASE_2S) || (c == APDU_CASE_2E))
174 res = 0;
175 else if (c == APDU_CASE_3S)
176// res = ((apdu->command[4] == 0) ? 256: apdu->command[4]);
177 res = apdu->command[4];
178 else if (c == APDU_CASE_4S)
179 res = ((apdu->command[apdu->length - 1] == 0) ? 256: apdu->command[apdu->length - 1]);
180 else if (c == APDU_CASE_3E)
181 res = ((((unsigned long)(apdu->command[5]) << 8) | apdu->command[6]) == 0 ? 65536 : (((unsigned long)(apdu->command[5]) << 8) | apdu->command[6]));
182 else if (c == APDU_CASE_4E)
183 res = ((((unsigned long)(apdu->command[apdu->length - 2]) << 8) | apdu->command[apdu->length - 1]) == 0 ? 65536 : (((unsigned long)(apdu->command[apdu->length - 2]) << 8) | apdu->command[apdu->length - 1]));
184 else
185 res = 0;
186
187 return res;
188}
189
190bool APDU_Cmd_Le_Available (APDU_Cmd * apdu)
191{
192 int c;
193 bool res;
194
195 c = APDU_Cmd_Case (apdu);
196
197 if (c == APDU_CASE_3S)
198 res = (apdu->command[4] == 0);
199 else if (c == APDU_CASE_4S)
200 res = (apdu->command[apdu->length - 1] == 0);
201 else if (c == APDU_CASE_3E)
202 res = ((((unsigned long)(apdu->command[5]) << 8) | apdu->command[6]) == 0);
203 else if (c == APDU_CASE_4E)
204 res = ((((unsigned long)(apdu->command[apdu->length - 2]) << 8) | apdu->command[apdu->length - 1]) == 0);
205 else
206 res = FALSE;
207
208 return res;
209}
210
211BYTE * APDU_Cmd_Header (APDU_Cmd * apdu)
212{
213 return apdu->command;
214}
215
216
217BYTE * APDU_Cmd_Data (APDU_Cmd * apdu)
218{
219 int c;
220 BYTE * res;
221
222 c = APDU_Cmd_Case (apdu);
223
224 if ((c == APDU_CASE_1) || (c == APDU_CASE_3S) || (c == APDU_CASE_3E))
225 res = NULL;
226 else if ((c == APDU_CASE_2S) || (c == APDU_CASE_4S))
227 res = apdu->command + 5;
228 else if ((c == APDU_CASE_2E) || (c == APDU_CASE_4E))
229 res = apdu->command + 7;
230 else
231 res = NULL;
232
233 return res;
234}
235
236BYTE * APDU_Cmd_Raw (APDU_Cmd * apdu)
237{
238 return apdu->command;
239}
240
241unsigned long APDU_Cmd_RawLen (APDU_Cmd * apdu)
242{
243 return apdu->length;
244}
245
246APDU_Rsp * APDU_Rsp_New (BYTE * data, unsigned long length)
247{
248 APDU_Rsp *apdu;
249
250 if (length < APDU_MIN_RSP_SIZE)
251 return NULL;
252
253 apdu = (APDU_Rsp *) malloc (sizeof (APDU_Rsp));
254
255 if (apdu != NULL)
256 {
257 apdu->length = length;
258 apdu->response = (BYTE *) calloc (length, sizeof (BYTE));
259
260 if (apdu->response != NULL)
261 {
262 memcpy (apdu->response, data, length);
263 }
264 else
265 {
266 free (apdu);
267 apdu = NULL;
268 }
269 }
270
271 return apdu;
272}
273
274void APDU_Rsp_Delete (APDU_Rsp * apdu)
275{
276 free (apdu->response);
277 free (apdu);
278}
279
280BYTE APDU_Rsp_SW1 (APDU_Rsp * apdu)
281{
282 return (apdu->response[(apdu->length) - 2]);
283}
284
285BYTE APDU_Rsp_SW2 (APDU_Rsp * apdu)
286{
287 return (apdu->response[(apdu->length) - 1]);
288}
289
290unsigned long
291APDU_Rsp_DataLen (APDU_Rsp * apdu)
292{
293 return (apdu->length - 2);
294}
295
296BYTE * APDU_Rsp_Data (APDU_Rsp * apdu)
297{
298 return apdu->response;
299}
300
301BYTE * APDU_Rsp_Raw (APDU_Rsp * apdu)
302{
303 return apdu->response;
304}
305
306unsigned long APDU_Rsp_RawLen (APDU_Rsp * apdu)
307{
308 return apdu->length;
309}
310
311void APDU_Rsp_TruncateData (APDU_Rsp * apdu, unsigned long length)
312{
313 if ((length > 0) && ((signed long)length < (signed long)(apdu->length - 2)))
314 {
315 apdu->response[length] = APDU_Rsp_SW1 (apdu);
316 apdu->response[length + 1] = APDU_Rsp_SW2 (apdu);
317 apdu->length = length +2;
318 }
319}
320
321int APDU_Rsp_AppendData (APDU_Rsp * apdu1, APDU_Rsp * apdu2)
322{
323 BYTE * response;
324 unsigned long length;
325 int ret;
326
327 length = APDU_Rsp_DataLen(apdu1) + APDU_Rsp_RawLen(apdu2);
328
329 if ((length > 2) && (length <= APDU_MAX_RSP_SIZE))
330 {
331 response = (BYTE *) realloc (apdu1->response, length);
332
333 if (response != NULL)
334 {
335 memcpy (response + APDU_Rsp_DataLen (apdu1),
336 APDU_Rsp_Raw (apdu2), APDU_Rsp_RawLen(apdu2));
337
338 apdu1->response = response;
339 apdu1->length = length;
340 ret = APDU_OK;
341 }
342 else
343 {
344 ret = APDU_MALFORMED;
345 }
346 }
347 else
348 {
349 ret = APDU_MALFORMED;
350 }
351
352 return ret;
353}
Note: See TracBrowser for help on using the repository browser.