aboutsummaryrefslogtreecommitdiffstats
path: root/scd
diff options
context:
space:
mode:
Diffstat (limited to 'scd')
-rw-r--r--scd/apdu.c42
-rw-r--r--scd/apdu.h1
-rw-r--r--scd/app-dinsig.c2
-rw-r--r--scd/app-geldkarte.c2
-rw-r--r--scd/app-openpgp.c28
-rw-r--r--scd/app.c2
-rw-r--r--scd/ccid-driver.c42
-rw-r--r--scd/ccid-driver.h6
-rw-r--r--scd/command.c28
-rw-r--r--scd/iso7816.c4
-rw-r--r--scd/scdaemon.c2
-rw-r--r--scd/scdaemon.h1
12 files changed, 142 insertions, 18 deletions
diff --git a/scd/apdu.c b/scd/apdu.c
index 66a16f820..f3e2a12e7 100644
--- a/scd/apdu.c
+++ b/scd/apdu.c
@@ -105,6 +105,7 @@ struct reader_table_s {
int (*check_pinpad)(int, int, pininfo_t *);
void (*dump_status_reader)(int);
int (*set_progress_cb)(int, gcry_handler_progress_t, void*);
+ int (*set_prompt_cb)(int, void (*) (void *, int), void*);
int (*pinpad_verify)(int, int, int, int, int, pininfo_t *);
int (*pinpad_modify)(int, int, int, int, int, pininfo_t *);
@@ -444,6 +445,7 @@ new_reader_slot (void)
reader_table[reader].check_pinpad = check_pcsc_pinpad;
reader_table[reader].dump_status_reader = NULL;
reader_table[reader].set_progress_cb = NULL;
+ reader_table[reader].set_prompt_cb = NULL;
reader_table[reader].pinpad_verify = pcsc_pinpad_verify;
reader_table[reader].pinpad_modify = pcsc_pinpad_modify;
@@ -965,7 +967,8 @@ pcsc_vendor_specific_init (int slot)
else if (strstr (reader_table[slot].rdrname, "cyberJack")
|| strstr (reader_table[slot].rdrname, "DIGIPASS")
|| strstr (reader_table[slot].rdrname, "Gnuk")
- || strstr (reader_table[slot].rdrname, "KAAN"))
+ || strstr (reader_table[slot].rdrname, "KAAN")
+ || strstr (reader_table[slot].rdrname, "Trustica"))
reader_table[slot].pinpad_varlen_supported = 1;
}
@@ -1039,7 +1042,8 @@ pcsc_vendor_specific_init (int slot)
else if (vendor == 0x0c4b /* Tested with Reiner cyberJack GO */
|| vendor == 0x1a44 /* Tested with Vasco DIGIPASS 920 */
|| vendor == 0x234b /* Tested with FSIJ Gnuk Token */
- || vendor == 0x0d46 /* Tested with KAAN Advanced??? */)
+ || vendor == 0x0d46 /* Tested with KAAN Advanced??? */
+ || (vendor == 0x1fc9 && product == 0x81e6) /* Tested with Trustica Cryptoucan */)
reader_table[slot].pinpad_varlen_supported = 1;
return 0;
@@ -1402,6 +1406,14 @@ set_progress_cb_ccid_reader (int slot, gcry_handler_progress_t cb, void *cb_arg)
return ccid_set_progress_cb (slotp->ccid.handle, cb, cb_arg);
}
+static int
+set_prompt_cb_ccid_reader (int slot, void (*cb) (void *, int ), void *cb_arg)
+{
+ reader_table_t slotp = reader_table + slot;
+
+ return ccid_set_prompt_cb (slotp->ccid.handle, cb, cb_arg);
+}
+
static int
get_status_ccid (int slot, unsigned int *status, int on_wire)
@@ -1541,6 +1553,7 @@ open_ccid_reader (struct dev_list *dl)
reader_table[slot].check_pinpad = check_ccid_pinpad;
reader_table[slot].dump_status_reader = dump_ccid_reader_status;
reader_table[slot].set_progress_cb = set_progress_cb_ccid_reader;
+ reader_table[slot].set_prompt_cb = set_prompt_cb_ccid_reader;
reader_table[slot].pinpad_verify = ccid_pinpad_operation;
reader_table[slot].pinpad_modify = ccid_pinpad_operation;
/* Our CCID reader code does not support T=0 at all, thus reset the
@@ -2380,6 +2393,29 @@ apdu_set_progress_cb (int slot, gcry_handler_progress_t cb, void *cb_arg)
}
+int
+apdu_set_prompt_cb (int slot, void (*cb) (void *, int), void *cb_arg)
+{
+ int sw;
+
+ if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used )
+ return SW_HOST_NO_DRIVER;
+
+ if (reader_table[slot].set_prompt_cb)
+ {
+ sw = lock_slot (slot);
+ if (!sw)
+ {
+ sw = reader_table[slot].set_prompt_cb (slot, cb, cb_arg);
+ unlock_slot (slot);
+ }
+ }
+ else
+ sw = 0;
+ return sw;
+}
+
+
/* Do a reset for the card in reader at SLOT. */
int
apdu_reset (int slot)
@@ -2610,7 +2646,7 @@ send_apdu (int slot, unsigned char *apdu, size_t apdulen,
}
-/* Core APDU tranceiver function. Parameters are described at
+/* Core APDU transceiver function. Parameters are described at
apdu_send_le with the exception of PININFO which indicates pinpad
related operations if not NULL. If EXTENDED_MODE is not 0
command chaining or extended length will be used according to these
diff --git a/scd/apdu.h b/scd/apdu.h
index 8a0d4bda8..8621ddc41 100644
--- a/scd/apdu.h
+++ b/scd/apdu.h
@@ -117,6 +117,7 @@ int apdu_connect (int slot);
int apdu_disconnect (int slot);
int apdu_set_progress_cb (int slot, gcry_handler_progress_t cb, void *cb_arg);
+int apdu_set_prompt_cb (int slot, void (*cb) (void *, int), void *cb_arg);
int apdu_reset (int slot);
int apdu_get_status (int slot, int hang, unsigned int *status);
diff --git a/scd/app-dinsig.c b/scd/app-dinsig.c
index bea285687..983bed6e1 100644
--- a/scd/app-dinsig.c
+++ b/scd/app-dinsig.c
@@ -415,7 +415,7 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
&& indatalen != (15+20) && indatalen != (19+32))
return gpg_error (GPG_ERR_INV_VALUE);
- /* Check that the provided ID is vaid. This is not really needed
+ /* Check that the provided ID is valid. This is not really needed
but we do it to enforce correct usage by the caller. */
if (strncmp (keyidstr, "DINSIG.", 7) )
return gpg_error (GPG_ERR_INV_ID);
diff --git a/scd/app-geldkarte.c b/scd/app-geldkarte.c
index 510beb550..85bcedc4f 100644
--- a/scd/app-geldkarte.c
+++ b/scd/app-geldkarte.c
@@ -254,7 +254,7 @@ copy_bcd (const unsigned char *string, size_t length)
}
-/* Convert the BCD number at STING of LENGTH into an integer and store
+/* Convert the BCD number at STRING of LENGTH into an integer and store
that at RESULT. Return 0 on success. */
static gpg_error_t
bcd_to_int (const unsigned char *string, size_t length, int *result)
diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c
index c17452555..789b72f00 100644
--- a/scd/app-openpgp.c
+++ b/scd/app-openpgp.c
@@ -119,8 +119,11 @@ static struct {
{ 0x0104, 0, 0, 0, 0, 0, 0, 2, "Private DO 4"},
{ 0x7F21, 1, 0, 1, 0, 0, 0, 1, "Cardholder certificate"},
/* V3.0 */
- { 0x7F74, 0, 0, 1, 0, 0, 0, 0, "General Feature Management"},
+ { 0x7F74, 0, 0x6E, 1, 0, 0, 0, 0, "General Feature Management"},
{ 0x00D5, 0, 0, 1, 0, 0, 0, 0, "AES key data"},
+ { 0x00D6, 0, 0x6E, 1, 0, 0, 0, 0, "UIF for Signature"},
+ { 0x00D7, 0, 0x6E, 1, 0, 0, 0, 0, "UIF for decryption"},
+ { 0x00D8, 0, 0x6E, 1, 0, 0, 0, 0, "UIF for authentication"},
{ 0x00F9, 0, 0, 1, 0, 0, 0, 0, "KDF data object"},
{ 0 }
};
@@ -640,7 +643,7 @@ count_bits (const unsigned char *a, size_t len)
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 0 = CHV1 and CHV2 are not synchronized
Bit 1 = CHV2 has been set to the default PIN of "123456"
(this implies that bit 0 is also set).
@@ -985,6 +988,9 @@ do_getattr (app_t app, ctrl_t ctrl, const char *name)
{ "PRIVATE-DO-4", 0x0104 },
{ "$AUTHKEYID", 0x0000, -3 },
{ "$DISPSERIALNO",0x0000, -4 },
+ { "UIF-1", 0x00D6, 0 },
+ { "UIF-2", 0x00D7, 0 },
+ { "UIF-3", 0x00D8, 0 },
{ "KDF", 0x00F9 },
{ NULL, 0 }
};
@@ -1827,6 +1833,9 @@ do_learn_status (app_t app, ctrl_t ctrl, unsigned int flags)
do_getattr (app, ctrl, "CA-FPR");
do_getattr (app, ctrl, "CHV-STATUS");
do_getattr (app, ctrl, "SIG-COUNTER");
+ do_getattr (app, ctrl, "UIF-1");
+ do_getattr (app, ctrl, "UIF-2");
+ do_getattr (app, ctrl, "UIF-3");
if (app->app_local->extcap.private_dos)
{
do_getattr (app, ctrl, "PRIVATE-DO-1");
@@ -2459,6 +2468,9 @@ do_setattr (app_t app, const char *name,
{ "SM-KEY-MAC", 0x00D2, 3, 0, 1 },
{ "KEY-ATTR", 0, 0, 3, 1 },
{ "AESKEY", 0x00D5, 3, 0, 1 },
+ { "UIF-1", 0x00D6, 3, 5, 1 },
+ { "UIF-2", 0x00D7, 3, 5, 1 },
+ { "UIF-3", 0x00D8, 3, 5, 1 },
{ "KDF", 0x00F9, 3, 4, 1 },
{ NULL, 0 }
};
@@ -2471,6 +2483,9 @@ do_setattr (app_t app, const char *name,
if (table[idx].need_v2 && !app->app_local->extcap.is_v2)
return gpg_error (GPG_ERR_NOT_SUPPORTED); /* Not yet supported. */
+ if (table[idx].special == 5 && app->app_local->extcap.has_button == 0)
+ return gpg_error (GPG_ERR_INV_OBJ);
+
if (table[idx].special == 3)
return change_keyattr_from_string (app, pincb, pincb_arg, value, valuelen);
@@ -2839,10 +2854,10 @@ do_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr,
pincb (pincb_arg, NULL, NULL); /* Dismiss the prompt. */
}
else
- {
+ {
rc = pin2hash_if_kdf (app, chvno, oldpinvalue, &pinlen0);
if (!rc)
- rc = pin2hash_if_kdf (app, chvno, pinvalue, &pinlen);
+ rc = pin2hash_if_kdf (app, chvno, pinvalue, &pinlen);
if (!rc)
rc = iso7816_change_reference_data (app->slot, 0x80 + chvno,
oldpinvalue, pinlen0,
@@ -4381,7 +4396,7 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
log_info (_("signatures created so far: %lu\n"), sigcount);
/* Check CHV if needed. */
- if (!app->did_chv1 || app->force_chv1 )
+ if (!app->did_chv1 || app->force_chv1)
{
char *pinvalue;
int pinlen;
@@ -4429,6 +4444,9 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
}
rc = iso7816_compute_ds (app->slot, exmode, data, datalen, le_value,
outdata, outdatalen);
+ if (!rc && app->force_chv1)
+ app->did_chv1 = 0;
+
return rc;
}
diff --git a/scd/app.c b/scd/app.c
index f3f1205f8..a82db26cd 100644
--- a/scd/app.c
+++ b/scd/app.c
@@ -67,6 +67,7 @@ lock_app (app_t app, ctrl_t ctrl)
}
apdu_set_progress_cb (app->slot, print_progress_line, ctrl);
+ apdu_set_prompt_cb (app->slot, popup_prompt, ctrl);
return 0;
}
@@ -76,6 +77,7 @@ static void
unlock_app (app_t app)
{
apdu_set_progress_cb (app->slot, NULL, NULL);
+ apdu_set_prompt_cb (app->slot, NULL, NULL);
if (npth_mutex_unlock (&app->lock))
{
diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c
index f33a36c83..ff82ef38b 100644
--- a/scd/ccid-driver.c
+++ b/scd/ccid-driver.c
@@ -255,6 +255,9 @@ struct ccid_driver_s
void (*progress_cb)(void *, const char *, int, int, int);
void *progress_cb_arg;
+ void (*prompt_cb)(void *, int);
+ void *prompt_cb_arg;
+
unsigned char intr_buf[64];
struct libusb_transfer *transfer;
};
@@ -1802,6 +1805,19 @@ ccid_set_progress_cb (ccid_driver_t handle,
}
+int
+ccid_set_prompt_cb (ccid_driver_t handle,
+ void (*cb)(void *, int), void *cb_arg)
+{
+ if (!handle)
+ return CCID_DRIVER_ERR_INV_VALUE;
+
+ handle->prompt_cb = cb;
+ handle->prompt_cb_arg = cb_arg;
+ return 0;
+}
+
+
/* Close the reader HANDLE. */
int
ccid_close_reader (ccid_driver_t handle)
@@ -1921,7 +1937,7 @@ bulk_out (ccid_driver_t handle, unsigned char *msg, size_t msglen,
is the sequence number used to send the request and EXPECTED_TYPE
the type of message we expect. Does checks on the ccid
header. TIMEOUT is the timeout value in ms. NO_DEBUG may be set to
- avoid debug messages in case of no error; this can be overriden
+ avoid debug messages in case of no error; this can be overridden
with a glibal debug level of at least 3. Returns 0 on success. */
static int
bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length,
@@ -1930,6 +1946,7 @@ bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length,
{
int rc;
int msglen;
+ int notified = 0;
/* Fixme: The next line for the current Valgrind without support
for USB IOCTLs. */
@@ -1982,14 +1999,25 @@ bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length,
we got the expected message type. This is in particular required
for the Cherry keyboard which sends a time extension request for
each key hit. */
- if ( !(buffer[7] & 0x03) && (buffer[7] & 0xC0) == 0x80)
+ if (!(buffer[7] & 0x03) && (buffer[7] & 0xC0) == 0x80)
{
/* Card present and active, time extension requested. */
DEBUGOUT_2 ("time extension requested (%02X,%02X)\n",
buffer[7], buffer[8]);
+
+ /* Gnuk enhancement to prompt user input by ack button */
+ if (buffer[8] == 0xff && !notified)
+ {
+ notified = 1;
+ handle->prompt_cb (handle->prompt_cb_arg, 1);
+ }
+
goto retry;
}
+ if (notified)
+ handle->prompt_cb (handle->prompt_cb_arg, 0);
+
if (buffer[0] != expected_type && buffer[0] != RDR_to_PC_SlotStatus)
{
DEBUGOUT_1 ("unexpected bulk-in msg type (%02x)\n", buffer[0]);
@@ -2928,7 +2956,7 @@ ccid_transceive_apdu_level (ccid_driver_t handle,
bit 3 unused
bit 2..0 Source Node Address (SAD)
- If node adresses are not used, SAD and DAD should be set to 0 on
+ If node addresses are not used, SAD and DAD should be set to 0 on
the first block sent to the card. If they are used they should
have different values (0 for one is okay); that first block sets up
the addresses of the nodes.
@@ -3270,7 +3298,7 @@ ccid_transceive (ccid_driver_t handle,
/* Wait time extension request. */
unsigned char bwi = tpdu[3];
- /* Check if it's unsual value which can't be expressed in ATR. */
+ /* Check if it's unusual value which can't be expressed in ATR. */
if (bwi > 15)
wait_more = 1;
@@ -3387,6 +3415,12 @@ ccid_transceive_secure (ccid_driver_t handle,
if (handle->id_product != CHERRY_ST2000)
cherry_mode = 1;
break;
+ case VENDOR_NXP:
+ if (handle->id_product == CRYPTOUCAN){
+ pininfo->maxlen = 25;
+ enable_varlen = 1;
+ }
+ break;
default:
if ((handle->id_vendor == VENDOR_GEMPC &&
handle->id_product == GEMPC_PINPAD)
diff --git a/scd/ccid-driver.h b/scd/ccid-driver.h
index b6da30c07..1550b3eba 100644
--- a/scd/ccid-driver.h
+++ b/scd/ccid-driver.h
@@ -68,7 +68,8 @@ enum {
VENDOR_REINER = 0x0c4b,
VENDOR_KAAN = 0x0d46,
VENDOR_FSIJ = 0x234b,
- VENDOR_VASCO = 0x1a44
+ VENDOR_VASCO = 0x1a44,
+ VENDOR_NXP = 0x1fc9,
};
@@ -84,6 +85,7 @@ enum {
#define GEMPC_CT30 0x3437
#define VEGA_ALPHA 0x0008
#define CYBERJACK_GO 0x0504
+#define CRYPTOUCAN 0x81e6
#endif /*CCID_DRIVER_INCLUDE_USB_IDS*/
@@ -124,6 +126,8 @@ int ccid_open_reader (const char *spec_reader_name,
int ccid_set_progress_cb (ccid_driver_t handle,
void (*cb)(void *, const char *, int, int, int),
void *cb_arg);
+int ccid_set_prompt_cb (ccid_driver_t handle, void (*cb)(void *, int),
+ void *cb_arg);
int ccid_shutdown_reader (ccid_driver_t handle);
int ccid_close_reader (ccid_driver_t handle);
int ccid_get_atr (ccid_driver_t handle,
diff --git a/scd/command.c b/scd/command.c
index 66d9fb971..0a9654693 100644
--- a/scd/command.c
+++ b/scd/command.c
@@ -1898,6 +1898,34 @@ send_status_direct (ctrl_t ctrl, const char *keyword, const char *args)
}
+void
+popup_prompt (void *opaque, int on)
+{
+ ctrl_t ctrl = opaque;
+
+ if (ctrl)
+ {
+ assuan_context_t ctx = ctrl->server_local->assuan_ctx;
+
+ if (ctx)
+ {
+ const char *cmd;
+ gpg_error_t err;
+ unsigned char *value;
+ size_t valuelen;
+
+ if (on)
+ cmd = "POPUPPINPADPROMPT --ack";
+ else
+ cmd = "DISMISSPINPADPROMPT";
+ err = assuan_inquire (ctx, cmd, &value, &valuelen, 100);
+ if (!err)
+ xfree (value);
+ }
+ }
+}
+
+
/* Helper to send the clients a status change notification. */
void
send_client_notifications (app_t app, int removal)
diff --git a/scd/iso7816.c b/scd/iso7816.c
index 29208c254..01faca5b4 100644
--- a/scd/iso7816.c
+++ b/scd/iso7816.c
@@ -427,7 +427,7 @@ iso7816_put_data_odd (int slot, int extended_mode, int tag,
/* Manage Security Environment. This is a weird operation and there
is no easy abstraction for it. Furthermore, some card seem to have
- a different interpreation of 7816-8 and thus we resort to let the
+ a different interpretation of 7816-8 and thus we resort to let the
caller decide what to do. */
gpg_error_t
iso7816_manage_security_env (int slot, int p1, int p2,
@@ -445,7 +445,7 @@ iso7816_manage_security_env (int slot, int p1, int p2,
/* Perform the security operation COMPUTE DIGITAL SIGANTURE. On
- success 0 is returned and the data is availavle in a newly
+ success 0 is returned and the data is available in a newly
allocated buffer stored at RESULT with its length stored at
RESULTLEN. For LE see do_generate_keypair. */
gpg_error_t
diff --git a/scd/scdaemon.c b/scd/scdaemon.c
index 8f8a02619..507108db0 100644
--- a/scd/scdaemon.c
+++ b/scd/scdaemon.c
@@ -1069,7 +1069,7 @@ handle_signal (int signo)
/* Create a name for the socket. We check for valid characters as
well as against a maximum allowed length for a unix domain socket
is done. The function terminates the process in case of an error.
- Retunrs: Pointer to an allcoated string with the absolute name of
+ Returns: Pointer to an allcoated string with the absolute name of
the socket used. */
static char *
create_socket_name (char *standard_name)
diff --git a/scd/scdaemon.h b/scd/scdaemon.h
index 4797f3df0..238e6a8fd 100644
--- a/scd/scdaemon.h
+++ b/scd/scdaemon.h
@@ -123,6 +123,7 @@ int scd_command_handler (ctrl_t, int);
void send_status_info (ctrl_t ctrl, const char *keyword, ...)
GPGRT_ATTR_SENTINEL(1);
void send_status_direct (ctrl_t ctrl, const char *keyword, const char *args);
+void popup_prompt (void *opaque, int on);
void send_client_notifications (app_t app, int removal);
void scd_kick_the_loop (void);
int get_active_connection_count (void);