/[pcsclite]/trunk/Drivers/ccid/src/commands.c
ViewVC logotype

Contents of /trunk/Drivers/ccid/src/commands.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2098 - (show annotations) (download)
Tue Jul 4 07:11:43 2006 UTC (6 years, 10 months ago) by rousseau
File MIME type: text/plain
File size: 41101 byte(s)
make pcscd detect a buffer overflow when the receiving buffer is too
small instead of silently ignoring the detected problem. This problem
only occured with readers supporting Extended APDU.
1 /*
2 commands.c: Commands sent to the card
3 Copyright (C) 2003-2004 Ludovic Rousseau
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20 /*
21 * $Id$
22 */
23
24 #include <string.h>
25 #include <stdlib.h>
26 #include <pcsclite.h>
27 #include <ifdhandler.h>
28 #include <reader.h>
29
30 #include "commands.h"
31 #include "openct/proto-t1.h"
32 #include "ccid.h"
33 #include "defs.h"
34 #include "ccid_ifdhandler.h"
35 #include "config.h"
36 #include "debug.h"
37
38 /* All the pinpad readers I used are more or less bogus
39 * I use code to change the user command and make the firmware happy */
40 #define BOGUS_PINPAD_FIRMWARE
41
42 #define max( a, b ) ( ( ( a ) > ( b ) ) ? ( a ) : ( b ) )
43 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
44 #define IFD_ERROR_INSUFFICIENT_BUFFER 700
45
46 /* internal functions */
47 static RESPONSECODE CmdXfrBlockAPDU_extended(unsigned int reader_index,
48 unsigned int tx_length, unsigned char tx_buffer[], unsigned int *rx_length,
49 unsigned char rx_buffer[]);
50
51 static RESPONSECODE CmdXfrBlockTPDU_T0(unsigned int reader_index,
52 unsigned int tx_length, unsigned char tx_buffer[], unsigned int *rx_length,
53 unsigned char rx_buffer[]);
54
55 static RESPONSECODE CmdXfrBlockCHAR_T0(unsigned int reader_index, unsigned int
56 tx_length, unsigned char tx_buffer[], unsigned int *rx_length, unsigned
57 char rx_buffer[]);
58
59 static RESPONSECODE CmdXfrBlockTPDU_T1(unsigned int reader_index,
60 unsigned int tx_length, unsigned char tx_buffer[], unsigned int *rx_length,
61 unsigned char rx_buffer[]);
62
63 static void i2dw(int value, unsigned char *buffer);
64
65
66 /*****************************************************************************
67 *
68 * CmdPowerOn
69 *
70 ****************************************************************************/
71 RESPONSECODE CmdPowerOn(unsigned int reader_index, unsigned int * nlength,
72 unsigned char buffer[], int voltage)
73 {
74 unsigned char cmd[10];
75 status_t res;
76 int length, count = 1;
77 unsigned int atr_len;
78 RESPONSECODE return_value = IFD_SUCCESS;
79 _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
80
81 /* store length of buffer[] */
82 length = *nlength;
83
84 if (ccid_descriptor->dwFeatures & CCID_CLASS_AUTO_VOLTAGE)
85 voltage = 0; /* automatic voltage selection */
86
87 again:
88 cmd[0] = 0x62; /* IccPowerOn */
89 cmd[1] = cmd[2] = cmd[3] = cmd[4] = 0; /* dwLength */
90 cmd[5] = ccid_descriptor->bCurrentSlotIndex; /* slot number */
91 cmd[6] = (*ccid_descriptor->pbSeq)++;
92 cmd[7] = voltage;
93 cmd[8] = cmd[9] = 0; /* RFU */
94
95 res = WritePort(reader_index, sizeof(cmd), cmd);
96 if (res != STATUS_SUCCESS)
97 return IFD_COMMUNICATION_ERROR;
98
99 /* reset available buffer size */
100 /* needed if we go back after a switch to ISO mode */
101 *nlength = length;
102
103 res = ReadPort(reader_index, nlength, buffer);
104 if (res != STATUS_SUCCESS)
105 return IFD_COMMUNICATION_ERROR;
106
107 if (buffer[STATUS_OFFSET] & CCID_COMMAND_FAILED)
108 {
109 ccid_error(buffer[ERROR_OFFSET], __FILE__, __LINE__, __FUNCTION__); /* bError */
110
111 if (0xBB == buffer[ERROR_OFFSET] && /* Protocol error in EMV mode */
112 ((GEMPC433 == ccid_descriptor->readerID)
113 || (CHERRYXX33 == ccid_descriptor->readerID)))
114 {
115 unsigned char cmd[] = {0x1F, 0x01};
116 unsigned char res[1];
117 unsigned int res_length = sizeof(res);
118
119 if ((return_value = CmdEscape(reader_index, cmd, sizeof(cmd), res,
120 &res_length)) != IFD_SUCCESS)
121 return return_value;
122
123 /* avoid looping if we can't switch mode */
124 if (count--)
125 goto again;
126 else
127 DEBUG_CRITICAL("Can't set reader in ISO mode");
128 }
129
130 /* continue with 3 volts and 5 volts */
131 if (voltage > 1)
132 {
133 char *voltage_code[] = { "auto", "5V", "3V", "1.8V" };
134
135 DEBUG_INFO3("Power up with %s failed. Try with %s.",
136 voltage_code[voltage], voltage_code[voltage-1]);
137 voltage--;
138 goto again;
139 }
140
141 return IFD_COMMUNICATION_ERROR;
142 }
143
144 /* extract the ATR */
145 atr_len = dw2i(buffer, 1); /* ATR length */
146 if (atr_len > *nlength)
147 atr_len = *nlength;
148 else
149 *nlength = atr_len;
150
151 memmove(buffer, buffer+10, atr_len);
152
153 return return_value;
154 } /* CmdPowerOn */
155
156
157 /*****************************************************************************
158 *
159 * SecurePINVerify
160 *
161 ****************************************************************************/
162 RESPONSECODE SecurePINVerify(unsigned int reader_index,
163 unsigned char TxBuffer[], unsigned int TxLength,
164 unsigned char RxBuffer[], unsigned int *RxLength)
165 {
166 unsigned char cmd[11+14+CMD_BUF_SIZE];
167 unsigned int a, b;
168 _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
169 int old_read_timeout;
170 RESPONSECODE ret;
171
172 cmd[0] = 0x69; /* Secure */
173 cmd[5] = ccid_descriptor->bCurrentSlotIndex; /* slot number */
174 cmd[6] = (*ccid_descriptor->pbSeq)++;
175 cmd[7] = 0; /* bBWI */
176 cmd[8] = 0; /* wLevelParameter */
177 cmd[9] = 0;
178 cmd[10] = 0; /* bPINOperation: PIN Verification */
179
180 /* 19 is the size of the PCSCv2 PIN verify structure
181 * The equivalent CCID structure is only 14-bytes long */
182 if (TxLength > 19+CMD_BUF_SIZE) /* command too large? */
183 {
184 DEBUG_INFO3("Command too long: %d > %d", TxLength, 19+CMD_BUF_SIZE);
185 *RxLength = 0;
186 return IFD_NOT_SUPPORTED;
187 }
188
189 if (TxLength < 19+4 /* 4 = APDU size */) /* command too short? */
190 {
191 DEBUG_INFO3("Command too short: %d < %d", TxLength, 19+4);
192 *RxLength = 0;
193 return IFD_NOT_SUPPORTED;
194 }
195
196 if (dw2i(TxBuffer, 15) + 19 != TxLength) /* ulDataLength field coherency */
197 {
198 DEBUG_INFO3("Wrong lengths: %d %d", dw2i(TxBuffer, 15) + 19, TxLength);
199 *RxLength = 0;
200 return IFD_NOT_SUPPORTED;
201 }
202
203 /* make sure bEntryValidationCondition is valid
204 * The Cherry XX44 reader crashes with a wrong value */
205 if ((0x00 == TxBuffer[7]) || (TxBuffer[7] > 0x07))
206 {
207 DEBUG_INFO2("Correct bEntryValidationCondition (was 0x%02X)",
208 TxBuffer[7]);
209 TxBuffer[7] = 0x02;
210 }
211
212 #ifdef BOGUS_PINPAD_FIRMWARE
213 /* bug circumvention for the GemPC Pinpad */
214 if (GEMPCPINPAD == ccid_descriptor->readerID)
215 {
216 /* the firmware reject the cases: 00h No string and FFh default
217 * CCID message. The only value supported is 01h (display 1 message) */
218 if (0x01 != TxBuffer[8])
219 {
220 DEBUG_INFO2("Correct bNumberMessage for GemPC Pinpad (was %d)",
221 TxBuffer[8]);
222 TxBuffer[8] = 0x01;
223 }
224 }
225 #endif
226
227 /* T=1 Protocol Management for a TPDU reader */
228 if ((SCARD_PROTOCOL_T1 == ccid_descriptor->cardProtocol)
229 && (CCID_CLASS_TPDU == (ccid_descriptor->dwFeatures & CCID_CLASS_EXCHANGE_MASK)))
230 {
231 ct_buf_t sbuf;
232 unsigned char sdata[T1_BUFFER_SIZE];
233
234 /* Initialize send buffer with the APDU */
235 ct_buf_set(&sbuf,
236 (void *)(TxBuffer + offsetof(PIN_VERIFY_STRUCTURE, abData)),
237 TxLength - offsetof(PIN_VERIFY_STRUCTURE, abData));
238
239 /* Create T=1 block */
240 ret = t1_build(&((get_ccid_slot(reader_index))->t1),
241 sdata, 0, T1_I_BLOCK, &sbuf, NULL);
242
243 /* Increment the sequence numbers */
244 get_ccid_slot(reader_index)->t1.ns ^= 1;
245 get_ccid_slot(reader_index)->t1.nr ^= 1;
246
247 /* Copy the generated T=1 block prologue into the teoprologue
248 * of the CCID command */
249 memcpy(TxBuffer + offsetof(PIN_VERIFY_STRUCTURE, bTeoPrologue),
250 sdata, 3);
251 }
252
253 /* Build a CCID block from a PC/SC V2.1.2 Part 10 block */
254 for (a = 11, b = 0; b < TxLength; b++)
255 {
256 if (1 == b) /* bTimeOut2 field */
257 /* Ignore the second timeout as there's nothing we can do with
258 * it currently */
259 continue;
260
261 if ((b >= 15) && (b <= 18)) /* ulDataLength field (4 bytes) */
262 /* the ulDataLength field is not present in the CCID frame
263 * so do not copy */
264 continue;
265
266 /* copy the CCID block 'verbatim' */
267 cmd[a] = TxBuffer[b];
268 a++;
269 }
270
271 /* SPR532 and Case 1 APDU */
272 if ((SPR532 == ccid_descriptor->readerID) && (TxBuffer[15] == 4))
273 {
274 RESPONSECODE return_value;
275 unsigned char cmd[] = { 0x80, 0x02, 0x00 };
276 unsigned char res[1];
277 unsigned int res_length = sizeof(res);
278
279 /* the SPR532 will append the PIN code without any padding */
280 return_value = CmdEscape(reader_index, cmd, sizeof(cmd), res,
281 &res_length);
282 if (return_value != IFD_SUCCESS)
283 {
284 ccid_error(res[ERROR_OFFSET], __FILE__, __LINE__, __FUNCTION__);
285 return return_value;
286 }
287 }
288
289 i2dw(a - 10, cmd + 1); /* CCID message length */
290
291 old_read_timeout = ccid_descriptor -> readTimeout;
292 ccid_descriptor -> readTimeout = max(30, TxBuffer[0]); /* at least 30 seconds */
293
294 if (WritePort(reader_index, a, cmd) != STATUS_SUCCESS)
295 {
296 *RxLength = 0;
297 return IFD_COMMUNICATION_ERROR;
298 }
299
300 ret = CCID_Receive(reader_index, RxLength, RxBuffer, NULL);
301
302 /* T=1 Protocol Management for a TPDU reader */
303 if ((IFD_SUCCESS == ret)
304 && (SCARD_PROTOCOL_T1 == ccid_descriptor->cardProtocol)
305 && (CCID_CLASS_TPDU == (ccid_descriptor->dwFeatures & CCID_CLASS_EXCHANGE_MASK)))
306 {
307 /* timeout and cancel cases are faked by CCID_Receive() */
308 if (2 == *RxLength)
309 {
310 /* Decrement the sequence numbers since no TPDU was sent */
311 get_ccid_slot(reader_index)->t1.ns ^= 1;
312 get_ccid_slot(reader_index)->t1.nr ^= 1;
313 }
314 else
315 {
316 /* get only the T=1 data */
317 /* FIXME: manage T=1 error blocks */
318 memmove(RxBuffer, RxBuffer+3, *RxLength -4);
319 *RxLength -= 4; /* remove NAD, PCB, LEN and CRC */
320 }
321 }
322
323 ccid_descriptor -> readTimeout = old_read_timeout;
324 return ret;
325 } /* SecurePINVerify */
326
327
328 /*****************************************************************************
329 *
330 * SecurePINModify
331 *
332 ****************************************************************************/
333 RESPONSECODE SecurePINModify(unsigned int reader_index,
334 unsigned char TxBuffer[], unsigned int TxLength,
335 unsigned char RxBuffer[], unsigned int *RxLength)
336 {
337 unsigned char cmd[11+19+CMD_BUF_SIZE];
338 unsigned int a, b;
339 _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
340 int old_read_timeout;
341 RESPONSECODE ret;
342
343 cmd[0] = 0x69; /* Secure */
344 cmd[5] = ccid_descriptor->bCurrentSlotIndex; /* slot number */
345 cmd[6] = (*ccid_descriptor->pbSeq)++;
346 cmd[7] = 0; /* bBWI */
347 cmd[8] = 0; /* wLevelParameter */
348 cmd[9] = 0;
349 cmd[10] = 1; /* bPINOperation: PIN Modification */
350
351 /* 24 is the size of the PCSC PIN modify structure
352 * The equivalent CCID structure is only 18 or 19-bytes long */
353 if (TxLength > 24+CMD_BUF_SIZE) /* command too large? */
354 {
355 DEBUG_INFO3("Command too long: %d > %d", TxLength, 24+CMD_BUF_SIZE);
356 *RxLength = 0;
357 return IFD_NOT_SUPPORTED;
358 }
359
360 if (TxLength < 24+4 /* 4 = APDU size */) /* command too short? */
361 {
362 DEBUG_INFO3("Command too short: %d < %d", TxLength, 24+4);
363 *RxLength = 0;
364 return IFD_NOT_SUPPORTED;
365 }
366
367 if (dw2i(TxBuffer, 20) + 24 != TxLength) /* ulDataLength field coherency */
368 {
369 DEBUG_INFO3("Wrong lengths: %d %d", dw2i(TxBuffer, 20) + 24, TxLength);
370 *RxLength = 0;
371 return IFD_NOT_SUPPORTED;
372 }
373
374 /* Make sure in the beginning if bNumberMessage is valid or not */
375 if (TxBuffer[11] > 3)
376 {
377 DEBUG_INFO2("Wrong bNumberMessage: %d", TxBuffer[11]);
378 *RxLength = 0;
379 return IFD_NOT_SUPPORTED;
380 }
381
382 /* Make sure bEntryValidationCondition is valid
383 * The Cherry XX44 reader crashes with a wrong value */
384 if ((0x00 == TxBuffer[10]) || (TxBuffer[10] > 0x07))
385 {
386 DEBUG_INFO2("Correct bEntryValidationCondition (was 0x%02X)",
387 TxBuffer[10]);
388 TxBuffer[10] = 0x02;
389 }
390
391 #ifdef BOGUS_PINPAD_FIRMWARE
392 /* some firmwares are buggy so we try to "correct" the frame */
393 /*
394 * SPR 532 and Cherry ST 2000C has no display but requires _all_
395 * bMsgIndex fields with bNumberMessage set to 0.
396 */
397 if ((SPR532 == ccid_descriptor->readerID)
398 || (CHERRYST2000 == ccid_descriptor->readerID))
399 {
400 TxBuffer[11] = 0x03; /* set bNumberMessages to 3 so that
401 all bMsgIndex123 are filled */
402 TxBuffer[14] = TxBuffer[15] = TxBuffer[16] = 0; /* bMsgIndex123 */
403 }
404
405 /* the bug is a bit different than for the Cherry ST 2000C
406 * with bNumberMessages < 3 the command seems to be accepted
407 * and the card sends 6B 80 */
408 if (CHERRYXX44 == ccid_descriptor->readerID)
409 {
410 TxBuffer[11] = 0x03; /* set bNumberMessages to 3 so that
411 all bMsgIndex123 are filled */
412 }
413
414 /* bug circumvention for the GemPC Pinpad */
415 if (GEMPCPINPAD == ccid_descriptor->readerID)
416 {
417 /* The reader does not support, and actively reject, "max size reached"
418 * and "timeout occured" validation conditions */
419 if (0x02 != TxBuffer[10])
420 {
421 DEBUG_INFO2("Correct bEntryValidationCondition for GemPC Pinpad (was %d)",
422 TxBuffer[10]);
423 TxBuffer[10] = 0x02; /* validation key pressed */
424 }
425
426 /* the reader does not support any other value than 3 for the number
427 * of messages */
428 if (0x03 != TxBuffer[11])
429 {
430 DEBUG_INFO2("Correct bNumberMessages for GemPC Pinpad (was %d)",
431 TxBuffer[11]);
432 TxBuffer[11] = 0x03; /* 3 messages */
433 }
434 }
435 #endif
436
437 /* T=1 Protocol Management for a TPDU reader */
438 if ((SCARD_PROTOCOL_T1 == ccid_descriptor->cardProtocol)
439 && (CCID_CLASS_TPDU == (ccid_descriptor->dwFeatures & CCID_CLASS_EXCHANGE_MASK)))
440 {
441 ct_buf_t sbuf;
442 unsigned char sdata[T1_BUFFER_SIZE];
443
444 /* Initialize send buffer with the APDU */
445 ct_buf_set(&sbuf,
446 (void *)(TxBuffer + offsetof(PIN_MODIFY_STRUCTURE, abData)),
447 TxLength - offsetof(PIN_MODIFY_STRUCTURE, abData));
448
449 /* Create T=1 block */
450 ret = t1_build(&((get_ccid_slot(reader_index))->t1),
451 sdata, 0, T1_I_BLOCK, &sbuf, NULL);
452
453 /* Increment the sequence numbers */
454 get_ccid_slot(reader_index)->t1.ns ^= 1;
455 get_ccid_slot(reader_index)->t1.nr ^= 1;
456
457 /* Copy the generated T=1 block prologue into the teoprologue
458 * of the CCID command */
459 memcpy(TxBuffer + offsetof(PIN_MODIFY_STRUCTURE, bTeoPrologue),
460 sdata, 3);
461 }
462
463 /* Build a CCID block from a PC/SC V2.1.2 Part 10 block */
464
465 /* Do adjustments as needed - CCID spec is not exact with some
466 * details in the format of the structure, per-reader adaptions
467 * might be needed.
468 */
469 for (a = 11, b = 0; b < TxLength; b++)
470 {
471 if (1 == b) /* bTimeOut2 */
472 /* Ignore the second timeout as there's nothing we can do with it
473 * currently */
474 continue;
475
476 if (15 == b) /* bMsgIndex2 */
477 {
478 /* in CCID the bMsgIndex2 is present only if bNumberMessage != 0 */
479 if (0 == TxBuffer[11])
480 continue;
481 }
482
483 if (16 == b) /* bMsgIndex3 */
484 {
485 /* in CCID the bMsgIndex3 is present only if bNumberMessage == 3 */
486 if (TxBuffer[11] < 3)
487 continue;
488 }
489
490 if ((b >= 20) && (b <= 23)) /* ulDataLength field (4 bytes) */
491 /* the ulDataLength field is not present in the CCID frame
492 * so do not copy */
493 continue;
494
495 /* copy to the CCID block 'verbatim' */
496 cmd[a] = TxBuffer[b];
497 a++;
498 }
499
500 #ifdef BOGUS_PINPAD_FIRMWARE
501 if ((SPR532 == ccid_descriptor->readerID)
502 || (CHERRYST2000 == ccid_descriptor->readerID))
503 {
504 cmd[21] = 0x00; /* set bNumberMessages to 0 */
505 }
506 #endif
507
508 /* We know the size of the CCID message now */
509 i2dw(a - 10, cmd + 1); /* command length (includes bPINOperation) */
510
511 old_read_timeout = ccid_descriptor -> readTimeout;
512 ccid_descriptor -> readTimeout = max(30, TxBuffer[0]); /* at least 30 seconds */
513
514 if (WritePort(reader_index, a, cmd) != STATUS_SUCCESS)
515 {
516 *RxLength = 0;
517 return IFD_COMMUNICATION_ERROR;
518 }
519
520 ret = CCID_Receive(reader_index, RxLength, RxBuffer, NULL);
521
522 /* T=1 Protocol Management for a TPDU reader */
523 if ((IFD_SUCCESS == ret)
524 && (SCARD_PROTOCOL_T1 == ccid_descriptor->cardProtocol)
525 && (CCID_CLASS_TPDU == (ccid_descriptor->dwFeatures & CCID_CLASS_EXCHANGE_MASK)))
526 {
527 /* timeout and cancel cases are faked by CCID_Receive() */
528 if (2 == *RxLength)
529 {
530 /* Decrement the sequence numbers since no TPDU was sent */
531 get_ccid_slot(reader_index)->t1.ns ^= 1;
532 get_ccid_slot(reader_index)->t1.nr ^= 1;
533 }
534 else
535 {
536 /* get only the T=1 data */
537 /* FIXME: manage T=1 error blocks */
538 memmove(RxBuffer, RxBuffer+3, *RxLength -4);
539 *RxLength -= 4; /* remove NAD, PCB, LEN and CRC */
540 }
541 }
542
543 ccid_descriptor -> readTimeout = old_read_timeout;
544 return ret;
545 } /* SecurePINModify */
546
547
548 /*****************************************************************************
549 *
550 * Escape
551 *
552 ****************************************************************************/
553 RESPONSECODE CmdEscape(unsigned int reader_index,
554 const unsigned char TxBuffer[], unsigned int TxLength,
555 unsigned char RxBuffer[], unsigned int *RxLength)
556 {
557 unsigned char *cmd_in, *cmd_out;
558 status_t res;
559 unsigned int length_in, length_out;
560 RESPONSECODE return_value = IFD_SUCCESS;
561 _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
562
563 again:
564 /* allocate buffers */
565 length_in = 10 + TxLength;
566 if (NULL == (cmd_in = malloc(length_in)))
567 return IFD_COMMUNICATION_ERROR;
568
569 length_out = 10 + *RxLength;
570 if (NULL == (cmd_out = malloc(length_out)))
571 {
572 free(cmd_in);
573 return IFD_COMMUNICATION_ERROR;
574 }
575
576 cmd_in[0] = 0x6B; /* PC_to_RDR_Escape */
577 i2dw(length_in - 10, cmd_in+1); /* dwLength */
578 cmd_in[5] = ccid_descriptor->bCurrentSlotIndex; /* slot number */
579 cmd_in[6] = (*ccid_descriptor->pbSeq)++;
580 cmd_in[7] = cmd_in[8] = cmd_in[9] = 0; /* RFU */
581
582 /* copy the command */
583 memcpy(&cmd_in[10], TxBuffer, TxLength);
584
585 res = WritePort(reader_index, length_in, cmd_in);
586 free(cmd_in);
587 if (res != STATUS_SUCCESS)
588 {
589 free(cmd_out);
590 return IFD_COMMUNICATION_ERROR;
591 }
592
593 res = ReadPort(reader_index, &length_out, cmd_out);
594
595 /* replay the command if NAK
596 * This (generally) happens only for the first command sent to the reader
597 * with the serial protocol so it is not really needed for all the other
598 * ReadPort() calls */
599 if (STATUS_COMM_NAK == res)
600 {
601 free(cmd_out);
602 goto again;
603 }
604
605 if (res != STATUS_SUCCESS)
606 {
607 free(cmd_out);
608 return IFD_COMMUNICATION_ERROR;
609 }
610
611 if (cmd_out[STATUS_OFFSET] & CCID_COMMAND_FAILED)
612 {
613 ccid_error(cmd_out[ERROR_OFFSET], __FILE__, __LINE__, __FUNCTION__); /* bError */
614 return_value = IFD_COMMUNICATION_ERROR;
615 }
616
617 /* copy the response */
618 length_out = dw2i(cmd_out, 1);
619 if (length_out > *RxLength)
620 length_out = *RxLength;
621 *RxLength = length_out;
622 memcpy(RxBuffer, &cmd_out[10], length_out);
623
624 free(cmd_out);
625
626 return return_value;
627 } /* Escape */
628
629
630 /*****************************************************************************
631 *
632 * CmdPowerOff
633 *
634 ****************************************************************************/
635 RESPONSECODE CmdPowerOff(unsigned int reader_index)
636 {
637 unsigned char cmd[10];
638 status_t res;
639 unsigned int length;
640 RESPONSECODE return_value = IFD_SUCCESS;
641 _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
642
643 cmd[0] = 0x63; /* IccPowerOff */
644 cmd[1] = cmd[2] = cmd[3] = cmd[4] = 0; /* dwLength */
645 cmd[5] = ccid_descriptor->bCurrentSlotIndex; /* slot number */
646 cmd[6] = (*ccid_descriptor->pbSeq)++;
647 cmd[7] = cmd[8] = cmd[9] = 0; /* RFU */
648
649 res = WritePort(reader_index, sizeof(cmd), cmd);
650 if (res != STATUS_SUCCESS)
651 return IFD_COMMUNICATION_ERROR;
652
653 length = sizeof(cmd);
654 res = ReadPort(reader_index, &length, cmd);
655 if (res != STATUS_SUCCESS)
656 return IFD_COMMUNICATION_ERROR;
657
658 if (cmd[STATUS_OFFSET] & CCID_COMMAND_FAILED)
659 {
660 ccid_error(cmd[ERROR_OFFSET], __FILE__, __LINE__, __FUNCTION__); /* bError */
661 return_value = IFD_COMMUNICATION_ERROR;
662 }
663
664 return return_value;
665 } /* CmdPowerOff */
666
667
668 /*****************************************************************************
669 *
670 * CmdGetSlotStatus
671 *
672 ****************************************************************************/
673 RESPONSECODE CmdGetSlotStatus(unsigned int reader_index, unsigned char buffer[])
674 {
675 unsigned char cmd[10];
676 status_t res;
677 unsigned int length;
678 RESPONSECODE return_value = IFD_SUCCESS;
679 _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
680
681 cmd[0] = 0x65; /* GetSlotStatus */
682 cmd[1] = cmd[2] = cmd[3] = cmd[4] = 0; /* dwLength */
683 cmd[5] = ccid_descriptor->bCurrentSlotIndex; /* slot number */
684 cmd[6] = (*ccid_descriptor->pbSeq)++;
685 cmd[7] = cmd[8] = cmd[9] = 0; /* RFU */
686
687 res = WritePort(reader_index, sizeof(cmd), cmd);
688 if (res != STATUS_SUCCESS)
689 return IFD_COMMUNICATION_ERROR;
690
691 length = SIZE_GET_SLOT_STATUS;
692 res = ReadPort(reader_index, &length, buffer);
693 if (res != STATUS_SUCCESS)
694 return IFD_COMMUNICATION_ERROR;
695
696 if (buffer[STATUS_OFFSET] & CCID_COMMAND_FAILED)
697 {
698 ccid_error(buffer[ERROR_OFFSET], __FILE__, __LINE__, __FUNCTION__); /* bError */
699
700 /* card absent or mute is not an communication error */
701 if (buffer[ERROR_OFFSET] != 0xFE)
702 return_value = IFD_COMMUNICATION_ERROR;
703 }
704
705 return return_value;
706 } /* CmdGetSlotStatus */
707
708
709 /*****************************************************************************
710 *
711 * CmdXfrBlock
712 *
713 ****************************************************************************/
714 RESPONSECODE CmdXfrBlock(unsigned int reader_index, unsigned int tx_length,
715 unsigned char tx_buffer[], unsigned int *rx_length,
716 unsigned char rx_buffer[], int protocol)
717 {
718 RESPONSECODE return_value = IFD_SUCCESS;
719 _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
720
721 /* APDU or TPDU? */
722 switch (ccid_descriptor->dwFeatures & CCID_CLASS_EXCHANGE_MASK)
723 {
724 case CCID_CLASS_TPDU:
725 if (protocol == T_0)
726 return_value = CmdXfrBlockTPDU_T0(reader_index,
727 tx_length, tx_buffer, rx_length, rx_buffer);
728 else
729 if (protocol == T_1)
730 return_value = CmdXfrBlockTPDU_T1(reader_index, tx_length,
731 tx_buffer, rx_length, rx_buffer);
732 else
733 return_value = IFD_PROTOCOL_NOT_SUPPORTED;
734 break;
735
736 case CCID_CLASS_SHORT_APDU:
737 return_value = CmdXfrBlockTPDU_T0(reader_index,
738 tx_length, tx_buffer, rx_length, rx_buffer);
739 break;
740
741 case CCID_CLASS_EXTENDED_APDU:
742 return_value = CmdXfrBlockAPDU_extended(reader_index,
743 tx_length, tx_buffer, rx_length, rx_buffer);
744 if (return_value != IFD_SUCCESS)
745 *rx_length = 0;
746 break;
747
748 case CCID_CLASS_CHARACTER:
749 if (protocol == T_0)
750 return_value = CmdXfrBlockCHAR_T0(reader_index, tx_length,
751 tx_buffer, rx_length, rx_buffer);
752 else
753 if (protocol == T_1)
754 return_value = CmdXfrBlockTPDU_T1(reader_index, tx_length,
755 tx_buffer, rx_length, rx_buffer);
756 else
757 return_value = IFD_PROTOCOL_NOT_SUPPORTED;
758 break;
759
760 default:
761 *rx_length = 0;
762 return_value = IFD_COMMUNICATION_ERROR;
763 }
764
765 return return_value;
766 } /* CmdXfrBlock */
767
768
769 /*****************************************************************************
770 *
771 * CCID_Transmit
772 *
773 ****************************************************************************/
774 RESPONSECODE CCID_Transmit(unsigned int reader_index, unsigned int tx_length,
775 const unsigned char tx_buffer[], unsigned short rx_length, unsigned char bBWI)
776 {
777 unsigned char cmd[10+CMD_BUF_SIZE]; /* CCID + APDU buffer */
778 _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
779
780 cmd[0] = 0x6F; /* XfrBlock */
781 i2dw(tx_length, cmd+1); /* APDU length */
782 cmd[5] = ccid_descriptor->bCurrentSlotIndex; /* slot number */
783 cmd[6] = (*ccid_descriptor->pbSeq)++;
784 cmd[7] = bBWI; /* extend block waiting timeout */
785 cmd[8] = rx_length & 0xFF; /* Expected length, in character mode only */
786 cmd[9] = (rx_length >> 8) & 0xFF;
787
788 /* check that the command is not too large */
789 if (tx_length > CMD_BUF_SIZE)
790 {
791 DEBUG_CRITICAL2("TX Length too big: %d", tx_length);
792 return IFD_NOT_SUPPORTED;
793 }
794
795 memcpy(cmd+10, tx_buffer, tx_length);
796
797 if (WritePort(reader_index, 10+tx_length, cmd) != STATUS_SUCCESS)
798 return IFD_COMMUNICATION_ERROR;
799
800 return IFD_SUCCESS;
801 } /* CCID_Transmit */
802
803
804 /*****************************************************************************
805 *
806 * CCID_Receive
807 *
808 ****************************************************************************/
809 RESPONSECODE CCID_Receive(unsigned int reader_index, unsigned int *rx_length,
810 unsigned char rx_buffer[], unsigned char *chain_parameter)
811 {
812 unsigned char cmd[10+CMD_BUF_SIZE]; /* CCID + APDU buffer */
813 unsigned int length;
814 RESPONSECODE return_value = IFD_SUCCESS;
815
816 time_request:
817 length = sizeof(cmd);
818 if (ReadPort(reader_index, &length, cmd) != STATUS_SUCCESS)
819 {
820 *rx_length = 0;
821 return IFD_COMMUNICATION_ERROR;
822 }
823
824 if (cmd[STATUS_OFFSET] & CCID_COMMAND_FAILED)
825 {
826 ccid_error(cmd[ERROR_OFFSET], __FILE__, __LINE__, __FUNCTION__); /* bError */
827 switch (cmd[ERROR_OFFSET])
828 {
829 case 0xEF: /* cancel */
830 if (*rx_length < 2)
831 return IFD_COMMUNICATION_ERROR;
832 rx_buffer[0]= 0x64;
833 rx_buffer[1]= 0x01;
834 *rx_length = 2;
835 return IFD_SUCCESS;
836
837 case 0xF0: /* timeout */
838 if (*rx_length < 2)
839 return IFD_COMMUNICATION_ERROR;
840 rx_buffer[0]= 0x64;
841 rx_buffer[1]= 0x00;
842 *rx_length = 2;
843 return IFD_SUCCESS;
844
845 case 0xFD: /* Parity error during exchange */
846 *rx_length = 0; /* nothing received */
847 return IFD_PARITY_ERROR;
848
849 default:
850 *rx_length = 0; /* nothing received */
851 return IFD_COMMUNICATION_ERROR;
852 }
853 }
854
855 if (cmd[STATUS_OFFSET] & CCID_TIME_EXTENSION)
856 {
857 DEBUG_COMM2("Time extension requested: 0x%02X", cmd[ERROR_OFFSET]);
858 goto time_request;
859 }
860
861 length = dw2i(cmd, 1);
862 if (length <= *rx_length)
863 *rx_length = length;
864 else
865 {
866 DEBUG_CRITICAL2("overrun by %d bytes", length - *rx_length);
867 length = *rx_length;
868 return_value = IFD_ERROR_INSUFFICIENT_BUFFER;
869 }
870 memcpy(rx_buffer, cmd+10, length);
871
872 /* Extended case?
873 * Only valid for RDR_to_PC_DataBlock frames */
874 if (chain_parameter)
875 *chain_parameter = cmd[CHAIN_PARAMETER_OFFSET];
876
877 return return_value;
878 } /* CCID_Receive */
879
880
881 /*****************************************************************************
882 *
883 * CmdXfrBlockAPDU_extended
884 *
885 ****************************************************************************/
886 static RESPONSECODE CmdXfrBlockAPDU_extended(unsigned int reader_index,
887 unsigned int tx_length, unsigned char tx_buffer[], unsigned int *rx_length,
888 unsigned char rx_buffer[])
889 {
890 RESPONSECODE return_value;
891 _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
892 unsigned char chain_parameter;
893 unsigned int local_tx_length, sent_length;
894 unsigned int local_rx_length, received_length;
895 int buffer_overflow = 0;
896
897 DEBUG_COMM2("T=0 (extended): %d bytes", tx_length);
898
899 /* send the APDU */
900 sent_length = 0;
901
902 /* we suppose one command is enough */
903 chain_parameter = 0x00;
904
905 local_tx_length = tx_length - sent_length;
906 if (local_tx_length > CMD_BUF_SIZE)
907 {
908 local_tx_length = CMD_BUF_SIZE;
909 /* the command APDU begins with this command, and continue in the next
910 * PC_to_RDR_XfrBlock */
911 chain_parameter = 0x01;
912 }
913 if (local_tx_length > ccid_descriptor->dwMaxCCIDMessageLength-10)
914 {
915 local_tx_length = ccid_descriptor->dwMaxCCIDMessageLength-10;
916 chain_parameter = 0x01;
917 }
918
919 send_next_block:
920 return_value = CCID_Transmit(reader_index, local_tx_length, tx_buffer,
921 chain_parameter, 0);
922 if (return_value != IFD_SUCCESS)
923 return return_value;
924
925 sent_length += local_tx_length;
926 tx_buffer += local_tx_length;
927
928 /* we just sent the last block (0x02) or only one block was needded (0x00) */
929 if ((0x02 == chain_parameter) || (0x00 == chain_parameter))
930 goto receive_block;
931
932 /* read a nul block */
933 return_value = CCID_Receive(reader_index, &local_rx_length, NULL, NULL);
934 if (return_value != IFD_SUCCESS)
935 return return_value;
936
937 /* size of the next block */
938 if (tx_length - sent_length > local_tx_length)
939 {
940 /* the abData field continues a command APDU and
941 * another block is to follow */
942 chain_parameter = 0x03;
943 }
944 else
945 {
946 /* this abData field continues a command APDU and ends
947 * the APDU command */
948 chain_parameter = 0x02;
949
950 /* last (smaller) block */
951 local_tx_length = tx_length - sent_length;
952 }
953
954 goto send_next_block;
955
956 receive_block:
957 /* receive the APDU */
958 received_length = 0;
959
960 receive_next_block:
961 local_rx_length = *rx_length - received_length;
962 return_value = CCID_Receive(reader_index, &local_rx_length, rx_buffer,
963 &chain_parameter);
964 if (IFD_ERROR_INSUFFICIENT_BUFFER == return_value)
965 {
966 buffer_overflow = 1;
967
968 /* we continue to read all the response APDU */
969 return_value = IFD_SUCCESS;
970 }
971
972 if (return_value != IFD_SUCCESS)
973 return return_value;
974
975 /* advance in the reiceiving buffer */
976 rx_buffer += local_rx_length;
977 received_length += local_rx_length;
978
979 switch (chain_parameter)
980 {
981 /* the response APDU begins and ends in this command */
982 case 0x00:
983 /* this abData field continues the response APDU and ends the response
984 * APDU */
985 case 0x02:
986 break;
987
988 /* the response APDU begins with this command and is to continue */
989 case 0x01:
990 /* this abData field continues the response APDU and another block is
991 * to follow */
992 case 0x03:
993 /* empty abData field, continuation of the command APDU is expected in
994 * next PC_to_RDR_XfrBlock command */
995 case 0x10:
996 /* send a nul block */
997 return_value = CCID_Transmit(reader_index, 0, NULL, 0, 0);
998 if (return_value != IFD_SUCCESS)
999 return return_value;
1000
1001 goto receive_next_block;
1002 }
1003
1004 *rx_length = received_length;
1005
1006 /* generate an overflow detected by pcscd */
1007 if (buffer_overflow)
1008 (*rx_length)++;
1009
1010 return IFD_SUCCESS;
1011 } /* CmdXfrBlockAPDU_extended */
1012
1013
1014 /*****************************************************************************
1015 *
1016 * CmdXfrBlockTPDU_T0
1017 *
1018 ****************************************************************************/
1019 static RESPONSECODE CmdXfrBlockTPDU_T0(unsigned int reader_index,
1020 unsigned int tx_length, unsigned char tx_buffer[], unsigned int *rx_length,
1021 unsigned char rx_buffer[])
1022 {
1023 RESPONSECODE return_value = IFD_SUCCESS;
1024 _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
1025
1026 DEBUG_COMM2("T=0: %d bytes", tx_length);
1027
1028 /* command length too big for CCID reader? */
1029 if (tx_length > ccid_descriptor->dwMaxCCIDMessageLength-10)
1030 {
1031 DEBUG_CRITICAL3("Command too long (%d bytes) for max: %d bytes",
1032 tx_length, ccid_descriptor->dwMaxCCIDMessageLength-10);
1033 return IFD_COMMUNICATION_ERROR;
1034 }
1035
1036 /* command length too big for CCID driver? */
1037 if (tx_length > CMD_BUF_SIZE)
1038 {
1039 DEBUG_CRITICAL3("Command too long (%d bytes) for max: %d bytes",
1040 tx_length, CMD_BUF_SIZE);
1041 return IFD_COMMUNICATION_ERROR;
1042 }
1043
1044 return_value = CCID_Transmit(reader_index, tx_length, tx_buffer, 0, 0);
1045 if (return_value != IFD_SUCCESS)
1046 return return_value;
1047
1048 return CCID_Receive(reader_index, rx_length, rx_buffer, NULL);
1049 } /* CmdXfrBlockTPDU_T0 */
1050
1051
1052 /*****************************************************************************
1053 *
1054 * T0CmdParsing
1055 *
1056 ****************************************************************************/
1057 static RESPONSECODE T0CmdParsing(unsigned char *cmd, unsigned int cmd_len,
1058 unsigned int *exp_len)
1059 {
1060 *exp_len = 0;
1061
1062 /* Ref: 7816-4 Annex A */
1063 switch (cmd_len)
1064 {
1065 case 4: /* Case 1 */
1066 *exp_len = 2; /* SW1 and SW2 only */
1067 break;
1068
1069 case 5: /* Case 2 */
1070 if (cmd[4] != 0)
1071 *exp_len = cmd[4] + 2;
1072 else
1073 *exp_len = 256 + 2;
1074 break;
1075
1076 default: /* Case 3 */
1077 if (cmd_len > 5 && cmd_len == (unsigned int)(cmd[4] + 5))
1078 *exp_len = 2; /* SW1 and SW2 only */
1079 else
1080 return IFD_COMMUNICATION_ERROR; /* situation not supported */
1081 break;
1082 }
1083
1084 return IFD_SUCCESS;
1085 } /* T0CmdParsing */
1086
1087
1088 /*****************************************************************************
1089 *
1090 * T0ProcACK
1091 *
1092 ****************************************************************************/
1093 static RESPONSECODE T0ProcACK(unsigned int reader_index,
1094 unsigned char **snd_buf, unsigned int *snd_len,
1095 unsigned char **rcv_buf, unsigned int *rcv_len,
1096 unsigned char **in_buf, unsigned int *in_len,
1097 unsigned int proc_len, int is_rcv)
1098 {
1099 RESPONSECODE return_value;
1100 unsigned int remain_len;
1101 unsigned char tmp_buf[512];
1102 unsigned int ret_len;
1103
1104 DEBUG_COMM2("Enter, is_rcv = %d", is_rcv);
1105
1106 if (is_rcv == 1)
1107 { /* Receiving mode */
1108 if (*in_len > 0)
1109 { /* There are still available data in our buffer */
1110 if (*in_len >= proc_len)
1111 {
1112 /* We only need to get the data from our buffer */
1113 memcpy(*rcv_buf, *in_buf, proc_len);
1114 *rcv_buf += proc_len;
1115 *in_buf += proc_len;
1116 *rcv_len += proc_len;
1117 *in_len -= proc_len;
1118
1119 return IFD_SUCCESS;
1120 }
1121 else
1122 {
1123 /* Move all data in the input buffer to the reply buffer */
1124 remain_len = proc_len - *in_len;
1125 memcpy(*rcv_buf, *in_buf, *in_len);
1126 *rcv_buf += *in_len;
1127 *in_buf += *in_len;
1128 *rcv_len += *in_len;
1129 *in_len = 0;
1130 }
1131 }
1132 else
1133 /* There is no data in our tmp_buf,
1134 * we have to read all data we needed */
1135 remain_len = proc_len;
1136
1137 /* Read the expected data from the smartcard */
1138 if (*in_len != 0)
1139 {
1140 DEBUG_CRITICAL("*in_len != 0");
1141 return IFD_COMMUNICATION_ERROR;
1142 }
1143
1144 memset(tmp_buf, 0, sizeof(tmp_buf));
1145
1146 ret_len = remain_len;
1147 return_value = CCID_Transmit(reader_index, 0, *snd_buf, ret_len, 0);
1148 if (return_value != IFD_SUCCESS)
1149 return return_value;
1150
1151 return_value = CCID_Receive(reader_index, &ret_len, tmp_buf, NULL);
1152 if (return_value != IFD_SUCCESS)
1153 return return_value;
1154
1155 memcpy(*rcv_buf, tmp_buf, remain_len);
1156 *rcv_buf += remain_len, *rcv_len += remain_len;
1157
1158 /* If ret_len != remain_len, our logic is erroneous */
1159 if (ret_len != remain_len)
1160 {
1161 DEBUG_CRITICAL("ret_len != remain_len");
1162 return IFD_COMMUNICATION_ERROR;
1163 }
1164 }
1165 else
1166 { /* Sending mode */
1167
1168 return_value = CCID_Transmit(reader_index, proc_len, *snd_buf, 1, 0);
1169 if (return_value != IFD_SUCCESS)
1170 return return_value;
1171
1172 *snd_len -= proc_len;
1173 *snd_buf += proc_len;
1174 }
1175
1176 DEBUG_COMM("Exit");
1177
1178 return IFD_SUCCESS;
1179 } /* T0ProcACK */
1180
1181
1182 /*****************************************************************************
1183 *
1184 * T0ProcSW1
1185 *
1186 ****************************************************************************/
1187 static RESPONSECODE T0ProcSW1(unsigned int reader_index,
1188 unsigned char *rcv_buf, unsigned int *rcv_len,
1189 unsigned char *in_buf, unsigned int in_len)
1190 {
1191 RESPONSECODE return_value = IFD_SUCCESS;
1192 UCHAR tmp_buf[512];
1193 unsigned char *rcv_buf_tmp = rcv_buf;
1194 const unsigned int rcv_len_tmp = *rcv_len;
1195 unsigned char sw1, sw2;
1196
1197 /* store the SW1 */
1198 sw1 = *rcv_buf = *in_buf;
1199 rcv_buf++;
1200 in_buf++;
1201 in_len--;
1202 (*rcv_len)++;
1203
1204 /* store the SW2 */
1205 if (0 == in_len)
1206 {
1207 return_value = CCID_Transmit(reader_index, 0, rcv_buf, 1, 0);
1208 if (return_value != IFD_SUCCESS)
1209 return return_value;
1210
1211 in_len = 1;
1212
1213 return_value = CCID_Receive(reader_index, &in_len, tmp_buf, NULL);
1214 if (return_value != IFD_SUCCESS)
1215 return return_value;
1216
1217 in_buf = tmp_buf;
1218 }
1219 sw2 = *rcv_buf = *in_buf;
1220 rcv_buf++;
1221 in_buf++;
1222 in_len--;
1223 (*rcv_len)++;
1224
1225 if (return_value != IFD_SUCCESS)
1226 {
1227 rcv_buf_tmp[0] = rcv_buf_tmp[1] = 0;
1228 *rcv_len = rcv_len_tmp;
1229 }
1230
1231 DEBUG_COMM3("Exit: SW=%02X %02X", sw1, sw2);
1232
1233 return return_value;
1234 } /* T0ProcSW1 */
1235
1236
1237 /*****************************************************************************
1238 *
1239 * CmdXfrBlockCHAR_T0
1240 *
1241 ****************************************************************************/
1242 static RESPONSECODE CmdXfrBlockCHAR_T0(unsigned int reader_index,
1243 unsigned int snd_len, unsigned char snd_buf[], unsigned int *rcv_len,
1244 unsigned char rcv_buf[])
1245 {
1246 int is_rcv;
1247 unsigned char cmd[5];
1248 unsigned char tmp_buf[512];
1249 unsigned int exp_len, in_len;
1250 unsigned char ins, *in_buf;
1251 RESPONSECODE return_value = IFD_SUCCESS;
1252
1253 DEBUG_COMM2("T=0: %d bytes", snd_len);
1254
1255 in_buf = tmp_buf;
1256 in_len = 0;
1257 *rcv_len = 0;
1258
1259 return_value = T0CmdParsing(snd_buf, snd_len, &exp_len);
1260 if (return_value != IFD_SUCCESS)
1261 {
1262 DEBUG_CRITICAL("T0CmdParsing failed");
1263 return IFD_COMMUNICATION_ERROR;
1264 }
1265
1266 if (snd_len == 5 || snd_len == 4)
1267 is_rcv = 1;
1268 else
1269 is_rcv = 0;
1270
1271 /* Command to send to the smart card (must be 5 bytes, from 7816 p.15) */
1272 memset(cmd, 0, sizeof(cmd));
1273 if (snd_len == 4)
1274 {
1275 memcpy(cmd, snd_buf, 4);
1276 snd_buf += 4;
1277 snd_len -= 4;
1278 }
1279 else
1280 {
1281 memcpy(cmd, snd_buf, 5);
1282 snd_buf += 5;
1283 snd_len -= 5;
1284 }
1285
1286 /* Make sure this is a valid command by checking the INS field */
1287 ins = cmd[1];
1288 if ((ins & 0xF0) == 0x60 || /* 7816-3 8.3.2 */
1289 (ins & 0xF0) == 0x90)
1290 {
1291 DEBUG_CRITICAL2("fatal: INS (0x%02X) = 0x6X or 0x9X", ins);
1292 return IFD_COMMUNICATION_ERROR;
1293 }
1294
1295 return_value = CCID_Transmit(reader_index, 5, cmd, 1, 0);
1296 if (return_value != IFD_SUCCESS)
1297 return return_value;
1298
1299 while (1)
1300 {
1301 if (in_len == 0)
1302 {
1303 in_len = 1;
1304 return_value = CCID_Receive(reader_index, &in_len, tmp_buf, NULL);
1305 if (return_value != IFD_SUCCESS)
1306 {
1307 DEBUG_CRITICAL("CCID_Receive failed");
1308 return return_value;
1309 }
1310 in_buf = tmp_buf;
1311 }
1312 if (in_len == 0)
1313 {
1314 /* Suppose we should be able to get data.
1315 * If not, error. Set the time-out error */
1316 DEBUG_CRITICAL("error: in_len = 0");
1317 return IFD_RESPONSE_TIMEOUT;
1318 }
1319
1320 /* Start to process the procedure bytes */
1321 if (*in_buf == 0x60)
1322 {
1323 in_len = 0;
1324 return_value = CCID_Transmit(reader_index, 0, cmd, 1, 0);
1325
1326 if (return_value != IFD_SUCCESS)
1327 return return_value;
1328
1329 continue;
1330 }
1331 else if (*in_buf == ins || *in_buf == (ins ^ 0x01))
1332 {
1333 /* ACK => To transfer all remaining data bytes */
1334 in_buf++, in_len--;
1335 if (is_rcv)
1336 return_value = T0ProcACK(reader_index, &snd_buf, &snd_len,
1337 &rcv_buf, rcv_len, &in_buf, &in_len, exp_len - *rcv_len, 1);
1338 else
1339 return_value = T0ProcACK(reader_index, &snd_buf, &snd_len,
1340 &rcv_buf, rcv_len, &in_buf, &in_len, snd_len, 0);
1341
1342 if (*rcv_len == exp_len)
1343 return return_value;
1344
1345 continue;
1346 }
1347 else if (*in_buf == (ins ^ 0xFF) || *in_buf == (ins ^ 0xFE))
1348 {
1349 /* ACK => To transfer 1 remaining bytes */
1350 in_buf++, in_len--;
1351 return_value = T0ProcACK(reader_index, &snd_buf, &snd_len,
1352 &rcv_buf, rcv_len, &in_buf, &in_len, 1, is_rcv);
1353
1354 if (return_value != IFD_SUCCESS)
1355 return return_value;
1356
1357 continue;
1358 }
1359 else if ((*in_buf & 0xF0) == 0x60 || (*in_buf & 0xF0) == 0x90)
1360 /* SW1 */
1361 return T0ProcSW1(reader_index, rcv_buf, rcv_len, in_buf, in_len);
1362
1363 /* Error, unrecognized situation found */
1364 DEBUG_CRITICAL2("Unrecognized Procedure byte (0x%02X) found!", *in_buf);
1365 return return_value;
1366 }
1367
1368 return return_value;
1369 } /* CmdXfrBlockCHAR_T0 */
1370
1371
1372 /*****************************************************************************
1373 *
1374 * CmdXfrBlockTPDU_T1
1375 *
1376 ****************************************************************************/
1377 static RESPONSECODE CmdXfrBlockTPDU_T1(unsigned int reader_index,
1378 unsigned int tx_length, unsigned char tx_buffer[], unsigned int *rx_length,
1379 unsigned char rx_buffer[])
1380 {
1381 RESPONSECODE return_value = IFD_SUCCESS;
1382 int ret;
1383
1384 DEBUG_COMM3("T=1: %d and %d bytes", tx_length, *rx_length);
1385
1386 ret = t1_transceive(&((get_ccid_slot(reader_index)) -> t1), 0,
1387 tx_buffer, tx_length, rx_buffer, *rx_length);
1388
1389 if (ret < 0)
1390 {
1391 *rx_length = 0;
1392 return_value = IFD_COMMUNICATION_ERROR;
1393 }
1394 else
1395 *rx_length = ret;
1396
1397 return return_value;
1398 } /* CmdXfrBlockTPDU_T1 */
1399
1400
1401 /*****************************************************************************
1402 *
1403 * SetParameters
1404 *
1405 ****************************************************************************/
1406 RESPONSECODE SetParameters(unsigned int reader_index, char protocol,
1407 unsigned int length, unsigned char buffer[])
1408 {
1409 unsigned char cmd[10+CMD_BUF_SIZE]; /* CCID + APDU buffer */
1410 _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
1411
1412 DEBUG_COMM2("length: %d bytes", length);
1413
1414 cmd[0] = 0x61; /* SetParameters */
1415 i2dw(length, cmd+1); /* APDU length */
1416 cmd[5] = ccid_descriptor->bCurrentSlotIndex; /* slot number */
1417 cmd[6] = (*ccid_descriptor->pbSeq)++;
1418 cmd[7] = protocol; /* bProtocolNum */
1419 cmd[8] = cmd[9] = 0; /* RFU */
1420
1421 /* check that the command is not too large */
1422 if (length > CMD_BUF_SIZE)
1423 return IFD_NOT_SUPPORTED;
1424
1425 memcpy(cmd+10, buffer, length);
1426
1427 if (WritePort(reader_index, 10+length, cmd) != STATUS_SUCCESS)
1428 return IFD_COMMUNICATION_ERROR;
1429
1430 length = sizeof(cmd);
1431 if (ReadPort(reader_index, &length, cmd) != STATUS_SUCCESS)
1432 return IFD_COMMUNICATION_ERROR;
1433
1434 if (cmd[STATUS_OFFSET] & CCID_COMMAND_FAILED)
1435 {
1436 ccid_error(cmd[ERROR_OFFSET], __FILE__, __LINE__, __FUNCTION__); /* bError */
1437 if (0x00 == cmd[ERROR_OFFSET]) /* command not supported */
1438 return IFD_NOT_SUPPORTED;
1439 else
1440 return IFD_COMMUNICATION_ERROR;
1441 }
1442
1443 return IFD_SUCCESS;
1444 } /* SetParameters */
1445
1446
1447 /*****************************************************************************
1448 *
1449 * isCharLevel
1450 *
1451 ****************************************************************************/
1452 int isCharLevel(int reader_index)
1453 {
1454 return CCID_CLASS_CHARACTER == (get_ccid_descriptor(reader_index)->dwFeatures & CCID_CLASS_EXCHANGE_MASK);
1455 } /* isCharLevel */
1456
1457
1458 /*****************************************************************************
1459 *
1460 * i2dw
1461 *
1462 ****************************************************************************/
1463 static void i2dw(int value, unsigned char buffer[])
1464 {
1465 buffer[0] = value & 0xFF;
1466 buffer[1] = (value >> 8) & 0xFF;
1467 buffer[2] = (value >> 16) & 0xFF;
1468 buffer[3] = (value >> 24) & 0xFF;
1469 } /* i2dw */
1470

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

  ViewVC Help
Powered by ViewVC 1.1.5