diff --git a/scd/app-common.h b/scd/app-common.h index d0c00df09..089907f07 100644 --- a/scd/app-common.h +++ b/scd/app-common.h @@ -47,6 +47,35 @@ #define APP_LEARN_FLAG_MULTI 2 /* Return info for all apps. */ +/* List of supported card types. Generic is the usual ISO7817-4 + * compliant card. More specific card or token versions can be given + * here. Introduced in 2.2 for easier backporting from 2.3. */ +typedef enum + { + CARDTYPE_GENERIC = 0, + CARDTYPE_GNUK, + CARDTYPE_YUBIKEY, + CARDTYPE_ZEITCONTROL + } cardtype_t; + + +/* List of supported card applications. The source code for each + * application can usually be found in an app-NAME.c file. Introduced + * in 2.2 for easier backporting from 2.3. */ +typedef enum + { + APPTYPE_NONE = 0, + APPTYPE_UNDEFINED, + APPTYPE_OPENPGP, + APPTYPE_PIV, + APPTYPE_NKS, + APPTYPE_P15, + APPTYPE_GELDKARTE, + APPTYPE_DINSIG, + APPTYPE_SC_HSM + } apptype_t; + + /* Forward declarations. */ struct app_ctx_s; struct app_local_s; /* Defined by all app-*.c. */ @@ -69,7 +98,9 @@ struct app_ctx_s { unsigned char *serialno; /* Serialnumber in raw form, allocated. */ size_t serialnolen; /* Length in octets of serialnumber. */ - const char *apptype; + apptype_t apptype; + unsigned int appversion; /* Version of the application or 0. */ + cardtype_t cardtype; /* The token's type. */ unsigned int card_version; unsigned int card_status; unsigned int reset_requested:1; diff --git a/scd/app-dinsig.c b/scd/app-dinsig.c index 74a7fb8ca..a349257fe 100644 --- a/scd/app-dinsig.c +++ b/scd/app-dinsig.c @@ -552,7 +552,7 @@ app_select_dinsig (app_t app) rc = iso7816_select_application (slot, aid, sizeof aid, 0); if (!rc) { - app->apptype = "DINSIG"; + app->apptype = APPTYPE_DINSIG; app->fnc.learn_status = do_learn_status; app->fnc.readcert = do_readcert; diff --git a/scd/app-geldkarte.c b/scd/app-geldkarte.c index 579fb48fa..5437263f9 100644 --- a/scd/app-geldkarte.c +++ b/scd/app-geldkarte.c @@ -311,7 +311,7 @@ app_select_geldkarte (app_t app) goto leave; /* Probably not a Geldkarte. */ } - app->apptype = "GELDKARTE"; + app->apptype = APPTYPE_GELDKARTE; app->fnc.deinit = do_deinit; /* If we don't have a serialno yet construct it from the EF_ID. */ diff --git a/scd/app-nks.c b/scd/app-nks.c index 26227d3ef..7440c1830 100644 --- a/scd/app-nks.c +++ b/scd/app-nks.c @@ -1387,7 +1387,7 @@ app_select_nks (app_t app) rc = iso7816_select_application (slot, aid_nks, sizeof aid_nks, 0); if (!rc) { - app->apptype = "NKS"; + app->apptype = APPTYPE_NKS; app->app_local = xtrycalloc (1, sizeof *app->app_local); if (!app->app_local) diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index 55833d876..9394ef908 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -509,7 +509,7 @@ get_one_do (app_t app, int tag, unsigned char **result, size_t *nbytes, for (i=0; data_objects[i].tag && data_objects[i].tag != tag; i++) ; - if (app->card_version > 0x0100 && data_objects[i].get_immediate_in_v11) + if (app->appversion > 0x0100 && data_objects[i].get_immediate_in_v11) { exmode = 0; rc = iso7816_get_data (app->slot, exmode, tag, &buffer, &buflen); @@ -849,7 +849,7 @@ store_fpr (app_t app, int keynumber, u32 timestamp, unsigned char *fpr, xfree (buffer); - tag = (app->card_version > 0x0007? 0xC7 : 0xC6) + keynumber; + tag = (app->appversion > 0x0007? 0xC7 : 0xC6) + keynumber; flush_cache_item (app, 0xC5); tag2 = 0xCE + keynumber; flush_cache_item (app, 0xCD); @@ -858,7 +858,7 @@ store_fpr (app_t app, int keynumber, u32 timestamp, unsigned char *fpr, if (rc) log_error (_("failed to store the fingerprint: %s\n"),gpg_strerror (rc)); - if (!rc && app->card_version > 0x0100) + if (!rc && app->appversion > 0x0100) { unsigned char buf[4]; @@ -1738,7 +1738,7 @@ get_public_key (app_t app, int keyno) m = e = NULL; /* (avoid cc warning) */ - if (app->card_version > 0x0100) + if (app->appversion > 0x0100) { int exmode, le_value; @@ -1923,7 +1923,7 @@ do_learn_status (app_t app, ctrl_t ctrl, unsigned int flags) err = do_getattr (app, ctrl, "LOGIN-DATA"); if (!err) err = do_getattr (app, ctrl, "KEY-FPR"); - if (!err && app->card_version > 0x0100) + if (!err && app->appversion > 0x0100) err = do_getattr (app, ctrl, "KEY-TIME"); if (!err) err = do_getattr (app, ctrl, "CA-FPR"); @@ -3818,7 +3818,7 @@ rsa_writekey (app_t app, gpg_error_t (*pincb)(void*, const char *, char **), /* Store the key. */ err = iso7816_put_data (app->slot, 0, - (app->card_version > 0x0007? 0xE0:0xE9)+keyno, + (app->appversion > 0x0007? 0xE0:0xE9)+keyno, template, template_len); } if (err) @@ -4962,7 +4962,7 @@ do_decipher (app_t app, const char *keyidstr, if (gpg_err_code (rc) == GPG_ERR_CARD /* actual SW is 0x640a */ && app->app_local->manufacturer == 5 - && app->card_version == 0x0200) + && app->appversion == 0x0200) log_info ("NOTE: Cards with manufacturer id 5 and s/n <= 346 (0x15a)" " do not work with encryption keys > 2048 bits\n"); @@ -5281,7 +5281,7 @@ app_select_openpgp (app_t app) { unsigned int manufacturer; - app->apptype = "OPENPGP"; + app->apptype = APPTYPE_OPENPGP; app->did_chv1 = 0; app->did_chv2 = 0; @@ -5302,8 +5302,8 @@ app_select_openpgp (app_t app) log_printhex (buffer, buflen, ""); } - app->card_version = buffer[6] << 8; - app->card_version |= buffer[7]; + app->appversion = buffer[6] << 8; + app->appversion |= buffer[7]; manufacturer = (buffer[8]<<8 | buffer[9]); xfree (app->serialno); @@ -5319,10 +5319,10 @@ app_select_openpgp (app_t app) app->app_local->manufacturer = manufacturer; - if (app->card_version >= 0x0200) + if (app->appversion >= 0x0200) app->app_local->extcap.is_v2 = 1; - if (app->card_version >= 0x0300) + if (app->appversion >= 0x0300) app->app_local->extcap.extcap_v3 = 1; /* Read the historical bytes. */ @@ -5389,7 +5389,7 @@ app_select_openpgp (app_t app) /* Some of the first cards accidentally don't set the CHANGE_FORCE_CHV bit but allow it anyway. */ - if (app->card_version <= 0x0100 && manufacturer == 1) + if (app->appversion <= 0x0100 && manufacturer == 1) app->app_local->extcap.change_force_chv = 1; /* Check optional DO of "General Feature Management" for button. */ diff --git a/scd/app-p15.c b/scd/app-p15.c index 15c068694..bd9c7c15f 100644 --- a/scd/app-p15.c +++ b/scd/app-p15.c @@ -4152,7 +4152,7 @@ app_select_p15 (app_t app) } if (!rc) { - app->apptype = "P15"; + app->apptype = APPTYPE_P15; app->app_local = xtrycalloc (1, sizeof *app->app_local); if (!app->app_local) diff --git a/scd/app-sc-hsm.c b/scd/app-sc-hsm.c index d8d60b20a..56c4ceb07 100644 --- a/scd/app-sc-hsm.c +++ b/scd/app-sc-hsm.c @@ -2049,7 +2049,7 @@ app_select_sc_hsm (app_t app) rc = iso7816_select_application (slot, sc_hsm_aid, sizeof sc_hsm_aid, 0); if (!rc) { - app->apptype = "SC-HSM"; + app->apptype = APPTYPE_SC_HSM; app->app_local = xtrycalloc (1, sizeof *app->app_local); if (!app->app_local) diff --git a/scd/app.c b/scd/app.c index d10229030..72ccad7d8 100644 --- a/scd/app.c +++ b/scd/app.c @@ -32,6 +32,25 @@ static npth_mutex_t app_list_lock; static app_t app_top; + + +/* List of all supported apps. */ +static struct +{ + apptype_t apptype; + char const *name; +} supported_app_list[] = + {{ APPTYPE_OPENPGP , "openpgp" }, + { APPTYPE_NKS , "nks" }, + { APPTYPE_P15 , "p15" }, + { APPTYPE_GELDKARTE, "geldkarte" }, + { APPTYPE_DINSIG , "dinsig" }, + { APPTYPE_SC_HSM , "sc-hsm" }, + { APPTYPE_NONE , NULL } + /* APPTYPE_UNDEFINED is special and not listed here. */ + }; + + static void print_progress_line (void *opaque, const char *what, int pc, int cur, int tot) @@ -47,6 +66,37 @@ print_progress_line (void *opaque, const char *what, int pc, int cur, int tot) } +/* Map an application type to a string. Never returns NULL. */ +const char * +strapptype (apptype_t t) +{ + int i; + + for (i=0; supported_app_list[i].apptype; i++) + if (supported_app_list[i].apptype == t) + return supported_app_list[i].name; + return t == APPTYPE_UNDEFINED? "undefined" : t? "?" : "none"; +} + + +/* Return the apptype for NAME. */ +static apptype_t +apptype_from_name (const char *name) +{ + int i; + + if (!name) + return APPTYPE_NONE; + + for (i=0; supported_app_list[i].apptype; i++) + if (!ascii_strcasecmp (supported_app_list[i].name, name)) + return supported_app_list[i].apptype; + if (!ascii_strcasecmp ("undefined", name)) + return APPTYPE_UNDEFINED; + return APPTYPE_NONE; +} + + /* Lock the reader SLOT. This function shall be used right before calling any of the actual application functions to serialize access to the reader. We do this always even if the reader is not @@ -96,7 +146,7 @@ app_dump_state (void) npth_mutex_lock (&app_list_lock); for (a = app_top; a; a = a->next) - log_info ("app_dump_state: app=%p type='%s'\n", a, a->apptype); + log_info ("app_dump_state: app=%p type='%s'\n", a, strapptype (a->apptype)); npth_mutex_unlock (&app_list_lock); } @@ -117,14 +167,15 @@ is_app_allowed (const char *name) static gpg_error_t check_conflict (app_t app, const char *name) { - if (!app || !name || (app->apptype && !ascii_strcasecmp (app->apptype, name))) + if (!app || !name + || (app->apptype && app->apptype == apptype_from_name (name))) return 0; - if (app->apptype && !strcmp (app->apptype, "UNDEFINED")) + if (app->apptype && app->apptype == APPTYPE_UNDEFINED) return 0; log_info ("application '%s' in use - can't switch\n", - app->apptype? app->apptype : ""); + strapptype (app->apptype)); return gpg_error (GPG_ERR_CONFLICT); } @@ -263,7 +314,7 @@ app_new_register (int slot, ctrl_t ctrl, const char *name, { /* We switch to the "undefined" application only if explicitly requested. */ - app->apptype = "UNDEFINED"; + app->apptype = APPTYPE_UNDEFINED; err = 0; } else @@ -579,7 +630,7 @@ app_write_learn_status (app_t app, ctrl_t ctrl, unsigned int flags) /* We do not send APPTYPE if only keypairinfo is requested. */ if (app->apptype && !(flags & 1)) - send_status_direct (ctrl, "APPTYPE", app->apptype); + send_status_direct (ctrl, "APPTYPE", strapptype (app->apptype)); err = lock_app (app, ctrl); if (err) return err; @@ -660,7 +711,7 @@ app_getattr (app_t app, ctrl_t ctrl, const char *name) if (app->apptype && name && !strcmp (name, "APPTYPE")) { - send_status_direct (ctrl, "APPTYPE", app->apptype); + send_status_direct (ctrl, "APPTYPE", strapptype (app->apptype)); return 0; } if (name && !strcmp (name, "SERIALNO"))