mirror of
git://git.gnupg.org/gnupg.git
synced 2025-01-02 12:01:32 +01:00
scd:p15: Implement CHV-STATUS attribute
* scd/command.c (send_status_direct): Return an error. * scd/app-p15.c (do_learn_status): Emit CHV-STATUS. (compare_aodf_objid): New. (do_getattr): Implement CHV-STATUS.
This commit is contained in:
parent
e4c2d7be22
commit
bf1d7bc369
114
scd/app-p15.c
114
scd/app-p15.c
@ -3885,6 +3885,10 @@ do_learn_status (app_t app, ctrl_t ctrl, unsigned int flags)
|
|||||||
if (!err)
|
if (!err)
|
||||||
err = send_keypairinfo (app, ctrl, app->app_local->private_key_info);
|
err = send_keypairinfo (app, ctrl, app->app_local->private_key_info);
|
||||||
|
|
||||||
|
if (!err)
|
||||||
|
err = do_getattr (app, ctrl, "CHV-STATUS");
|
||||||
|
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4068,6 +4072,27 @@ do_readcert (app_t app, const char *certid,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Sort helper for an array of authentication objects. */
|
||||||
|
static int
|
||||||
|
compare_aodf_objid (const void *arg_a, const void *arg_b)
|
||||||
|
{
|
||||||
|
const aodf_object_t a = *(const aodf_object_t *)arg_a;
|
||||||
|
const aodf_object_t b = *(const aodf_object_t *)arg_b;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = memcmp (a->objid, b->objid,
|
||||||
|
a->objidlen < b->objidlen? a->objidlen : b->objidlen);
|
||||||
|
if (!rc)
|
||||||
|
{
|
||||||
|
if (a->objidlen < b->objidlen)
|
||||||
|
rc = -1;
|
||||||
|
else if (a->objidlen > b->objidlen)
|
||||||
|
rc = 1;
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Implement the GETATTR command. This is similar to the LEARN
|
/* Implement the GETATTR command. This is similar to the LEARN
|
||||||
command but returns just one value via the status interface. */
|
command but returns just one value via the status interface. */
|
||||||
@ -4195,6 +4220,46 @@ do_getattr (app_t app, ctrl_t ctrl, const char *name)
|
|||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
else if (!strcmp (name, "CHV-STATUS"))
|
||||||
|
{
|
||||||
|
aodf_object_t aodf;
|
||||||
|
aodf_object_t aodfarray[16];
|
||||||
|
int naodf = 0;
|
||||||
|
membuf_t mb;
|
||||||
|
char *p;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Put the AODFs into an array for easier sorting. Note that we
|
||||||
|
* handle onl the first 16 encountrer which should be more than
|
||||||
|
* enough. */
|
||||||
|
for (aodf = app->app_local->auth_object_info;
|
||||||
|
aodf && naodf < DIM(aodfarray); aodf = aodf->next)
|
||||||
|
if (aodf->objidlen && aodf->pin_reference_valid)
|
||||||
|
aodfarray[naodf++] = aodf;
|
||||||
|
qsort (aodfarray, naodf, sizeof *aodfarray, compare_aodf_objid);
|
||||||
|
|
||||||
|
init_membuf (&mb, 256);
|
||||||
|
for (i = 0; i < naodf; i++)
|
||||||
|
{
|
||||||
|
/* int j; */
|
||||||
|
/* log_debug ("p15: AODF[%d] pinref=%lu id=", */
|
||||||
|
/* i, aodfarray[i]->pin_reference); */
|
||||||
|
/* for (j=0; j < aodfarray[i]->objidlen; j++) */
|
||||||
|
/* log_printf ("%02X", aodfarray[i]->objid[j]); */
|
||||||
|
|
||||||
|
put_membuf_printf
|
||||||
|
(&mb, "%s%d", i? " ":"",
|
||||||
|
iso7816_verify_status (app_get_slot (app),
|
||||||
|
aodfarray[i]->pin_reference));
|
||||||
|
}
|
||||||
|
put_membuf( &mb, "", 1);
|
||||||
|
p = get_membuf (&mb, NULL);
|
||||||
|
if (!p)
|
||||||
|
return gpg_error_from_syserror ();
|
||||||
|
err = send_status_direct (ctrl, "CHV-STATUS", p);
|
||||||
|
xfree (p);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
return gpg_error (GPG_ERR_INV_NAME);
|
return gpg_error (GPG_ERR_INV_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4463,7 +4528,7 @@ make_pin_prompt (app_t app, int remaining, const char *firstline,
|
|||||||
|
|
||||||
|
|
||||||
/* Given the private key object PRKDF and its authentication object
|
/* Given the private key object PRKDF and its authentication object
|
||||||
* AODF ask for the PIN and verify that PIN. IF AODF is NULL, no
|
* AODF ask for the PIN and verify that PIN. If AODF is NULL, no
|
||||||
* authentication is done. */
|
* authentication is done. */
|
||||||
static gpg_error_t
|
static gpg_error_t
|
||||||
verify_pin (app_t app,
|
verify_pin (app_t app,
|
||||||
@ -4985,7 +5050,7 @@ do_decipher (app_t app, ctrl_t ctrl, const char *keyidstr,
|
|||||||
return err;
|
return err;
|
||||||
if (!(prkdf->usageflags.decrypt || prkdf->usageflags.unwrap))
|
if (!(prkdf->usageflags.decrypt || prkdf->usageflags.unwrap))
|
||||||
{
|
{
|
||||||
log_error ("p15: key %s may not be used for decruption\n", keyidstr);
|
log_error ("p15: key %s may not be used for decryption\n", keyidstr);
|
||||||
return gpg_error (GPG_ERR_WRONG_KEY_USAGE);
|
return gpg_error (GPG_ERR_WRONG_KEY_USAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5082,6 +5147,49 @@ do_decipher (app_t app, ctrl_t ctrl, const char *keyidstr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Perform a simple verify operation for the PIN specified by
|
||||||
|
* KEYIDSTR. Note that we require a key reference which is then used
|
||||||
|
* to select the authentication object. Return GPG_ERR_NO_PIN if a
|
||||||
|
* PIN is not required for using the private key KEYIDSTR. */
|
||||||
|
static gpg_error_t
|
||||||
|
do_check_pin (app_t app, ctrl_t ctrl, const char *keyidstr,
|
||||||
|
gpg_error_t (*pincb)(void*, const char *, char **),
|
||||||
|
void *pincb_arg)
|
||||||
|
{
|
||||||
|
gpg_error_t err;
|
||||||
|
prkdf_object_t prkdf; /* The private key object. */
|
||||||
|
aodf_object_t aodf; /* The associated authentication object. */
|
||||||
|
|
||||||
|
(void)ctrl;
|
||||||
|
|
||||||
|
if (!keyidstr || !*keyidstr)
|
||||||
|
return gpg_error (GPG_ERR_INV_VALUE);
|
||||||
|
|
||||||
|
err = prkdf_object_from_keyidstr (app, keyidstr, &prkdf);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
/* Find the authentication object to this private key object. */
|
||||||
|
if (!prkdf->authid)
|
||||||
|
{
|
||||||
|
log_error ("p15: no authentication object defined for %s\n", keyidstr);
|
||||||
|
return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
|
||||||
|
}
|
||||||
|
for (aodf = app->app_local->auth_object_info; aodf; aodf = aodf->next)
|
||||||
|
if (aodf->objidlen == prkdf->authidlen
|
||||||
|
&& !memcmp (aodf->objid, prkdf->authid, prkdf->authidlen))
|
||||||
|
break;
|
||||||
|
if (!aodf) /* None found. */
|
||||||
|
return gpg_error (GPG_ERR_NO_PIN);
|
||||||
|
|
||||||
|
err = prepare_verify_pin (app, keyidstr, prkdf, aodf);
|
||||||
|
if (!err)
|
||||||
|
err = verify_pin (app, pincb, pincb_arg, prkdf, aodf);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Process the various keygrip based info requests. */
|
/* Process the various keygrip based info requests. */
|
||||||
static gpg_error_t
|
static gpg_error_t
|
||||||
do_with_keygrip (app_t app, ctrl_t ctrl, int action,
|
do_with_keygrip (app_t app, ctrl_t ctrl, int action,
|
||||||
@ -5404,7 +5512,7 @@ app_select_p15 (app_t app)
|
|||||||
app->fnc.auth = do_auth;
|
app->fnc.auth = do_auth;
|
||||||
app->fnc.decipher = do_decipher;
|
app->fnc.decipher = do_decipher;
|
||||||
app->fnc.change_pin = NULL;
|
app->fnc.change_pin = NULL;
|
||||||
app->fnc.check_pin = NULL;
|
app->fnc.check_pin = do_check_pin;
|
||||||
app->fnc.with_keygrip = do_with_keygrip;
|
app->fnc.with_keygrip = do_with_keygrip;
|
||||||
|
|
||||||
leave:
|
leave:
|
||||||
|
@ -2458,15 +2458,17 @@ send_status_info (ctrl_t ctrl, const char *keyword, ...)
|
|||||||
|
|
||||||
|
|
||||||
/* Send a ready formatted status line via assuan. */
|
/* Send a ready formatted status line via assuan. */
|
||||||
void
|
gpg_error_t
|
||||||
send_status_direct (ctrl_t ctrl, const char *keyword, const char *args)
|
send_status_direct (ctrl_t ctrl, const char *keyword, const char *args)
|
||||||
{
|
{
|
||||||
assuan_context_t ctx = ctrl->server_local->assuan_ctx;
|
assuan_context_t ctx = ctrl->server_local->assuan_ctx;
|
||||||
|
|
||||||
if (strchr (args, '\n'))
|
if (strchr (args, '\n'))
|
||||||
log_error ("error: LF detected in status line - not sending\n");
|
{
|
||||||
else
|
log_error ("error: LF detected in status line - not sending\n");
|
||||||
assuan_write_status (ctx, keyword, args);
|
return gpg_error (GPG_ERR_INTERNAL);
|
||||||
|
}
|
||||||
|
return assuan_write_status (ctx, keyword, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -133,7 +133,8 @@ gpg_error_t initialize_module_command (void);
|
|||||||
int scd_command_handler (ctrl_t, int);
|
int scd_command_handler (ctrl_t, int);
|
||||||
void send_status_info (ctrl_t ctrl, const char *keyword, ...)
|
void send_status_info (ctrl_t ctrl, const char *keyword, ...)
|
||||||
GPGRT_ATTR_SENTINEL(1);
|
GPGRT_ATTR_SENTINEL(1);
|
||||||
void send_status_direct (ctrl_t ctrl, const char *keyword, const char *args);
|
gpg_error_t send_status_direct (ctrl_t ctrl,
|
||||||
|
const char *keyword, const char *args);
|
||||||
gpg_error_t send_status_printf (ctrl_t ctrl, const char *keyword,
|
gpg_error_t send_status_printf (ctrl_t ctrl, const char *keyword,
|
||||||
const char *format, ...) GPGRT_ATTR_PRINTF(3,4);
|
const char *format, ...) GPGRT_ATTR_PRINTF(3,4);
|
||||||
void send_keyinfo (ctrl_t ctrl, int data, const char *keygrip_str,
|
void send_keyinfo (ctrl_t ctrl, int data, const char *keygrip_str,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user