diff options
-rw-r--r-- | scd/apdu.c | 145 | ||||
-rw-r--r-- | scd/apdu.h | 9 | ||||
-rw-r--r-- | scd/app-dinsig.c | 4 | ||||
-rw-r--r-- | scd/app-nks.c | 6 | ||||
-rw-r--r-- | scd/app-openpgp.c | 122 | ||||
-rw-r--r-- | scd/app.c | 2 | ||||
-rw-r--r-- | scd/ccid-driver.c | 242 | ||||
-rw-r--r-- | scd/ccid-driver.h | 3 | ||||
-rw-r--r-- | scd/command.c | 1 | ||||
-rw-r--r-- | scd/iso7816.c | 18 | ||||
-rw-r--r-- | scd/iso7816.h | 19 | ||||
-rw-r--r-- | scd/sc-copykeys.c | 1 | ||||
-rw-r--r-- | scd/scdaemon.c | 6 | ||||
-rw-r--r-- | scd/scdaemon.h | 1 |
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) @@ -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 |