aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--scd/apdu.c145
-rw-r--r--scd/apdu.h9
-rw-r--r--scd/app-dinsig.c4
-rw-r--r--scd/app-nks.c6
-rw-r--r--scd/app-openpgp.c122
-rw-r--r--scd/app.c2
-rw-r--r--scd/ccid-driver.c242
-rw-r--r--scd/ccid-driver.h3
-rw-r--r--scd/command.c1
-rw-r--r--scd/iso7816.c18
-rw-r--r--scd/iso7816.h19
-rw-r--r--scd/sc-copykeys.c1
-rw-r--r--scd/scdaemon.c6
-rw-r--r--scd/scdaemon.h1
14 files changed, 335 insertions, 244 deletions
diff --git a/scd/apdu.c b/scd/apdu.c
index 278e08a36..f78463ae2 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_keypad)(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 (*keypad_verify)(int, int, int, int, int, pininfo_t *);
+ int (*keypad_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 check_pcsc_keypad (int slot, int command, pininfo_t *pininfo);
static int pcsc_keypad_verify (int slot, int class, int ins, int p0, int p1,
- struct pininfo_s *pininfo);
+ pininfo_t *pininfo);
static int pcsc_keypad_modify (int slot, int class, int ins, int p0, int p1,
- struct pininfo_s *pininfo);
+ pininfo_t *pininfo);
@@ -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];
@@ -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);
@@ -1992,17 +1980,13 @@ open_pcsc_reader (const char *portstr)
/* Check whether the reader supports the ISO command code COMMAND
on the keypad. 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_keypad (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)
@@ -2054,11 +2038,11 @@ 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)
+ 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 */
@@ -2104,7 +2085,7 @@ pcsc_keypad_verify (int slot, int class, int ins, int p0, int p1,
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[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",
@@ -2138,11 +2121,11 @@ 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)
+ 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);
@@ -2199,7 +2179,7 @@ pcsc_keypad_modify (int slot, int class, int ins, int p0, int p1,
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[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,
@@ -2350,22 +2328,19 @@ send_apdu_ccid (int slot, unsigned char *apdu, size_t apdulen,
on the keypad. 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_keypad (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)
+ 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;
@@ -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;
@@ -3422,12 +3395,14 @@ apdu_get_status (int slot, int hang,
the keypad. 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_keypad (int slot, int command, pininfo_t *pininfo)
{
if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used )
return SW_HOST_NO_DRIVER;
+ if (opt.enable_keypad_varlen)
+ pininfo->fixedlen = 0;
+
if (reader_table[slot].check_keypad)
{
int sw;
@@ -3435,9 +3410,7 @@ apdu_check_keypad (int slot, int command, int pin_mode,
if ((sw = lock_slot (slot)))
return sw;
- sw = reader_table[slot].check_keypad (slot, command,
- pin_mode, pinlen_min, pinlen_max,
- pin_padlen);
+ sw = reader_table[slot].check_keypad (slot, command, pininfo);
unlock_slot (slot);
return sw;
}
@@ -3447,16 +3420,9 @@ apdu_check_keypad (int slot, int command, int pin_mode,
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_keypad_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;
@@ -3468,7 +3434,7 @@ apdu_keypad_verify (int slot, int class, int ins, int p0, int p1, int pin_mode,
return sw;
sw = reader_table[slot].keypad_verify (slot, class, ins, p0, p1,
- &pininfo);
+ pininfo);
unlock_slot (slot);
return sw;
}
@@ -3478,16 +3444,9 @@ apdu_keypad_verify (int slot, int class, int ins, int p0, int p1, int pin_mode,
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_keypad_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;
@@ -3499,7 +3458,7 @@ apdu_keypad_modify (int slot, int class, int ins, int p0, int p1, int pin_mode,
return sw;
sw = reader_table[slot].keypad_modify (slot, class, ins, p0, p1,
- &pininfo);
+ pininfo);
unlock_slot (slot);
return sw;
}
@@ -3512,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;
@@ -3544,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. */
diff --git a/scd/apdu.h b/scd/apdu.h
index bf5534634..c69fe364e 100644
--- a/scd/apdu.h
+++ b/scd/apdu.h
@@ -114,14 +114,11 @@ int apdu_set_progress_cb (int slot, gcry_handler_progress_t cb, void *cb_arg);
int apdu_reset (int slot);
int apdu_get_status (int slot, int hang,
unsigned int *status, unsigned int *changed);
-int apdu_check_keypad (int slot, int command, int pin_mode,
- int pinlen_min, int pinlen_max, int pin_padlen);
+int apdu_check_keypad (int slot, int command, pininfo_t *pininfo);
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);
+ pininfo_t *pininfo);
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);
+ pininfo_t *pininfo);
int apdu_send_simple (int slot, int extended_mode,
int class, int ins, int p0, int p1,
int lc, const char *data);
diff --git a/scd/app-dinsig.c b/scd/app-dinsig.c
index 50db78e1f..9d4ebe247 100644
--- a/scd/app-dinsig.c
+++ b/scd/app-dinsig.c
@@ -282,13 +282,13 @@ verify_pin (app_t app,
{
const char *s;
int rc;
- iso7816_pininfo_t pininfo;
+ pininfo_t pininfo;
if ( app->did_chv1 && !app->force_chv1 )
return 0; /* No need to verify it again. */
memset (&pininfo, 0, sizeof pininfo);
- pininfo.mode = 1;
+ pininfo.fixedlen = -1;
pininfo.minlen = 6;
pininfo.maxlen = 8;
diff --git a/scd/app-nks.c b/scd/app-nks.c
index 28ccb9af7..8a48871ad 100644
--- a/scd/app-nks.c
+++ b/scd/app-nks.c
@@ -781,14 +781,14 @@ verify_pin (app_t app, int pwid, const char *desc,
gpg_error_t (*pincb)(void*, const char *, char **),
void *pincb_arg)
{
- iso7816_pininfo_t pininfo;
+ pininfo_t pininfo;
int rc;
if (!desc)
desc = "PIN";
memset (&pininfo, 0, sizeof pininfo);
- pininfo.mode = 1;
+ pininfo.fixedlen = -1;
pininfo.minlen = 6;
pininfo.maxlen = 16;
@@ -1144,7 +1144,7 @@ do_change_pin (app_t app, ctrl_t ctrl, const char *pwidstr,
int is_sigg;
const char *newdesc;
int pwid;
- iso7816_pininfo_t pininfo;
+ pininfo_t pininfo;
(void)ctrl;
diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c
index 5928ec620..9c85c61c9 100644
--- a/scd/app-openpgp.c
+++ b/scd/app-openpgp.c
@@ -1,6 +1,6 @@
/* app-openpgp.c - The OpenPGP card application.
* Copyright (C) 2003, 2004, 2005, 2007, 2008,
- * 2009 Free Software Foundation, Inc.
+ * 2009, 2013 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -191,6 +191,14 @@ struct app_local_s {
unsigned int def_chv2:1; /* Use 123456 for CHV2. */
} flags;
+ /* Keypad request specified on card. */
+ struct
+ {
+ unsigned int specified:1;
+ int fixedlen_user;
+ int fixedlen_admin;
+ } keypad;
+
struct
{
unsigned int n_bits; /* Size of the modulus in bits. The rest
@@ -581,17 +589,23 @@ count_bits (const unsigned char *a, size_t len)
Everything up to a LF is considered a mailbox or account name. If
the first LF is followed by DC4 (0x14) control sequence are
expected up to the next LF. Control sequences are separated by FS
- (0x18) and consist of key=value pairs. There is one key defined:
+ (0x18) and consist of key=value pairs. There are two keys defined:
F=<flags>
- Were FLAGS is a plain hexadecimal number representing flag values.
+ Where FLAGS is a plain hexadecimal number representing flag values.
The lsb is here the rightmost bit. Defined flags bits are:
Bit 0 = CHV1 and CHV2 are not syncronized
Bit 1 = CHV2 has been been set to the default PIN of "123456"
(this implies that bit 0 is also set).
+ P=<keypad-request>
+
+ Where KEYPAD_REQUEST is 0 or a pair of two integers: <n>,<m>.
+ 0 means use keypad with variable length input. <n>,<m> means use
+ keypad with fixed length input. N for user PIN, M for admin PIN.
+
*/
static void
parse_login_data (app_t app)
@@ -603,6 +617,9 @@ parse_login_data (app_t app)
/* Set defaults. */
app->app_local->flags.no_sync = 0;
app->app_local->flags.def_chv2 = 0;
+ app->app_local->keypad.specified = 0;
+ app->app_local->keypad.fixedlen_user = -1;
+ app->app_local->keypad.fixedlen_admin = -1;
/* Read the DO. */
relptr = get_one_do (app, 0x005E, &buffer, &buflen, NULL);
@@ -628,11 +645,56 @@ parse_login_data (app_t app)
any leading digits but bail out on invalid characters. */
for (p=buffer+2, len = buflen-2; len && hexdigitp (p); p++, len--)
lastdig = xtoi_1 (p);
+ buffer = p;
+ buflen = len;
if (len && !(*p == '\n' || *p == '\x18'))
goto next; /* Invalid characters in field. */
app->app_local->flags.no_sync = !!(lastdig & 1);
app->app_local->flags.def_chv2 = (lastdig & 3) == 3;
}
+ else if (buflen > 1 && *buffer == 'P' && buffer[1] == '=')
+ {
+ /* Keypad request control sequence found. */
+ buffer += 2;
+ buflen -= 2;
+
+ if (buflen)
+ {
+ if (*buffer == '0')
+ {
+ buffer++;
+ buflen--;
+ if (buflen && !(*buffer == '\n' || *buffer == '\x18'))
+ goto next;
+ /* Disable use of pinpad. */
+ app->app_local->keypad.specified = 1;
+ }
+ else if (digitp (buffer))
+ {
+ char *q;
+ int n, m;
+
+ n = strtol (buffer, &q, 10);
+ if (*q++ != ',' || !digitp (q))
+ goto next;
+ m = strtol (q, &q, 10);
+ buffer = q;
+ if (buflen < ((unsigned char *)q - buffer))
+ {
+ buflen = 0;
+ break;
+ }
+ else
+ buflen -= ((unsigned char *)q - buffer);
+
+ if (buflen && !(*buffer == '\n' || *buffer == '\x18'))
+ goto next;
+ app->app_local->keypad.specified = 1;
+ app->app_local->keypad.fixedlen_user = n;
+ app->app_local->keypad.fixedlen_admin = m;
+ }
+ }
+ }
next:
for (; buflen && *buffer != '\x18'; buflen--, buffer++)
if (*buffer == '\n')
@@ -1470,6 +1532,39 @@ do_readcert (app_t app, const char *certid,
}
+/* Decide if we use the keypad of the reader for PIN input according
+ to the user preference on the card, and the capability of the
+ reader. This routine is only called when the reader has keypad.
+ Returns 0 if we use keypad, 1 otherwise. */
+static int
+check_keypad_request (app_t app, pininfo_t *pininfo, int admin_pin)
+{
+ if (app->app_local->keypad.specified == 0) /* No preference on card. */
+ if (pininfo->fixedlen == 0) /* Reader has varlen capability. */
+ return 0; /* Then, use pinpad. */
+ else
+ /*
+ * Reader has limited capability, and it may not match PIN of
+ * the card.
+ */
+ return 1;
+
+ if (admin_pin)
+ pininfo->fixedlen = app->app_local->keypad.fixedlen_admin;
+ else
+ pininfo->fixedlen = app->app_local->keypad.fixedlen_user;
+
+ if (pininfo->fixedlen < 0 /* User requests disable pinpad. */
+ || pininfo->fixedlen < pininfo->minlen
+ || pininfo->fixedlen > pininfo->maxlen
+ /* Reader doesn't have the capability to input a PIN which
+ * length is FIXEDLEN. */)
+ return 1;
+
+ return 0;
+}
+
+
/* Verify a CHV either using using the pinentry or if possibile by
using a keypad. PINCB and PINCB_ARG describe the usual callback
for the pinentry. CHVNO must be either 1 or 2. SIGCOUNT is only
@@ -1489,7 +1584,7 @@ verify_a_chv (app_t app,
int rc = 0;
char *prompt_buffer = NULL;
const char *prompt;
- iso7816_pininfo_t pininfo;
+ pininfo_t pininfo;
int minlen = 6;
assert (chvno == 1 || chvno == 2);
@@ -1516,7 +1611,7 @@ verify_a_chv (app_t app,
}
memset (&pininfo, 0, sizeof pininfo);
- pininfo.mode = 1;
+ pininfo.fixedlen = -1;
pininfo.minlen = minlen;
@@ -1537,7 +1632,8 @@ verify_a_chv (app_t app,
if (!opt.disable_keypad
- && !iso7816_check_keypad (app->slot, ISO7816_VERIFY, &pininfo) )
+ && !iso7816_check_keypad (app->slot, ISO7816_VERIFY, &pininfo)
+ && !check_keypad_request (app, &pininfo, 0))
{
/* The reader supports the verify command through the keypad.
Note that the pincb appends a text to the prompt telling the
@@ -1707,12 +1803,12 @@ verify_chv3 (app_t app,
if (!app->did_chv3)
{
- iso7816_pininfo_t pininfo;
+ pininfo_t pininfo;
int minlen = 8;
char *prompt;
memset (&pininfo, 0, sizeof pininfo);
- pininfo.mode = 1;
+ pininfo.fixedlen = -1;
pininfo.minlen = minlen;
rc = build_enter_admin_pin_prompt (app, &prompt);
@@ -1720,7 +1816,8 @@ verify_chv3 (app_t app,
return rc;
if (!opt.disable_keypad
- && !iso7816_check_keypad (app->slot, ISO7816_VERIFY, &pininfo) )
+ && !iso7816_check_keypad (app->slot, ISO7816_VERIFY, &pininfo)
+ && !check_keypad_request (app, &pininfo, 1))
{
/* The reader supports the verify command through the keypad. */
rc = pincb (pincb_arg, prompt, NULL);
@@ -1917,13 +2014,13 @@ do_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr,
char *pinvalue = NULL;
int reset_mode = !!(flags & APP_CHANGE_FLAG_RESET);
int set_resetcode = 0;
- iso7816_pininfo_t pininfo;
+ pininfo_t pininfo;
int use_keypad = 0;
int minlen = 6;
(void)ctrl;
memset (&pininfo, 0, sizeof pininfo);
- pininfo.mode = 1;
+ pininfo.fixedlen = -1;
pininfo.minlen = minlen;
if (reset_mode && chvno == 3)
@@ -1970,7 +2067,8 @@ do_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr,
if (!opt.disable_keypad
&& !iso7816_check_keypad (app->slot,
- ISO7816_CHANGE_REFERENCE_DATA, &pininfo))
+ ISO7816_CHANGE_REFERENCE_DATA, &pininfo)
+ && !check_keypad_request (app, &pininfo, chvno == 3))
use_keypad = 1;
if (reset_mode)
diff --git a/scd/app.c b/scd/app.c
index dfb59913d..e6a663e1e 100644
--- a/scd/app.c
+++ b/scd/app.c
@@ -26,8 +26,8 @@
#include "scdaemon.h"
#include "app-common.h"
-#include "apdu.h"
#include "iso7816.h"
+#include "apdu.h"
#include "tlv.h"
/* This table is used to keep track of locks on a per reader base.
diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c
index 5b3bcaf9a..e9f39f48c 100644
--- a/scd/ccid-driver.c
+++ b/scd/ccid-driver.c
@@ -1,6 +1,6 @@
/* ccid-driver.c - USB ChipCardInterfaceDevices driver
* Copyright (C) 2003, 2004, 2005, 2006, 2007
- * 2008, 2009 Free Software Foundation, Inc.
+ * 2008, 2009, 2013 Free Software Foundation, Inc.
* Written by Werner Koch.
*
* This file is part of GnuPG.
@@ -89,6 +89,8 @@
#include <usb.h>
+#include "scdaemon.h"
+#include "iso7816.h"
#include "ccid-driver.h"
#define DRVNAME "ccid-driver: "
@@ -207,6 +209,7 @@ enum {
VENDOR_SCM = 0x04e6,
VENDOR_OMNIKEY= 0x076b,
VENDOR_GEMPC = 0x08e6,
+ VENDOR_VEGA = 0x0982,
VENDOR_KAAN = 0x0d46,
VENDOR_FSIJ = 0x234b,
VENDOR_VASCO = 0x1a44
@@ -220,6 +223,8 @@ enum {
#define SCM_SPR532 0xe003
#define CHERRY_ST2000 0x003e
#define VASCO_920 0x0920
+#define GEMPC_PINPAD 0x3478
+#define VEGA_ALPHA 0x0008
/* A list and a table with special transport descriptions. */
enum {
@@ -2379,7 +2384,7 @@ update_param_by_atr (unsigned char *param, unsigned char *atr, size_t atrlen)
NEXTBYTE ();
if (atr[i] == 0x3F)
- param[1] |= 0x02; /* Convention is inverse. */
+ param[1] |= 0x02; /* Convention is inverse. */
NEXTBYTE ();
y = (atr[i] >> 4);
@@ -2388,91 +2393,91 @@ update_param_by_atr (unsigned char *param, unsigned char *atr, size_t atrlen)
if ((y & 1))
{
- param[0] = atr[i]; /* TA1 - Fi & Di */
+ param[0] = atr[i]; /* TA1 - Fi & Di */
NEXTBYTE ();
}
if ((y & 2))
- NEXTBYTE (); /* TB1 - ignore */
+ NEXTBYTE (); /* TB1 - ignore */
if ((y & 4))
{
- param[2] = atr[i]; /* TC1 - Guard Time */
+ param[2] = atr[i]; /* TC1 - Guard Time */
NEXTBYTE ();
}
if ((y & 8))
{
- y = (atr[i] >> 4); /* TD1 */
+ y = (atr[i] >> 4); /* TD1 */
t = atr[i] & 0x0f;
NEXTBYTE ();
if ((y & 1))
- { /* TA2 - PPS mode */
- if ((atr[i] & 0x0f) != 1)
- return -2; /* Wrong card protocol (!= 1). */
+ { /* TA2 - PPS mode */
+ if ((atr[i] & 0x0f) != 1)
+ return -2; /* Wrong card protocol (!= 1). */
- if ((atr[i] & 0x10) != 0x10)
- return -3; /* Transmission parameters are implicitly defined. */
+ if ((atr[i] & 0x10) != 0x10)
+ return -3; /* Transmission parameters are implicitly defined. */
- negotiable = 0; /* TA2 means specific mode. */
- NEXTBYTE ();
- }
+ negotiable = 0; /* TA2 means specific mode. */
+ NEXTBYTE ();
+ }
if ((y & 2))
- NEXTBYTE (); /* TB2 - ignore */
+ NEXTBYTE (); /* TB2 - ignore */
if ((y & 4))
- NEXTBYTE (); /* TC2 - ignore */
+ NEXTBYTE (); /* TC2 - ignore */
if ((y & 8))
- {
- y = (atr[i] >> 4); /* TD2 */
- t = atr[i] & 0x0f;
- NEXTBYTE ();
- }
+ {
+ y = (atr[i] >> 4); /* TD2 */
+ t = atr[i] & 0x0f;
+ NEXTBYTE ();
+ }
else
- y = 0;
+ y = 0;
while (y)
- {
- if ((y & 1))
- { /* TAx */
- if (t == 1)
- param[5] = atr[i]; /* IFSC */
- else if (t == 15)
- /* XXX: check voltage? */
- param[4] = (atr[i] >> 6); /* ClockStop */
-
- NEXTBYTE ();
- }
-
- if ((y & 2))
- {
- if (t == 1)
- param[3] = atr[i]; /* TBx - BWI & CWI */
- NEXTBYTE ();
- }
-
- if ((y & 4))
- {
- if (t == 1)
- param[1] |= (atr[i] & 0x01); /* TCx - LRC/CRC */
- NEXTBYTE ();
-
- if (param[1] & 0x01)
- return -4; /* CRC not supported yet. */
- }
-
- if ((y & 8))
- {
- y = (atr[i] >> 4); /* TDx */
- t = atr[i] & 0x0f;
- NEXTBYTE ();
- }
- else
- y = 0;
- }
+ {
+ if ((y & 1))
+ { /* TAx */
+ if (t == 1)
+ param[5] = atr[i]; /* IFSC */
+ else if (t == 15)
+ /* XXX: check voltage? */
+ param[4] = (atr[i] >> 6); /* ClockStop */
+
+ NEXTBYTE ();
+ }
+
+ if ((y & 2))
+ {
+ if (t == 1)
+ param[3] = atr[i]; /* TBx - BWI & CWI */
+ NEXTBYTE ();
+ }
+
+ if ((y & 4))
+ {
+ if (t == 1)
+ param[1] |= (atr[i] & 0x01); /* TCx - LRC/CRC */
+ NEXTBYTE ();
+
+ if (param[1] & 0x01)
+ return -4; /* CRC not supported yet. */
+ }
+
+ if ((y & 8))
+ {
+ y = (atr[i] >> 4); /* TDx */
+ t = atr[i] & 0x0f;
+ NEXTBYTE ();
+ }
+ else
+ y = 0;
+ }
}
i += historical_bytes_num - 1;
@@ -2601,16 +2606,16 @@ ccid_get_atr (ccid_driver_t handle,
msglen = 10;
rc = bulk_out (handle, msg, msglen, 0);
if (!rc)
- rc = bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_Parameters,
- seqno, 2000, 0);
+ rc = bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_Parameters,
+ seqno, 2000, 0);
if (rc)
- DEBUGOUT ("GetParameters failed\n");
+ DEBUGOUT ("GetParameters failed\n");
else if (msglen == 17 && msg[9] == 1)
- got_param = 1;
+ got_param = 1;
}
else if (handle->auto_pps)
;
- else if (rc == 1) /* It's negotiable, send PPS. */
+ else if (rc == 1) /* It's negotiable, send PPS. */
{
msg[0] = PC_to_RDR_XfrBlock;
msg[5] = 0; /* slot */
@@ -2618,33 +2623,33 @@ ccid_get_atr (ccid_driver_t handle,
msg[7] = 0;
msg[8] = 0;
msg[9] = 0;
- msg[10] = 0xff; /* PPSS */
- msg[11] = 0x11; /* PPS0: PPS1, Protocol T=1 */
- msg[12] = param[0]; /* PPS1: Fi / Di */
+ msg[10] = 0xff; /* PPSS */
+ msg[11] = 0x11; /* PPS0: PPS1, Protocol T=1 */
+ msg[12] = param[0]; /* PPS1: Fi / Di */
msg[13] = 0xff ^ 0x11 ^ param[0]; /* PCK */
set_msg_len (msg, 4);
msglen = 10 + 4;
rc = bulk_out (handle, msg, msglen, 0);
if (rc)
- return rc;
+ return rc;
rc = bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_DataBlock,
- seqno, 5000, 0);
+ seqno, 5000, 0);
if (rc)
- return rc;
+ return rc;
if (msglen != 10 + 4)
- {
- DEBUGOUT_1 ("Setting PPS failed: %d\n", msglen);
- return CCID_DRIVER_ERR_CARD_IO_ERROR;
- }
+ {
+ DEBUGOUT_1 ("Setting PPS failed: %d\n", msglen);
+ return CCID_DRIVER_ERR_CARD_IO_ERROR;
+ }
if (msg[10] != 0xff || msg[11] != 0x11 || msg[12] != param[0])
- {
- DEBUGOUT_1 ("Setting PPS failed: 0x%02x\n", param[0]);
- return CCID_DRIVER_ERR_CARD_IO_ERROR;
- }
+ {
+ DEBUGOUT_1 ("Setting PPS failed: 0x%02x\n", param[0]);
+ return CCID_DRIVER_ERR_CARD_IO_ERROR;
+ }
}
/* Setup parameters to select T=1. */
@@ -3287,7 +3292,7 @@ ccid_transceive (ccid_driver_t handle,
The APDU should me made up of 4 bytes without Lc.
PINLEN_MIN and PINLEN_MAX define the limits for the pin length. 0
- may be used t enable reasonable defaults. PIN_PADLEN should be 0.
+ may be used t enable reasonable defaults.
When called with RESP and NRESP set to NULL, the function will
merely check whether the reader supports the secure command for the
@@ -3295,8 +3300,7 @@ ccid_transceive (ccid_driver_t handle,
int
ccid_transceive_secure (ccid_driver_t handle,
const unsigned char *apdu_buf, size_t apdu_buflen,
- int pin_mode, int pinlen_min, int pinlen_max,
- int pin_padlen,
+ pininfo_t *pininfo,
unsigned char *resp, size_t maxresplen, size_t *nresp)
{
int rc;
@@ -3307,6 +3311,7 @@ ccid_transceive_secure (ccid_driver_t handle,
size_t dummy_nresp;
int testmode;
int cherry_mode = 0;
+ int enable_varlen = 0;
testmode = !resp && !nresp;
@@ -3321,21 +3326,15 @@ ccid_transceive_secure (ccid_driver_t handle,
else
return CCID_DRIVER_ERR_NO_KEYPAD;
- if (pin_mode != 1)
- return CCID_DRIVER_ERR_NOT_SUPPORTED;
-
- if (pin_padlen != 0)
- return CCID_DRIVER_ERR_NOT_SUPPORTED;
-
- if (!pinlen_min)
- pinlen_min = 1;
- if (!pinlen_max)
- pinlen_max = 25;
+ if (!pininfo->minlen)
+ pininfo->minlen = 1;
+ if (!pininfo->maxlen)
+ pininfo->maxlen = 25;
/* Note that the 25 is the maximum value the SPR532 allows. */
- if (pinlen_min < 1 || pinlen_min > 25
- || pinlen_max < 1 || pinlen_max > 25
- || pinlen_min > pinlen_max)
+ if (pininfo->minlen < 1 || pininfo->minlen > 25
+ || pininfo->maxlen < 1 || pininfo->maxlen > 25
+ || pininfo->minlen > pininfo->maxlen)
return CCID_DRIVER_ERR_INV_VALUE;
/* We have only tested a few readers so better don't risk anything
@@ -3345,11 +3344,14 @@ ccid_transceive_secure (ccid_driver_t handle,
case VENDOR_SCM: /* Tested with SPR 532. */
case VENDOR_KAAN: /* Tested with KAAN Advanced (1.02). */
case VENDOR_FSIJ: /* Tested with the gnuk code (2011-01-05). */
+ enable_varlen = 1;
break;
case VENDOR_VASCO: /* Tested with DIGIPASS 920 */
- pinlen_max = 15;
+ enable_varlen = 1;
+ pininfo->maxlen = 15;
break;
case VENDOR_CHERRY:
+ enable_varlen = 1;
/* The CHERRY XX44 keyboard echos an asterisk for each entered
character on the keyboard channel. We use a special variant
of PC_to_RDR_Secure which directs these characters to the
@@ -3361,12 +3363,28 @@ ccid_transceive_secure (ccid_driver_t handle,
cherry_mode = 1;
break;
default:
+ if ((handle->id_vendor == VENDOR_GEMPC &&
+ handle->id_product == GEMPC_PINPAD)
+ || (handle->id_vendor == VENDOR_VEGA &&
+ handle->id_product == VEGA_ALPHA))
+ {
+ enable_varlen = 0;
+ pininfo->minlen = 4;
+ pininfo->maxlen = 8;
+ break;
+ }
return CCID_DRIVER_ERR_NOT_SUPPORTED;
}
+ if (enable_varlen)
+ pininfo->fixedlen = 0;
+
if (testmode)
return 0; /* Success */
+ if (pininfo->fixedlen < 0 || pininfo->fixedlen >= 16)
+ return CCID_DRIVER_ERR_NOT_SUPPORTED;
+
msg = send_buffer;
if (handle->id_vendor == VENDOR_SCM)
{
@@ -3396,9 +3414,9 @@ ccid_transceive_secure (ccid_driver_t handle,
}
else
{
- msg[13] = 0x00; /* bmPINBlockString:
- 0 bits of pin length to insert.
- 0 bytes of PIN block size. */
+ msg[13] = pininfo->fixedlen; /* bmPINBlockString:
+ 0 bits of pin length to insert.
+ PIN block size by fixedlen. */
msg[14] = 0x00; /* bmPINLengthFormat:
Units are bytes, position is 0. */
}
@@ -3407,12 +3425,12 @@ ccid_transceive_secure (ccid_driver_t handle,
if (apdu_buf[1] == 0x24)
{
msg[msglen++] = 0; /* bInsertionOffsetOld */
- msg[msglen++] = 0; /* bInsertionOffsetNew */
+ msg[msglen++] = pininfo->fixedlen; /* bInsertionOffsetNew */
}
/* The following is a little endian word. */
- msg[msglen++] = pinlen_max; /* wPINMaxExtraDigit-Maximum. */
- msg[msglen++] = pinlen_min; /* wPINMaxExtraDigit-Minimum. */
+ msg[msglen++] = pininfo->maxlen; /* wPINMaxExtraDigit-Maximum. */
+ msg[msglen++] = pininfo->minlen; /* wPINMaxExtraDigit-Minimum. */
if (apdu_buf[1] == 0x24)
msg[msglen++] = apdu_buf[2] == 0 ? 0x03 : 0x01;
@@ -3425,12 +3443,12 @@ ccid_transceive_secure (ccid_driver_t handle,
msg[msglen] = 0x02; /* bEntryValidationCondition:
Validation key pressed */
- if (pinlen_min && pinlen_max && pinlen_min == pinlen_max)
+ if (pininfo->minlen && pininfo->maxlen && pininfo->minlen == pininfo->maxlen)
msg[msglen] |= 0x01; /* Max size reached. */
msglen++;
if (apdu_buf[1] == 0x20)
- msg[msglen++] = 0xff; /* bNumberMessage: Default. */
+ msg[msglen++] = 0x01; /* bNumberMessage. */
else
msg[msglen++] = 0x03; /* bNumberMessage. */
@@ -3446,10 +3464,18 @@ ccid_transceive_secure (ccid_driver_t handle,
msg[msglen++] = 2; /* bMsgIndex3. */
}
+ /* Calculate Lc. */
+ n = pininfo->fixedlen;
+ if (apdu_buf[1] == 0x24)
+ n += pininfo->fixedlen;
+
/* bTeoProlog follows: */
msg[msglen++] = handle->nonnull_nad? ((1 << 4) | 0): 0;
msg[msglen++] = ((handle->t1_ns & 1) << 6); /* I-block */
- msg[msglen++] = 0; /* The apdulen will be filled in by the reader. */
+ if (n)
+ msg[msglen++] = n + 5; /* apdulen should be filled for fixed length. */
+ else
+ msg[msglen++] = 0; /* The apdulen will be filled in by the reader. */
/* APDU follows: */
msg[msglen++] = apdu_buf[0]; /* CLA */
msg[msglen++] = apdu_buf[1]; /* INS */
@@ -3457,6 +3483,12 @@ ccid_transceive_secure (ccid_driver_t handle,
msg[msglen++] = apdu_buf[3]; /* P2 */
if (cherry_mode)
msg[msglen++] = 0;
+ else if (pininfo->fixedlen != 0)
+ {
+ msg[msglen++] = n;
+ memset (&msg[msglen], 0xff, n);
+ msglen += n;
+ }
/* An EDC is not required. */
set_msg_len (msg, msglen - 10);
diff --git a/scd/ccid-driver.h b/scd/ccid-driver.h
index 121cb945b..217bb72d8 100644
--- a/scd/ccid-driver.h
+++ b/scd/ccid-driver.h
@@ -93,8 +93,7 @@ int ccid_transceive (ccid_driver_t handle,
unsigned char *resp, size_t maxresplen, size_t *nresp);
int ccid_transceive_secure (ccid_driver_t handle,
const unsigned char *apdu, size_t apdulen,
- int pin_mode,
- int pinlen_min, int pinlen_max, int pin_padlen,
+ pininfo_t *pininfo,
unsigned char *resp, size_t maxresplen, size_t *nresp);
int ccid_transceive_escape (ccid_driver_t handle,
const unsigned char *data, size_t datalen,
diff --git a/scd/command.c b/scd/command.c
index 40e61a48b..343830aac 100644
--- a/scd/command.c
+++ b/scd/command.c
@@ -34,6 +34,7 @@
#include <assuan.h>
#include <ksba.h>
#include "app-common.h"
+#include "iso7816.h"
#include "apdu.h" /* Required for apdu_*_reader (). */
#include "atr.h"
#include "exechelp.h"
diff --git a/scd/iso7816.c b/scd/iso7816.c
index 45f5e08bf..b2324b42d 100644
--- a/scd/iso7816.c
+++ b/scd/iso7816.c
@@ -269,13 +269,11 @@ iso7816_apdu_direct (int slot, const void *apdudata, size_t apdudatalen,
/* Check whether the reader supports the ISO command code COMMAND on
the keypad. Returns 0 on success. */
gpg_error_t
-iso7816_check_keypad (int slot, int command, iso7816_pininfo_t *pininfo)
+iso7816_check_keypad (int slot, int command, pininfo_t *pininfo)
{
int sw;
- sw = apdu_check_keypad (slot, command,
- pininfo->mode, pininfo->minlen, pininfo->maxlen,
- pininfo->padlen);
+ sw = apdu_check_keypad (slot, command, pininfo);
return iso7816_map_sw (sw);
}
@@ -284,13 +282,11 @@ iso7816_check_keypad (int slot, int command, iso7816_pininfo_t *pininfo)
vector CHVNO. With PININFO non-NULL the keypad of the reader will
be used. Returns 0 on success. */
gpg_error_t
-iso7816_verify_kp (int slot, int chvno, iso7816_pininfo_t *pininfo)
+iso7816_verify_kp (int slot, int chvno, pininfo_t *pininfo)
{
int sw;
- sw = apdu_keypad_verify (slot, 0x00, CMD_VERIFY, 0, chvno,
- pininfo->mode, pininfo->minlen, pininfo->maxlen,
- pininfo->padlen);
+ sw = apdu_keypad_verify (slot, 0x00, CMD_VERIFY, 0, chvno, pininfo);
return map_sw (sw);
}
@@ -311,14 +307,12 @@ iso7816_verify (int slot, int chvno, const char *chv, size_t chvlen)
data" is done, otherwise an "exchange reference data". */
gpg_error_t
iso7816_change_reference_data_kp (int slot, int chvno, int is_exchange,
- iso7816_pininfo_t *pininfo)
+ pininfo_t *pininfo)
{
int sw;
sw = apdu_keypad_modify (slot, 0x00, CMD_CHANGE_REFERENCE_DATA,
- is_exchange ? 1 : 0,
- chvno, pininfo->mode, pininfo->minlen,
- pininfo->maxlen, pininfo->padlen);
+ is_exchange ? 1 : 0, chvno, pininfo);
return map_sw (sw);
}
diff --git a/scd/iso7816.h b/scd/iso7816.h
index 336208aba..bf195ea00 100644
--- a/scd/iso7816.h
+++ b/scd/iso7816.h
@@ -32,15 +32,18 @@
/* Information to be passed to keypad equipped readers. See
ccid-driver.c for details. */
-struct iso7816_pininfo_s
+struct pininfo_s
{
- int mode; /* A mode of 0 means: Do not use the keypad. */
+ int fixedlen; /*
+ * -1: Variable length input is not supported,
+ * no information of fixed length yet.
+ * 0: Use variable length input.
+ * >0: Fixed length of PIN.
+ */
int minlen;
int maxlen;
- int padlen;
- int padchar;
};
-typedef struct iso7816_pininfo_s iso7816_pininfo_t;
+typedef struct pininfo_s pininfo_t;
gpg_error_t iso7816_map_sw (int sw);
@@ -60,16 +63,16 @@ gpg_error_t iso7816_apdu_direct (int slot,
int handle_more,
unsigned char **result, size_t *resultlen);
gpg_error_t iso7816_check_keypad (int slot, int command,
- iso7816_pininfo_t *pininfo);
+ pininfo_t *pininfo);
gpg_error_t iso7816_verify (int slot,
int chvno, const char *chv, size_t chvlen);
-gpg_error_t iso7816_verify_kp (int slot, int chvno, iso7816_pininfo_t *pininfo);
+gpg_error_t iso7816_verify_kp (int slot, int chvno, pininfo_t *pininfo);
gpg_error_t iso7816_change_reference_data (int slot, int chvno,
const char *oldchv, size_t oldchvlen,
const char *newchv, size_t newchvlen);
gpg_error_t iso7816_change_reference_data_kp (int slot, int chvno,
int is_exchange,
- iso7816_pininfo_t *pininfo);
+ pininfo_t *pininfo);
gpg_error_t iso7816_reset_retry_counter (int slot, int chvno,
const char *newchv, size_t newchvlen);
gpg_error_t iso7816_reset_retry_counter_with_rc (int slot, int chvno,
diff --git a/scd/sc-copykeys.c b/scd/sc-copykeys.c
index 3f34d6983..e503d3665 100644
--- a/scd/sc-copykeys.c
+++ b/scd/sc-copykeys.c
@@ -33,6 +33,7 @@
#include "../common/ttyio.h"
#include "../common/simple-pwquery.h"
+#include "iso7816.h"
#include "apdu.h" /* for open_reader */
#include "atr.h"
#include "app-common.h"
diff --git a/scd/scdaemon.c b/scd/scdaemon.c
index af4c9c1ce..f8a86c888 100644
--- a/scd/scdaemon.c
+++ b/scd/scdaemon.c
@@ -48,6 +48,7 @@
#include "i18n.h"
#include "sysutils.h"
#include "app-common.h"
+#include "iso7816.h"
#include "apdu.h"
#include "ccid-driver.h"
#include "mkdtemp.h"
@@ -95,6 +96,7 @@ enum cmd_and_opt_values
oAllowAdmin,
oDenyAdmin,
oDisableApplication,
+ oEnableKeypadVarlen,
oDebugDisableTicker
};
@@ -148,6 +150,8 @@ static ARGPARSE_OPTS opts[] = {
ARGPARSE_s_n (oDenyAdmin, "deny-admin",
N_("deny the use of admin card commands")),
ARGPARSE_s_s (oDisableApplication, "disable-application", "@"),
+ ARGPARSE_s_n (oEnableKeypadVarlen, "enable-keypad-varlen",
+ N_("use variable length input for keypad")),
ARGPARSE_end ()
};
@@ -587,6 +591,8 @@ main (int argc, char **argv )
add_to_strlist (&opt.disabled_applications, pargs.r.ret_str);
break;
+ case oEnableKeypadVarlen: opt.enable_keypad_varlen = 1; break;
+
default:
pargs.err = configfp? ARGPARSE_PRINT_WARNING:ARGPARSE_PRINT_ERROR;
break;
diff --git a/scd/scdaemon.h b/scd/scdaemon.h
index 74e8b7d44..8f048d5f3 100644
--- a/scd/scdaemon.h
+++ b/scd/scdaemon.h
@@ -57,6 +57,7 @@ struct
const char *reader_port; /* NULL or reder port to use. */
int disable_ccid; /* Disable the use of the internal CCID driver. */
int disable_keypad; /* Do not use a keypad. */
+ int enable_keypad_varlen; /* Use variable length input for keypad. */
int allow_admin; /* Allow the use of admin commands for certain
cards. */
strlist_t disabled_applications; /* Card applications we do not