diff --git a/scd/app.c b/scd/app.c index b415668f0..34ed99d57 100644 --- a/scd/app.c +++ b/scd/app.c @@ -841,30 +841,35 @@ app_write_learn_status (card_t card, ctrl_t ctrl, unsigned int flags) if (!card) return gpg_error (GPG_ERR_INV_VALUE); - if (!card->app) - return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); - app = card->app; - if (!app->fnc.learn_status) - return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); - - /* We do not send CARD and APPTYPE if only keypairinfo is requested. */ - if (!(flags &1)) - { - if (card->cardtype) - send_status_direct (ctrl, "CARDTYPE", strcardtype (card->cardtype)); - if (card->cardversion) - send_status_printf (ctrl, "CARDVERSION", "%X", card->cardversion); - if (app->apptype) - send_status_direct (ctrl, "APPTYPE", strapptype (app->apptype)); - if (app->appversion) - send_status_printf (ctrl, "APPVERSION", "%X", app->appversion); - /* FIXME: Send info for the other active apps of the card? */ - } err = lock_card (card, ctrl); if (err) return err; - err = app->fnc.learn_status (card->app, ctrl, flags); + + app = card->app; + if (!app) + err = gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); + else if (!app->fnc.learn_status) + err = gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); + else + { + /* We do not send CARD and APPTYPE if only keypairinfo is requested. */ + if (!(flags &1)) + { + if (card->cardtype) + send_status_direct (ctrl, "CARDTYPE", strcardtype (card->cardtype)); + if (card->cardversion) + send_status_printf (ctrl, "CARDVERSION", "%X", card->cardversion); + if (app->apptype) + send_status_direct (ctrl, "APPTYPE", strapptype (app->apptype)); + if (app->appversion) + send_status_printf (ctrl, "APPVERSION", "%X", app->appversion); + /* FIXME: Send info for the other active apps of the card? */ + } + + err = app->fnc.learn_status (app, ctrl, flags); + } + unlock_card (card); return err; } @@ -882,14 +887,17 @@ app_readcert (card_t card, ctrl_t ctrl, const char *certid, if (!card) return gpg_error (GPG_ERR_INV_VALUE); - if (!card->ref_count || !card->app) - return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); - if (!card->app->fnc.readcert) - return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); err = lock_card (card, ctrl); if (err) return err; - err = card->app->fnc.readcert (card->app, certid, cert, certlen); + + if (!card->ref_count || !card->app) + err = gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); + else if (!card->app->fnc.readcert) + err = gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); + else + err = card->app->fnc.readcert (card->app, certid, cert, certlen); + unlock_card (card); return err; } @@ -916,14 +924,17 @@ app_readkey (card_t card, ctrl_t ctrl, const char *keyid, unsigned int flags, if (!card || !keyid) return gpg_error (GPG_ERR_INV_VALUE); - if (!card->ref_count || !card->app) - return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); - if (!card->app->fnc.readkey) - return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); err = lock_card (card, ctrl); if (err) return err; - err = card->app->fnc.readkey (card->app, ctrl, keyid, flags, pk, pklen); + + if (!card->ref_count || !card->app) + err = gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); + else if (!card->app->fnc.readkey) + err = gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); + else + err = card->app->fnc.readkey (card->app, ctrl, keyid, flags, pk, pklen); + unlock_card (card); return err; } @@ -937,38 +948,38 @@ app_getattr (card_t card, ctrl_t ctrl, const char *name) if (!card || !name || !*name) return gpg_error (GPG_ERR_INV_VALUE); - if (!card->ref_count || !card->app) - return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); + err = lock_card (card, ctrl); + if (err) + return err; - if (name && !strcmp (name, "CARDTYPE")) + if (!card->ref_count || !card->app) + err = gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); + else if (name && !strcmp (name, "CARDTYPE")) { send_status_direct (ctrl, "CARDTYPE", strcardtype (card->cardtype)); - return 0; } - if (name && !strcmp (name, "APPTYPE")) + else if (name && !strcmp (name, "APPTYPE")) { send_status_direct (ctrl, "APPTYPE", strapptype (card->app->apptype)); - return 0; } - if (name && !strcmp (name, "SERIALNO")) + else if (name && !strcmp (name, "SERIALNO")) { char *serial; serial = card_get_serialno (card); if (!serial) - return gpg_error (GPG_ERR_INV_VALUE); - - send_status_direct (ctrl, "SERIALNO", serial); - xfree (serial); - return 0; + err = gpg_error (GPG_ERR_INV_VALUE); + else + { + send_status_direct (ctrl, "SERIALNO", serial); + xfree (serial); + } } + else if (!card->app->fnc.getattr) + err = gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); + else + err = card->app->fnc.getattr (card->app, ctrl, name); - if (!card->app->fnc.getattr) - return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); - err = lock_card (card, ctrl); - if (err) - return err; - err = card->app->fnc.getattr (card->app, ctrl, name); unlock_card (card); return err; } @@ -985,15 +996,18 @@ app_setattr (card_t card, ctrl_t ctrl, const char *name, if (!card || !name || !*name || !value) return gpg_error (GPG_ERR_INV_VALUE); - if (!card->ref_count || !card->app) - return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); - if (!card->app->fnc.setattr) - return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); err = lock_card (card, ctrl); if (err) return err; - err = card->app->fnc.setattr (card->app, name, pincb, pincb_arg, - value, valuelen); + + if (!card->ref_count || !card->app) + err = gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); + else if (!card->app->fnc.setattr) + err = gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); + else + err = card->app->fnc.setattr (card->app, name, pincb, pincb_arg, + value, valuelen); + unlock_card (card); return err; } @@ -1013,17 +1027,20 @@ app_sign (card_t card, ctrl_t ctrl, const char *keyidstr, int hashalgo, if (!card || !indata || !indatalen || !outdata || !outdatalen || !pincb) return gpg_error (GPG_ERR_INV_VALUE); - if (!card->ref_count || !card->app) - return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); - if (!card->app->fnc.sign) - return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); err = lock_card (card, ctrl); if (err) return err; - err = card->app->fnc.sign (card->app, keyidstr, hashalgo, - pincb, pincb_arg, - indata, indatalen, - outdata, outdatalen); + + if (!card->ref_count || !card->app) + err = gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); + else if (!card->app->fnc.sign) + err = gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); + else + err = card->app->fnc.sign (card->app, keyidstr, hashalgo, + pincb, pincb_arg, + indata, indatalen, + outdata, outdatalen); + unlock_card (card); if (opt.verbose) log_info ("operation sign result: %s\n", gpg_strerror (err)); @@ -1046,17 +1063,20 @@ app_auth (card_t card, ctrl_t ctrl, const char *keyidstr, if (!card || !indata || !indatalen || !outdata || !outdatalen || !pincb) return gpg_error (GPG_ERR_INV_VALUE); - if (!card->ref_count || !card->app) - return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); - if (!card->app->fnc.auth) - return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); err = lock_card (card, ctrl); if (err) return err; - err = card->app->fnc.auth (card->app, keyidstr, - pincb, pincb_arg, - indata, indatalen, - outdata, outdatalen); + + if (!card->ref_count || !card->app) + err = gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); + else if (!card->app->fnc.auth) + err = gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); + else + err = card->app->fnc.auth (card->app, keyidstr, + pincb, pincb_arg, + indata, indatalen, + outdata, outdatalen); + unlock_card (card); if (opt.verbose) log_info ("operation auth result: %s\n", gpg_strerror (err)); @@ -1081,18 +1101,21 @@ app_decipher (card_t card, ctrl_t ctrl, const char *keyidstr, if (!card || !indata || !indatalen || !outdata || !outdatalen || !pincb) return gpg_error (GPG_ERR_INV_VALUE); - if (!card->ref_count || !card->app) - return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); - if (!card->app->fnc.decipher) - return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); err = lock_card (card, ctrl); if (err) return err; - err = card->app->fnc.decipher (card->app, keyidstr, - pincb, pincb_arg, - indata, indatalen, - outdata, outdatalen, - r_info); + + if (!card->ref_count || !card->app) + err = gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); + else if (!card->app->fnc.decipher) + err = gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); + else + err = card->app->fnc.decipher (card->app, keyidstr, + pincb, pincb_arg, + indata, indatalen, + outdata, outdatalen, + r_info); + unlock_card (card); if (opt.verbose) log_info ("operation decipher result: %s\n", gpg_strerror (err)); @@ -1112,15 +1135,18 @@ app_writecert (card_t card, ctrl_t ctrl, if (!card || !certidstr || !*certidstr || !pincb) return gpg_error (GPG_ERR_INV_VALUE); - if (!card->ref_count || !card->app) - return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); - if (!card->app->fnc.writecert) - return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); err = lock_card (card, ctrl); if (err) return err; - err = card->app->fnc.writecert (card->app, ctrl, certidstr, - pincb, pincb_arg, data, datalen); + + if (!card->ref_count || !card->app) + err = gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); + else if (!card->app->fnc.writecert) + err = gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); + else + err = card->app->fnc.writecert (card->app, ctrl, certidstr, + pincb, pincb_arg, data, datalen); + unlock_card (card); if (opt.verbose) log_info ("operation writecert result: %s\n", gpg_strerror (err)); @@ -1140,15 +1166,18 @@ app_writekey (card_t card, ctrl_t ctrl, if (!card || !keyidstr || !*keyidstr || !pincb) return gpg_error (GPG_ERR_INV_VALUE); - if (!card->ref_count || !card->app) - return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); - if (!card->app->fnc.writekey) - return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); err = lock_card (card, ctrl); if (err) return err; - err = card->app->fnc.writekey (card->app, ctrl, keyidstr, flags, - pincb, pincb_arg, keydata, keydatalen); + + if (!card->ref_count || !card->app) + err = gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); + else if (!card->app->fnc.writekey) + err = gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); + else + err = card->app->fnc.writekey (card->app, ctrl, keyidstr, flags, + pincb, pincb_arg, keydata, keydatalen); + unlock_card (card); if (opt.verbose) log_info ("operation writekey result: %s\n", gpg_strerror (err)); @@ -1156,7 +1185,7 @@ app_writekey (card_t card, ctrl_t ctrl, } -/* Perform a SETATTR operation. */ +/* Perform a GENKEY operation. */ gpg_error_t app_genkey (card_t card, ctrl_t ctrl, const char *keynostr, const char *keytype, unsigned int flags, time_t createtime, @@ -1167,15 +1196,18 @@ app_genkey (card_t card, ctrl_t ctrl, const char *keynostr, if (!card || !keynostr || !*keynostr || !pincb) return gpg_error (GPG_ERR_INV_VALUE); - if (!card->ref_count || !card->app) - return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); - if (!card->app->fnc.genkey) - return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); err = lock_card (card, ctrl); if (err) return err; - err = card->app->fnc.genkey (card->app, ctrl, keynostr, keytype, flags, - createtime, pincb, pincb_arg); + + if (!card->ref_count || !card->app) + err = gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); + else if (!card->app->fnc.genkey) + err = gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); + else + err = card->app->fnc.genkey (card->app, ctrl, keynostr, keytype, flags, + createtime, pincb, pincb_arg); + unlock_card (card); if (opt.verbose) log_info ("operation genkey result: %s\n", gpg_strerror (err)); @@ -1194,12 +1226,15 @@ app_get_challenge (card_t card, ctrl_t ctrl, if (!card || !nbytes || !buffer) return gpg_error (GPG_ERR_INV_VALUE); - if (!card->ref_count) - return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); err = lock_card (card, ctrl); if (err) return err; - err = iso7816_get_challenge (card->slot, nbytes, buffer); + + if (!card->ref_count) + err = gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); + else + err = iso7816_get_challenge (card->slot, nbytes, buffer); + unlock_card (card); return err; } @@ -1216,15 +1251,18 @@ app_change_pin (card_t card, ctrl_t ctrl, const char *chvnostr, if (!card || !chvnostr || !*chvnostr || !pincb) return gpg_error (GPG_ERR_INV_VALUE); - if (!card->ref_count || !card->app) - return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); - if (!card->app->fnc.change_pin) - return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); err = lock_card (card, ctrl); if (err) return err; - err = card->app->fnc.change_pin (card->app, ctrl, - chvnostr, flags, pincb, pincb_arg); + + if (!card->ref_count || !card->app) + err = gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); + else if (!card->app->fnc.change_pin) + err = gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); + else + err = card->app->fnc.change_pin (card->app, ctrl, + chvnostr, flags, pincb, pincb_arg); + unlock_card (card); if (opt.verbose) log_info ("operation change_pin result: %s\n", gpg_strerror (err)); @@ -1244,14 +1282,17 @@ app_check_pin (card_t card, ctrl_t ctrl, const char *keyidstr, if (!card || !keyidstr || !*keyidstr || !pincb) return gpg_error (GPG_ERR_INV_VALUE); - if (!card->ref_count || !card->app) - return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); - if (!card->app->fnc.check_pin) - return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); err = lock_card (card, ctrl); if (err) return err; - err = card->app->fnc.check_pin (card->app, keyidstr, pincb, pincb_arg); + + if (!card->ref_count || !card->app) + err = gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); + else if (!card->app->fnc.check_pin) + err = gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); + else + err = card->app->fnc.check_pin (card->app, keyidstr, pincb, pincb_arg); + unlock_card (card); if (opt.verbose) log_info ("operation check_pin result: %s\n", gpg_strerror (err)); @@ -1464,7 +1505,7 @@ app_do_with_keygrip (ctrl_t ctrl, int action, const char *keygrip_str) /* FIXME: Add app switching logic. The above code assumes that the * actions can be performend without switching. This needs to be * checked. For a lookup we also need to reorder the apps so that - * the selected one will be used. */ + * the selected one will be used. */ npth_mutex_unlock (&card_list_lock); return c;