/src/opensc/src/libopensc/apdu.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * apdu.c: basic APDU handling functions |
3 | | * |
4 | | * Copyright (C) 2005 Nils Larsch <nils@larsch.net> |
5 | | * |
6 | | * This library is free software; you can redistribute it and/or |
7 | | * modify it under the terms of the GNU Lesser General Public |
8 | | * License as published by the Free Software Foundation; either |
9 | | * version 2.1 of the License, or (at your option) any later version. |
10 | | * |
11 | | * This library is distributed in the hope that it will be useful, |
12 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
14 | | * Lesser General Public License for more details. |
15 | | * |
16 | | * You should have received a copy of the GNU Lesser General Public |
17 | | * License along with this library; if not, write to the Free Software |
18 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
19 | | */ |
20 | | |
21 | | #ifdef HAVE_CONFIG_H |
22 | | #include "config.h" |
23 | | #endif |
24 | | |
25 | | #include <stdio.h> |
26 | | #include <stdlib.h> |
27 | | #include <assert.h> |
28 | | #include <string.h> |
29 | | |
30 | | #include "internal.h" |
31 | | #include "asn1.h" |
32 | | |
33 | | /*********************************************************************/ |
34 | | /* low level APDU handling functions */ |
35 | | /*********************************************************************/ |
36 | | |
37 | | /** Calculates the length of the encoded APDU in octets. |
38 | | * @param apdu the APDU |
39 | | * @param proto the desired protocol |
40 | | * @return length of the encoded APDU |
41 | | */ |
42 | | size_t sc_apdu_get_length(const sc_apdu_t *apdu, unsigned int proto) |
43 | 0 | { |
44 | 0 | size_t ret = 4; |
45 | |
|
46 | 0 | switch (apdu->cse) { |
47 | 0 | case SC_APDU_CASE_1: |
48 | 0 | if (proto == SC_PROTO_T0) |
49 | 0 | ret++; |
50 | 0 | break; |
51 | 0 | case SC_APDU_CASE_2_SHORT: |
52 | 0 | ret++; |
53 | 0 | break; |
54 | 0 | case SC_APDU_CASE_2_EXT: |
55 | 0 | ret += (proto == SC_PROTO_T0 ? 1 : 3); |
56 | 0 | break; |
57 | 0 | case SC_APDU_CASE_3_SHORT: |
58 | 0 | ret += 1 + apdu->lc; |
59 | 0 | break; |
60 | 0 | case SC_APDU_CASE_3_EXT: |
61 | 0 | ret += apdu->lc + (proto == SC_PROTO_T0 ? 1 : 3); |
62 | 0 | break; |
63 | 0 | case SC_APDU_CASE_4_SHORT: |
64 | 0 | ret += apdu->lc + (proto != SC_PROTO_T0 ? 2 : 1); |
65 | 0 | break; |
66 | 0 | case SC_APDU_CASE_4_EXT: |
67 | 0 | ret += apdu->lc + (proto == SC_PROTO_T0 ? 1 : 5); |
68 | 0 | break; |
69 | 0 | default: |
70 | 0 | return 0; |
71 | 0 | } |
72 | 0 | return ret; |
73 | 0 | } |
74 | | |
75 | | /** Encodes a APDU as an octet string |
76 | | * @param ctx sc_context_t object (used for logging) |
77 | | * @param apdu APDU to be encoded as an octet string |
78 | | * @param proto protocol version to be used |
79 | | * @param out output buffer of size outlen. |
80 | | * @param outlen size of the output buffer |
81 | | * @return SC_SUCCESS on success and an error code otherwise |
82 | | */ |
83 | | int sc_apdu2bytes(sc_context_t *ctx, const sc_apdu_t *apdu, |
84 | | unsigned int proto, u8 *out, size_t outlen) |
85 | 0 | { |
86 | 0 | u8 *p = out; |
87 | |
|
88 | 0 | size_t len = sc_apdu_get_length(apdu, proto); |
89 | |
|
90 | 0 | if (out == NULL || outlen < len) |
91 | 0 | return SC_ERROR_INVALID_ARGUMENTS; |
92 | | /* CLA, INS, P1 and P2 */ |
93 | 0 | *p++ = apdu->cla; |
94 | 0 | *p++ = apdu->ins; |
95 | 0 | *p++ = apdu->p1; |
96 | 0 | *p++ = apdu->p2; |
97 | | /* case depend part */ |
98 | 0 | switch (apdu->cse) { |
99 | 0 | case SC_APDU_CASE_1: |
100 | | /* T0 needs an additional 0x00 byte */ |
101 | 0 | if (proto == SC_PROTO_T0) |
102 | 0 | *p = (u8)0x00; |
103 | 0 | break; |
104 | 0 | case SC_APDU_CASE_2_SHORT: |
105 | 0 | *p = (u8)apdu->le; |
106 | 0 | break; |
107 | 0 | case SC_APDU_CASE_2_EXT: |
108 | 0 | if (proto == SC_PROTO_T0) |
109 | | /* T0 extended APDUs look just like short APDUs */ |
110 | 0 | *p = (u8)apdu->le; |
111 | 0 | else { |
112 | | /* in case of T1 always use 3 bytes for length */ |
113 | 0 | *p++ = (u8)0x00; |
114 | 0 | *p++ = (u8)(apdu->le >> 8); |
115 | 0 | *p = (u8)apdu->le; |
116 | 0 | } |
117 | 0 | break; |
118 | 0 | case SC_APDU_CASE_3_SHORT: |
119 | 0 | *p++ = (u8)apdu->lc; |
120 | 0 | memcpy(p, apdu->data, apdu->lc); |
121 | 0 | break; |
122 | 0 | case SC_APDU_CASE_3_EXT: |
123 | 0 | if (proto == SC_PROTO_T0) { |
124 | | /* in case of T0 the command is transmitted in chunks |
125 | | * < 255 using the ENVELOPE command ... */ |
126 | 0 | if (apdu->lc > 255) { |
127 | | /* ... so if Lc is greater than 255 bytes |
128 | | * an error has occurred on a higher level */ |
129 | 0 | sc_log(ctx, "invalid Lc length for CASE 3 extended APDU (need ENVELOPE)"); |
130 | 0 | return SC_ERROR_INVALID_ARGUMENTS; |
131 | 0 | } |
132 | 0 | } |
133 | 0 | else { |
134 | | /* in case of T1 always use 3 bytes for length */ |
135 | 0 | *p++ = (u8)0x00; |
136 | 0 | *p++ = (u8)(apdu->lc >> 8); |
137 | 0 | *p++ = (u8)apdu->lc; |
138 | 0 | } |
139 | 0 | memcpy(p, apdu->data, apdu->lc); |
140 | 0 | break; |
141 | 0 | case SC_APDU_CASE_4_SHORT: |
142 | 0 | *p++ = (u8)apdu->lc; |
143 | 0 | memcpy(p, apdu->data, apdu->lc); |
144 | 0 | p += apdu->lc; |
145 | | /* in case of T0 no Le byte is added */ |
146 | 0 | if (proto != SC_PROTO_T0) |
147 | 0 | *p = (u8)apdu->le; |
148 | 0 | break; |
149 | 0 | case SC_APDU_CASE_4_EXT: |
150 | 0 | if (proto == SC_PROTO_T0) { |
151 | | /* again a T0 extended case 4 APDU looks just |
152 | | * like a short APDU, the additional data is |
153 | | * transferred using ENVELOPE and GET RESPONSE */ |
154 | 0 | *p++ = (u8)apdu->lc; |
155 | 0 | memcpy(p, apdu->data, apdu->lc); |
156 | 0 | } |
157 | 0 | else { |
158 | 0 | *p++ = (u8)0x00; |
159 | 0 | *p++ = (u8)(apdu->lc >> 8); |
160 | 0 | *p++ = (u8)apdu->lc; |
161 | 0 | memcpy(p, apdu->data, apdu->lc); |
162 | 0 | p += apdu->lc; |
163 | | /* only 2 bytes are use to specify the length of the |
164 | | * expected data */ |
165 | 0 | *p++ = (u8)(apdu->le >> 8); |
166 | 0 | *p = (u8)apdu->le; |
167 | 0 | } |
168 | 0 | break; |
169 | 0 | } |
170 | | |
171 | 0 | return SC_SUCCESS; |
172 | 0 | } |
173 | | |
174 | | int sc_apdu_get_octets(sc_context_t *ctx, const sc_apdu_t *apdu, u8 **buf, |
175 | | size_t *len, unsigned int proto) |
176 | 0 | { |
177 | 0 | size_t nlen; |
178 | 0 | u8 *nbuf; |
179 | |
|
180 | 0 | if (apdu == NULL || buf == NULL || len == NULL) |
181 | 0 | return SC_ERROR_INVALID_ARGUMENTS; |
182 | | |
183 | | /* get the estimated length of encoded APDU */ |
184 | 0 | nlen = sc_apdu_get_length(apdu, proto); |
185 | 0 | if (nlen == 0) |
186 | 0 | return SC_ERROR_INTERNAL; |
187 | 0 | nbuf = malloc(nlen); |
188 | 0 | if (nbuf == NULL) |
189 | 0 | return SC_ERROR_OUT_OF_MEMORY; |
190 | | /* encode the APDU in the buffer */ |
191 | 0 | if (sc_apdu2bytes(ctx, apdu, proto, nbuf, nlen) != SC_SUCCESS) { |
192 | 0 | free(nbuf); |
193 | 0 | return SC_ERROR_INTERNAL; |
194 | 0 | } |
195 | 0 | *buf = nbuf; |
196 | 0 | *len = nlen; |
197 | |
|
198 | 0 | return SC_SUCCESS; |
199 | 0 | } |
200 | | |
201 | | int sc_apdu_set_resp(sc_context_t *ctx, sc_apdu_t *apdu, const u8 *buf, |
202 | | size_t len) |
203 | 0 | { |
204 | 0 | if (len < 2) { |
205 | | /* no SW1 SW2 ... something went terrible wrong */ |
206 | 0 | sc_log(ctx, "invalid response: SW1 SW2 missing"); |
207 | 0 | return SC_ERROR_INTERNAL; |
208 | 0 | } |
209 | | /* set the SW1 and SW2 status bytes (the last two bytes of |
210 | | * the response */ |
211 | 0 | apdu->sw1 = (unsigned int)buf[len - 2]; |
212 | 0 | apdu->sw2 = (unsigned int)buf[len - 1]; |
213 | 0 | len -= 2; |
214 | | /* set output length and copy the returned data if necessary */ |
215 | 0 | if (len <= apdu->resplen) |
216 | 0 | apdu->resplen = len; |
217 | |
|
218 | 0 | if (apdu->resplen != 0) |
219 | 0 | memcpy(apdu->resp, buf, apdu->resplen); |
220 | |
|
221 | 0 | return SC_SUCCESS; |
222 | 0 | } |
223 | | |
224 | | |
225 | | /*********************************************************************/ |
226 | | /* higher level APDU transfer handling functions */ |
227 | | /*********************************************************************/ |
228 | | /* +------------------+ |
229 | | * | sc_transmit_apdu | |
230 | | * +------------------+ |
231 | | * | | | |
232 | | * | | | detect APDU cse +--------------------+ |
233 | | * | | +---------------------------------> | sc_detect_apdu_cse | |
234 | | * | | +--------------------+ |
235 | | * | | check consistency of APDU +--------------------+ |
236 | | * | +------------------------------------> | sc_check_apdu | |
237 | | * | +--------------------+ |
238 | | * | send single APDU +--------------------+ |
239 | | * +---------------------------------------> | sc_transmit | |
240 | | * ^ +--------------------+ |
241 | | * | | |
242 | | * | re-transmit if wrong length | |
243 | | * | or GET RESPONSE | |
244 | | * +-------------------------------+ |
245 | | * | |
246 | | * v |
247 | | * card->reader->ops->transmit |
248 | | */ |
249 | | |
250 | | /** basic consistency check of the sc_apdu_t object |
251 | | * @param ctx sc_context_t object for error messages |
252 | | * @param apdu sc_apdu_t object to check |
253 | | * @return SC_SUCCESS on success and an error code otherwise |
254 | | */ |
255 | | int |
256 | | sc_check_apdu(sc_card_t *card, const sc_apdu_t *apdu) |
257 | 724 | { |
258 | 724 | if ((apdu->cse & ~SC_APDU_SHORT_MASK) == 0) { |
259 | | /* length check for short APDU */ |
260 | 724 | if (apdu->le > 256 || (apdu->lc > 255 && (apdu->flags & SC_APDU_FLAGS_CHAINING) == 0)) { |
261 | 0 | sc_log(card->ctx, "failed length check for short APDU"); |
262 | 0 | goto error; |
263 | 0 | } |
264 | 724 | } |
265 | 0 | else if ((apdu->cse & SC_APDU_EXT) != 0) { |
266 | | /* check if the card supports extended APDUs */ |
267 | 0 | if ((card->caps & SC_CARD_CAP_APDU_EXT) == 0) { |
268 | 0 | sc_log(card->ctx, "card doesn't support extended APDUs"); |
269 | 0 | goto error; |
270 | 0 | } |
271 | | /* length check for extended APDU */ |
272 | 0 | if (apdu->le > 65536 || apdu->lc > 65535) { |
273 | 0 | sc_log(card->ctx, "failed length check for extended APDU"); |
274 | 0 | goto error; |
275 | 0 | } |
276 | 0 | } |
277 | 0 | else { |
278 | 0 | goto error; |
279 | 0 | } |
280 | | |
281 | 724 | switch (apdu->cse & SC_APDU_SHORT_MASK) { |
282 | 1 | case SC_APDU_CASE_1: |
283 | | /* no data is sent or received */ |
284 | 1 | if (apdu->datalen != 0 || apdu->lc != 0 || apdu->le != 0) |
285 | 0 | goto error; |
286 | 1 | break; |
287 | 38 | case SC_APDU_CASE_2_SHORT: |
288 | | /* no data is sent */ |
289 | 38 | if (apdu->datalen != 0 || apdu->lc != 0) |
290 | 0 | goto error; |
291 | | /* data is expected */ |
292 | 38 | if (apdu->resplen == 0 || apdu->resp == NULL) |
293 | 0 | goto error; |
294 | 38 | break; |
295 | 87 | case SC_APDU_CASE_3_SHORT: |
296 | | /* data is sent */ |
297 | 87 | if (apdu->datalen == 0 || apdu->data == NULL || apdu->lc == 0) |
298 | 0 | goto error; |
299 | | /* no data is expected */ |
300 | 87 | if (apdu->le != 0) |
301 | 0 | goto error; |
302 | | /* inconsistent datalen */ |
303 | 87 | if (apdu->datalen != apdu->lc) |
304 | 0 | goto error; |
305 | 87 | break; |
306 | 598 | case SC_APDU_CASE_4_SHORT: |
307 | | /* data is sent */ |
308 | 598 | if (apdu->datalen == 0 || apdu->data == NULL || apdu->lc == 0) |
309 | 0 | goto error; |
310 | | /* data is expected */ |
311 | 598 | if (apdu->resplen == 0 || apdu->resp == NULL) |
312 | 0 | goto error; |
313 | | /* inconsistent datalen */ |
314 | 598 | if (apdu->datalen != apdu->lc) |
315 | 0 | goto error; |
316 | 598 | break; |
317 | 598 | default: |
318 | 0 | sc_log(card->ctx, "Invalid APDU case %d", apdu->cse); |
319 | 0 | return SC_ERROR_INVALID_ARGUMENTS; |
320 | 724 | } |
321 | 724 | return SC_SUCCESS; |
322 | 0 | error: |
323 | 0 | sc_log(card->ctx, "Invalid Case %d %s APDU:\n" |
324 | 0 | "cse=%02x cla=%02x ins=%02x p1=%02x p2=%02x lc=%lu le=%lu\n" |
325 | 0 | "resp=%p resplen=%lu data=%p datalen=%lu flags=0x%8.8lx", |
326 | 0 | apdu->cse & SC_APDU_SHORT_MASK, |
327 | 0 | (apdu->cse & SC_APDU_EXT) != 0 ? "extended" : "short", |
328 | 0 | apdu->cse, apdu->cla, apdu->ins, apdu->p1, apdu->p2, |
329 | 0 | (unsigned long) apdu->lc, (unsigned long) apdu->le, |
330 | 0 | apdu->resp, (unsigned long) apdu->resplen, |
331 | 0 | apdu->data, (unsigned long) apdu->datalen, apdu->flags); |
332 | 0 | return SC_ERROR_INVALID_ARGUMENTS; |
333 | 724 | } |
334 | | |
335 | | /** Tries to determine the APDU type (short or extended) of the supplied |
336 | | * APDU if one of the SC_APDU_CASE_? types is used. |
337 | | * @param apdu APDU object |
338 | | */ |
339 | | static void |
340 | | sc_detect_apdu_cse(const sc_card_t *card, sc_apdu_t *apdu) |
341 | 722 | { |
342 | 722 | if (apdu->cse == SC_APDU_CASE_2 || apdu->cse == SC_APDU_CASE_3 || |
343 | 722 | apdu->cse == SC_APDU_CASE_4) { |
344 | 16 | int btype = apdu->cse & SC_APDU_SHORT_MASK; |
345 | | /* if either Lc or Le is bigger than the maximum for |
346 | | * short APDUs and the card supports extended APDUs |
347 | | * use extended APDUs (unless Lc is greater than |
348 | | * 255 and command chaining is activated) */ |
349 | 16 | if ((apdu->le > 256 || (apdu->lc > 255 && (apdu->flags & SC_APDU_FLAGS_CHAINING) == 0)) && |
350 | 16 | (card->caps & SC_CARD_CAP_APDU_EXT) != 0) |
351 | 0 | btype |= SC_APDU_EXT; |
352 | 16 | apdu->cse = btype; |
353 | 16 | } |
354 | 722 | } |
355 | | |
356 | | |
357 | | static int |
358 | | sc_single_transmit(struct sc_card *card, struct sc_apdu *apdu) |
359 | 722 | { |
360 | 722 | struct sc_context *ctx = card->ctx; |
361 | 722 | int rv; |
362 | | |
363 | 722 | LOG_FUNC_CALLED(ctx); |
364 | 722 | if (card->reader->ops->transmit == NULL) |
365 | 722 | LOG_TEST_RET(card->ctx, SC_ERROR_NOT_SUPPORTED, "cannot transmit APDU"); |
366 | | |
367 | 722 | sc_log(ctx, |
368 | 722 | "CLA:%X, INS:%X, P1:%X, P2:%X, data(%"SC_FORMAT_LEN_SIZE_T"u) %p", |
369 | 722 | apdu->cla, apdu->ins, apdu->p1, apdu->p2, apdu->datalen, |
370 | 722 | apdu->data); |
371 | 722 | #ifdef ENABLE_SM |
372 | 722 | if (card->sm_ctx.sm_mode == SM_MODE_TRANSMIT |
373 | 722 | && (apdu->flags & SC_APDU_FLAGS_NO_SM) == 0) { |
374 | 0 | LOG_FUNC_RETURN(ctx, sc_sm_single_transmit(card, apdu)); |
375 | 0 | } |
376 | 722 | #endif |
377 | | |
378 | | /* send APDU to the reader driver */ |
379 | 722 | rv = card->reader->ops->transmit(card->reader, apdu); |
380 | 722 | LOG_TEST_RET(ctx, rv, "unable to transmit APDU"); |
381 | | |
382 | 722 | LOG_FUNC_RETURN(ctx, rv); |
383 | 722 | } |
384 | | |
385 | | |
386 | | static int |
387 | | sc_set_le_and_transmit(struct sc_card *card, struct sc_apdu *apdu, size_t olen) |
388 | 0 | { |
389 | 0 | struct sc_context *ctx = card->ctx; |
390 | 0 | size_t nlen = apdu->sw2 ? (size_t)apdu->sw2 : 256; |
391 | 0 | int rv; |
392 | |
|
393 | 0 | LOG_FUNC_CALLED(ctx); |
394 | | /* we cannot re-transmit the APDU with the demanded Le value |
395 | | * as the buffer is too small => error */ |
396 | 0 | if (olen < nlen) |
397 | 0 | LOG_TEST_RET(ctx, SC_ERROR_WRONG_LENGTH, "wrong length: required length exceeds resplen"); |
398 | | |
399 | | /* don't try again if it doesn't work this time */ |
400 | 0 | apdu->flags |= SC_APDU_FLAGS_NO_RETRY_WL; |
401 | | /* set the new expected length */ |
402 | 0 | apdu->resplen = olen; |
403 | 0 | apdu->le = nlen; |
404 | | #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION |
405 | | /* Belpic V1 applets have a problem: if the card sends a 6C XX (only XX bytes available), |
406 | | * and we resend the command too soon (i.e. the reader is too fast), the card doesn't respond. |
407 | | * So we build in a delay. */ |
408 | | if (card->type == SC_CARD_TYPE_BELPIC_EID) |
409 | | msleep(40); |
410 | | #endif |
411 | | |
412 | | /* re-transmit the APDU with new Le length */ |
413 | 0 | rv = sc_single_transmit(card, apdu); |
414 | 0 | LOG_TEST_RET(ctx, rv, "cannot re-transmit APDU"); |
415 | | |
416 | 0 | LOG_FUNC_RETURN(ctx, rv); |
417 | 0 | } |
418 | | |
419 | | |
420 | | static int |
421 | | sc_get_response(struct sc_card *card, struct sc_apdu *apdu, size_t olen) |
422 | 19 | { |
423 | 19 | struct sc_context *ctx = card->ctx; |
424 | 19 | size_t le, minlen, buflen; |
425 | 19 | unsigned char *buf; |
426 | 19 | int rv; |
427 | | |
428 | 19 | LOG_FUNC_CALLED(ctx); |
429 | 19 | if (apdu->le == 0) { |
430 | | /* no data is requested => change return value to 0x9000 and ignore the remaining data */ |
431 | 3 | apdu->sw1 = 0x90; |
432 | 3 | apdu->sw2 = 0x00; |
433 | 3 | return SC_SUCCESS; |
434 | 3 | } |
435 | | |
436 | | /* this should _never_ happen */ |
437 | 16 | if (!card->ops->get_response) |
438 | 16 | LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "no GET RESPONSE command"); |
439 | | |
440 | | /* call GET RESPONSE until we have read all data requested or until the card returns 0x9000, |
441 | | * whatever happens first. */ |
442 | | |
443 | | /* if there are already data in response append a new data to the end of the buffer */ |
444 | 16 | buf = apdu->resp + apdu->resplen; |
445 | | |
446 | | /* read as much data as fits in apdu->resp (i.e. min(apdu->resplen, amount of data available)). */ |
447 | 16 | buflen = olen - apdu->resplen; |
448 | | |
449 | | /* 0x6100 means at least 256 more bytes to read */ |
450 | 16 | le = apdu->sw2 != 0 ? (size_t)apdu->sw2 : 256; |
451 | | /* we try to read at least as much as bytes as promised in the response bytes */ |
452 | 16 | minlen = le; |
453 | | |
454 | 17 | do { |
455 | 17 | unsigned char resp[256]; |
456 | 17 | size_t resp_len = le; |
457 | | |
458 | | /* we have all the data the caller requested even if the card has more data */ |
459 | 17 | if (buflen == 0) |
460 | 7 | break; |
461 | | |
462 | | /* call GET RESPONSE to get more date from the card; |
463 | | * note: GET RESPONSE returns the left amount of data (== SW2) */ |
464 | 10 | memset(resp, 0, sizeof(resp)); |
465 | 10 | rv = card->ops->get_response(card, &resp_len, resp); |
466 | 10 | if (rv < 0) { |
467 | 6 | #ifdef ENABLE_SM |
468 | 6 | if (resp_len) { |
469 | 4 | sc_log_hex(ctx, "SM response data", resp, resp_len); |
470 | 4 | sc_sm_update_apdu_response(card, resp, resp_len, rv, apdu); |
471 | 4 | } |
472 | 6 | #endif |
473 | 6 | LOG_TEST_RET(ctx, rv, "GET RESPONSE error"); |
474 | 6 | } |
475 | | |
476 | 4 | le = resp_len; |
477 | | /* copy as much as will fit in requested buffer */ |
478 | 4 | if (buflen < le) |
479 | 2 | le = buflen; |
480 | | |
481 | 4 | memcpy(buf, resp, le); |
482 | 4 | buf += le; |
483 | 4 | buflen -= le; |
484 | | |
485 | 4 | minlen -= le; |
486 | 4 | if (rv != 0) |
487 | 1 | le = minlen = (size_t)rv; |
488 | 3 | else |
489 | | /* if the card has returned 0x9000 but we still expect data ask for more |
490 | | * until we have read enough bytes */ |
491 | 3 | le = minlen; |
492 | 4 | } while (rv != 0 && minlen != 0); |
493 | | |
494 | | /* we've read all data, let's return 0x9000 */ |
495 | 10 | apdu->resplen = buf - apdu->resp; |
496 | 10 | apdu->sw1 = 0x90; |
497 | 10 | apdu->sw2 = 0x00; |
498 | | |
499 | 10 | LOG_FUNC_RETURN(ctx, SC_SUCCESS); |
500 | 10 | } |
501 | | |
502 | | |
503 | | /** Sends a single APDU to the card reader and calls GET RESPONSE to get the return data if necessary. |
504 | | * @param card sc_card_t object for the smartcard |
505 | | * @param apdu APDU to be sent |
506 | | * @return SC_SUCCESS on success and an error value otherwise |
507 | | */ |
508 | | static int |
509 | | sc_transmit(sc_card_t *card, sc_apdu_t *apdu) |
510 | 722 | { |
511 | 722 | struct sc_context *ctx = card->ctx; |
512 | 722 | size_t olen = apdu->resplen; |
513 | 722 | int r; |
514 | | |
515 | 722 | LOG_FUNC_CALLED(ctx); |
516 | | |
517 | 722 | r = sc_single_transmit(card, apdu); |
518 | 722 | LOG_TEST_RET(ctx, r, "transmit APDU failed"); |
519 | | |
520 | | /* ok, the APDU was successfully transmitted. Now we have two special cases: |
521 | | * 1. the card returned 0x6Cxx: in this case APDU will be re-transmitted with Le set to SW2 |
522 | | * (possible only if response buffer size is larger than new Le = SW2) |
523 | | */ |
524 | 722 | if (apdu->sw1 == 0x6C && (apdu->flags & SC_APDU_FLAGS_NO_RETRY_WL) == 0) { |
525 | 0 | r = sc_set_le_and_transmit(card, apdu, olen); |
526 | 0 | LOG_TEST_RET(ctx, r, "cannot re-transmit APDU "); |
527 | 0 | } |
528 | | |
529 | | /* 2. the card returned 0x61xx: more data can be read from the card |
530 | | * using the GET RESPONSE command (mostly used in the T0 protocol). |
531 | | * Unless the SC_APDU_FLAGS_NO_GET_RESP is set we try to read as |
532 | | * much data as possible using GET RESPONSE. |
533 | | */ |
534 | 722 | if (apdu->sw1 == 0x61 && (apdu->flags & SC_APDU_FLAGS_NO_GET_RESP) == 0) { |
535 | 19 | r = sc_get_response(card, apdu, olen); |
536 | 19 | LOG_TEST_RET(ctx, r, "cannot get all data with 'GET RESPONSE'"); |
537 | 19 | } |
538 | | |
539 | 716 | LOG_FUNC_RETURN(ctx, SC_SUCCESS); |
540 | 716 | } |
541 | | |
542 | | |
543 | | int sc_transmit_apdu(sc_card_t *card, sc_apdu_t *apdu) |
544 | 722 | { |
545 | 722 | int r = SC_SUCCESS; |
546 | | |
547 | 722 | if (card == NULL || apdu == NULL) |
548 | 0 | return SC_ERROR_INVALID_ARGUMENTS; |
549 | | |
550 | 722 | LOG_FUNC_CALLED(card->ctx); |
551 | | |
552 | | /* determine the APDU type if necessary, i.e. to use |
553 | | * short or extended APDUs */ |
554 | 722 | sc_detect_apdu_cse(card, apdu); |
555 | | /* basic APDU consistency check */ |
556 | 722 | r = sc_check_apdu(card, apdu); |
557 | 722 | if (r != SC_SUCCESS) |
558 | 0 | return SC_ERROR_INVALID_ARGUMENTS; |
559 | | |
560 | 722 | r = sc_lock(card); /* acquire card lock*/ |
561 | 722 | if (r != SC_SUCCESS) { |
562 | 0 | sc_log(card->ctx, "unable to acquire lock"); |
563 | 0 | return r; |
564 | 0 | } |
565 | | |
566 | 722 | #if ENABLE_SM |
567 | 722 | if (card->sm_ctx.sm_mode == SM_MODE_TRANSMIT |
568 | 722 | && (apdu->flags & SC_APDU_FLAGS_CHAINING) != 0 |
569 | 722 | && (apdu->flags & SC_APDU_FLAGS_SM_CHAINING) != 0) { |
570 | 0 | sc_log(card->ctx,"Let SM do the chaining"); |
571 | 0 | r = sc_transmit(card, apdu); |
572 | 0 | } else |
573 | 722 | #endif |
574 | 722 | if ((apdu->flags & SC_APDU_FLAGS_CHAINING) != 0) { |
575 | | /* divide et impera: transmit APDU in chunks with Lc <= max_send_size |
576 | | * bytes using command chaining */ |
577 | 2 | size_t len = apdu->datalen; |
578 | 2 | const u8 *buf = apdu->data; |
579 | 2 | size_t max_send_size = sc_get_max_send_size(card); |
580 | | |
581 | 4 | while (len != 0) { |
582 | 2 | size_t plen; |
583 | 2 | sc_apdu_t tapdu; |
584 | 2 | int last = 0; |
585 | | |
586 | 2 | tapdu = *apdu; |
587 | | /* clear chaining flag */ |
588 | 2 | tapdu.flags &= ~SC_APDU_FLAGS_CHAINING; |
589 | 2 | if (len > max_send_size) { |
590 | | /* adjust APDU case: in case of CASE 4 APDU |
591 | | * the intermediate APDU are of CASE 3 */ |
592 | 0 | if ((tapdu.cse & SC_APDU_SHORT_MASK) == SC_APDU_CASE_4_SHORT) |
593 | 0 | tapdu.cse--; |
594 | | /* XXX: the chunk size must be adjusted when |
595 | | * secure messaging is used */ |
596 | 0 | plen = max_send_size; |
597 | 0 | tapdu.cla |= 0x10; |
598 | | /* the intermediate APDU don't expect response data */ |
599 | 0 | tapdu.le = 0; |
600 | 0 | tapdu.resplen = 0; |
601 | 0 | tapdu.resp = NULL; |
602 | 2 | } else { |
603 | 2 | plen = len; |
604 | 2 | last = 1; |
605 | 2 | } |
606 | 2 | tapdu.data = buf; |
607 | 2 | tapdu.datalen = tapdu.lc = plen; |
608 | | |
609 | 2 | r = sc_check_apdu(card, &tapdu); |
610 | 2 | if (r != SC_SUCCESS) { |
611 | 0 | sc_log(card->ctx, "inconsistent APDU while chaining"); |
612 | 0 | break; |
613 | 0 | } |
614 | | |
615 | 2 | r = sc_transmit(card, &tapdu); |
616 | 2 | if (r != SC_SUCCESS) |
617 | 0 | break; |
618 | 2 | if (last != 0) { |
619 | | /* in case of the last APDU set the SW1 |
620 | | * and SW2 bytes in the original APDU */ |
621 | 2 | apdu->sw1 = tapdu.sw1; |
622 | 2 | apdu->sw2 = tapdu.sw2; |
623 | 2 | apdu->resplen = tapdu.resplen; |
624 | 2 | } else { |
625 | | /* otherwise check the status bytes */ |
626 | 0 | r = sc_check_sw(card, tapdu.sw1, tapdu.sw2); |
627 | 0 | if (r != SC_SUCCESS) |
628 | 0 | break; |
629 | 0 | } |
630 | 2 | len -= plen; |
631 | 2 | buf += plen; |
632 | 2 | } |
633 | 720 | } else { |
634 | | /* transmit single APDU */ |
635 | 720 | r = sc_transmit(card, apdu); |
636 | 720 | } |
637 | | |
638 | 722 | if (r == SC_ERROR_CARD_RESET || r == SC_ERROR_READER_REATTACHED) { |
639 | | /* give card driver a chance to react on resets */ |
640 | 0 | if (card->ops->card_reader_lock_obtained) |
641 | 0 | card->ops->card_reader_lock_obtained(card, 1); |
642 | 0 | } |
643 | | |
644 | | /* all done => release lock */ |
645 | 722 | if (sc_unlock(card) != SC_SUCCESS) |
646 | 0 | sc_log(card->ctx, "sc_unlock failed"); |
647 | | |
648 | 722 | return r; |
649 | 722 | } |
650 | | |
651 | | |
652 | | int |
653 | | sc_bytes2apdu(sc_context_t *ctx, const u8 *buf, size_t len, sc_apdu_t *apdu) |
654 | 0 | { |
655 | 0 | const unsigned char *p; |
656 | 0 | size_t len0; |
657 | |
|
658 | 0 | if (!buf || !apdu) |
659 | 0 | return SC_ERROR_INVALID_ARGUMENTS; |
660 | | |
661 | 0 | len0 = len; |
662 | 0 | if (len < 4) { |
663 | 0 | sc_log(ctx, "APDU too short (must be at least 4 bytes)"); |
664 | 0 | return SC_ERROR_INVALID_DATA; |
665 | 0 | } |
666 | | |
667 | 0 | memset(apdu, 0, sizeof *apdu); |
668 | 0 | p = buf; |
669 | 0 | apdu->cla = *p++; |
670 | 0 | apdu->ins = *p++; |
671 | 0 | apdu->p1 = *p++; |
672 | 0 | apdu->p2 = *p++; |
673 | 0 | len -= 4; |
674 | |
|
675 | 0 | if (!len) { |
676 | 0 | apdu->cse = SC_APDU_CASE_1; |
677 | 0 | sc_log(ctx, |
678 | 0 | "CASE_1 APDU: %"SC_FORMAT_LEN_SIZE_T"u bytes:\tins=%02x p1=%02x p2=%02x lc=%04"SC_FORMAT_LEN_SIZE_T"x le=%04"SC_FORMAT_LEN_SIZE_T"x", |
679 | 0 | len0, apdu->ins, apdu->p1, apdu->p2, apdu->lc, apdu->le); |
680 | 0 | return SC_SUCCESS; |
681 | 0 | } |
682 | | |
683 | 0 | if (*p == 0 && len >= 3) { |
684 | | /* ...must be an extended APDU */ |
685 | 0 | p++; |
686 | 0 | if (len == 3) { |
687 | 0 | apdu->le = (*p++)<<8; |
688 | 0 | apdu->le += *p++; |
689 | 0 | if (apdu->le == 0) |
690 | 0 | apdu->le = 0xffff+1; |
691 | 0 | len -= 3; |
692 | 0 | apdu->cse = SC_APDU_CASE_2_EXT; |
693 | 0 | } |
694 | 0 | else { |
695 | | /* len > 3 */ |
696 | 0 | apdu->lc = (*p++)<<8; |
697 | 0 | apdu->lc += *p++; |
698 | 0 | len -= 3; |
699 | 0 | if (len < apdu->lc) { |
700 | 0 | sc_log(ctx, |
701 | 0 | "APDU too short (need %"SC_FORMAT_LEN_SIZE_T"u more bytes)", |
702 | 0 | apdu->lc - len); |
703 | 0 | return SC_ERROR_INVALID_DATA; |
704 | 0 | } |
705 | 0 | apdu->data = p; |
706 | 0 | apdu->datalen = apdu->lc; |
707 | 0 | len -= apdu->lc; |
708 | 0 | p += apdu->lc; |
709 | 0 | if (!len) { |
710 | 0 | apdu->cse = SC_APDU_CASE_3_EXT; |
711 | 0 | } |
712 | 0 | else { |
713 | | /* at this point the apdu has a Lc, so Le is on 2 bytes */ |
714 | 0 | if (len < 2) { |
715 | 0 | sc_debug(ctx, SC_LOG_DEBUG_VERBOSE, "APDU too short (need 2 more bytes)\n"); |
716 | 0 | return SC_ERROR_INVALID_DATA; |
717 | 0 | } |
718 | 0 | apdu->le = (*p++)<<8; |
719 | 0 | apdu->le += *p++; |
720 | 0 | if (apdu->le == 0) |
721 | 0 | apdu->le = 0xffff+1; |
722 | 0 | len -= 2; |
723 | 0 | apdu->cse = SC_APDU_CASE_4_EXT; |
724 | 0 | } |
725 | 0 | } |
726 | 0 | } |
727 | 0 | else { |
728 | | /* ...must be a short APDU */ |
729 | 0 | if (len == 1) { |
730 | 0 | apdu->le = *p++; |
731 | 0 | if (apdu->le == 0) |
732 | 0 | apdu->le = 0xff+1; |
733 | 0 | len--; |
734 | 0 | apdu->cse = SC_APDU_CASE_2_SHORT; |
735 | 0 | } |
736 | 0 | else { |
737 | 0 | apdu->lc = *p++; |
738 | 0 | len--; |
739 | 0 | if (len < apdu->lc) { |
740 | 0 | sc_log(ctx, |
741 | 0 | "APDU too short (need %"SC_FORMAT_LEN_SIZE_T"u more bytes)", |
742 | 0 | apdu->lc - len); |
743 | 0 | return SC_ERROR_INVALID_DATA; |
744 | 0 | } |
745 | 0 | apdu->data = p; |
746 | 0 | apdu->datalen = apdu->lc; |
747 | 0 | len -= apdu->lc; |
748 | 0 | p += apdu->lc; |
749 | 0 | if (!len) { |
750 | 0 | apdu->cse = SC_APDU_CASE_3_SHORT; |
751 | 0 | } |
752 | 0 | else { |
753 | 0 | apdu->le = *p++; |
754 | 0 | if (apdu->le == 0) |
755 | 0 | apdu->le = 0xff+1; |
756 | 0 | len--; |
757 | 0 | apdu->cse = SC_APDU_CASE_4_SHORT; |
758 | 0 | } |
759 | 0 | } |
760 | 0 | } |
761 | 0 | if (len) { |
762 | 0 | sc_log(ctx, "APDU too long (%lu bytes extra)",(unsigned long) len); |
763 | 0 | return SC_ERROR_INVALID_DATA; |
764 | 0 | } |
765 | | |
766 | 0 | sc_log(ctx, |
767 | 0 | "Case %d %s APDU, %"SC_FORMAT_LEN_SIZE_T"u bytes:\tins=%02x p1=%02x p2=%02x lc=%04"SC_FORMAT_LEN_SIZE_T"x le=%04"SC_FORMAT_LEN_SIZE_T"x", |
768 | 0 | apdu->cse & SC_APDU_SHORT_MASK, |
769 | 0 | (apdu->cse & SC_APDU_EXT) != 0 ? "extended" : "short", |
770 | 0 | len0, apdu->ins, apdu->p1, apdu->p2, apdu->lc, |
771 | 0 | apdu->le); |
772 | |
|
773 | 0 | return SC_SUCCESS; |
774 | 0 | } |