aboutsummaryrefslogtreecommitdiffstats
path: root/scd/app-openpgp.c
diff options
context:
space:
mode:
authorNIIBE Yutaka <[email protected]>2019-01-23 03:01:51 +0000
committerNIIBE Yutaka <[email protected]>2019-01-23 03:12:54 +0000
commitfec75a3868da72196f76aca95c7ab07debb7dc04 (patch)
tree2c62375a68db65a32f7ecf56d6fe92b4473aefc3 /scd/app-openpgp.c
parentgpg: Stop early when trying to create a primary Elgamal key. (diff)
downloadgnupg-fec75a3868da72196f76aca95c7ab07debb7dc04.tar.gz
gnupg-fec75a3868da72196f76aca95c7ab07debb7dc04.zip
scd: Support PASSWD --clear for OpenPGP card.
* scd/app-openpgp.c (do_change_pin): Implement handling APP_CHANGE_FLAG_CLEAR. -- It is specified in the specification version 3.1 or later. Some version 2 cards (including Gnuk) support this feature. Any version 1 card has no support for this feature. For CHVNO = 1, it clears for both of 81 and 82; That is, user's key usages for signing and others (decryption and auth). For CHVNO = 3, it clears for 83, admin key. For CHVNO = 2, it clears 82; That is, user's key usages others (decryption and auth). Signed-off-by: NIIBE Yutaka <[email protected]>
Diffstat (limited to 'scd/app-openpgp.c')
-rw-r--r--scd/app-openpgp.c33
1 files changed, 32 insertions, 1 deletions
diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c
index fddc3b8cf..db5188e33 100644
--- a/scd/app-openpgp.c
+++ b/scd/app-openpgp.c
@@ -2608,7 +2608,38 @@ do_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr,
pininfo.minlen = minlen;
if ((flags & APP_CHANGE_FLAG_CLEAR))
- return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
+ {
+ 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;
+ }
if (reset_mode && chvno == 3)
{