scd:p15: New flag APP_LEARN_FLAG_REREAD.

* scd/app-p15.c (do_deinit): Factor code out to ...
(release_lists, release_tokeninfo): new.
(read_ef_tokeninfo): Reset all data before reading.
(read_p15_info): Ditto.
(do_learn_status): Implement reread flag.
--

Objects of a card may be protected by a PIN and thus only readble
after a verify command.  This new flag makes it possible to gather the
entire PKCS#15 card info again without a need for a reset (and thus
loss of the verify status).

Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
Werner Koch 2021-04-01 10:28:07 +02:00
parent 1c16878efd
commit e17d3f8660
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
2 changed files with 72 additions and 26 deletions

View File

@ -45,6 +45,7 @@
/* Flags used by the app_write_learn_status. */
#define APP_LEARN_FLAG_KEYPAIRINFO 1 /* Return only keypair infos. */
#define APP_LEARN_FLAG_MULTI 2 /* Return info for all apps. */
#define APP_LEARN_FLAG_REREAD 4 /* Re-read ifnos from the token. */
/* List of supported card types. Generic is the usual ISO7817-4

View File

@ -589,22 +589,46 @@ release_aodflist (aodf_object_t a)
}
static void
release_lists (app_t app)
{
release_cdflist (app->app_local->certificate_info);
app->app_local->certificate_info = NULL;
release_cdflist (app->app_local->trusted_certificate_info);
app->app_local->trusted_certificate_info = NULL;
release_cdflist (app->app_local->useful_certificate_info);
app->app_local->useful_certificate_info = NULL;
release_pukdflist (app->app_local->public_key_info);
app->app_local->public_key_info = NULL;
release_prkdflist (app->app_local->private_key_info);
app->app_local->private_key_info = NULL;
release_aodflist (app->app_local->auth_object_info);
app->app_local->auth_object_info = NULL;
}
static void
release_tokeninfo (app_t app)
{
xfree (app->app_local->manufacturer_id);
app->app_local->manufacturer_id = NULL;
xfree (app->app_local->token_label);
app->app_local->token_label = NULL;
xfree (app->app_local->tokenflags);
app->app_local->tokenflags = NULL;
xfree (app->app_local->serialno);
app->app_local->serialno = NULL;
}
/* Release all local resources. */
static void
do_deinit (app_t app)
{
if (app && app->app_local)
{
release_cdflist (app->app_local->certificate_info);
release_cdflist (app->app_local->trusted_certificate_info);
release_cdflist (app->app_local->useful_certificate_info);
release_pukdflist (app->app_local->public_key_info);
release_prkdflist (app->app_local->private_key_info);
release_aodflist (app->app_local->auth_object_info);
xfree (app->app_local->manufacturer_id);
xfree (app->app_local->token_label);
xfree (app->app_local->tokenflags);
xfree (app->app_local->serialno);
release_lists (app);
release_tokeninfo (app);
xfree (app->app_local);
app->app_local = NULL;
}
@ -939,6 +963,17 @@ read_ef_odf (app_t app, unsigned short odf_fid)
size_t offset;
unsigned short home_df = 0;
app->app_local->odf.private_keys = 0;
app->app_local->odf.public_keys = 0;
app->app_local->odf.trusted_public_keys = 0;
app->app_local->odf.secret_keys = 0;
app->app_local->odf.certificates = 0;
app->app_local->odf.trusted_certificates = 0;
app->app_local->odf.useful_certificates = 0;
app->app_local->odf.data_objects = 0;
app->app_local->odf.auth_objects = 0;
err = select_and_read_binary (app, odf_fid, "ODF",
&buffer, &buflen);
if (err)
@ -3270,8 +3305,7 @@ read_ef_tokeninfo (app_t app)
int class, tag, constructed, ndef;
unsigned long ul;
xfree (app->app_local->manufacturer_id);
app->app_local->manufacturer_id = NULL;
release_tokeninfo (app);
app->app_local->card_product = CARD_PRODUCT_UNKNOWN;
err = select_and_read_binary (app, 0x5032, "TokenInfo", &buffer, &buflen);
@ -3401,22 +3435,24 @@ read_p15_info (app_t app)
prkdf_object_t prkdf;
unsigned int flag;
if (!read_ef_tokeninfo (app))
err = read_ef_tokeninfo (app);
if (err)
return err;
/* If we don't have a serial number yet but the TokenInfo provides
* one, use that. */
if (!APP_CARD(app)->serialno && app->app_local->serialno)
{
/* If we don't have a serial number yet but the TokenInfo provides
one, use that. */
if (!APP_CARD(app)->serialno && app->app_local->serialno)
{
APP_CARD(app)->serialno = app->app_local->serialno;
APP_CARD(app)->serialnolen = app->app_local->serialnolen;
app->app_local->serialno = NULL;
app->app_local->serialnolen = 0;
err = app_munge_serialno (APP_CARD(app));
if (err)
return err;
}
APP_CARD(app)->serialno = app->app_local->serialno;
APP_CARD(app)->serialnolen = app->app_local->serialnolen;
app->app_local->serialno = NULL;
app->app_local->serialnolen = 0;
err = app_munge_serialno (APP_CARD(app));
if (err)
return err;
}
release_lists (app);
/* Read the ODF so that we know the location of all directory
files. */
/* Fixme: We might need to get a non-standard ODF FID from TokenInfo. */
@ -4009,12 +4045,21 @@ send_keypairinfo (app_t app, ctrl_t ctrl, prkdf_object_t prkdf)
/* This is the handler for the LEARN command. */
/* This is the handler for the LEARN command. Note that if
* APP_LEARN_FLAG_REREAD is set and this function returns an error,
* the caller must deinitialize this application. */
static gpg_error_t
do_learn_status (app_t app, ctrl_t ctrl, unsigned int flags)
{
gpg_error_t err;
if (flags & APP_LEARN_FLAG_REREAD)
{
err = read_p15_info (app);
if (err)
return err;
}
if ((flags & APP_LEARN_FLAG_KEYPAIRINFO))
err = 0;
else