summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNIIBE Yutaka <gniibe@fsij.org>2019-04-23 03:51:01 +0200
committerNIIBE Yutaka <gniibe@fsij.org>2019-04-23 03:51:01 +0200
commite769609cd3c12d2e26955538399172016f78d2d4 (patch)
tree1119f6df61c3cfb9f96b506076f3b0b8896e7cd5
parentscd: Factor out a function to check keyidstr. (diff)
downloadgnupg2-e769609cd3c12d2e26955538399172016f78d2d4.tar.xz
gnupg2-e769609cd3c12d2e26955538399172016f78d2d4.zip
scd: Allow KEYGRIP as KEYIDSTR.
* scd/app-openpgp.c (struct app_local_s): Add keygrip_str. (store_keygrip): New. (read_public_key): Call store_keygrip to hold keygrip. (get_public_key): Likewise. (send_keypair_info): Use stored keygrip_str. (check_keyidstr): Allow use of KEYGRIP. (do_check_pin): Allow use of KEYGRIP of signing slot. Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
-rw-r--r--scd/app-openpgp.c67
1 files changed, 52 insertions, 15 deletions
diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c
index 25ec834c8..02d388695 100644
--- a/scd/app-openpgp.c
+++ b/scd/app-openpgp.c
@@ -176,6 +176,7 @@ struct app_local_s {
is usually only required for cross checks
because the length of an S-expression is
implicitly available. */
+ unsigned char keygrip_str[41]; /* The keygrip, null terminated */
} pk[3];
unsigned char status_indicator; /* The card status indicator. */
@@ -1575,6 +1576,23 @@ ecc_read_pubkey (app_t app, ctrl_t ctrl, u32 created_at, int keyno,
}
+static gpg_error_t
+store_keygrip (app_t app, int keyno)
+{
+ gpg_error_t err;
+ unsigned char grip[20];
+
+ err = keygrip_from_canon_sexp (app->app_local->pk[keyno].key,
+ app->app_local->pk[keyno].keylen,
+ grip);
+ if (err)
+ return err;
+
+ bin2hex (grip, 20, app->app_local->pk[keyno].keygrip_str);
+ return 0;
+}
+
+
/* Parse tag-length-value data for public key in BUFFER of BUFLEN
length. Key of KEYNO in APP is updated with an S-expression of
public key. When CTRL is not NULL, fingerprint is computed with
@@ -1626,6 +1644,8 @@ read_public_key (app_t app, ctrl_t ctrl, u32 created_at, int keyno,
app->app_local->pk[keyno].key = keybuf;
/* Decrement for trailing '\0' */
app->app_local->pk[keyno].keylen = len - 1;
+
+ err = store_keygrip (app, keyno);
}
return err;
@@ -1773,11 +1793,13 @@ get_public_key (app_t app, int keyno)
app->app_local->pk[keyno].key = (unsigned char*)keybuf;
/* Decrement for trailing '\0' */
app->app_local->pk[keyno].keylen = len - 1;
+ err = store_keygrip (app, keyno);
}
leave:
/* Set a flag to indicate that we tried to read the key. */
- app->app_local->pk[keyno].read_done = 1;
+ if (!err)
+ app->app_local->pk[keyno].read_done = 1;
xfree (buffer);
return err;
@@ -1796,8 +1818,6 @@ send_keypair_info (app_t app, ctrl_t ctrl, int key)
/* Note that GnuPG 1.x does not need this and it would be too time
consuming to send it just for the fun of it. */
#if GNUPG_MAJOR_VERSION > 1
- unsigned char grip[20];
- char gripstr[41];
char idbuf[50];
const char *usage;
@@ -1809,14 +1829,6 @@ send_keypair_info (app_t app, ctrl_t ctrl, int key)
if (!app->app_local->pk[keyno].key)
goto leave; /* No such key - ignore. */
- err = keygrip_from_canon_sexp (app->app_local->pk[keyno].key,
- app->app_local->pk[keyno].keylen,
- grip);
- if (err)
- goto leave;
-
- bin2hex (grip, 20, gripstr);
-
switch (keyno)
{
case 0: usage = "sc"; break;
@@ -1827,7 +1839,7 @@ send_keypair_info (app_t app, ctrl_t ctrl, int key)
sprintf (idbuf, "OPENPGP.%d", keyno+1);
send_status_info (ctrl, "KEYPAIRINFO",
- gripstr, 40,
+ app->app_local->pk[keyno].keygrip_str, 40,
idbuf, strlen (idbuf),
usage, strlen (usage),
NULL, (size_t)0);
@@ -4294,6 +4306,17 @@ check_against_given_fingerprint (app_t app, const char *fpr, int key)
}
+/* Check KEYIDSTR, if it's valid.
+ When KEYNO is 0, it means it's for PIN check.
+ Otherwise, KEYNO corresponds to the slot (signing, decipher and auth).
+ KEYIDSTR is either:
+ (1) Serial number
+ (2) Serial number "/" fingerprint
+ (3) keygrip
+
+ When KEYNO is 0 and KEYIDSTR is for a keygrip, the keygrip should
+ be to be compared is the first one (keygrip for signing).
+ */
static int
check_keyidstr (app_t app, const char *keyidstr, int keyno)
{
@@ -4303,13 +4326,26 @@ check_keyidstr (app_t app, const char *keyidstr, int keyno)
const char *fpr = NULL;
unsigned char tmp_sn[20]; /* Actually 16 bytes but also for the fpr. */
- if (strlen (keyidstr) < 32 || strncmp (keyidstr, "D27600012401", 12))
+ if (strlen (keyidstr) < 32)
return gpg_error (GPG_ERR_INV_ID);
else
{
for (s=keyidstr, n=0; hexdigitp (s); s++, n++)
;
- if (n != 32)
+
+ /* Check if it's a keygrip */
+ if (n == 40)
+ {
+ const unsigned char *keygrip_str;
+
+ keygrip_str = app->app_local->pk[keyno?keyno-1:0].keygrip_str;
+ if (!strncmp (keygrip_str, keyidstr, 40))
+ return 0;
+ else
+ return gpg_error (GPG_ERR_INV_ID);
+ }
+
+ if (n != 32 || strncmp (keyidstr, "D27600012401", 12))
return gpg_error (GPG_ERR_INV_ID);
else if (!*s)
; /* no fingerprint given: we allow this for now. */
@@ -4864,7 +4900,8 @@ do_check_pin (app_t app, const char *keyidstr,
if (rc)
return rc;
- if (strlen (keyidstr) >= 32+6 && !strcmp (keyidstr+32, "[CHV3]"))
+ if ((strlen (keyidstr) >= 32+6 && !strcmp (keyidstr+32, "[CHV3]"))
+ || (strlen (keyidstr) >= 40+6 && !strcmp (keyidstr+40, "[CHV3]")))
admin_pin = 1;
/* Yes, there is a race conditions: The user might pull the card