From e900bf29737b3f7a09f749a271f2c5d7b59c49eb Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Mon, 17 Jun 2019 18:04:36 +0200 Subject: [PATCH] scd:piv: Add the do_with_keygrip feature. * scd/app-piv.c (do_with_keygrip): New. (app_select_piv): Register function. Signed-off-by: Werner Koch --- scd/app-piv.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++ scd/command.c | 6 ++++ 2 files changed, 95 insertions(+) diff --git a/scd/app-piv.c b/scd/app-piv.c index f13ef52ee..2ee72e0fc 100644 --- a/scd/app-piv.c +++ b/scd/app-piv.c @@ -3300,6 +3300,94 @@ do_writecert (app_t app, ctrl_t ctrl, } +/* Process the various keygrip based info requests. */ +static gpg_error_t +do_with_keygrip (app_t app, ctrl_t ctrl, int action, + const char *want_keygripstr) +{ + gpg_error_t err; + char *keygripstr = NULL; + char *serialno = NULL; + char idbuf[20]; + int data = 0; + int i, tag, dummy_got_cert; + + /* First a quick check for valid parameters. */ + switch (action) + { + case KEYGRIP_ACTION_LOOKUP: + if (!want_keygripstr) + { + err = gpg_error (GPG_ERR_NOT_FOUND); + goto leave; + } + break; + case KEYGRIP_ACTION_SEND_DATA: + data = 1; + break; + case KEYGRIP_ACTION_WRITE_STATUS: + break; + default: + err = gpg_error (GPG_ERR_INV_ARG); + goto leave; + } + + /* Allocate the s/n string if needed. */ + if (action != KEYGRIP_ACTION_LOOKUP) + { + serialno = app_get_serialno (app); + if (!serialno) + { + err = gpg_error_from_syserror (); + goto leave; + } + } + + for (i = 0; (tag = data_objects[i].tag); i++) + { + if (!data_objects[i].keypair) + continue; + + xfree (keygripstr); + if (get_keygrip_by_tag (app, tag, &keygripstr, &dummy_got_cert)) + continue; + + if (action == KEYGRIP_ACTION_LOOKUP) + { + if (!strcmp (keygripstr, want_keygripstr)) + { + err = 0; /* Found */ + goto leave; + } + } + else if (!want_keygripstr || !strcmp (keygripstr, want_keygripstr)) + { + snprintf (idbuf, sizeof idbuf, "PIV.%s", data_objects[i].keyref); + send_keyinfo (ctrl, data, keygripstr, serialno, idbuf); + if (want_keygripstr) + { + err = 0; /* Found */ + goto leave; + } + } + } + + /* Return an error so that the dispatcher keeps on looping over the + * other applications. For clarity we use a different error code + * when listing all keys. Note that in lookup mode WANT_KEYGRIPSTR + * is not NULL. */ + if (!want_keygripstr) + err = gpg_error (GPG_ERR_TRUE); + else + err = gpg_error (GPG_ERR_NOT_FOUND); + + leave: + xfree (keygripstr); + xfree (serialno); + return err; +} + + /* Select the PIV application on the card in SLOT. This function must * be used before any other PIV application functions. */ gpg_error_t @@ -3398,6 +3486,7 @@ app_select_piv (app_t app) app->fnc.decipher = do_decipher; app->fnc.change_pin = do_change_chv; app->fnc.check_pin = do_check_chv; + app->fnc.with_keygrip = do_with_keygrip; leave: diff --git a/scd/command.c b/scd/command.c index 426615c8b..4f4005458 100644 --- a/scd/command.c +++ b/scd/command.c @@ -1874,6 +1874,10 @@ cmd_keyinfo (assuan_context_t ctx, char *line) return 0; } + +/* Send a keyinfo string as used by the KEYGRIP_ACTION_SEND_DATA. If + * DATA is true the string is emitted as a data line, else as a status + * line. */ void send_keyinfo (ctrl_t ctrl, int data, const char *keygrip_str, const char *serialno, const char *idstr) @@ -1895,6 +1899,8 @@ send_keyinfo (ctrl_t ctrl, int data, const char *keygrip_str, xfree (string); return; } + + /* Tell the assuan library about our commands */ static int