1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-12-22 10:19:57 +01:00

scd:p15: Implement do_with_keygrip and capabilities.

* scd/app-p15.c (prepare_verify_pin): Allow use without an AODF.
(verify_pin): Ditto.
(do_with_keygrip): Implement capability restrictions.

Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
Werner Koch 2020-04-02 14:23:26 +02:00
parent 8149742ddf
commit 61c5b0767f
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B

View File

@ -3100,7 +3100,7 @@ micardo_mse (app_t app, unsigned short fid)
/* Prepare the verification of the PIN for the key PRKDF by checking /* Prepare the verification of the PIN for the key PRKDF by checking
* the AODF and selecting the key file. KEYREF is used for error * the AODF and selecting the key file. KEYREF is used for error
* messages. */ * messages. AODF may be NULL if no verification needs to be done. */
static gpg_error_t static gpg_error_t
prepare_verify_pin (app_t app, const char *keyref, prepare_verify_pin (app_t app, const char *keyref,
prkdf_object_t prkdf, aodf_object_t aodf) prkdf_object_t prkdf, aodf_object_t aodf)
@ -3108,6 +3108,8 @@ prepare_verify_pin (app_t app, const char *keyref,
gpg_error_t err; gpg_error_t err;
int i; int i;
if (aodf)
{
if (opt.verbose) if (opt.verbose)
{ {
log_info ("p15: using AODF %04hX id=", aodf->fid); log_info ("p15: using AODF %04hX id=", aodf->fid);
@ -3122,16 +3124,17 @@ prepare_verify_pin (app_t app, const char *keyref,
if (aodf->pinflags.integrity_protected if (aodf->pinflags.integrity_protected
|| aodf->pinflags.confidentiality_protected) || aodf->pinflags.confidentiality_protected)
{ {
log_error ("p15: " log_error ("p15: PIN verification requires"
"PIN verification requires unsupported protection method\n"); " unsupported protection method\n");
return gpg_error (GPG_ERR_BAD_PIN_METHOD); return gpg_error (GPG_ERR_BAD_PIN_METHOD);
} }
if (!aodf->stored_length && aodf->pinflags.needs_padding) if (!aodf->stored_length && aodf->pinflags.needs_padding)
{ {
log_error ("p15: " log_error ("p15: PIN verification requires"
"PIN verification requires padding but no length known\n"); " padding but no length known\n");
return gpg_error (GPG_ERR_INV_CARD); return gpg_error (GPG_ERR_INV_CARD);
} }
}
/* Select the key file. Note that this may change the security /* Select the key file. Note that this may change the security
* environment thus we need to do it before PIN verification. */ * environment thus we need to do it before PIN verification. */
@ -3145,7 +3148,8 @@ prepare_verify_pin (app_t app, const char *keyref,
/* 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. */ * AODF ask for the PIN and verify that PIN. IF AODF is NULL, no
* authentication is done. */
static gpg_error_t static gpg_error_t
verify_pin (app_t app, verify_pin (app_t app,
gpg_error_t (*pincb)(void*, const char *, char **), void *pincb_arg, gpg_error_t (*pincb)(void*, const char *, char **), void *pincb_arg,
@ -3158,6 +3162,9 @@ verify_pin (app_t app,
const char *s; const char *s;
int i; int i;
if (!aodf)
return 0;
if (prkdf->pin_verified) if (prkdf->pin_verified)
return 0; /* Already done. */ return 0; /* Already done. */
@ -3385,10 +3392,7 @@ do_sign (app_t app, ctrl_t ctrl, const char *keyidstr, int hashalgo,
&& !memcmp (aodf->objid, prkdf->authid, prkdf->authidlen)) && !memcmp (aodf->objid, prkdf->authid, prkdf->authidlen))
break; break;
if (!aodf) if (!aodf)
{ log_info ("p15: no authentication for %s needed\n", keyidstr);
log_error ("p15: authentication object for %s missing\n", keyidstr);
return gpg_error (GPG_ERR_INV_CARD);
}
/* We need some more info about the key - get the keygrip to /* We need some more info about the key - get the keygrip to
* populate these fields. */ * populate these fields. */
@ -3399,7 +3403,6 @@ do_sign (app_t app, ctrl_t ctrl, const char *keyidstr, int hashalgo,
return err; return err;
} }
/* Prepare PIN verification. This is split so that we can do /* Prepare PIN verification. This is split so that we can do
* MSE operation for some task after having selected the key file but * MSE operation for some task after having selected the key file but
* before sending the verify APDU. */ * before sending the verify APDU. */
@ -3654,10 +3657,7 @@ do_decipher (app_t app, ctrl_t ctrl, const char *keyidstr,
&& !memcmp (aodf->objid, prkdf->authid, prkdf->authidlen)) && !memcmp (aodf->objid, prkdf->authid, prkdf->authidlen))
break; break;
if (!aodf) if (!aodf)
{ log_info ("p15: no authentication for %s needed\n", keyidstr);
log_error ("p15: authentication object for %s missing\n", keyidstr);
return gpg_error (GPG_ERR_INV_CARD);
}
/* We need some more info about the key - get the keygrip to /* We need some more info about the key - get the keygrip to
* populate these fields. */ * populate these fields. */
@ -3758,7 +3758,6 @@ do_with_keygrip (app_t app, ctrl_t ctrl, int action,
for (prkdf = app->app_local->private_key_info; for (prkdf = app->app_local->private_key_info;
prkdf; prkdf = prkdf->next) prkdf; prkdf = prkdf->next)
{ {
if (keygrip_from_prkdf (app, prkdf)) if (keygrip_from_prkdf (app, prkdf))
continue; continue;
@ -3774,8 +3773,22 @@ do_with_keygrip (app_t app, ctrl_t ctrl, int action,
{ {
char *keyref; char *keyref;
/* FIXME: Consider ... */ if (capability == GCRY_PK_USAGE_SIGN)
(void)capability; {
if (!(prkdf->usageflags.sign || prkdf->usageflags.sign_recover
|| prkdf->usageflags.non_repudiation))
continue;
}
else if (capability == GCRY_PK_USAGE_ENCR)
{
if (!(prkdf->usageflags.decrypt || prkdf->usageflags.unwrap))
continue;
}
else if (capability == GCRY_PK_USAGE_AUTH)
{
if (!(prkdf->usageflags.sign || prkdf->usageflags.sign_recover))
continue;
}
keyref = keyref_from_prkdf (app, prkdf); keyref = keyref_from_prkdf (app, prkdf);
if (!keyref) if (!keyref)
@ -3785,6 +3798,7 @@ do_with_keygrip (app_t app, ctrl_t ctrl, int action,
} }
send_keyinfo (ctrl, as_data, prkdf->keygrip, serialno, keyref); send_keyinfo (ctrl, as_data, prkdf->keygrip, serialno, keyref);
xfree (keyref);
if (want_keygripstr) if (want_keygripstr)
{ {
err = 0; /* Found */ err = 0; /* Found */