1 /* iso7816.c - ISO 7816 commands
2 * Copyright (C) 2003, 2004, 2008, 2009 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
6 * GnuPG is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * GnuPG 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
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
26 #if defined(GNUPG_SCD_MAIN_HEADER)
27 #include GNUPG_SCD_MAIN_HEADER
28 #elif GNUPG_MAJOR_VERSION == 1
29 /* This is used with GnuPG version < 1.9. The code has been source
30 copied from the current GnuPG >= 1.9 and is maintained over
37 #else /* GNUPG_MAJOR_VERSION != 1 */
39 #endif /* GNUPG_MAJOR_VERSION != 1 */
45 #define CMD_SELECT_FILE 0xA4
46 #define CMD_VERIFY ISO7816_VERIFY
47 #define CMD_CHANGE_REFERENCE_DATA ISO7816_CHANGE_REFERENCE_DATA
48 #define CMD_RESET_RETRY_COUNTER ISO7816_RESET_RETRY_COUNTER
49 #define CMD_GET_DATA 0xCA
50 #define CMD_PUT_DATA 0xDA
53 #define CMD_INTERNAL_AUTHENTICATE 0x88
54 #define CMD_GENERATE_KEYPAIR 0x47
55 #define CMD_GET_CHALLENGE 0x84
56 #define CMD_READ_BINARY 0xB0
57 #define CMD_READ_RECORD 0xB2
66 case SW_EEPROM_FAILURE
: ec
= GPG_ERR_HARDWARE
; break;
67 case SW_TERM_STATE
: ec
= GPG_ERR_CARD
; break;
68 case SW_WRONG_LENGTH
: ec
= GPG_ERR_INV_VALUE
; break;
69 case SW_SM_NOT_SUP
: ec
= GPG_ERR_NOT_SUPPORTED
; break;
70 case SW_CC_NOT_SUP
: ec
= GPG_ERR_NOT_SUPPORTED
; break;
71 case SW_CHV_WRONG
: ec
= GPG_ERR_BAD_PIN
; break;
72 case SW_CHV_BLOCKED
: ec
= GPG_ERR_PIN_BLOCKED
; break;
73 case SW_USE_CONDITIONS
: ec
= GPG_ERR_USE_CONDITIONS
; break;
74 case SW_NOT_SUPPORTED
: ec
= GPG_ERR_NOT_SUPPORTED
; break;
75 case SW_BAD_PARAMETER
: ec
= GPG_ERR_INV_VALUE
; break;
76 case SW_FILE_NOT_FOUND
: ec
= GPG_ERR_ENOENT
; break;
77 case SW_RECORD_NOT_FOUND
:ec
= GPG_ERR_NOT_FOUND
; break;
78 case SW_REF_NOT_FOUND
: ec
= GPG_ERR_NO_OBJ
; break;
79 case SW_BAD_P0_P1
: ec
= GPG_ERR_INV_VALUE
; break;
80 case SW_EXACT_LENGTH
: ec
= GPG_ERR_INV_VALUE
; break;
81 case SW_INS_NOT_SUP
: ec
= GPG_ERR_CARD
; break;
82 case SW_CLA_NOT_SUP
: ec
= GPG_ERR_CARD
; break;
83 case SW_SUCCESS
: ec
= 0; break;
85 case SW_HOST_OUT_OF_CORE
: ec
= GPG_ERR_ENOMEM
; break;
86 case SW_HOST_INV_VALUE
: ec
= GPG_ERR_INV_VALUE
; break;
87 case SW_HOST_INCOMPLETE_CARD_RESPONSE
: ec
= GPG_ERR_CARD
; break;
88 case SW_HOST_NOT_SUPPORTED
: ec
= GPG_ERR_NOT_SUPPORTED
; break;
89 case SW_HOST_LOCKING_FAILED
: ec
= GPG_ERR_BUG
; break;
90 case SW_HOST_BUSY
: ec
= GPG_ERR_EBUSY
; break;
91 case SW_HOST_NO_CARD
: ec
= GPG_ERR_CARD_NOT_PRESENT
; break;
92 case SW_HOST_CARD_INACTIVE
: ec
= GPG_ERR_CARD_RESET
; break;
93 case SW_HOST_CARD_IO_ERROR
: ec
= GPG_ERR_EIO
; break;
94 case SW_HOST_GENERAL_ERROR
: ec
= GPG_ERR_GENERAL
; break;
95 case SW_HOST_NO_READER
: ec
= GPG_ERR_ENODEV
; break;
96 case SW_HOST_ABORTED
: ec
= GPG_ERR_CANCELED
; break;
97 case SW_HOST_NO_KEYPAD
: ec
= GPG_ERR_NOT_SUPPORTED
; break;
101 ec
= GPG_ERR_GENERAL
; /* Should not happen. */
102 else if ((sw
& 0xff00) == SW_MORE_DATA
)
103 ec
= 0; /* This should actually never been seen here. */
107 return gpg_error (ec
);
110 /* Map a status word from the APDU layer to a gpg-error code. */
112 iso7816_map_sw (int sw
)
114 /* All APDU functions should return 0x9000 on success but for
115 historical reasons of the implementation some return 0 to
116 indicate success. We allow for that here. */
117 return sw
? map_sw (sw
) : 0;
121 /* This function is specialized version of the SELECT FILE command.
122 SLOT is the card and reader as created for example by
123 apdu_open_reader (), AID is a buffer of size AIDLEN holding the
124 requested application ID. The function can't be used to enumerate
125 AIDs and won't return the AID on success. The return value is 0
126 for okay or a GPG error code. Note that ISO error codes are
127 internally mapped. Bit 0 of FLAGS should be set if the card does
128 not understand P2=0xC0. */
130 iso7816_select_application (int slot
, const char *aid
, size_t aidlen
,
134 sw
= apdu_send_simple (slot
, 0, 0x00, CMD_SELECT_FILE
, 4,
135 (flags
&1)? 0 :0x0c, aidlen
, aid
);
141 iso7816_select_file (int slot
, int tag
, int is_dir
,
142 unsigned char **result
, size_t *resultlen
)
145 unsigned char tagbuf
[2];
147 tagbuf
[0] = (tag
>> 8) & 0xff;
148 tagbuf
[1] = tag
& 0xff;
150 if (result
|| resultlen
)
154 return gpg_error (GPG_ERR_NOT_IMPLEMENTED
);
158 p0
= (tag
== 0x3F00)? 0: is_dir
? 1:2;
159 p1
= 0x0c; /* No FC return. */
160 sw
= apdu_send_simple (slot
, 0, 0x00, CMD_SELECT_FILE
,
161 p0
, p1
, 2, (char*)tagbuf
);
169 /* Do a select file command with a direct path. */
171 iso7816_select_path (int slot
, const unsigned short *path
, size_t pathlen
,
172 unsigned char **result
, size_t *resultlen
)
175 unsigned char buffer
[100];
178 if (result
|| resultlen
)
182 return gpg_error (GPG_ERR_NOT_IMPLEMENTED
);
185 if (pathlen
/2 >= sizeof buffer
)
186 return gpg_error (GPG_ERR_TOO_LARGE
);
188 for (buflen
= 0; pathlen
; pathlen
--, path
++)
190 buffer
[buflen
++] = (*path
>> 8);
191 buffer
[buflen
++] = *path
;
195 p1
= 0x0c; /* No FC return. */
196 sw
= apdu_send_simple (slot
, 0, 0x00, CMD_SELECT_FILE
,
197 p0
, p1
, buflen
, (char*)buffer
);
202 /* This is a private command currently only working for TCOS cards. */
204 iso7816_list_directory (int slot
, int list_dirs
,
205 unsigned char **result
, size_t *resultlen
)
209 if (!result
|| !resultlen
)
210 return gpg_error (GPG_ERR_INV_VALUE
);
214 sw
= apdu_send (slot
, 0, 0x80, 0xAA, list_dirs
? 1:2, 0, -1, NULL
,
216 if (sw
!= SW_SUCCESS
)
218 /* Make sure that pending buffers are released. */
227 /* This funcion sends an already formatted APDU to the card. With
228 HANDLE_MORE set to true a MORE DATA status will be handled
229 internally. The return value is a gpg error code (i.e. a mapped
230 status word). This is basically the same as apdu_send_direct but
231 it maps the status word and does not return it in the result
234 iso7816_apdu_direct (int slot
, const void *apdudata
, size_t apdudatalen
,
236 unsigned char **result
, size_t *resultlen
)
240 if (!result
|| !resultlen
)
241 return gpg_error (GPG_ERR_INV_VALUE
);
245 sw
= apdu_send_direct (slot
, 0, apdudata
, apdudatalen
, handle_more
,
250 sw
= SW_HOST_GENERAL_ERROR
;
253 sw
= ((*result
)[*resultlen
-2] << 8) | (*result
)[*resultlen
-1];
258 if (sw
!= SW_SUCCESS
)
260 /* Make sure that pending buffers are released. */
269 /* Check whether the reader supports the ISO command code COMMAND on
270 the keypad. Returns 0 on success. */
272 iso7816_check_keypad (int slot
, int command
, iso7816_pininfo_t
*pininfo
)
276 sw
= apdu_check_keypad (slot
, command
,
277 pininfo
->mode
, pininfo
->minlen
, pininfo
->maxlen
,
279 return iso7816_map_sw (sw
);
283 /* Perform a VERIFY command on SLOT using the card holder verification
284 vector CHVNO with a CHV of lenght CHVLEN. With PININFO non-NULL
285 the keypad of the reader will be used. Returns 0 on success. */
287 iso7816_verify_kp (int slot
, int chvno
, const char *chv
, size_t chvlen
,
288 iso7816_pininfo_t
*pininfo
)
292 if (pininfo
&& pininfo
->mode
)
293 sw
= apdu_send_simple_kp (slot
, 0x00, CMD_VERIFY
, 0, chvno
, chvlen
, chv
,
299 sw
= apdu_send_simple (slot
, 0, 0x00, CMD_VERIFY
, 0, chvno
, chvlen
, chv
);
303 /* Perform a VERIFY command on SLOT using the card holder verification
304 vector CHVNO with a CHV of lenght CHVLEN. Returns 0 on success. */
306 iso7816_verify (int slot
, int chvno
, const char *chv
, size_t chvlen
)
308 return iso7816_verify_kp (slot
, chvno
, chv
, chvlen
, NULL
);
311 /* Perform a CHANGE_REFERENCE_DATA command on SLOT for the card holder
312 verification vector CHVNO. If the OLDCHV is NULL (and OLDCHVLEN
313 0), a "change reference data" is done, otherwise an "exchange
314 reference data". The new reference data is expected in NEWCHV of
315 length NEWCHVLEN. With PININFO non-NULL the keypad of the reader
318 iso7816_change_reference_data_kp (int slot
, int chvno
,
319 const char *oldchv
, size_t oldchvlen
,
320 const char *newchv
, size_t newchvlen
,
321 iso7816_pininfo_t
*pininfo
)
326 if ((!oldchv
&& oldchvlen
)
327 || (oldchv
&& !oldchvlen
)
328 || !newchv
|| !newchvlen
)
329 return gpg_error (GPG_ERR_INV_VALUE
);
331 buf
= xtrymalloc (oldchvlen
+ newchvlen
);
333 return gpg_error (gpg_err_code_from_errno (errno
));
335 memcpy (buf
, oldchv
, oldchvlen
);
336 memcpy (buf
+oldchvlen
, newchv
, newchvlen
);
338 if (pininfo
&& pininfo
->mode
)
339 sw
= apdu_send_simple_kp (slot
, 0x00, CMD_CHANGE_REFERENCE_DATA
,
340 oldchvlen
? 0 : 1, chvno
, oldchvlen
+newchvlen
, buf
,
346 sw
= apdu_send_simple (slot
, 0, 0x00, CMD_CHANGE_REFERENCE_DATA
,
347 oldchvlen
? 0 : 1, chvno
, oldchvlen
+newchvlen
, buf
);
353 /* Perform a CHANGE_REFERENCE_DATA command on SLOT for the card holder
354 verification vector CHVNO. If the OLDCHV is NULL (and OLDCHVLEN
355 0), a "change reference data" is done, otherwise an "exchange
356 reference data". The new reference data is expected in NEWCHV of
359 iso7816_change_reference_data (int slot
, int chvno
,
360 const char *oldchv
, size_t oldchvlen
,
361 const char *newchv
, size_t newchvlen
)
363 return iso7816_change_reference_data_kp (slot
, chvno
, oldchv
, oldchvlen
,
364 newchv
, newchvlen
, NULL
);
369 iso7816_reset_retry_counter_kp (int slot
, int chvno
,
370 const char *newchv
, size_t newchvlen
,
371 iso7816_pininfo_t
*pininfo
)
375 if (!newchv
|| !newchvlen
)
376 return gpg_error (GPG_ERR_INV_VALUE
);
378 /* FIXME: The keypad mode has not yet been tested. */
379 if (pininfo
&& pininfo
->mode
)
380 sw
= apdu_send_simple_kp (slot
, 0x00, CMD_RESET_RETRY_COUNTER
,
381 2, chvno
, newchvlen
, newchv
,
387 sw
= apdu_send_simple (slot
, 0, 0x00, CMD_RESET_RETRY_COUNTER
,
388 2, chvno
, newchvlen
, newchv
);
394 iso7816_reset_retry_counter_with_rc (int slot
, int chvno
,
395 const char *data
, size_t datalen
)
399 if (!data
|| !datalen
)
400 return gpg_error (GPG_ERR_INV_VALUE
);
402 sw
= apdu_send_simple (slot
, 0, 0x00, CMD_RESET_RETRY_COUNTER
,
403 0, chvno
, datalen
, data
);
409 iso7816_reset_retry_counter (int slot
, int chvno
,
410 const char *newchv
, size_t newchvlen
)
412 return iso7816_reset_retry_counter_kp (slot
, chvno
, newchv
, newchvlen
, NULL
);
417 /* Perform a GET DATA command requesting TAG and storing the result in
418 a newly allocated buffer at the address passed by RESULT. Return
419 the length of this data at the address of RESULTLEN. */
421 iso7816_get_data (int slot
, int extended_mode
, int tag
,
422 unsigned char **result
, size_t *resultlen
)
427 if (!result
|| !resultlen
)
428 return gpg_error (GPG_ERR_INV_VALUE
);
432 if (extended_mode
> 0 && extended_mode
< 256)
433 le
= 65534; /* Not 65535 in case it is used as some special flag. */
434 else if (extended_mode
> 0)
439 sw
= apdu_send_le (slot
, extended_mode
, 0x00, CMD_GET_DATA
,
440 ((tag
>> 8) & 0xff), (tag
& 0xff), -1, NULL
, le
,
442 if (sw
!= SW_SUCCESS
)
444 /* Make sure that pending buffers are released. */
455 /* Perform a PUT DATA command on card in SLOT. Write DATA of length
456 DATALEN to TAG. EXTENDED_MODE controls whether extended length
457 headers or command chaining is used instead of single length
460 iso7816_put_data (int slot
, int extended_mode
, int tag
,
461 const void *data
, size_t datalen
)
465 sw
= apdu_send_simple (slot
, extended_mode
, 0x00, CMD_PUT_DATA
,
466 ((tag
>> 8) & 0xff), (tag
& 0xff),
467 datalen
, (const char*)data
);
471 /* Same as iso7816_put_data but uses an odd instruction byte. */
473 iso7816_put_data_odd (int slot
, int extended_mode
, int tag
,
474 const void *data
, size_t datalen
)
478 sw
= apdu_send_simple (slot
, extended_mode
, 0x00, CMD_PUT_DATA
+1,
479 ((tag
>> 8) & 0xff), (tag
& 0xff),
480 datalen
, (const char*)data
);
484 /* Manage Security Environment. This is a weird operation and there
485 is no easy abstraction for it. Furthermore, some card seem to have
486 a different interpreation of 7816-8 and thus we resort to let the
487 caller decide what to do. */
489 iso7816_manage_security_env (int slot
, int p1
, int p2
,
490 const unsigned char *data
, size_t datalen
)
494 if (p1
< 0 || p1
> 255 || p2
< 0 || p2
> 255 )
495 return gpg_error (GPG_ERR_INV_VALUE
);
497 sw
= apdu_send_simple (slot
, 0, 0x00, CMD_MSE
, p1
, p2
,
498 data
? datalen
: -1, (const char*)data
);
503 /* Perform the security operation COMPUTE DIGITAL SIGANTURE. On
504 success 0 is returned and the data is availavle in a newly
505 allocated buffer stored at RESULT with its length stored at
506 RESULTLEN. For LE see do_generate_keypair. */
508 iso7816_compute_ds (int slot
, int extended_mode
,
509 const unsigned char *data
, size_t datalen
, int le
,
510 unsigned char **result
, size_t *resultlen
)
514 if (!data
|| !datalen
|| !result
|| !resultlen
)
515 return gpg_error (GPG_ERR_INV_VALUE
);
520 le
= 256; /* Ignore provided Le and use what apdu_send uses. */
521 else if (le
>= 0 && le
< 256)
524 sw
= apdu_send_le (slot
, extended_mode
,
525 0x00, CMD_PSO
, 0x9E, 0x9A,
526 datalen
, (const char*)data
,
529 if (sw
!= SW_SUCCESS
)
531 /* Make sure that pending buffers are released. */
542 /* Perform the security operation DECIPHER. PADIND is the padding
543 indicator to be used. It should be 0 if no padding is required, a
544 value of -1 suppresses the padding byte. On success 0 is returned
545 and the plaintext is available in a newly allocated buffer stored
546 at RESULT with its length stored at RESULTLEN. For LE see
547 do_generate_keypair. */
549 iso7816_decipher (int slot
, int extended_mode
,
550 const unsigned char *data
, size_t datalen
, int le
,
551 int padind
, unsigned char **result
, size_t *resultlen
)
556 if (!data
|| !datalen
|| !result
|| !resultlen
)
557 return gpg_error (GPG_ERR_INV_VALUE
);
562 le
= 256; /* Ignore provided Le and use what apdu_send uses. */
563 else if (le
>= 0 && le
< 256)
568 /* We need to prepend the padding indicator. */
569 buf
= xtrymalloc (datalen
+ 1);
571 return gpg_error (gpg_err_code_from_errno (errno
));
573 *buf
= padind
; /* Padding indicator. */
574 memcpy (buf
+1, data
, datalen
);
575 sw
= apdu_send_le (slot
, extended_mode
,
576 0x00, CMD_PSO
, 0x80, 0x86,
577 datalen
+1, (char*)buf
, le
,
583 sw
= apdu_send_le (slot
, extended_mode
,
584 0x00, CMD_PSO
, 0x80, 0x86,
585 datalen
, (const char *)data
, le
,
588 if (sw
!= SW_SUCCESS
)
590 /* Make sure that pending buffers are released. */
601 /* For LE see do_generate_keypair. */
603 iso7816_internal_authenticate (int slot
, int extended_mode
,
604 const unsigned char *data
, size_t datalen
,
606 unsigned char **result
, size_t *resultlen
)
610 if (!data
|| !datalen
|| !result
|| !resultlen
)
611 return gpg_error (GPG_ERR_INV_VALUE
);
616 le
= 256; /* Ignore provided Le and use what apdu_send uses. */
617 else if (le
>= 0 && le
< 256)
620 sw
= apdu_send_le (slot
, extended_mode
,
621 0x00, CMD_INTERNAL_AUTHENTICATE
, 0, 0,
622 datalen
, (const char*)data
,
625 if (sw
!= SW_SUCCESS
)
627 /* Make sure that pending buffers are released. */
638 /* LE is the expected return length. This is usually 0 except if
639 extended length mode is used and more than 256 byte will be
640 returned. In that case a value of -1 uses a large default
641 (e.g. 4096 bytes), a value larger 256 used that value. */
643 do_generate_keypair (int slot
, int extended_mode
, int readonly
,
644 const unsigned char *data
, size_t datalen
,
646 unsigned char **result
, size_t *resultlen
)
650 if (!data
|| !datalen
|| !result
|| !resultlen
)
651 return gpg_error (GPG_ERR_INV_VALUE
);
655 sw
= apdu_send_le (slot
, extended_mode
,
656 0x00, CMD_GENERATE_KEYPAIR
, readonly
? 0x81:0x80, 0,
657 datalen
, (const char*)data
,
658 le
>= 0 && le
< 256? 256:le
,
660 if (sw
!= SW_SUCCESS
)
662 /* Make sure that pending buffers are released. */
674 iso7816_generate_keypair (int slot
, int extended_mode
,
675 const unsigned char *data
, size_t datalen
,
677 unsigned char **result
, size_t *resultlen
)
679 return do_generate_keypair (slot
, extended_mode
, 0,
680 data
, datalen
, le
, result
, resultlen
);
685 iso7816_read_public_key (int slot
, int extended_mode
,
686 const unsigned char *data
, size_t datalen
,
688 unsigned char **result
, size_t *resultlen
)
690 return do_generate_keypair (slot
, extended_mode
, 1,
691 data
, datalen
, le
, result
, resultlen
);
697 iso7816_get_challenge (int slot
, int length
, unsigned char *buffer
)
700 unsigned char *result
;
703 if (!buffer
|| length
< 1)
704 return gpg_error (GPG_ERR_INV_VALUE
);
709 n
= length
> 254? 254 : length
;
710 sw
= apdu_send_le (slot
, 0,
711 0x00, CMD_GET_CHALLENGE
, 0, 0, -1, NULL
, n
,
712 &result
, &resultlen
);
713 if (sw
!= SW_SUCCESS
)
715 /* Make sure that pending buffers are released. */
721 memcpy (buffer
, result
, resultlen
);
731 /* Perform a READ BINARY command requesting a maximum of NMAX bytes
732 from OFFSET. With NMAX = 0 the entire file is read. The result is
733 stored in a newly allocated buffer at the address passed by RESULT.
734 Returns the length of this data at the address of RESULTLEN. */
736 iso7816_read_binary (int slot
, size_t offset
, size_t nmax
,
737 unsigned char **result
, size_t *resultlen
)
740 unsigned char *buffer
;
742 int read_all
= !nmax
;
745 if (!result
|| !resultlen
)
746 return gpg_error (GPG_ERR_INV_VALUE
);
750 /* We can only encode 15 bits in p0,p1 to indicate an offset. Thus
751 we check for this limit. */
753 return gpg_error (GPG_ERR_INV_VALUE
);
759 n
= read_all
? 0 : nmax
;
760 sw
= apdu_send_le (slot
, 0, 0x00, CMD_READ_BINARY
,
761 ((offset
>>8) & 0xff), (offset
& 0xff) , -1, NULL
,
762 n
, &buffer
, &bufferlen
);
763 if ( SW_EXACT_LENGTH_P(sw
) )
766 sw
= apdu_send_le (slot
, 0, 0x00, CMD_READ_BINARY
,
767 ((offset
>>8) & 0xff), (offset
& 0xff) , -1, NULL
,
768 n
, &buffer
, &bufferlen
);
771 if (*result
&& sw
== SW_BAD_P0_P1
)
773 /* Bad Parameter means that the offset is outside of the
774 EF. When reading all data we take this as an indication
779 if (sw
!= SW_SUCCESS
&& sw
!= SW_EOF_REACHED
)
781 /* Make sure that pending buffers are released. */
788 if (*result
) /* Need to extend the buffer. */
790 unsigned char *p
= xtryrealloc (*result
, *resultlen
+ bufferlen
);
793 gpg_error_t err
= gpg_error_from_syserror ();
801 memcpy (*result
+ *resultlen
, buffer
, bufferlen
);
802 *resultlen
+= bufferlen
;
806 else /* Transfer the buffer into our result. */
809 *resultlen
= bufferlen
;
813 break; /* We simply truncate the result for too large
815 if (nmax
> bufferlen
)
820 while ((read_all
&& sw
!= SW_EOF_REACHED
) || (!read_all
&& nmax
));
825 /* Perform a READ RECORD command. RECNO gives the record number to
826 read with 0 indicating the current record. RECCOUNT must be 1 (not
827 all cards support reading of more than one record). SHORT_EF
828 should be 0 to read the current EF or contain a short EF. The
829 result is stored in a newly allocated buffer at the address passed
830 by RESULT. Returns the length of this data at the address of
833 iso7816_read_record (int slot
, int recno
, int reccount
, int short_ef
,
834 unsigned char **result
, size_t *resultlen
)
837 unsigned char *buffer
;
840 if (!result
|| !resultlen
)
841 return gpg_error (GPG_ERR_INV_VALUE
);
845 /* We can only encode 15 bits in p0,p1 to indicate an offset. Thus
846 we check for this limit. */
847 if (recno
< 0 || recno
> 255 || reccount
!= 1
848 || short_ef
< 0 || short_ef
> 254 )
849 return gpg_error (GPG_ERR_INV_VALUE
);
853 sw
= apdu_send_le (slot
, 0, 0x00, CMD_READ_RECORD
,
855 short_ef
? short_ef
: 0x04,
857 0, &buffer
, &bufferlen
);
859 if (sw
!= SW_SUCCESS
&& sw
!= SW_EOF_REACHED
)
861 /* Make sure that pending buffers are released. */
869 *resultlen
= bufferlen
;