[PATCH] pcsc pinpad support (part 3)
NIIBE Yutaka
gniibe at fsij.org
Fri Jan 14 02:55:27 CET 2011
Here is the part 3.
You can test the feature of pcsc pinpad suport with part 1, part 2 and
part 3.
Before this change, it is layered like following:
iso7816_verify
iso7816_verify_kp
apdu_send_simple, apdu_send_simple_kp
...
After this change, it will be layered like:
iso7816_verify iso7816_verify_kp
apdu_send_simple apdu_keypad_verify
...
and apdu_send_simple_kp will be deprecated.
For PC/SC API, we use SCardControl API to compose CCID
PC_to_RDR_Secure message and SCardTransmit API to compose CCID
PC_to_RDR_XfrBlock message.
Considering the support of PC/SC, we have nothing to share between _kp
version of iso7816_* and no _kp version. (This will be more clear
when we support change_reference_data.)
2011-01-14 NIIBE Yutaka <gniibe at fsij.org>
* apdu.h (apdu_keypad_verify): New.
* apdu.c (struct reader_table_s): Add keypad_verify.
(pcsc_keypad_verify): Rename from pcsc_pinpad_verify.
(ccid_keypad_verify): New.
(apdu_keypad_verify): New.
* iso7816.c (iso7816_verify_kp): Call apdu_keypad_verify. Only
handle the case with PININFO.
(iso7816_verify): Call apdu_send_simple.
* iso7816.h (iso7816_verify_kp): Remove argument of CHV and CHVLEN.
* app-openpgp.c (verify_a_chv, verify_chv3): Follow the change of
iso7816_verify_kp.
* app-dinsig.c (verify_pin): Likewise.
* app-nks.c (verify_pin): Likewise.
---
scd/apdu.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
scd/apdu.h | 3 ++
scd/app-dinsig.c | 2 +-
scd/app-nks.c | 2 +-
scd/app-openpgp.c | 4 +-
scd/iso7816.c | 23 ++++++++-----------
scd/iso7816.h | 4 +--
7 files changed, 77 insertions(+), 21 deletions(-)
diff --git a/scd/apdu.c b/scd/apdu.c
index bc75dc9..5b7f883 100644
--- a/scd/apdu.c
+++ b/scd/apdu.c
@@ -110,6 +110,7 @@ struct reader_table_s {
int (*check_keypad)(int, int, int, int, int, int);
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 *);
struct {
ccid_driver_t handle;
@@ -328,6 +329,8 @@ static int apdu_get_status_internal (int slot, int hang, int no_atr_reset,
unsigned int *changed);
static int check_pcsc_keypad (int slot, int command, int pin_mode,
int pinlen_min, int pinlen_max, int pin_padlen);
+static int pcsc_keypad_verify (int slot, int class, int ins, int p0, int p1,
+ struct pininfo_s *pininfo);
@@ -374,6 +377,7 @@ new_reader_slot (void)
reader_table[reader].check_keypad = check_pcsc_keypad;
reader_table[reader].dump_status_reader = NULL;
reader_table[reader].set_progress_cb = NULL;
+ reader_table[reader].keypad_verify = pcsc_keypad_verify;
reader_table[reader].used = 1;
reader_table[reader].any_status = 0;
@@ -660,6 +664,7 @@ open_ct_reader (int port)
reader_table[reader].send_apdu_reader = ct_send_apdu;
reader_table[reader].check_keypad = NULL;
reader_table[reader].dump_status_reader = ct_dump_reader_status;
+ reader_table[reader].keypad_verify = NULL;
dump_reader_status (reader);
return reader;
@@ -2029,7 +2034,7 @@ check_pcsc_keypad (int slot, int command, int pin_mode,
#define PIN_VERIFY_STRUCTURE_SIZE 23
static int
-pcsc_pinpad_verify (int slot, int class, int ins, int p0, int p1,
+pcsc_keypad_verify (int slot, int class, int ins, int p0, int p1,
struct pininfo_s *pininfo)
{
int sw;
@@ -2234,6 +2239,35 @@ check_ccid_keypad (int slot, int command, int pin_mode,
}
+static int
+ccid_keypad_verify (int slot, int class, int ins, int p0, int p1,
+ struct pininfo_s *pininfo)
+{
+ unsigned char apdu[4];
+ int err, sw;
+ unsigned char result[2];
+ size_t resultlen = 2;
+
+ apdu[0] = class;
+ apdu[1] = ins;
+ 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,
+ result, 2, &resultlen);
+ if (err)
+ return err;
+
+ if (resultlen < 2)
+ return SW_HOST_INCOMPLETE_CARD_RESPONSE;
+
+ sw = (result[resultlen-2] << 8) | result[resultlen-1];
+ return sw;
+}
+
+
/* Open the reader and try to read an ATR. */
static int
open_ccid_reader (const char *portstr)
@@ -2278,6 +2312,7 @@ open_ccid_reader (const char *portstr)
reader_table[slot].check_keypad = check_ccid_keypad;
reader_table[slot].dump_status_reader = dump_ccid_reader_status;
reader_table[slot].set_progress_cb = set_progress_cb_ccid_reader;
+ reader_table[slot].keypad_verify = ccid_keypad_verify;
/* Our CCID reader code does not support T=0 at all, thus reset the
flag. */
reader_table[slot].is_t0 = 0;
@@ -2570,6 +2605,7 @@ open_rapdu_reader (int portno,
reader_table[slot].send_apdu_reader = my_rapdu_send_apdu;
reader_table[slot].check_keypad = NULL;
reader_table[slot].dump_status_reader = NULL;
+ reader_table[slot].keypad_verify = NULL;
dump_reader_status (slot);
rapdu_msg_release (msg);
@@ -3165,6 +3201,28 @@ 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)
+{
+ struct pininfo_s pininfo;
+
+ pininfo.mode = pin_mode;
+ pininfo.minlen = pinlen_min;
+ pininfo.maxlen = pinlen_max;
+ pininfo.padlen = pin_padlen;
+
+ if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used )
+ return SW_HOST_NO_DRIVER;
+
+ if (reader_table[slot].keypad_verify)
+ return reader_table[slot].keypad_verify (slot, class, ins, p0, p1,
+ &pininfo);
+ else
+ return SW_HOST_NOT_SUPPORTED;
+}
+
+
/* Dispatcher for the actual send_apdu function. Note, that this
function should be called in locked state. */
static int
diff --git a/scd/apdu.h b/scd/apdu.h
index c47dea8..4d21fb8 100644
--- a/scd/apdu.h
+++ b/scd/apdu.h
@@ -114,6 +114,9 @@ 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_keypad_verify (int slot, int class, int ins, int p0, int p1,
+ int pin_mode, int pinlen_min, int pinlen_max,
+ int pin_padlen);
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 46e9a6a..34fbd13 100644
--- a/scd/app-dinsig.c
+++ b/scd/app-dinsig.c
@@ -304,7 +304,7 @@ verify_pin (app_t app,
gpg_strerror (rc));
return rc;
}
- rc = iso7816_verify_kp (app->slot, 0x81, "", 0, &pininfo);
+ rc = iso7816_verify_kp (app->slot, 0x81, &pininfo);
/* Dismiss the prompt. */
pincb (pincb_arg, NULL, NULL);
}
diff --git a/scd/app-nks.c b/scd/app-nks.c
index 076b913..27a6413 100644
--- a/scd/app-nks.c
+++ b/scd/app-nks.c
@@ -803,7 +803,7 @@ verify_pin (app_t app, int pwid, const char *desc,
return rc;
}
- rc = iso7816_verify_kp (app->slot, pwid, "", 0, &pininfo);
+ rc = iso7816_verify_kp (app->slot, pwid, &pininfo);
pincb (pincb_arg, NULL, NULL); /* Dismiss the prompt. */
}
else
diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c
index 029d99f..ac8eacb 100644
--- a/scd/app-openpgp.c
+++ b/scd/app-openpgp.c
@@ -1541,7 +1541,7 @@ verify_a_chv (app_t app,
gpg_strerror (rc));
return rc;
}
- rc = iso7816_verify_kp (app->slot, 0x80+chvno, "", 0, &pininfo);
+ rc = iso7816_verify_kp (app->slot, 0x80+chvno, &pininfo);
/* Dismiss the prompt. */
pincb (pincb_arg, NULL, NULL);
@@ -1721,7 +1721,7 @@ verify_chv3 (app_t app,
gpg_strerror (rc));
return rc;
}
- rc = iso7816_verify_kp (app->slot, 0x83, "", 0, &pininfo);
+ rc = iso7816_verify_kp (app->slot, 0x83, &pininfo);
/* Dismiss the prompt. */
pincb (pincb_arg, NULL, NULL);
}
diff --git a/scd/iso7816.c b/scd/iso7816.c
index b55da41..8490dad 100644
--- a/scd/iso7816.c
+++ b/scd/iso7816.c
@@ -281,22 +281,16 @@ iso7816_check_keypad (int slot, int command, iso7816_pininfo_t *pininfo)
/* Perform a VERIFY command on SLOT using the card holder verification
- vector CHVNO with a CHV of lenght CHVLEN. With PININFO non-NULL
- the keypad of the reader will be used. Returns 0 on success. */
+ 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, const char *chv, size_t chvlen,
- iso7816_pininfo_t *pininfo)
+iso7816_verify_kp (int slot, int chvno, iso7816_pininfo_t *pininfo)
{
int sw;
- if (pininfo && pininfo->mode)
- sw = apdu_send_simple_kp (slot, 0x00, CMD_VERIFY, 0, chvno, chvlen, chv,
- pininfo->mode,
- pininfo->minlen,
- pininfo->maxlen,
- pininfo->padlen);
- else
- sw = apdu_send_simple (slot, 0, 0x00, CMD_VERIFY, 0, chvno, chvlen, chv);
+ sw = apdu_keypad_verify (slot, 0x00, CMD_VERIFY, 0, chvno,
+ pininfo->mode, pininfo->minlen, pininfo->maxlen,
+ pininfo->padlen);
return map_sw (sw);
}
@@ -305,7 +299,10 @@ iso7816_verify_kp (int slot, int chvno, const char *chv, size_t chvlen,
gpg_error_t
iso7816_verify (int slot, int chvno, const char *chv, size_t chvlen)
{
- return iso7816_verify_kp (slot, chvno, chv, chvlen, NULL);
+ int sw;
+
+ sw = apdu_send_simple (slot, 0, 0x00, CMD_VERIFY, 0, chvno, chvlen, chv);
+ return map_sw (sw);
}
/* Perform a CHANGE_REFERENCE_DATA command on SLOT for the card holder
diff --git a/scd/iso7816.h b/scd/iso7816.h
index 8519712..6af4701 100644
--- a/scd/iso7816.h
+++ b/scd/iso7816.h
@@ -63,9 +63,7 @@ gpg_error_t iso7816_check_keypad (int slot, int command,
iso7816_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, const char *chv, size_t chvlen,
- iso7816_pininfo_t *pininfo);
+gpg_error_t iso7816_verify_kp (int slot, int chvno, iso7816_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);
--
1.7.2.3
More information about the Gnupg-devel
mailing list