summaryrefslogtreecommitdiff
path: root/src/exchangedb/exchangedb_denomkeys.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/exchangedb/exchangedb_denomkeys.c')
-rw-r--r--src/exchangedb/exchangedb_denomkeys.c256
1 files changed, 153 insertions, 103 deletions
diff --git a/src/exchangedb/exchangedb_denomkeys.c b/src/exchangedb/exchangedb_denomkeys.c
index 400912168..9dfb0e855 100644
--- a/src/exchangedb/exchangedb_denomkeys.c
+++ b/src/exchangedb/exchangedb_denomkeys.c
@@ -25,66 +25,70 @@
#include "taler_exchangedb_lib.h"
+GNUNET_NETWORK_STRUCT_BEGIN
+
+/**
+ * Contents of a file with a revocation certificate.
+ */
+struct RevocationFileP
+{
+
+ /**
+ * Hash of the denomination public key being revoked.
+ */
+ struct GNUNET_HashCode denom_hash;
+
+ /**
+ * Master signature over the revocation, must match purpose
+ * #TALER_SIGNATURE_MASTER_DENOMINATION_KEY_REVOKED.
+ */
+ struct TALER_MasterSignatureP msig;
+};
+
+GNUNET_NETWORK_STRUCT_END
+
+
/**
* Mark the given denomination key as revoked and request the wallets
* to initiate /payback.
*
- * @param exchange_base_dir base directory for the exchange,
- * the signing keys must be in the #TALER_EXCHANGEDB_DIR_DENOMINATION_KEYS
- * subdirectory
- * @param alias coin alias
- * @param dki the denomination key to revoke
- * @param mpriv master private key to sign
+ * @param revocation_dir where to write the revocation certificate
+ * @param denom_hash hash of the denomination key to revoke
+ * @param mpriv master private key to sign with
* @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure.
*/
int
-TALER_EXCHANGEDB_denomination_key_revoke (const char *exchange_base_dir,
- const char *alias,
- const struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki,
+TALER_EXCHANGEDB_denomination_key_revoke (const char *revocation_dir,
+ const struct GNUNET_HashCode *denom_hash,
const struct TALER_MasterPrivateKeyP *mpriv)
{
- struct GNUNET_TIME_Absolute start;
- struct TALER_MasterDenominationKeyRevocation rm;
- struct TALER_MasterSignatureP msig;
+ struct TALER_MasterDenominationKeyRevocationPS rm;
char *fn;
- struct GNUNET_DISK_FileHandle *fh;
- ssize_t wrote;
int ret;
+ struct RevocationFileP rd;
ret = GNUNET_SYSERR;
- start = GNUNET_TIME_absolute_ntoh (dki->issue.properties.start);
GNUNET_asprintf (&fn,
- "%s" DIR_SEPARATOR_STR
- TALER_EXCHANGEDB_DIR_DENOMINATION_KEYS DIR_SEPARATOR_STR
- "%s" DIR_SEPARATOR_STR
- "%llu.rev",
- exchange_base_dir,
- alias,
- (unsigned long long) start.abs_value_us);
-
+ "%s" DIR_SEPARATOR_STR
+ "%s.rev",
+ revocation_dir,
+ GNUNET_h2s_full (denom_hash));
rm.purpose.purpose = htonl (TALER_SIGNATURE_MASTER_DENOMINATION_KEY_REVOKED);
rm.purpose.size = htonl (sizeof (rm));
- rm.h_denom_pub = dki->issue.properties.denom_hash;
+ rm.h_denom_pub = *denom_hash;
GNUNET_assert (GNUNET_OK ==
GNUNET_CRYPTO_eddsa_sign (&mpriv->eddsa_priv,
&rm.purpose,
- &msig.eddsa_signature));
- if (NULL == (fh = GNUNET_DISK_file_open
- (fn,
- GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE | GNUNET_DISK_OPEN_TRUNCATE,
- GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE)))
- goto cleanup;
- if (GNUNET_SYSERR ==
- (wrote = GNUNET_DISK_file_write (fh,
- &msig,
- sizeof (msig))))
- goto cleanup;
- if (wrote != sizeof (msig))
- goto cleanup;
- ret = GNUNET_OK;
-cleanup:
- if (NULL != fh)
- (void) GNUNET_DISK_file_close (fh);
+ &rd.msig.eddsa_signature));
+ rd.denom_hash = *denom_hash;
+ if (sizeof (rd) !=
+ GNUNET_DISK_fn_write (fn,
+ &rd,
+ sizeof (rd),
+ GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE))
+ ret = GNUNET_SYSERR;
+ else
+ ret = GNUNET_OK;
GNUNET_free (fn);
return ret;
}
@@ -229,11 +233,6 @@ struct DenomkeysIterateContext
const char *alias;
/**
- * Master public key to use to validate revocations.
- */
- const struct TALER_MasterPublicKeyP *master_pub;
-
- /**
* Function to call on each denomination key.
*/
TALER_EXCHANGEDB_DenominationKeyIterator it;
@@ -263,16 +262,6 @@ denomkeys_iterate_keydir_iter (void *cls,
struct DenomkeysIterateContext *dic = cls;
struct TALER_EXCHANGEDB_DenominationKeyIssueInformation issue;
int ret;
- char *rev;
- struct TALER_MasterSignatureP msig;
- struct TALER_MasterDenominationKeyRevocation rm;
- const struct TALER_MasterSignatureP *revoked;
-
- /* FIXME: #5536: should move .rev files into DB! */
- if ( (strlen(filename) > strlen (".rev")) &&
- (0 == strcmp (&filename[strlen(filename) - strlen (".rev")],
- ".rev")) )
- return GNUNET_OK; /* ignore revocation files _here_; we'll try for them just below */
memset (&issue, 0, sizeof (issue));
if (GNUNET_OK !=
@@ -284,52 +273,9 @@ denomkeys_iterate_keydir_iter (void *cls,
filename);
return GNUNET_OK;
}
- /* check for revocation file */
- GNUNET_asprintf (&rev,
- "%s.rev",
- filename);
- revoked = NULL;
- if (GNUNET_YES == GNUNET_DISK_file_test (rev))
- {
- /* Check if revocation is valid... */
- if (sizeof (msig) !=
- GNUNET_DISK_fn_read (rev,
- &msig,
- sizeof (msig)))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- _("Invalid revocation file `%s' found and ignored (bad size)\n"),
- rev);
- }
- else
- {
- rm.purpose.purpose = htonl (TALER_SIGNATURE_MASTER_DENOMINATION_KEY_REVOKED);
- rm.purpose.size = htonl (sizeof (rm));
- rm.h_denom_pub = issue.issue.properties.denom_hash;
- if (GNUNET_OK !=
- GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MASTER_DENOMINATION_KEY_REVOKED,
- &rm.purpose,
- &msig.eddsa_signature,
- &dic->master_pub->eddsa_pub))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- _("Invalid revocation file `%s' found and ignored (bad signature)\n"),
- rev);
- }
- else
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Denomination key `%s' was revoked!\n",
- filename);
- revoked = &msig;
- }
- }
- }
- GNUNET_free (rev);
ret = dic->it (dic->it_cls,
dic->alias,
- &issue,
- revoked);
+ &issue);
GNUNET_CRYPTO_rsa_private_key_free (issue.denom_priv.rsa_private_key);
GNUNET_CRYPTO_rsa_public_key_free (issue.denom_pub.rsa_public_key);
return ret;
@@ -367,7 +313,6 @@ denomkeys_iterate_topdir_iter (void *cls,
* @param exchange_base_dir base directory for the exchange,
* the signing keys must be in the #TALER_EXCHANGEDB_DIR_DENOMINATION_KEYS
* subdirectory
- * @param master_pub master public key (used to check revocations)
* @param it function to call on each denomination key found
* @param it_cls closure for @a it
* @return -1 on error, 0 if no files were found, otherwise
@@ -377,7 +322,6 @@ denomkeys_iterate_topdir_iter (void *cls,
*/
int
TALER_EXCHANGEDB_denomination_keys_iterate (const char *exchange_base_dir,
- const struct TALER_MasterPublicKeyP *master_pub,
TALER_EXCHANGEDB_DenominationKeyIterator it,
void *it_cls)
{
@@ -388,7 +332,6 @@ TALER_EXCHANGEDB_denomination_keys_iterate (const char *exchange_base_dir,
GNUNET_asprintf (&dir,
"%s" DIR_SEPARATOR_STR TALER_EXCHANGEDB_DIR_DENOMINATION_KEYS,
exchange_base_dir);
- dic.master_pub = master_pub;
dic.it = it;
dic.it_cls = it_cls;
ret = GNUNET_DISK_directory_scan (dir,
@@ -399,4 +342,111 @@ TALER_EXCHANGEDB_denomination_keys_iterate (const char *exchange_base_dir,
}
+/**
+ * Closure for #revocations_iterate_cb().
+ */
+struct RevocationsIterateContext
+{
+
+ /**
+ * Function to call on each revoked denomination key.
+ */
+ TALER_EXCHANGEDB_RevocationIterator it;
+
+ /**
+ * Closure for @e it.
+ */
+ void *it_cls;
+
+ /**
+ * Master public key to use to validate revocations.
+ */
+ const struct TALER_MasterPublicKeyP *master_pub;
+
+};
+
+
+/**
+ * Decode the revocation certificate in the given file @a filename and call
+ * the callback in @a cls with the information.
+ *
+ * @param cls the `struct RevocationsIterateContext *`
+ * @param filename name of a file that should contain
+ * a denomination key
+ * @return #GNUNET_OK to continue to iterate
+ * #GNUNET_NO to abort iteration with success
+ * #GNUNET_SYSERR to abort iteration with failure
+ */
+static int
+revocations_iterate_cb (void *cls,
+ const char *filename)
+{
+ struct RevocationsIterateContext *ric = cls;
+ struct RevocationFileP rf;
+ struct TALER_MasterDenominationKeyRevocationPS rm;
+
+ /* Check if revocation is valid... */
+ if (sizeof (rm) !=
+ GNUNET_DISK_fn_read (filename,
+ &rf,
+ sizeof (rf)))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ _("Invalid revocation file `%s' found and ignored (bad size)\n"),
+ filename);
+ return GNUNET_OK;
+ }
+ rm.purpose.purpose = htonl (TALER_SIGNATURE_MASTER_DENOMINATION_KEY_REVOKED);
+ rm.purpose.size = htonl (sizeof (rm));
+ rm.h_denom_pub = rf.denom_hash;
+ if (GNUNET_OK !=
+ GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MASTER_DENOMINATION_KEY_REVOKED,
+ &rm.purpose,
+ &rf.msig.eddsa_signature,
+ &ric->master_pub->eddsa_pub))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ _("Invalid revocation file `%s' found and ignored (bad signature)\n"),
+ filename);
+ return GNUNET_OK;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Denomination key `%s' was revoked!\n",
+ GNUNET_h2s (&rm.h_denom_pub));
+ return ric->it (ric->it_cls,
+ &rm.h_denom_pub,
+ &rf.msig);
+}
+
+
+/**
+ * Call @a it for each revoked denomination key found in the @a revocation_dir.
+ *
+ * @param revocation_dir base directory where revocations are stored
+ * @param master_pub master public key (used to check revocations)
+ * @param it function to call on each revoked denomination key found
+ * @param it_cls closure for @a it
+ * @return -1 on error, 0 if no files were found, otherwise
+ * a positive number (however, even with a positive
+ * number it is possible that @a it was never called
+ * as maybe none of the files were well-formed)
+ */
+int
+TALER_EXCHANGEDB_revocations_iterate (const char *revocation_dir,
+ const struct TALER_MasterPublicKeyP *master_pub,
+ TALER_EXCHANGEDB_RevocationIterator it,
+ void *it_cls)
+{
+ struct RevocationsIterateContext ric = {
+ .it = it,
+ .it_cls = it_cls,
+ .master_pub = master_pub
+ };
+
+ return GNUNET_DISK_directory_scan (revocation_dir,
+ &revocations_iterate_cb,
+ &ric);
+}
+
+
/* end of exchangedb_denomkeys.c */