diff options
Diffstat (limited to 'scd')
-rw-r--r-- | scd/apdu.c | 42 | ||||
-rw-r--r-- | scd/apdu.h | 1 | ||||
-rw-r--r-- | scd/app-dinsig.c | 2 | ||||
-rw-r--r-- | scd/app-geldkarte.c | 2 | ||||
-rw-r--r-- | scd/app-openpgp.c | 28 | ||||
-rw-r--r-- | scd/app.c | 2 | ||||
-rw-r--r-- | scd/ccid-driver.c | 42 | ||||
-rw-r--r-- | scd/ccid-driver.h | 6 | ||||
-rw-r--r-- | scd/command.c | 28 | ||||
-rw-r--r-- | scd/iso7816.c | 4 | ||||
-rw-r--r-- | scd/scdaemon.c | 2 | ||||
-rw-r--r-- | scd/scdaemon.h | 1 |
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; } @@ -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); |