aboutsummaryrefslogtreecommitdiffstats
path: root/scd/apdu.c
diff options
context:
space:
mode:
Diffstat (limited to 'scd/apdu.c')
-rw-r--r--scd/apdu.c230
1 files changed, 108 insertions, 122 deletions
diff --git a/scd/apdu.c b/scd/apdu.c
index 68d4e9970..6824ded55 100644
--- a/scd/apdu.c
+++ b/scd/apdu.c
@@ -60,10 +60,9 @@
#include "exechelp.h"
#endif /* GNUPG_MAJOR_VERSION != 1 */
+#include "iso7816.h"
#include "apdu.h"
#include "ccid-driver.h"
-#include "iso7816.h"
-
/* Due to conflicting use of threading libraries we usually can't link
against libpcsclite. Instead we use a wrapper program. */
@@ -83,16 +82,6 @@
#define DLSTDCALL
#endif
-
-/* Helper to pass parameters related to keypad based operations. */
-struct pininfo_s
-{
- int mode;
- int minlen;
- int maxlen;
- int padlen;
-};
-
/* A structure to collect information pertaining to one reader
slot. */
struct reader_table_s {
@@ -107,12 +96,12 @@ struct reader_table_s {
int (*reset_reader)(int);
int (*get_status_reader)(int, unsigned int *);
int (*send_apdu_reader)(int,unsigned char *,size_t,
- unsigned char *, size_t *, struct pininfo_s *);
- int (*check_keypad)(int, int, int, int, int, int);
+ unsigned char *, size_t *, pininfo_t *);
+ int (*check_pinpad)(int, int, pininfo_t *);
void (*dump_status_reader)(int);
int (*set_progress_cb)(int, gcry_handler_progress_t, void*);
- int (*keypad_verify)(int, int, int, int, int, struct pininfo_s *);
- int (*keypad_modify)(int, int, int, int, int, struct pininfo_s *);
+ int (*pinpad_verify)(int, int, int, int, int, pininfo_t *);
+ int (*pinpad_modify)(int, int, int, int, int, pininfo_t *);
struct {
ccid_driver_t handle;
@@ -330,12 +319,11 @@ static int reset_pcsc_reader (int slot);
static int apdu_get_status_internal (int slot, int hang, int no_atr_reset,
unsigned int *status,
unsigned int *changed);
-static int check_pcsc_keypad (int slot, int command, int pin_mode,
- int pinlen_min, int pinlen_max, int pin_padlen);
-static int pcsc_keypad_verify (int slot, int class, int ins, int p0, int p1,
- struct pininfo_s *pininfo);
-static int pcsc_keypad_modify (int slot, int class, int ins, int p0, int p1,
- struct pininfo_s *pininfo);
+static int check_pcsc_pinpad (int slot, int command, pininfo_t *pininfo);
+static int pcsc_pinpad_verify (int slot, int class, int ins, int p0, int p1,
+ pininfo_t *pininfo);
+static int pcsc_pinpad_modify (int slot, int class, int ins, int p0, int p1,
+ pininfo_t *pininfo);
@@ -381,11 +369,11 @@ new_reader_slot (void)
reader_table[reader].reset_reader = NULL;
reader_table[reader].get_status_reader = NULL;
reader_table[reader].send_apdu_reader = NULL;
- reader_table[reader].check_keypad = check_pcsc_keypad;
+ reader_table[reader].check_pinpad = check_pcsc_pinpad;
reader_table[reader].dump_status_reader = NULL;
reader_table[reader].set_progress_cb = NULL;
- reader_table[reader].keypad_verify = pcsc_keypad_verify;
- reader_table[reader].keypad_modify = pcsc_keypad_modify;
+ reader_table[reader].pinpad_verify = pcsc_pinpad_verify;
+ reader_table[reader].pinpad_modify = pcsc_pinpad_modify;
reader_table[reader].used = 1;
reader_table[reader].any_status = 0;
@@ -440,7 +428,7 @@ host_sw_string (long err)
case SW_HOST_GENERAL_ERROR: return "general error";
case SW_HOST_NO_READER: return "no reader";
case SW_HOST_ABORTED: return "aborted";
- case SW_HOST_NO_KEYPAD: return "no keypad";
+ case SW_HOST_NO_PINPAD: return "no pinpad";
case SW_HOST_ALREADY_CONNECTED: return "already connected";
default: return "unknown host status error";
}
@@ -608,7 +596,7 @@ ct_get_status (int slot, unsigned int *status)
set to BUFLEN. Returns: CT API error code. */
static int
ct_send_apdu (int slot, unsigned char *apdu, size_t apdulen,
- unsigned char *buffer, size_t *buflen, struct pininfo_s *pininfo)
+ unsigned char *buffer, size_t *buflen, pininfo_t *pininfo)
{
int rc;
unsigned char dad[1], sad[1];
@@ -673,10 +661,10 @@ open_ct_reader (int port)
reader_table[reader].reset_reader = reset_ct_reader;
reader_table[reader].get_status_reader = ct_get_status;
reader_table[reader].send_apdu_reader = ct_send_apdu;
- reader_table[reader].check_keypad = NULL;
+ reader_table[reader].check_pinpad = NULL;
reader_table[reader].dump_status_reader = ct_dump_reader_status;
- reader_table[reader].keypad_verify = NULL;
- reader_table[reader].keypad_modify = NULL;
+ reader_table[reader].pinpad_verify = NULL;
+ reader_table[reader].pinpad_modify = NULL;
dump_reader_status (reader);
return reader;
@@ -1039,7 +1027,7 @@ pcsc_get_status (int slot, unsigned int *status)
static int
pcsc_send_apdu_direct (int slot, unsigned char *apdu, size_t apdulen,
unsigned char *buffer, size_t *buflen,
- struct pininfo_s *pininfo)
+ pininfo_t *pininfo)
{
long err;
struct pcsc_io_request_s send_pci;
@@ -1075,7 +1063,7 @@ pcsc_send_apdu_direct (int slot, unsigned char *apdu, size_t apdulen,
static int
pcsc_send_apdu_wrapped (int slot, unsigned char *apdu, size_t apdulen,
unsigned char *buffer, size_t *buflen,
- struct pininfo_s *pininfo)
+ pininfo_t *pininfo)
{
long err;
reader_table_t slotp;
@@ -1195,7 +1183,7 @@ pcsc_send_apdu_wrapped (int slot, unsigned char *apdu, size_t apdulen,
static int
pcsc_send_apdu (int slot, unsigned char *apdu, size_t apdulen,
unsigned char *buffer, size_t *buflen,
- struct pininfo_s *pininfo)
+ pininfo_t *pininfo)
{
#ifdef NEED_PCSC_WRAPPER
return pcsc_send_apdu_wrapped (slot, apdu, apdulen, buffer, buflen, pininfo);
@@ -1990,19 +1978,15 @@ open_pcsc_reader (const char *portstr)
/* Check whether the reader supports the ISO command code COMMAND
- on the keypad. Return 0 on success. */
+ on the pinpad. Return 0 on success. */
static int
-check_pcsc_keypad (int slot, int command, int pin_mode,
- int pinlen_min, int pinlen_max, int pin_padlen)
+check_pcsc_pinpad (int slot, int command, pininfo_t *pininfo)
{
unsigned char buf[256];
size_t len = 256;
int sw;
- (void)pin_mode;
- (void)pinlen_min;
- (void)pinlen_max;
- (void)pin_padlen;
+ (void)pininfo; /* XXX: Identify reader and set pininfo->fixedlen. */
check_again:
if (command == ISO7816_VERIFY)
@@ -2053,12 +2037,12 @@ check_pcsc_keypad (int slot, int command, int pin_mode,
#define PIN_VERIFY_STRUCTURE_SIZE 24
static int
-pcsc_keypad_verify (int slot, int class, int ins, int p0, int p1,
- struct pininfo_s *pininfo)
+pcsc_pinpad_verify (int slot, int class, int ins, int p0, int p1,
+ pininfo_t *pininfo)
{
int sw;
unsigned char *pin_verify;
- int len = PIN_VERIFY_STRUCTURE_SIZE;
+ int len = PIN_VERIFY_STRUCTURE_SIZE + pininfo->fixedlen;
unsigned char result[2];
size_t resultlen = 2;
@@ -2066,10 +2050,7 @@ pcsc_keypad_verify (int slot, int class, int ins, int p0, int p1,
&& (sw = reset_pcsc_reader (slot)))
return sw;
- if (pininfo->mode != 1)
- return SW_NOT_SUPPORTED;
-
- if (pininfo->padlen != 0)
+ if (pininfo->fixedlen < 0 || pininfo->fixedlen >= 16)
return SW_NOT_SUPPORTED;
if (!pininfo->minlen)
@@ -2090,7 +2071,7 @@ pcsc_keypad_verify (int slot, int class, int ins, int p0, int p1,
pin_verify[0] = 0x00; /* bTimerOut */
pin_verify[1] = 0x00; /* bTimerOut2 */
pin_verify[2] = 0x82; /* bmFormatString: Byte, pos=0, left, ASCII. */
- pin_verify[3] = 0x00; /* bmPINBlockString */
+ pin_verify[3] = pininfo->fixedlen; /* bmPINBlockString */
pin_verify[4] = 0x00; /* bmPINLengthFormat */
pin_verify[5] = pininfo->maxlen; /* wPINMaxExtraDigit */
pin_verify[6] = pininfo->minlen; /* wPINMaxExtraDigit */
@@ -2103,8 +2084,8 @@ pcsc_keypad_verify (int slot, int class, int ins, int p0, int p1,
pin_verify[11] = 0x00; /* bMsgIndex */
pin_verify[12] = 0x00; /* bTeoPrologue[0] */
pin_verify[13] = 0x00; /* bTeoPrologue[1] */
- pin_verify[14] = 0x00; /* bTeoPrologue[2] */
- pin_verify[15] = 0x05; /* ulDataLength */
+ pin_verify[14] = pininfo->fixedlen + 0x05; /* bTeoPrologue[2] */
+ pin_verify[15] = pininfo->fixedlen + 0x05; /* ulDataLength */
pin_verify[16] = 0x00; /* ulDataLength */
pin_verify[17] = 0x00; /* ulDataLength */
pin_verify[18] = 0x00; /* ulDataLength */
@@ -2112,7 +2093,9 @@ pcsc_keypad_verify (int slot, int class, int ins, int p0, int p1,
pin_verify[20] = ins; /* abData[1] */
pin_verify[21] = p0; /* abData[2] */
pin_verify[22] = p1; /* abData[3] */
- pin_verify[23] = 0x00; /* abData[4] */
+ pin_verify[23] = pininfo->fixedlen; /* abData[4] */
+ if (pininfo->fixedlen)
+ memset (&pin_verify[24], 0xff, pininfo->fixedlen);
if (DBG_CARD_IO)
log_debug ("send secure: c=%02X i=%02X p1=%02X p2=%02X len=%d pinmax=%d\n",
@@ -2137,12 +2120,12 @@ pcsc_keypad_verify (int slot, int class, int ins, int p0, int p1,
#define PIN_MODIFY_STRUCTURE_SIZE 29
static int
-pcsc_keypad_modify (int slot, int class, int ins, int p0, int p1,
- struct pininfo_s *pininfo)
+pcsc_pinpad_modify (int slot, int class, int ins, int p0, int p1,
+ pininfo_t *pininfo)
{
int sw;
unsigned char *pin_modify;
- int len = PIN_MODIFY_STRUCTURE_SIZE;
+ int len = PIN_MODIFY_STRUCTURE_SIZE + 2 * pininfo->fixedlen;
unsigned char result[2];
size_t resultlen = 2;
@@ -2150,10 +2133,7 @@ pcsc_keypad_modify (int slot, int class, int ins, int p0, int p1,
&& (sw = reset_pcsc_reader (slot)))
return sw;
- if (pininfo->mode != 1)
- return SW_NOT_SUPPORTED;
-
- if (pininfo->padlen != 0)
+ if (pininfo->fixedlen < 0 || pininfo->fixedlen >= 16)
return SW_NOT_SUPPORTED;
if (!pininfo->minlen)
@@ -2174,10 +2154,10 @@ pcsc_keypad_modify (int slot, int class, int ins, int p0, int p1,
pin_modify[0] = 0x00; /* bTimerOut */
pin_modify[1] = 0x00; /* bTimerOut2 */
pin_modify[2] = 0x82; /* bmFormatString: Byte, pos=0, left, ASCII. */
- pin_modify[3] = 0x00; /* bmPINBlockString */
+ pin_modify[3] = pininfo->fixedlen; /* bmPINBlockString */
pin_modify[4] = 0x00; /* bmPINLengthFormat */
pin_modify[5] = 0x00; /* bInsertionOffsetOld */
- pin_modify[6] = 0x00; /* bInsertionOffsetNew */
+ pin_modify[6] = pininfo->fixedlen; /* bInsertionOffsetNew */
pin_modify[7] = pininfo->maxlen; /* wPINMaxExtraDigit */
pin_modify[8] = pininfo->minlen; /* wPINMaxExtraDigit */
pin_modify[9] = (p0 == 0 ? 0x03 : 0x01);
@@ -2198,8 +2178,8 @@ pcsc_keypad_modify (int slot, int class, int ins, int p0, int p1,
pin_modify[16] = 0x00; /* bMsgIndex3 */
pin_modify[17] = 0x00; /* bTeoPrologue[0] */
pin_modify[18] = 0x00; /* bTeoPrologue[1] */
- pin_modify[19] = 0x00; /* bTeoPrologue[2] */
- pin_modify[20] = 0x05; /* ulDataLength */
+ pin_modify[19] = 2 * pininfo->fixedlen + 0x05; /* bTeoPrologue[2] */
+ pin_modify[20] = 2 * pininfo->fixedlen + 0x05; /* ulDataLength */
pin_modify[21] = 0x00; /* ulDataLength */
pin_modify[22] = 0x00; /* ulDataLength */
pin_modify[23] = 0x00; /* ulDataLength */
@@ -2207,7 +2187,9 @@ pcsc_keypad_modify (int slot, int class, int ins, int p0, int p1,
pin_modify[25] = ins; /* abData[1] */
pin_modify[26] = p0; /* abData[2] */
pin_modify[27] = p1; /* abData[3] */
- pin_modify[28] = 0x00; /* abData[4] */
+ pin_modify[28] = 2 * pininfo->fixedlen; /* abData[4] */
+ if (pininfo->fixedlen)
+ memset (&pin_modify[29], 0xff, 2 * pininfo->fixedlen);
if (DBG_CARD_IO)
log_debug ("send secure: c=%02X i=%02X p1=%02X p2=%02X len=%d pinmax=%d\n",
@@ -2312,7 +2294,7 @@ get_status_ccid (int slot, unsigned int *status)
static int
send_apdu_ccid (int slot, unsigned char *apdu, size_t apdulen,
unsigned char *buffer, size_t *buflen,
- struct pininfo_s *pininfo)
+ pininfo_t *pininfo)
{
long err;
size_t maxbuflen;
@@ -2328,11 +2310,7 @@ send_apdu_ccid (int slot, unsigned char *apdu, size_t apdulen,
maxbuflen = *buflen;
if (pininfo)
err = ccid_transceive_secure (reader_table[slot].ccid.handle,
- apdu, apdulen,
- pininfo->mode,
- pininfo->minlen,
- pininfo->maxlen,
- pininfo->padlen,
+ apdu, apdulen, pininfo,
buffer, maxbuflen, buflen);
else
err = ccid_transceive (reader_table[slot].ccid.handle,
@@ -2347,25 +2325,22 @@ send_apdu_ccid (int slot, unsigned char *apdu, size_t apdulen,
/* Check whether the CCID reader supports the ISO command code COMMAND
- on the keypad. Return 0 on success. For a description of the pin
+ on the pinpad. Return 0 on success. For a description of the pin
parameters, see ccid-driver.c */
static int
-check_ccid_keypad (int slot, int command, int pin_mode,
- int pinlen_min, int pinlen_max, int pin_padlen)
+check_ccid_pinpad (int slot, int command, pininfo_t *pininfo)
{
unsigned char apdu[] = { 0, 0, 0, 0x81 };
apdu[1] = command;
- return ccid_transceive_secure (reader_table[slot].ccid.handle,
- apdu, sizeof apdu,
- pin_mode, pinlen_min, pinlen_max, pin_padlen,
- NULL, 0, NULL);
+ return ccid_transceive_secure (reader_table[slot].ccid.handle, apdu,
+ sizeof apdu, pininfo, NULL, 0, NULL);
}
static int
-ccid_keypad_operation (int slot, int class, int ins, int p0, int p1,
- struct pininfo_s *pininfo)
+ccid_pinpad_operation (int slot, int class, int ins, int p0, int p1,
+ pininfo_t *pininfo)
{
unsigned char apdu[4];
int err, sw;
@@ -2377,9 +2352,7 @@ ccid_keypad_operation (int slot, int class, int ins, int p0, int p1,
apdu[2] = p0;
apdu[3] = p1;
err = ccid_transceive_secure (reader_table[slot].ccid.handle,
- apdu, sizeof apdu,
- pininfo->mode, pininfo->minlen, pininfo->maxlen,
- pininfo->padlen,
+ apdu, sizeof apdu, pininfo,
result, 2, &resultlen);
if (err)
return err;
@@ -2433,11 +2406,11 @@ open_ccid_reader (const char *portstr)
reader_table[slot].reset_reader = reset_ccid_reader;
reader_table[slot].get_status_reader = get_status_ccid;
reader_table[slot].send_apdu_reader = send_apdu_ccid;
- reader_table[slot].check_keypad = check_ccid_keypad;
+ reader_table[slot].check_pinpad = check_ccid_pinpad;
reader_table[slot].dump_status_reader = dump_ccid_reader_status;
reader_table[slot].set_progress_cb = set_progress_cb_ccid_reader;
- reader_table[slot].keypad_verify = ccid_keypad_operation;
- reader_table[slot].keypad_modify = ccid_keypad_operation;
+ reader_table[slot].pinpad_verify = ccid_pinpad_operation;
+ reader_table[slot].pinpad_modify = ccid_pinpad_operation;
/* Our CCID reader code does not support T=0 at all, thus reset the
flag. */
reader_table[slot].is_t0 = 0;
@@ -2597,7 +2570,7 @@ my_rapdu_get_status (int slot, unsigned int *status)
static int
my_rapdu_send_apdu (int slot, unsigned char *apdu, size_t apdulen,
unsigned char *buffer, size_t *buflen,
- struct pininfo_s *pininfo)
+ pininfo_t *pininfo)
{
int err;
reader_table_t slotp;
@@ -2728,10 +2701,10 @@ open_rapdu_reader (int portno,
reader_table[slot].reset_reader = reset_rapdu_reader;
reader_table[slot].get_status_reader = my_rapdu_get_status;
reader_table[slot].send_apdu_reader = my_rapdu_send_apdu;
- reader_table[slot].check_keypad = NULL;
+ reader_table[slot].check_pinpad = NULL;
reader_table[slot].dump_status_reader = NULL;
- reader_table[slot].keypad_verify = NULL;
- reader_table[slot].keypad_modify = NULL;
+ reader_table[slot].pinpad_verify = NULL;
+ reader_table[slot].pinpad_modify = NULL;
dump_reader_status (slot);
rapdu_msg_release (msg);
@@ -3419,63 +3392,76 @@ apdu_get_status (int slot, int hang,
/* Check whether the reader supports the ISO command code COMMAND on
- the keypad. Return 0 on success. For a description of the pin
+ the pinpad. Return 0 on success. For a description of the pin
parameters, see ccid-driver.c */
int
-apdu_check_keypad (int slot, int command, int pin_mode,
- int pinlen_min, int pinlen_max, int pin_padlen)
+apdu_check_pinpad (int slot, int command, pininfo_t *pininfo)
{
if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used )
return SW_HOST_NO_DRIVER;
- if (reader_table[slot].check_keypad)
- return reader_table[slot].check_keypad (slot, command,
- pin_mode, pinlen_min, pinlen_max,
- pin_padlen);
+ if (opt.enable_pinpad_varlen)
+ pininfo->fixedlen = 0;
+
+ if (reader_table[slot].check_pinpad)
+ {
+ int sw;
+
+ if ((sw = lock_slot (slot)))
+ return sw;
+
+ sw = reader_table[slot].check_pinpad (slot, command, pininfo);
+ unlock_slot (slot);
+ return sw;
+ }
else
return SW_HOST_NOT_SUPPORTED;
}
int
-apdu_keypad_verify (int slot, int class, int ins, int p0, int p1, int pin_mode,
- int pinlen_min, int pinlen_max, int pin_padlen)
+apdu_pinpad_verify (int slot, int class, int ins, int p0, int p1,
+ pininfo_t *pininfo)
{
- struct pininfo_s pininfo;
-
- pininfo.mode = pin_mode;
- pininfo.minlen = pinlen_min;
- pininfo.maxlen = pinlen_max;
- pininfo.padlen = pin_padlen;
-
if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used )
return SW_HOST_NO_DRIVER;
- if (reader_table[slot].keypad_verify)
- return reader_table[slot].keypad_verify (slot, class, ins, p0, p1,
- &pininfo);
+ if (reader_table[slot].pinpad_verify)
+ {
+ int sw;
+
+ if ((sw = lock_slot (slot)))
+ return sw;
+
+ sw = reader_table[slot].pinpad_verify (slot, class, ins, p0, p1,
+ pininfo);
+ unlock_slot (slot);
+ return sw;
+ }
else
return SW_HOST_NOT_SUPPORTED;
}
int
-apdu_keypad_modify (int slot, int class, int ins, int p0, int p1, int pin_mode,
- int pinlen_min, int pinlen_max, int pin_padlen)
+apdu_pinpad_modify (int slot, int class, int ins, int p0, int p1,
+ pininfo_t *pininfo)
{
- struct pininfo_s pininfo;
-
- pininfo.mode = pin_mode;
- pininfo.minlen = pinlen_min;
- pininfo.maxlen = pinlen_max;
- pininfo.padlen = pin_padlen;
-
if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used )
return SW_HOST_NO_DRIVER;
- if (reader_table[slot].keypad_modify)
- return reader_table[slot].keypad_modify (slot, class, ins, p0, p1,
- &pininfo);
+ if (reader_table[slot].pinpad_modify)
+ {
+ int sw;
+
+ if ((sw = lock_slot (slot)))
+ return sw;
+
+ sw = reader_table[slot].pinpad_modify (slot, class, ins, p0, p1,
+ pininfo);
+ unlock_slot (slot);
+ return sw;
+ }
else
return SW_HOST_NOT_SUPPORTED;
}
@@ -3485,7 +3471,7 @@ apdu_keypad_modify (int slot, int class, int ins, int p0, int p1, int pin_mode,
function should be called in locked state. */
static int
send_apdu (int slot, unsigned char *apdu, size_t apdulen,
- unsigned char *buffer, size_t *buflen, struct pininfo_s *pininfo)
+ unsigned char *buffer, size_t *buflen, pininfo_t *pininfo)
{
if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used )
return SW_HOST_NO_DRIVER;
@@ -3501,7 +3487,7 @@ send_apdu (int slot, unsigned char *apdu, size_t apdulen,
/* Core APDU tranceiver function. Parameters are described at
- apdu_send_le with the exception of PININFO which indicates keypad
+ apdu_send_le with the exception of PININFO which indicates pinpad
related operations if not NULL. If EXTENDED_MODE is not 0
command chaining or extended length will be used according to these
values:
@@ -3517,7 +3503,7 @@ static int
send_le (int slot, int class, int ins, int p0, int p1,
int lc, const char *data, int le,
unsigned char **retbuf, size_t *retbuflen,
- struct pininfo_s *pininfo, int extended_mode)
+ pininfo_t *pininfo, int extended_mode)
{
#define SHORT_RESULT_BUFFER_SIZE 258
/* We allocate 8 extra bytes as a safety margin towards a driver bug. */