implementing private key deletion (#5536)

This commit is contained in:
Christian Grothoff 2019-03-11 03:24:32 +01:00
parent 82ce84fe67
commit a9268421d7
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
4 changed files with 85 additions and 58 deletions

View File

@ -1,3 +1,7 @@
Mon Mar 11 03:24:07 CET 2019
Completed implementation of #5536 (delete private keys once we
no longer need them). -CG
Sat Mar 2 19:09:43 CET 2019 Sat Mar 2 19:09:43 CET 2019
Changing denomination key revocation file format and moving them Changing denomination key revocation file format and moving them
to their own directory (preparations for #5536 resolution). -CG to their own directory (preparations for #5536 resolution). -CG

View File

@ -1,6 +1,6 @@
/* /*
This file is part of TALER This file is part of TALER
Copyright (C) 2014-2017 GNUnet e.V. Copyright (C) 2014--2019 GNUnet e.V.
TALER is free software; you can redistribute it and/or modify it under the TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU Affero General Public License as published by the Free Software terms of the GNU Affero General Public License as published by the Free Software
@ -629,7 +629,19 @@ add_revocations_transaction (void *cls,
int *mhd_ret) int *mhd_ret)
{ {
struct AddRevocationContext *arc = cls; struct AddRevocationContext *arc = cls;
enum GNUNET_DB_QueryStatus qs;
struct TALER_MasterSignatureP master_sig;
uint64_t rowid;
qs = TEH_plugin->get_denomination_revocation (TEH_plugin->cls,
session,
&arc->dki->issue.properties.denom_hash,
&master_sig,
&rowid);
if (0 > qs)
return qs; /* failure */
if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
return qs; /* already exists == success */
return TEH_plugin->insert_denomination_revocation (TEH_plugin->cls, return TEH_plugin->insert_denomination_revocation (TEH_plugin->cls,
session, session,
&arc->dki->issue.properties.denom_hash, &arc->dki->issue.properties.denom_hash,
@ -692,7 +704,6 @@ reload_keys_denom_iter (void *cls,
struct GNUNET_TIME_Absolute start; struct GNUNET_TIME_Absolute start;
struct GNUNET_TIME_Absolute horizon; struct GNUNET_TIME_Absolute horizon;
struct GNUNET_TIME_Absolute expire_deposit; struct GNUNET_TIME_Absolute expire_deposit;
int res;
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Loading denomination key `%s' (%s)\n", "Loading denomination key `%s' (%s)\n",
@ -747,10 +758,10 @@ reload_keys_denom_iter (void *cls,
"Adding denomination key `%s' (%s) to active set\n", "Adding denomination key `%s' (%s) to active set\n",
alias, alias,
GNUNET_h2s (&dki->issue.properties.denom_hash)); GNUNET_h2s (&dki->issue.properties.denom_hash));
res = store_in_map (key_state->denomkey_map, if (GNUNET_NO /* entry already exists */ ==
dki); store_in_map (key_state->denomkey_map,
if (GNUNET_NO == res) dki))
return GNUNET_OK; return GNUNET_OK; /* do not update expiration if entry exists */
key_state->min_dk_expire = GNUNET_TIME_absolute_min (key_state->min_dk_expire, key_state->min_dk_expire = GNUNET_TIME_absolute_min (key_state->min_dk_expire,
expire_deposit); expire_deposit);
return GNUNET_OK; return GNUNET_OK;
@ -774,51 +785,43 @@ revocations_iter (void *cls,
{ {
struct ResponseFactoryContext *rfc = cls; struct ResponseFactoryContext *rfc = cls;
struct TEH_KS_StateHandle *key_state = rfc->key_state; struct TEH_KS_StateHandle *key_state = rfc->key_state;
int res;
struct AddRevocationContext arc; struct AddRevocationContext arc;
const struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki; struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki;
dki = GNUNET_CONTAINER_multihashmap_get (key_state->denomkey_map,
denom_hash);
if (NULL == dki)
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"Revoked denomination `%s' unknown (or duplicate file), ignoring revocation\n",
GNUNET_h2s (denom_hash));
return GNUNET_OK;
}
GNUNET_log (GNUNET_ERROR_TYPE_INFO, GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Adding denomination key `%s' to revocation set\n", "Adding denomination key `%s' to revocation set\n",
GNUNET_h2s (denom_hash)); GNUNET_h2s (denom_hash));
dki = GNUNET_CONTAINER_multihashmap_get (key_state->denomkey_map,
denom_hash);
// FIXME: what do we do if dki is not known?
// especially what if we have neither private key NOR
// DB entry? (maybe ancient revocation? should we ignore it?)
if (NULL != dki)
{
GNUNET_assert (GNUNET_YES == GNUNET_assert (GNUNET_YES ==
GNUNET_CONTAINER_multihashmap_remove (key_state->denomkey_map, GNUNET_CONTAINER_multihashmap_remove (key_state->denomkey_map,
denom_hash, denom_hash,
dki)); dki));
if (GNUNET_NO == GNUNET_assert (GNUNET_YES ==
GNUNET_CONTAINER_multihashmap_put (key_state->revoked_map, GNUNET_CONTAINER_multihashmap_put (key_state->revoked_map,
&dki->issue.properties.denom_hash, &dki->issue.properties.denom_hash,
dki, dki,
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)) GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
{ /* Try to insert revocation into DB */
/* revocation file must exist twice, keep only one of the dkis */
GNUNET_CRYPTO_rsa_private_key_free (dki->denom_priv.rsa_private_key);
GNUNET_CRYPTO_rsa_public_key_free (dki->denom_pub.rsa_public_key);
GNUNET_free (dki);
return GNUNET_OK;
}
}
/* Try to insert DKI into DB until we succeed; note that if the DB
failure is persistent, we need to die, as we cannot continue
without the DKI being in the DB). */
arc.dki = dki; arc.dki = dki;
arc.revocation_master_sig = revocation_master_sig; arc.revocation_master_sig = revocation_master_sig;
if (GNUNET_OK != if (GNUNET_OK !=
TEH_DB_run_transaction (NULL, TEH_DB_run_transaction (NULL,
"add denomination key revocations", "add denomination key revocation",
NULL, NULL,
&add_revocations_transaction, &add_revocations_transaction,
&arc)) &arc))
{ {
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Giving up, this is fatal. Committing suicide via SIGTERM.\n"); "Failed to add revocation to database. This is fatal. Committing suicide via SIGTERM.\n");
handle_signal (SIGTERM); handle_signal (SIGTERM);
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
@ -1576,6 +1579,16 @@ make_fresh_key_state ()
return NULL; return NULL;
} }
/* We do not get expired DKIs from
TALER_EXCHANGEDB_denomination_keys_iterate(), so we must fetch
the old keys (where we only have the public keys) from the
database! */
qs = TEH_plugin->iterate_denomination_info (TEH_plugin->cls,
&reload_public_denoms_cb,
&rfc);
GNUNET_break (0 <= qs); /* warn, but continue, fingers crossed */
/* process revocations */
if (-1 == if (-1 ==
TALER_EXCHANGEDB_revocations_iterate (TEH_revocation_directory, TALER_EXCHANGEDB_revocations_iterate (TEH_revocation_directory,
&TEH_master_public_key, &TEH_master_public_key,
@ -1591,22 +1604,7 @@ make_fresh_key_state ()
json_decref (rfc.sign_keys_array); json_decref (rfc.sign_keys_array);
return NULL; return NULL;
} }
if (0 == GNUNET_CONTAINER_multihashmap_size (key_state->denomkey_map))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Have no denomination keys. Bad configuration.\n");
key_state->refcnt = 1;
ks_release (key_state);
destroy_response_factory (&rfc);
return NULL;
}
/* Once we no longer get expired DKIs from
TALER_EXCHANGEDB_denomination_keys_iterate(),
we must fetch the information from the database! */
qs = TEH_plugin->iterate_denomination_info (TEH_plugin->cls,
&reload_public_denoms_cb,
&rfc);
GNUNET_break (0 <= qs); /* warn, but continue, fingers crossed */
/* Initialize `current_sign_key_issue` and `rfc.sign_keys_array` */ /* Initialize `current_sign_key_issue` and `rfc.sign_keys_array` */
TALER_EXCHANGEDB_signing_keys_iterate (TEH_exchange_directory, TALER_EXCHANGEDB_signing_keys_iterate (TEH_exchange_directory,
&reload_keys_sign_iter, &reload_keys_sign_iter,
@ -1624,6 +1622,17 @@ make_fresh_key_state ()
return NULL; return NULL;
} }
/* sanity check */
if (0 == GNUNET_CONTAINER_multihashmap_size (key_state->denomkey_map))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Have no denomination keys. Bad configuration.\n");
key_state->refcnt = 1;
ks_release (key_state);
destroy_response_factory (&rfc);
return NULL;
}
/* Initialize and sort the `denomkey_array` */ /* Initialize and sort the `denomkey_array` */
rfc.denomkey_array rfc.denomkey_array
= GNUNET_new_array (GNUNET_CONTAINER_multihashmap_size (key_state->denomkey_map), = GNUNET_new_array (GNUNET_CONTAINER_multihashmap_size (key_state->denomkey_map),

View File

@ -158,8 +158,14 @@ TALER_EXCHANGEDB_denomination_key_read (const char *filename,
if (0 == GNUNET_TIME_absolute_get_remaining if (0 == GNUNET_TIME_absolute_get_remaining
(GNUNET_TIME_absolute_ntoh (dki->issue.properties.expire_withdraw)).rel_value_us) (GNUNET_TIME_absolute_ntoh (dki->issue.properties.expire_withdraw)).rel_value_us)
{ {
/* FIXME: #5536: we should delete this file, the if (0 != UNLINK (filename))
private key is no longer needed (and return SYSERR!) */ {
GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
"unlink",
filename);
return GNUNET_OK; /* yes, we had an error, but the file content
was fine and is being returned */
}
} }
return GNUNET_OK; return GNUNET_OK;
} }

View File

@ -76,8 +76,16 @@ signkeys_iterate_dir_iter (void *cls,
if (0 == GNUNET_TIME_absolute_get_remaining if (0 == GNUNET_TIME_absolute_get_remaining
(GNUNET_TIME_absolute_ntoh (issue.issue.expire)).rel_value_us) (GNUNET_TIME_absolute_ntoh (issue.issue.expire)).rel_value_us)
{ {
/* FIXME: #5536: we should delete this file, the if (0 != UNLINK (filename))
private key is no longer needed (and return SYSERR!) */ {
GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
"unlink",
filename);
return GNUNET_OK; /* yes, we had an error, but continue to iterate anyway */
}
/* Expired file deleted, continue to iterate -without- calling iterator
as this key is expired */
return GNUNET_OK;
} }
return skc->it (skc->it_cls, return skc->it (skc->it_cls,
filename, filename,