diff options
author | NIIBE Yutaka <gniibe@fsij.org> | 2020-01-10 07:58:49 +0100 |
---|---|---|
committer | NIIBE Yutaka <gniibe@fsij.org> | 2020-01-10 07:58:49 +0100 |
commit | 0cfded4bb1484366c785c268f2fb1061c7be5fdb (patch) | |
tree | f0616de7da099c3b413b0cdf59dfe6e78036c7fe | |
parent | scd:openpgp: Implement PIN cache. (diff) | |
download | gnupg2-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.c | 16 | ||||
-rw-r--r-- | scd/command.c | 153 |
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; } |