mirror of
git://git.gnupg.org/gnupg.git
synced 2025-02-01 16:33:02 +01:00
scd:piv: Allow writecert to only write matching certs.
* scd/app-piv.c (do_readkey): Read the key from the cert here instead of letting the upper layer do this. (do_writecert): Check that the cert matches the key and that a key has already been generated. Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
parent
280baee72d
commit
696d4c290d
@ -1450,27 +1450,32 @@ do_readkey (app_t app, const char *keyrefstr,
|
|||||||
goto leave;
|
goto leave;
|
||||||
if (!mechanism)
|
if (!mechanism)
|
||||||
{
|
{
|
||||||
/* We got a certificate. Let the upper layer handle the
|
/* We got a certificate. Extract the pubkey from it. */
|
||||||
* extraction of the key. FIXME: It would be better to have a
|
err = app_help_pubkey_from_cert (cert, certlen, &pk, &pklen);
|
||||||
* shared fucntion to dothis here. */
|
if (err)
|
||||||
err = gpg_error (GPG_ERR_NOT_FOUND);
|
{
|
||||||
goto leave;
|
log_error ("failed to parse the certificate: %s\n",
|
||||||
|
gpg_strerror (err));
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Convert the public key into the expected s-expression. */
|
|
||||||
if (mechanism == PIV_ALGORITHM_RSA)
|
|
||||||
err = genkey_parse_rsa (cert, certlen, &s_pkey);
|
|
||||||
else if (mechanism == PIV_ALGORITHM_ECC_P256
|
|
||||||
|| mechanism == PIV_ALGORITHM_ECC_P384)
|
|
||||||
err = genkey_parse_ecc (cert, certlen, mechanism, &s_pkey);
|
|
||||||
else
|
else
|
||||||
err = gpg_error (GPG_ERR_PUBKEY_ALGO);
|
{
|
||||||
if (err)
|
/* Convert the public key into the expected s-expression. */
|
||||||
goto leave;
|
if (mechanism == PIV_ALGORITHM_RSA)
|
||||||
|
err = genkey_parse_rsa (cert, certlen, &s_pkey);
|
||||||
|
else if (mechanism == PIV_ALGORITHM_ECC_P256
|
||||||
|
|| mechanism == PIV_ALGORITHM_ECC_P384)
|
||||||
|
err = genkey_parse_ecc (cert, certlen, mechanism, &s_pkey);
|
||||||
|
else
|
||||||
|
err = gpg_error (GPG_ERR_PUBKEY_ALGO);
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
|
||||||
err = make_canon_sexp (s_pkey, &pk, &pklen);
|
err = make_canon_sexp (s_pkey, &pk, &pklen);
|
||||||
if (err)
|
if (err)
|
||||||
goto leave;
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
*r_pk = pk;
|
*r_pk = pk;
|
||||||
pk = NULL;
|
pk = NULL;
|
||||||
@ -2735,6 +2740,9 @@ do_writecert (app_t app, ctrl_t ctrl,
|
|||||||
{
|
{
|
||||||
gpg_error_t err;
|
gpg_error_t err;
|
||||||
data_object_t dobj;
|
data_object_t dobj;
|
||||||
|
unsigned char *pk = NULL;
|
||||||
|
unsigned char *orig_pk = NULL;
|
||||||
|
size_t pklen, orig_pklen;
|
||||||
|
|
||||||
(void)ctrl;
|
(void)ctrl;
|
||||||
(void)pincb; /* Not used; instead authentication is needed. */
|
(void)pincb; /* Not used; instead authentication is needed. */
|
||||||
@ -2746,10 +2754,33 @@ do_writecert (app_t app, ctrl_t ctrl,
|
|||||||
|
|
||||||
/* FIXME: Check that the authentication has already been done. */
|
/* FIXME: Check that the authentication has already been done. */
|
||||||
|
|
||||||
/* FIXME: Check that the public key parameters from the certificate
|
|
||||||
* match an already stored key. */
|
|
||||||
|
|
||||||
flush_cached_data (app, dobj->tag);
|
flush_cached_data (app, dobj->tag);
|
||||||
|
|
||||||
|
/* Check that the public key parameters from the certificate match
|
||||||
|
* an already stored key. Note that we do not allow writing a
|
||||||
|
* certificate if no key has yet been created (GPG_ERR_NOT_FOUND) or
|
||||||
|
* if there is a problem reading the public key from the certificate
|
||||||
|
* GPG_ERR_NO_PUBKEY). We enforce this because otherwise the only
|
||||||
|
* way to detect whether a key exists is by trying to use that
|
||||||
|
* key. */
|
||||||
|
err = do_readkey (app, certrefstr, &orig_pk, &orig_pklen);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
if (gpg_err_code (err) == GPG_ERR_NOT_FOUND)
|
||||||
|
err = gpg_error (GPG_ERR_NO_SECKEY); /* Use a better error code. */
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
/* Compare pubkeys. */
|
||||||
|
err = app_help_pubkey_from_cert (cert, certlen, &pk, &pklen);
|
||||||
|
if (err)
|
||||||
|
goto leave; /* No public key in new certificate. */
|
||||||
|
if (orig_pklen != pklen || memcmp (orig_pk, pk, pklen))
|
||||||
|
{
|
||||||
|
err = gpg_error (GPG_ERR_CONFLICT);
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
err = put_data (app->slot, dobj->tag,
|
err = put_data (app->slot, dobj->tag,
|
||||||
(int)0x70, (size_t)certlen, cert,/* Certificate */
|
(int)0x70, (size_t)certlen, cert,/* Certificate */
|
||||||
(int)0x71, (size_t)1, "", /* No compress */
|
(int)0x71, (size_t)1, "", /* No compress */
|
||||||
@ -2762,7 +2793,9 @@ do_writecert (app_t app, ctrl_t ctrl,
|
|||||||
log_error ("piv: failed to write cert to %s: %s\n",
|
log_error ("piv: failed to write cert to %s: %s\n",
|
||||||
dobj->keyref, gpg_strerror (err));
|
dobj->keyref, gpg_strerror (err));
|
||||||
|
|
||||||
|
leave:
|
||||||
|
xfree (pk);
|
||||||
|
xfree (orig_pk);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user