summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNIIBE Yutaka <gniibe@fsij.org>2020-01-10 07:58:49 +0100
committerNIIBE Yutaka <gniibe@fsij.org>2020-01-10 07:58:49 +0100
commit0cfded4bb1484366c785c268f2fb1061c7be5fdb (patch)
treef0616de7da099c3b413b0cdf59dfe6e78036c7fe
parentscd:openpgp: Implement PIN cache. (diff)
downloadgnupg2-0cfded4bb1484366c785c268f2fb1061c7be5fdb.tar.xz
gnupg2-0cfded4bb1484366c785c268f2fb1061c7be5fdb.zip
scd: Implement direct access by KEYGRIP for GETATTR and READKEY.
* scd/app-openpgp.c (do_readkey): Handle KEYGRIP access. * scd/command.c (do_readkey): New. (cmd_readkey): Use do_readkey supporting KEYGRIP access. (cmd_getattr): Supporting KEYGRIP access. Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
Diffstat (limited to '')
-rw-r--r--scd/app-openpgp.c16
-rw-r--r--scd/command.c153
2 files changed, 119 insertions, 50 deletions
diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c
index b5906f887..2301ba3f5 100644
--- a/scd/app-openpgp.c
+++ b/scd/app-openpgp.c
@@ -1920,7 +1920,21 @@ do_readkey (app_t app, ctrl_t ctrl, const char *keyid, unsigned int flags,
int keyno;
unsigned char *buf;
- if (!strcmp (keyid, "OPENPGP.1"))
+ if (strlen (keyid) == 40)
+ {
+ const unsigned char *keygrip_str;
+
+ for (keyno = 0; keyno < 3; keyno++)
+ {
+ keygrip_str = app->app_local->pk[keyno].keygrip_str;
+ if (!strncmp (keygrip_str, keyid, 40))
+ break;
+ }
+
+ if (keyno >= 3)
+ return gpg_error (GPG_ERR_INV_ID);
+ }
+ else if (!strcmp (keyid, "OPENPGP.1"))
keyno = 0;
else if (!strcmp (keyid, "OPENPGP.2"))
keyno = 1;
diff --git a/scd/command.c b/scd/command.c
index 60da1a2da..9c58484c4 100644
--- a/scd/command.c
+++ b/scd/command.c
@@ -537,74 +537,56 @@ cmd_readcert (assuan_context_t ctx, char *line)
}
-static const char hlp_readkey[] =
- "READKEY [--advanced] [--info[-only]] <keyid>|<oid>\n"
- "\n"
- "Return the public key for the given cert or key ID as a standard\n"
- "S-expression. With --advanced the S-expression is returned in\n"
- "advanced format. With --info a KEYPAIRINFO status line is also\n"
- "emitted; with --info-only the regular output is suppressed.";
static gpg_error_t
-cmd_readkey (assuan_context_t ctx, char *line)
+do_readkey (card_t card, ctrl_t ctrl, const char *line,
+ int opt_info, int opt_nokey,
+ unsigned char **pk_p, size_t *pklen_p)
{
- ctrl_t ctrl = assuan_get_pointer (ctx);
int rc;
- int advanced = 0;
- int opt_info = 0;
- int opt_nokey = 0;
- unsigned char *cert = NULL;
- unsigned char *pk = NULL;
- size_t ncert, pklen;
-
- if ((rc = open_card (ctrl)))
- return rc;
-
- if (has_option (line, "--advanced"))
- advanced = 1;
- if (has_option (line, "--info"))
- opt_info = 1;
- if (has_option (line, "--info-only"))
- opt_info = opt_nokey = 1;
-
- line = skip_options (line);
- line = xstrdup (line); /* Need a copy of the line. */
/* If the application supports the READKEY function we use that.
Otherwise we use the old way by extracting it from the
certificate. */
- rc = app_readkey (ctrl->card_ctx, ctrl, line,
+ rc = app_readkey (card, ctrl, line,
opt_info? APP_READKEY_FLAG_INFO : 0,
- opt_nokey? NULL : &pk, &pklen);
+ opt_nokey? NULL : pk_p, pklen_p);
if (!rc)
- ; /* Okay, got that key. */
- else if (gpg_err_code (rc) == GPG_ERR_UNSUPPORTED_OPERATION
- || gpg_err_code (rc) == GPG_ERR_NOT_FOUND)
+ /* Okay, got that key. */
+ return 0;
+
+ if (gpg_err_code (rc) == GPG_ERR_UNSUPPORTED_OPERATION
+ || gpg_err_code (rc) == GPG_ERR_NOT_FOUND)
{
+ unsigned char *cert = NULL;
+ size_t ncert;
+
/* Fall back to certificate reading. */
- rc = app_readcert (ctrl->card_ctx, ctrl, line, &cert, &ncert);
+ rc = app_readcert (card, ctrl, line, &cert, &ncert);
if (rc)
{
log_error ("app_readcert failed: %s\n", gpg_strerror (rc));
- goto leave;
+ return rc;
}
- rc = app_help_pubkey_from_cert (cert, ncert, &pk, &pklen);
+
+ rc = app_help_pubkey_from_cert (cert, ncert, pk_p, pklen_p);
+ xfree (cert);
if (rc)
{
log_error ("failed to parse the certificate: %s\n",
gpg_strerror (rc));
- goto leave;
+ return rc;
}
if (opt_info)
{
char keygripstr[KEYGRIP_LEN*2+1];
- rc = app_help_get_keygrip_string_pk (pk, pklen, keygripstr);
+ rc = app_help_get_keygrip_string_pk (*pk_p, *pklen_p, keygripstr);
if (rc)
{
log_error ("app_help_get_keygrip_string failed: %s\n",
gpg_strerror (rc));
- goto leave;
+ return rc;
}
/* FIXME: Using LINE is not correct because it might be an
@@ -616,10 +598,64 @@ cmd_readkey (assuan_context_t ctx, char *line)
}
}
else
+ log_error ("app_readkey failed: %s\n", gpg_strerror (rc));
+
+ return rc;
+}
+
+static const char hlp_readkey[] =
+ "READKEY [--advanced] [--info[-only]] <keyid>|<oid>|<keygrip>\n"
+ "\n"
+ "Return the public key for the given cert or key ID as a standard\n"
+ "S-expression. With --advanced the S-expression is returned in\n"
+ "advanced format. With --info a KEYPAIRINFO status line is also\n"
+ "emitted; with --info-only the regular output is suppressed.";
+static gpg_error_t
+cmd_readkey (assuan_context_t ctx, char *line)
+{
+ ctrl_t ctrl = assuan_get_pointer (ctx);
+ int rc;
+ int advanced = 0;
+ int opt_info = 0;
+ int opt_nokey = 0;
+ unsigned char *pk = NULL;
+ size_t pklen;
+ card_t card;
+ int direct = 0;
+
+ if ((rc = open_card (ctrl)))
+ return rc;
+
+ if (has_option (line, "--advanced"))
+ advanced = 1;
+ if (has_option (line, "--info"))
+ opt_info = 1;
+ if (has_option (line, "--info-only"))
+ opt_info = opt_nokey = 1;
+
+ line = skip_options (line);
+ line = xstrdup (line); /* Need a copy of the line. */
+
+ if (strlen (line) == 40)
+ {
+ card = app_do_with_keygrip (ctrl, KEYGRIP_ACTION_LOOKUP, line, 0);
+ direct = 1;
+ }
+ else
+ card = ctrl->card_ctx;
+
+ if (card)
{
- log_error ("app_readkey failed: %s\n", gpg_strerror (rc));
- goto leave;
+ if (direct)
+ card_ref (card);
+
+ rc = do_readkey (card, ctrl, line, opt_info, opt_nokey, &pk, &pklen);
+
+ if (direct)
+ card_unref (card);
}
+ else
+ rc = gpg_error (GPG_ERR_NO_SECKEY);
if (opt_nokey)
;
@@ -653,7 +689,6 @@ cmd_readkey (assuan_context_t ctx, char *line)
leave:
xfree (pk);
- xfree (cert);
return rc;
}
@@ -1004,7 +1039,7 @@ cmd_pkdecrypt (assuan_context_t ctx, char *line)
static const char hlp_getattr[] =
- "GETATTR <name>\n"
+ "GETATTR <name> [<keygrip>]\n"
"\n"
"This command is used to retrieve data from a smartcard. The\n"
"allowed names depend on the currently selected smartcard\n"
@@ -1014,13 +1049,16 @@ static const char hlp_getattr[] =
"However, the current implementation assumes that Name is not escaped;\n"
"this works as long as no one uses arbitrary escaping. \n"
"\n"
- "Note, that this function may even be used on a locked card.";
+ "Note, that this function may even be used on a locked card.\n"
+ "When KEYGRIP is specified, it accesses directly with the KEYGRIP.";
static gpg_error_t
cmd_getattr (assuan_context_t ctx, char *line)
{
ctrl_t ctrl = assuan_get_pointer (ctx);
int rc;
const char *keyword;
+ card_t card;
+ int direct = 0;
if ((rc = open_card (ctrl)))
return rc;
@@ -1029,13 +1067,30 @@ cmd_getattr (assuan_context_t ctx, char *line)
for (; *line && !spacep (line); line++)
;
if (*line)
- *line++ = 0;
+ *line++ = 0;
+
+ if (strlen (line) == 40)
+ {
+ card = app_do_with_keygrip (ctrl, KEYGRIP_ACTION_LOOKUP, line, 0);
+ direct = 1;
+ }
+ else
+ card = ctrl->card_ctx;
- /* (We ignore any garbage for now.) */
+ if (card)
+ {
+ if (direct)
+ card_ref (card);
- /* FIXME: Applications should not return sensitive data if the card
- is locked. */
- rc = app_getattr (ctrl->card_ctx, ctrl, keyword);
+ /* FIXME: Applications should not return sensitive data if the card
+ is locked. */
+ rc = app_getattr (card, ctrl, keyword);
+
+ if (direct)
+ card_unref (card);
+ }
+ else
+ rc = gpg_error (GPG_ERR_NO_SECKEY);
return rc;
}