diff --git a/scd/apdu.c b/scd/apdu.c index 1e776df76..8c968b732 100644 --- a/scd/apdu.c +++ b/scd/apdu.c @@ -1986,7 +1986,7 @@ check_pcsc_keypad (int slot, int command, pininfo_t *pininfo) size_t len = 256; int sw; - (void)pininfo; + (void)pininfo; /* XXX: Identify reader and set pininfo->fixedlen. */ check_again: if (command == ISO7816_VERIFY) @@ -2050,7 +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) + if (pininfo->fixedlen != 0) return SW_NOT_SUPPORTED; if (!pininfo->minlen) @@ -2131,7 +2131,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) + if (pininfo->fixedlen != 0) return SW_NOT_SUPPORTED; if (!pininfo->minlen) @@ -3397,7 +3397,7 @@ apdu_check_keypad (int slot, int command, pininfo_t *pininfo) return SW_HOST_NO_DRIVER; if (opt.enable_keypad_varlen) - pininfo->mode = 0; + pininfo->fixedlen = 0; if (reader_table[slot].check_keypad) return reader_table[slot].check_keypad (slot, command, pininfo); diff --git a/scd/app-dinsig.c b/scd/app-dinsig.c index f3f7d4b9c..9d4ebe247 100644 --- a/scd/app-dinsig.c +++ b/scd/app-dinsig.c @@ -288,7 +288,7 @@ verify_pin (app_t app, 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 4e7a43c81..8a48871ad 100644 --- a/scd/app-nks.c +++ b/scd/app-nks.c @@ -788,7 +788,7 @@ verify_pin (app_t app, int pwid, const char *desc, desc = "PIN"; memset (&pininfo, 0, sizeof pininfo); - pininfo.mode = 1; + pininfo.fixedlen = -1; pininfo.minlen = 6; pininfo.maxlen = 16; diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index 968ef9816..dcc312044 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -1516,7 +1516,7 @@ verify_a_chv (app_t app, } memset (&pininfo, 0, sizeof pininfo); - pininfo.mode = 1; + pininfo.fixedlen = -1; pininfo.minlen = minlen; @@ -1712,7 +1712,7 @@ verify_chv3 (app_t app, char *prompt; memset (&pininfo, 0, sizeof pininfo); - pininfo.mode = 1; + pininfo.fixedlen = -1; pininfo.minlen = minlen; rc = build_enter_admin_pin_prompt (app, &prompt); @@ -1923,7 +1923,7 @@ do_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr, (void)ctrl; memset (&pininfo, 0, sizeof pininfo); - pininfo.mode = 1; + pininfo.fixedlen = -1; pininfo.minlen = minlen; if (reset_mode && chvno == 3) diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c index c16c7ac67..3244c71b1 100644 --- a/scd/ccid-driver.c +++ b/scd/ccid-driver.c @@ -3361,23 +3361,27 @@ ccid_transceive_secure (ccid_driver_t handle, cherry_mode = 1; break; case VENDOR_GEMPC: - enable_varlen = 0; if (handle->id_product == GEMPC_PINPAD) - break; + { + enable_varlen = 0; + pininfo->minlen = 4; + pininfo->maxlen = 8; + break; + } /* fall through */ default: return CCID_DRIVER_ERR_NOT_SUPPORTED; } if (enable_varlen) - pininfo->mode = 0; - - if (pininfo->mode != 0 && pininfo->mode != 1) - return CCID_DRIVER_ERR_NOT_SUPPORTED; + 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) { @@ -3407,9 +3411,14 @@ 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. */ + if (pininfo->fixedlen == 0) + msg[13] = 0x00; /* bmPINBlockString: + 0 bits of pin length to insert. + 0 bytes of PIN block size. */ + else + 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. */ } @@ -3418,7 +3427,10 @@ ccid_transceive_secure (ccid_driver_t handle, if (apdu_buf[1] == 0x24) { msg[msglen++] = 0; /* bInsertionOffsetOld */ - msg[msglen++] = 0; /* bInsertionOffsetNew */ + if (pininfo->fixedlen == 0) + msg[msglen++] = 0; /* bInsertionOffsetNew */ + else + msg[msglen++] = pininfo->fixedlen; /* bInsertionOffsetNew */ } /* The following is a little endian word. */ @@ -3457,10 +3469,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 */ @@ -3468,6 +3488,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/iso7816.h b/scd/iso7816.h index e6dfecd31..bf195ea00 100644 --- a/scd/iso7816.h +++ b/scd/iso7816.h @@ -34,7 +34,12 @@ ccid-driver.c for details. */ struct pininfo_s { - int mode; /* 0: Use variable length input. 1: Use fixed length input. */ + 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; };