From b27e20a95cb7af59dcaa6e59aacf52ed766be1f3 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Mon, 17 Feb 2020 17:44:59 +0900 Subject: [PATCH] scd: Disable pinpad if it's impossible by KDF DO. * scd/app-openpgp.c (struct app_local_s): Add pinpad.disabled field. (do_getattr): Set pinpad.disabled field. (check_pinpad_request): Use the pinpad.disabled field. (do_setattr): Update pinpad.disabled field. -- GnuPG-bug-id: 4832 Signed-off-by: NIIBE Yutaka (cherry picked from commit 95c7498b76231d3297541172d878f6a26702539b) Signed-off-by: Werner Koch --- scd/app-openpgp.c | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index eac71a251..95b9a359b 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -71,6 +71,9 @@ #include "../common/openpgpdefs.h" +#define KDF_DATA_LENGTH_MIN 90 +#define KDF_DATA_LENGTH_MAX 110 + /* A table describing the DOs of the card. */ static struct { int tag; @@ -200,7 +203,7 @@ struct app_local_s { unsigned int private_dos:1; unsigned int algo_attr_change:1; /* Algorithm attributes changeable. */ unsigned int has_decrypt:1; /* Support symmetric decryption. */ - unsigned int kdf_do:1; /* Support KDF DO. */ + unsigned int kdf_do:1; /* Support KDF DO. */ unsigned int sm_algo:2; /* Symmetric crypto algo for SM. */ unsigned int pin_blk2:1; /* PIN block 2 format supported. */ @@ -220,6 +223,7 @@ struct app_local_s { /* Pinpad request specified on card. */ struct { + unsigned int disabled:1; /* No pinpad use because of KDF DO. */ unsigned int specified:1; int fixedlen_user; int fixedlen_admin; @@ -987,7 +991,7 @@ do_getattr (app_t app, ctrl_t ctrl, const char *name) { "$ENCRKEYID", 0x0000, -6 }, { "$SIGNKEYID", 0x0000, -7 }, { "$DISPSERIALNO",0x0000, -4 }, - { "KDF", 0x00F9 }, + { "KDF", 0x00F9, 5 }, { NULL, 0 } }; int idx, i, rc; @@ -1112,11 +1116,25 @@ do_getattr (app_t app, ctrl_t ctrl, const char *name) for (i=0; i < 3; i++) send_fprtime_if_not_null (ctrl, table[idx].name, i+1, value+i*4); } + else if (table[idx].special == 5) + { + if ((valuelen == KDF_DATA_LENGTH_MIN + || valuelen == KDF_DATA_LENGTH_MAX) + && (value[2] == 0x03)) + app->app_local->pinpad.disabled = 1; + else + app->app_local->pinpad.disabled = 0; + } else send_status_info (ctrl, table[idx].name, value, valuelen, NULL, 0); xfree (relptr); } + else + { + if (table[idx].special == 5) + app->app_local->pinpad.disabled = 0; + } return rc; } @@ -1993,6 +2011,9 @@ do_readcert (app_t app, const char *certid, static int check_pinpad_request (app_t app, pininfo_t *pininfo, int admin_pin) { + if (app->app_local->pinpad.disabled) + return 1; + if (app->app_local->pinpad.specified == 0) /* No preference on card. */ { if (pininfo->fixedlen == 0) /* Reader has varlen capability. */ @@ -2087,9 +2108,6 @@ get_prompt_info (app_t app, int chvno, unsigned long sigcount, int remaining) return result; } -#define KDF_DATA_LENGTH_MIN 90 -#define KDF_DATA_LENGTH_MAX 110 - /* Compute hash if KDF-DO is available. CHVNO must be 0 for reset code, 1 or 2 for user pin and 3 for admin pin. */ @@ -2540,6 +2558,12 @@ do_setattr (app_t app, const char *name, app->did_chv1 = 0; app->did_chv2 = 0; app->did_chv3 = 0; + + if ((valuelen == KDF_DATA_LENGTH_MIN || valuelen == KDF_DATA_LENGTH_MAX) + && (value[2] == 0x03)) + app->app_local->pinpad.disabled = 1; + else + app->app_local->pinpad.disabled = 0; } return rc; @@ -4259,7 +4283,6 @@ check_against_given_fingerprint (app_t app, const char *fpr, int key) } - /* Compute a digital signature on INDATA which is expected to be the raw message digest. For this application the KEYIDSTR consists of the serialnumber and the fingerprint delimited by a slash.