aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNIIBE Yutaka <[email protected]>2019-02-21 06:50:43 +0000
committerNIIBE Yutaka <[email protected]>2019-02-21 06:50:43 +0000
commit2013cb5ee667610de35f8b92c2f979f5caa09d4c (patch)
tree032ebc3d5f88a628e068b2642391761ee9acaea9
parentscd: Handle ack button timeout as GPG_ERR_TIMEOUT. (diff)
downloadgnupg-2013cb5ee667610de35f8b92c2f979f5caa09d4c.tar.gz
gnupg-2013cb5ee667610de35f8b92c2f979f5caa09d4c.zip
scd: Clear CHV status on timeout error.
* scd/app-openpgp.c (clear_chv_status): New. (do_change_pin): Use clear_chv_status. (do_sign): Call clear_chv_status on GPG_ERR_TIMEOUT. (do_auth, do_decipher): Likewise. Signed-off-by: NIIBE Yutaka <[email protected]>
-rw-r--r--scd/app-openpgp.c79
1 files changed, 45 insertions, 34 deletions
diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c
index ae87d19f1..d7243ccd6 100644
--- a/scd/app-openpgp.c
+++ b/scd/app-openpgp.c
@@ -2568,6 +2568,42 @@ do_writecert (app_t app, ctrl_t ctrl,
}
+static gpg_error_t
+clear_chv_status (app_t app, int chvno)
+{
+ unsigned char apdu[4];
+ gpg_error_t err;
+
+ if (!app->app_local->extcap.is_v2)
+ return GPG_ERR_UNSUPPORTED_OPERATION;
+
+ apdu[0] = 0x00;
+ apdu[1] = ISO7816_VERIFY;
+ apdu[2] = 0xff;
+ apdu[3] = 0x80+chvno;
+
+ err = iso7816_apdu_direct (app->slot, apdu, 4, 0, NULL, NULL, NULL);
+ if (err)
+ {
+ if (gpg_err_code (err) == GPG_ERR_INV_VALUE)
+ err = gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
+ return err;
+ }
+
+ if (chvno == 1)
+ {
+ apdu[3]++;
+ err = iso7816_apdu_direct (app->slot, apdu, 4, 0, NULL, NULL, NULL);
+ app->did_chv1 = app->did_chv2 = 0;
+ }
+ else if (chvno == 2)
+ app->did_chv2 = 0;
+ else if (chvno == 3)
+ app->did_chv3 = 0;
+
+ return err;
+}
+
/* Handle the PASSWD command. The following combinations are
possible:
@@ -2623,38 +2659,7 @@ do_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr,
pininfo.minlen = minlen;
if ((flags & APP_CHANGE_FLAG_CLEAR))
- {
- unsigned char apdu[4];
-
- if (!app->app_local->extcap.is_v2)
- return GPG_ERR_UNSUPPORTED_OPERATION;
-
- apdu[0] = 0x00;
- apdu[1] = ISO7816_VERIFY;
- apdu[2] = 0xff;
- apdu[3] = 0x80+chvno;
-
- rc = iso7816_apdu_direct (app->slot, apdu, 4, 0, NULL, NULL, NULL);
- if (rc)
- {
- if (rc == GPG_ERR_INV_VALUE)
- rc = GPG_ERR_UNSUPPORTED_OPERATION;
- return rc;
- }
-
- if (chvno == 1)
- {
- apdu[3]++;
- rc = iso7816_apdu_direct (app->slot, apdu, 4, 0, NULL, NULL, NULL);
- app->did_chv1 = app->did_chv2 = 0;
- }
- else if (chvno == 2)
- app->did_chv2 = 0;
- else if (chvno == 3)
- app->did_chv3 = 0;
-
- return rc;
- }
+ return clear_chv_status (app, chvno);
if (reset_mode && chvno == 3)
{
@@ -4501,7 +4506,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)
+ if (gpg_err_code (rc) == GPG_ERR_TIMEOUT)
+ clear_chv_status (app, 1);
+ else if (!rc && app->force_chv1)
app->did_chv1 = 0;
return rc;
@@ -4610,6 +4617,8 @@ do_auth (app_t app, const char *keyidstr,
rc = iso7816_internal_authenticate (app->slot, exmode,
indata, indatalen, le_value,
outdata, outdatalen);
+ if (gpg_err_code (rc) == GPG_ERR_TIMEOUT)
+ clear_chv_status (app, 1);
}
return rc;
}
@@ -4833,7 +4842,7 @@ do_decipher (app_t app, const char *keyidstr,
indata, indatalen, le_value, padind,
outdata, outdatalen);
xfree (fixbuf);
- if (app->app_local->keyattr[1].key_type == KEY_TYPE_ECC)
+ if (!rc && app->app_local->keyattr[1].key_type == KEY_TYPE_ECC)
{
unsigned char prefix = 0;
@@ -4857,6 +4866,8 @@ do_decipher (app_t app, const char *keyidstr,
*outdatalen = *outdatalen + 1;
}
}
+ if (gpg_err_code (rc) == GPG_ERR_TIMEOUT)
+ clear_chv_status (app, 1);
if (gpg_err_code (rc) == GPG_ERR_CARD /* actual SW is 0x640a */
&& app->app_local->manufacturer == 5