From 11b8710a5caac9c81cb0eb6094b363fa46a74809 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 8 Apr 2017 22:52:32 +0200 Subject: [PATCH] implement checking of denomination revocation status in auditor --- src/auditor/taler-auditor.c | 41 ++++++++++++- src/exchange-tools/taler-exchange-keycheck.c | 4 +- src/exchange-tools/taler-exchange-keyup.c | 6 +- src/exchange/taler-exchange-httpd_keystate.c | 64 ++++++++++++++++---- src/exchangedb/exchangedb_denomkeys.c | 7 +-- src/exchangedb/test_exchangedb_denomkeys.c | 4 +- src/include/taler_exchangedb_lib.h | 4 +- src/include/taler_exchangedb_plugin.h | 2 + 8 files changed, 106 insertions(+), 26 deletions(-) diff --git a/src/auditor/taler-auditor.c b/src/auditor/taler-auditor.c index 5576bd6a2..c4fb025d2 100644 --- a/src/auditor/taler-auditor.c +++ b/src/auditor/taler-auditor.c @@ -831,6 +831,8 @@ handle_payback_by_reserve (void *cls, struct ReserveSummary *rs; struct GNUNET_TIME_Absolute expiry; struct TALER_PaybackRequestPS pr; + struct TALER_MasterSignatureP msig; + int ret; /* should be monotonically increasing */ GNUNET_assert (rowid >= pp.last_reserve_payback_serial_id); @@ -859,7 +861,44 @@ handle_payback_by_reserve (void *cls, rowid, "coin payback signature invalid"); } - /* TODO: check that the coin was eligible for payback! #3887!*/ + + /* check that the coin was eligible for payback!*/ + ret = edb->get_denomination_revocation (edb->cls, + esession, + &pr.h_denom_pub, + &msig); + if (GNUNET_SYSERR == ret) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + if (GNUNET_NO == ret) + { + report_row_inconsistency ("payback", + rowid, + "denomination key not in revocation set"); + } + else + { + /* verify msig */ + struct TALER_MasterDenominationKeyRevocation kr; + + kr.purpose.purpose = htonl (TALER_SIGNATURE_MASTER_DENOMINATION_KEY_REVOKED); + kr.purpose.size = htonl (sizeof (kr)); + kr.h_denom_pub = pr.h_denom_pub; + if (GNUNET_OK != + GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MASTER_DENOMINATION_KEY_REVOKED, + &kr.purpose, + &msig.eddsa_signature, + &master_pub.eddsa_pub)) + { + report_row_inconsistency ("denomination_revocations", + 0, /* FIXME: modify DB API to return rowid! (#4984) */ + "master signature invalid"); + } + /* TODO: cache result so we don't do this every time! (#4983) */ + } + GNUNET_CRYPTO_hash (reserve_pub, sizeof (*reserve_pub), diff --git a/src/exchange-tools/taler-exchange-keycheck.c b/src/exchange-tools/taler-exchange-keycheck.c index 3286cff4c..8018e3521 100644 --- a/src/exchange-tools/taler-exchange-keycheck.c +++ b/src/exchange-tools/taler-exchange-keycheck.c @@ -122,7 +122,7 @@ exchange_signkeys_check () * @param cls closure (NULL) * @param dki the denomination key * @param alias coin alias - * @param was_revoked #GNUNET_YES if the @a dki was revoked and wallets should trigger /payback + * @param revocation_master_sig non-NULL if @a dki was revoked * @return #GNUNET_OK to continue to iterate, * #GNUNET_NO to stop iteration with no error, * #GNUNET_SYSERR to abort iteration with error! @@ -131,7 +131,7 @@ static int denomkeys_iter (void *cls, const char *alias, const struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki, - int was_revoked) + const struct TALER_MasterSignatureP *revocation_master_sig) { struct GNUNET_HashCode hc; diff --git a/src/exchange-tools/taler-exchange-keyup.c b/src/exchange-tools/taler-exchange-keyup.c index abf8793c7..f5e5961f0 100644 --- a/src/exchange-tools/taler-exchange-keyup.c +++ b/src/exchange-tools/taler-exchange-keyup.c @@ -1054,7 +1054,7 @@ struct RevokeClosure * @param cls a `struct RevokeClosure` with information about what to revoke * @param dki the denomination key * @param alias coin alias - * @param was_revoked #GNUNET_YES if the @a dki was revoked and wallets should trigger /payback + * @param revocation_master_sig non-NULL if @a dki was revoked * @return #GNUNET_OK to continue to iterate, * #GNUNET_NO to stop iteration with no error, * #GNUNET_SYSERR to abort iteration with error! @@ -1063,11 +1063,11 @@ static int exchange_keys_revoke_by_dki (void *cls, const char *alias, const struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki, - int was_revoked) + const struct TALER_MasterSignatureP *revocation_master_sig) { struct RevokeClosure *rc = cls; - if (GNUNET_YES == was_revoked) + if (NULL != revocation_master_sig) return GNUNET_OK; /* refuse to do it twice */ if (0 != memcmp (rc->hc, &dki->issue.properties.denom_hash, diff --git a/src/exchange/taler-exchange-httpd_keystate.c b/src/exchange/taler-exchange-httpd_keystate.c index a2025c9d5..2b7019594 100644 --- a/src/exchange/taler-exchange-httpd_keystate.c +++ b/src/exchange/taler-exchange-httpd_keystate.c @@ -261,7 +261,7 @@ store_in_map (struct GNUNET_CONTAINER_MultiHashMap *map, * @param cls closure * @param dki the denomination key issue * @param alias coin alias - * @param was_revoked #GNUNET_YES if @a dki has been revoked + * @param revocation_master_sig non-NULL if @a dki was revoked * @return #GNUNET_OK to continue to iterate, * #GNUNET_NO to stop iteration with no error, * #GNUNET_SYSERR to abort iteration with error! @@ -270,7 +270,7 @@ static int reload_keys_denom_iter (void *cls, const char *alias, const struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki, - int was_revoked) + const struct TALER_MasterSignatureP *revocation_master_sig) { struct TEH_KS_StateHandle *ctx = cls; struct GNUNET_TIME_Absolute now; @@ -292,12 +292,61 @@ reload_keys_denom_iter (void *cls, alias); return GNUNET_OK; } - if (GNUNET_YES == was_revoked) + if (0 != memcmp (&dki->issue.properties.master, + &TEH_master_public_key, + sizeof (struct TALER_MasterPublicKeyP))) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Master key in denomination key file `%s' does not match! Skipping it.\n", + alias); + return GNUNET_OK; + } + + session = TEH_plugin->get_session (TEH_plugin->cls); + if (NULL == session) + return GNUNET_SYSERR; + + if (NULL != revocation_master_sig) { res = store_in_map (ctx->revoked_map, dki); if (GNUNET_NO == res) return GNUNET_OK; + /* Try to insert DKI into DB until we succeed; note that if the DB + failure is persistent, this code may loop forever (as there is no + sane alternative, we cannot continue without the DKI being in the + DB). */ + res = GNUNET_SYSERR; + while (GNUNET_OK != res) + { + res = TEH_plugin->start (TEH_plugin->cls, + session); + if (GNUNET_OK != res) + { + /* Transaction start failed!? Very bad error, log and retry */ + GNUNET_break (0); + continue; + } + res = TEH_plugin->insert_denomination_revocation (TEH_plugin->cls, + session, + &dki->issue.properties.denom_hash, + revocation_master_sig); + if (GNUNET_SYSERR == res) + { + GNUNET_break (0); + TEH_plugin->rollback (TEH_plugin->cls, + session); + continue; + } + if (GNUNET_NO == res) + { + TEH_plugin->rollback (TEH_plugin->cls, + session); + break; /* already in is also OK! */ + } + res = TEH_plugin->commit (TEH_plugin->cls, + session); + } GNUNET_assert (0 == json_array_append_new (ctx->payback_array, GNUNET_JSON_from_data_auto (&dki->issue.properties.denom_hash))); @@ -319,15 +368,6 @@ reload_keys_denom_iter (void *cls, &denom_key_hash, sizeof (struct GNUNET_HashCode)); - if (0 != memcmp (&dki->issue.properties.master, - &TEH_master_public_key, - sizeof (struct TALER_MasterPublicKeyP))) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Master key in denomination key file `%s' does not match! Skipping it.\n", - alias); - return GNUNET_OK; - } session = TEH_plugin->get_session (TEH_plugin->cls); diff --git a/src/exchangedb/exchangedb_denomkeys.c b/src/exchangedb/exchangedb_denomkeys.c index bfc3ab8eb..017960277 100644 --- a/src/exchangedb/exchangedb_denomkeys.c +++ b/src/exchangedb/exchangedb_denomkeys.c @@ -257,7 +257,7 @@ denomkeys_iterate_keydir_iter (void *cls, char *rev; struct TALER_MasterSignatureP msig; struct TALER_MasterDenominationKeyRevocation rm; - int revoked; + const struct TALER_MasterSignatureP *revoked; if ( (strlen(filename) > strlen (".rev")) && (0 == strcmp (&filename[strlen(filename) - strlen (".rev")], @@ -278,7 +278,7 @@ denomkeys_iterate_keydir_iter (void *cls, GNUNET_asprintf (&rev, "%s.rev", filename); - revoked = GNUNET_NO; + revoked = NULL; if (GNUNET_YES == GNUNET_DISK_file_test (rev)) { /* Check if revocation is valid... */ @@ -311,10 +311,9 @@ denomkeys_iterate_keydir_iter (void *cls, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Denomination key `%s' was revoked!\n", filename); - revoked = GNUNET_YES; + revoked = &msig; } } - } GNUNET_free (rev); ret = dic->it (dic->it_cls, diff --git a/src/exchangedb/test_exchangedb_denomkeys.c b/src/exchangedb/test_exchangedb_denomkeys.c index e7803c2ef..fb728115a 100644 --- a/src/exchangedb/test_exchangedb_denomkeys.c +++ b/src/exchangedb/test_exchangedb_denomkeys.c @@ -38,7 +38,7 @@ * @param cls closure with expected DKI * @param dki the denomination key * @param alias coin alias - * @param was_revoked #GNUNET_YES if revoked + * @param revocation_master_sig non-NULL if @a dki was revoked * @return #GNUNET_OK to continue to iterate, * #GNUNET_NO to stop iteration with no error, * #GNUNET_SYSERR to abort iteration with error! @@ -47,7 +47,7 @@ static int dki_iter (void *cls, const char *alias, const struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki, - int was_revoked) + const struct TALER_MasterSignatureP *revocation_master_sig) { const struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *exp = cls; diff --git a/src/include/taler_exchangedb_lib.h b/src/include/taler_exchangedb_lib.h index d70270e8e..70ae3634a 100644 --- a/src/include/taler_exchangedb_lib.h +++ b/src/include/taler_exchangedb_lib.h @@ -162,7 +162,7 @@ TALER_EXCHANGEDB_signing_key_write (const char *exchange_base_dir, * @param cls closure * @param alias coin alias * @param dki the denomination key - * @param was_revoked #GNUNET_YES if the @a dki was revoked and wallets should trigger /payback + * @param revocation_master_sig non-NULL if @a dki was revoked * @return #GNUNET_OK to continue to iterate, * #GNUNET_NO to stop iteration with no error, * #GNUNET_SYSERR to abort iteration with error! @@ -171,7 +171,7 @@ typedef int (*TALER_EXCHANGEDB_DenominationKeyIterator)(void *cls, const char *alias, const struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki, - int was_revoked); + const struct TALER_MasterSignatureP *revocation_master_sig); /** diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h index 40499b2b2..a5295378b 100644 --- a/src/include/taler_exchangedb_plugin.h +++ b/src/include/taler_exchangedb_plugin.h @@ -2030,6 +2030,8 @@ struct TALER_EXCHANGEDB_Plugin struct TALER_EXCHANGEDB_Session *session, const struct GNUNET_HashCode *denom_pub_hash, const struct TALER_MasterSignatureP *master_sig); + + /** * Obtain information about a denomination key's revocation from * the database.