aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNIIBE Yutaka <[email protected]>2013-01-09 07:23:55 +0000
committerNIIBE Yutaka <[email protected]>2013-01-09 07:23:55 +0000
commit638b84f93b6325b3db016e7a0621554d6d8a1c7f (patch)
treee782c78941a10d1910f052437f71ea508d2a9689
parentSCD: API cleanup for keypad handling. (diff)
downloadgnupg-638b84f93b6325b3db016e7a0621554d6d8a1c7f.tar.gz
gnupg-638b84f93b6325b3db016e7a0621554d6d8a1c7f.zip
SCD: Support fixed length PIN input for keypad.
* scd/iso7816.h (struct pininfo_s): Remove MODE and add FIXEDLEN. * scd/app-dinsig.c (verify_pin): Initialize FIXEDLEN to unknown. * scd/app-nks.c (verify_pin): Likewise. * scd/app-openpgp.c (verify_a_chv, verify_chv3, do_change_pin): Likewise. * scd/apdu.c (check_pcsc_keypad): Add comment. (pcsc_keypad_verify, pcsc_keypad_modify): PC/SC driver only support readers with the feature of variable length input (yet). (apdu_check_keypad): Set FIXEDLEN. * scd/ccid-driver.c (ccid_transceive_secure): Add GEMPC_PINPAD specific settings. Support fixed length PIN input for keypad.
-rw-r--r--scd/apdu.c8
-rw-r--r--scd/app-dinsig.c2
-rw-r--r--scd/app-nks.c2
-rw-r--r--scd/app-openpgp.c6
-rw-r--r--scd/ccid-driver.c48
-rw-r--r--scd/iso7816.h7
6 files changed, 52 insertions, 21 deletions
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;
};