scd:nks: Handle APP_READKEY_FLAG_INFO.

* scd/app-nks.c (keygripstr_from_pk_file): Fix ignored error.
(get_nks_tag): New.
(do_learn_status_core): Use it.  Make sure not to mange the
KEYPAIRINFO line if no usage is known.
(do_readkey): Output the KEYPAIRINFO for the keygrip case.
--

Note that this only handles the most common case of providing a
keygrip.  $AUTHKEYID and ODLM are not yet supported.

Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
Werner Koch 2021-04-08 19:30:51 +02:00
parent 22fd48e48d
commit 63320ba2f8
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
1 changed files with 117 additions and 62 deletions

View File

@ -440,8 +440,9 @@ keygripstr_from_pk_file (app_t app, int pkfid, int cfid, char *r_gripstr,
}
err = pubkey_from_pk_file (app, pkfid, cfid, &pk, &pklen);
err = app_help_get_keygrip_string_pk (pk, pklen, r_gripstr, NULL,
&algo, &algostr);
if (!err)
err = app_help_get_keygrip_string_pk (pk, pklen, r_gripstr, NULL,
&algo, &algostr);
xfree (pk);
if (!err)
@ -794,14 +795,9 @@ do_getattr (app_t app, ctrl_t ctrl, const char *name)
}
static void
do_learn_status_core (app_t app, ctrl_t ctrl, unsigned int flags,
int nks_app_id)
const char *
get_nks_tag (app_t app, int nks_app_id)
{
gpg_error_t err;
char ct_buf[100], id_buf[100];
int i;
const char *tag;
if (nks_app_id == NKS_APP_ESIGN)
@ -815,6 +811,18 @@ do_learn_status_core (app_t app, ctrl_t ctrl, unsigned int flags,
else
tag = "NKS3";
return tag;
}
static void
do_learn_status_core (app_t app, ctrl_t ctrl, unsigned int flags,
int nks_app_id)
{
gpg_error_t err;
char ct_buf[100], id_buf[100];
int i;
const char *tag = get_nks_tag (app, nks_app_id);
/* Output information about all useful objects in the NKS application. */
for (i=0; filelist[i].fid; i++)
{
@ -867,6 +875,8 @@ do_learn_status_core (app_t app, ctrl_t ctrl, unsigned int flags,
usagebuf[usageidx++] = 'a';
if (filelist[i].isencrkey)
usagebuf[usageidx++] = 'e';
if (!usageidx)
usagebuf[usageidx++] = '-';
usagebuf[usageidx] = 0;
send_status_info (ctrl, "KEYPAIRINFO",
gripstr, 40,
@ -1198,13 +1208,63 @@ do_readkey (app_t app, ctrl_t ctrl, const char *keyid, unsigned int flags,
unsigned char **pk, size_t *pklen)
{
gpg_error_t err;
unsigned char *buffer[2];
size_t buflen[2];
unsigned short path[1] = { 0x4500 };
unsigned char *dummy_pk = NULL;
size_t dummy_pklen = 0;
if (!pk)
pk = &dummy_pk;
if (!pklen)
pklen = &dummy_pklen;
/* We use a generic name to retrieve PK.AUT.IFD-SPK. */
if (!strcmp (keyid, "$IFDAUTHKEY") && app->appversion >= 3)
;
{
unsigned short path[1] = { 0x4500 };
unsigned char *buffer[2];
size_t buflen[2];
/* Access the KEYD file which is always in the master directory. */
err = iso7816_select_path (app_get_slot (app), path, DIM (path), 0);
if (err)
goto leave;
/* Due to the above select we need to re-select our application. */
app->app_local->need_app_select = 1;
/* Get the two records. */
err = iso7816_read_record (app_get_slot (app), 5, 1, 0,
&buffer[0], &buflen[0]);
if (err)
goto leave;
if (all_zero_p (buffer[0], buflen[0]))
{
xfree (buffer[0]);
err = gpg_error (GPG_ERR_NOT_FOUND);
goto leave;
}
err = iso7816_read_record (app_get_slot (app), 6, 1, 0,
&buffer[1], &buflen[1]);
if (err)
{
xfree (buffer[0]);
goto leave;
}
if ((flags & APP_READKEY_FLAG_INFO))
{
/* FIXME */
}
if (pk && pklen && pk != &dummy_pk)
{
*pk = make_canon_sexp_from_rsa_pk (buffer[0], buflen[0],
buffer[1], buflen[1],
pklen);
if (!*pk)
err = gpg_error_from_syserror ();
}
xfree (buffer[0]);
xfree (buffer[1]);
}
else if (strlen (keyid) == 40)
{
char keygripstr[2*KEYGRIP_LEN+1];
@ -1212,10 +1272,42 @@ do_readkey (app_t app, ctrl_t ctrl, const char *keyid, unsigned int flags,
err = iterate_over_filelist (app, keyid, 0, keygripstr, &i);
if (err)
return err;
goto leave;
return pubkey_from_pk_file (app, filelist[i].fid, filelist[i].iskeypair,
pk, pklen);
err = pubkey_from_pk_file (app, filelist[i].fid, filelist[i].iskeypair,
pk, pklen);
if (!err && (flags & APP_READKEY_FLAG_INFO))
{
char *algostr;
char usagebuf[5];
int usageidx = 0;
char id_buf[100];
if (app_help_get_keygrip_string_pk (*pk, *pklen, NULL, NULL, NULL,
&algostr))
algostr = NULL; /* Ooops. */
snprintf (id_buf, sizeof id_buf, "NKS-%s.%04X",
get_nks_tag (app, filelist[i].nks_app_id),
filelist[i].fid);
if (filelist[i].issignkey)
usagebuf[usageidx++] = 's';
if (filelist[i].isauthkey)
usagebuf[usageidx++] = 'a';
if (filelist[i].isencrkey)
usagebuf[usageidx++] = 'e';
if (!usageidx)
usagebuf[usageidx++] = '-';
usagebuf[usageidx] = 0;
send_status_info (ctrl, "KEYPAIRINFO",
keygripstr, strlen (keygripstr),
id_buf, strlen (id_buf),
usagebuf, strlen (usagebuf),
"-", (size_t)1,
algostr, strlen (algostr?algostr:""),
NULL, (size_t)0);
xfree (algostr);
}
}
else if (!strncmp (keyid, "NKS-IDLM.", 9))
{
@ -1223,56 +1315,19 @@ do_readkey (app_t app, ctrl_t ctrl, const char *keyid, unsigned int flags,
if (!hexdigitp (keyid) || !hexdigitp (keyid+1)
|| !hexdigitp (keyid+2) || !hexdigitp (keyid+3)
|| keyid[4])
return gpg_error (GPG_ERR_INV_ID);
{
err = gpg_error (GPG_ERR_INV_ID);
goto leave;
}
return pubkey_from_pk_file (app, xtoi_4 (keyid), -1, pk, pklen);
err = pubkey_from_pk_file (app, xtoi_4 (keyid), -1, pk, pklen);
/* FIXME: Implement KEYPAIRINFO. */
}
else /* Return the error code expected by cmd_readkey. */
return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
err = gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
/* Access the KEYD file which is always in the master directory. */
err = iso7816_select_path (app_get_slot (app), path, DIM (path), 0);
if (err)
return err;
/* Due to the above select we need to re-select our application. */
app->app_local->need_app_select = 1;
/* Get the two records. */
err = iso7816_read_record (app_get_slot (app), 5, 1, 0,
&buffer[0], &buflen[0]);
if (err)
return err;
if (all_zero_p (buffer[0], buflen[0]))
{
xfree (buffer[0]);
return gpg_error (GPG_ERR_NOT_FOUND);
}
err = iso7816_read_record (app_get_slot (app), 6, 1, 0,
&buffer[1], &buflen[1]);
if (err)
{
xfree (buffer[0]);
return err;
}
if ((flags & APP_READKEY_FLAG_INFO))
{
/* Not yet implemented but we won't get here for any regular
* keyrefs anyway, thus the top layer will provide the
* keypairinfo from the certificate. */
(void)ctrl;
}
if (pk && pklen)
{
*pk = make_canon_sexp_from_rsa_pk (buffer[0], buflen[0],
buffer[1], buflen[1],
pklen);
if (!*pk)
err = gpg_error_from_syserror ();
}
xfree (buffer[0]);
xfree (buffer[1]);
leave:
xfree (dummy_pk);
return err;
}