aboutsummaryrefslogtreecommitdiff
path: root/src/exchangedb
diff options
context:
space:
mode:
Diffstat (limited to 'src/exchangedb')
-rw-r--r--src/exchangedb/exchangedb_auditorkeys.c2
-rw-r--r--src/exchangedb/exchangedb_denomkeys.c262
-rw-r--r--src/exchangedb/exchangedb_plugin.c2
-rw-r--r--src/exchangedb/test_exchangedb_denomkeys.c57
4 files changed, 178 insertions, 145 deletions
diff --git a/src/exchangedb/exchangedb_auditorkeys.c b/src/exchangedb/exchangedb_auditorkeys.c
index 5f98743d3..38498d9b5 100644
--- a/src/exchangedb/exchangedb_auditorkeys.c
+++ b/src/exchangedb/exchangedb_auditorkeys.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2014, 2015, 2016, 2017 Inria & GNUnet e.V.
+ Copyright (C) 2014--2019 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
diff --git a/src/exchangedb/exchangedb_denomkeys.c b/src/exchangedb/exchangedb_denomkeys.c
index 400912168..418a1074b 100644
--- a/src/exchangedb/exchangedb_denomkeys.c
+++ b/src/exchangedb/exchangedb_denomkeys.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2014-2017 Inria & GNUnet e.V.
+ Copyright (C) 2014-2019 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
@@ -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,115 @@ 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 (rf) !=
+ 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
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_DISK_directory_create (revocation_dir))
+ return 0; /* directory doesn't exist and we couldn't even create it,
+ clearly means there are no revocations there */
+ return GNUNET_DISK_directory_scan (revocation_dir,
+ &revocations_iterate_cb,
+ &ric);
+}
+
+
/* end of exchangedb_denomkeys.c */
diff --git a/src/exchangedb/exchangedb_plugin.c b/src/exchangedb/exchangedb_plugin.c
index ec8f25fa2..50394c6e3 100644
--- a/src/exchangedb/exchangedb_plugin.c
+++ b/src/exchangedb/exchangedb_plugin.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2015 GNUnet e.V.
+ Copyright (C) 2015 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
diff --git a/src/exchangedb/test_exchangedb_denomkeys.c b/src/exchangedb/test_exchangedb_denomkeys.c
index 06465a4ea..b558b3b3b 100644
--- a/src/exchangedb/test_exchangedb_denomkeys.c
+++ b/src/exchangedb/test_exchangedb_denomkeys.c
@@ -38,7 +38,6 @@
* @param cls closure with expected DKI
* @param dki the denomination key
* @param alias coin alias
- * @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!
@@ -46,16 +45,10 @@
static int
dki_iter (void *cls,
const char *alias,
- const struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki,
- const struct TALER_MasterSignatureP *revocation_master_sig)
+ const struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki)
{
const struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *exp = cls;
- if (NULL != revocation_master_sig)
- {
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
if (0 != memcmp (&exp->issue,
&dki->issue,
sizeof (struct TALER_EXCHANGEDB_DenominationKeyInformationP)))
@@ -85,8 +78,7 @@ dki_iter (void *cls,
* @brief Iterator called on revoked denomination key.
*
* @param cls closure with expected DKI
- * @param dki the denomination key
- * @param alias coin alias
+ * @param denom_hash hash of the revoked denomination key
* @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,
@@ -94,8 +86,7 @@ dki_iter (void *cls,
*/
static int
dki_iter_revoked (void *cls,
- const char *alias,
- const struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki,
+ const struct GNUNET_HashCode *denom_hash,
const struct TALER_MasterSignatureP *revocation_master_sig)
{
const struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *exp = cls;
@@ -105,28 +96,13 @@ dki_iter_revoked (void *cls,
GNUNET_break (0);
return GNUNET_SYSERR;
}
- if (0 != memcmp (&exp->issue,
- &dki->issue,
- sizeof (struct TALER_EXCHANGEDB_DenominationKeyInformationP)))
+ if (0 != memcmp (denom_hash,
+ &exp->issue.properties.denom_hash,
+ sizeof (struct GNUNET_HashCode)))
{
GNUNET_break (0);
return GNUNET_SYSERR;
}
- if (0 !=
- GNUNET_CRYPTO_rsa_private_key_cmp (exp->denom_priv.rsa_private_key,
- dki->denom_priv.rsa_private_key))
- {
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- if (0 !=
- GNUNET_CRYPTO_rsa_public_key_cmp (exp->denom_pub.rsa_public_key,
- dki->denom_pub.rsa_public_key))
- {
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
-
return GNUNET_OK;
}
@@ -146,6 +122,7 @@ main (int argc,
size_t enc_read_size;
char *tmpfile;
char *tmpdir;
+ char *revdir;
int ret;
struct GNUNET_TIME_Absolute start;
@@ -180,6 +157,10 @@ main (int argc,
TALER_EXCHANGEDB_DIR_DENOMINATION_KEYS,
"cur-unit-uuid",
(unsigned long long) start.abs_value_us);
+ GNUNET_asprintf (&revdir,
+ "%s/revocations/",
+ tmpdir,
+ TALER_EXCHANGEDB_DIR_DENOMINATION_KEYS);
EXITIF (GNUNET_OK !=
TALER_EXCHANGEDB_denomination_key_write (tmpfile,
&dki));
@@ -188,21 +169,19 @@ main (int argc,
&dki_read));
EXITIF (1 !=
TALER_EXCHANGEDB_denomination_keys_iterate (tmpdir,
- &master_pub,
&dki_iter,
&dki));
EXITIF (GNUNET_OK !=
- TALER_EXCHANGEDB_denomination_key_revoke (tmpdir,
- "cur-unit-uuid",
- &dki,
+ TALER_EXCHANGEDB_denomination_key_revoke (revdir,
+ &dki.issue.properties.denom_hash,
&master_priv));
EXITIF (1 !=
- TALER_EXCHANGEDB_denomination_keys_iterate (tmpdir,
- &master_pub,
- &dki_iter_revoked,
- &dki));
-
+ TALER_EXCHANGEDB_revocations_iterate (revdir,
+ &master_pub,
+ &dki_iter_revoked,
+ &dki));
+ GNUNET_free (revdir);
enc_read_size = GNUNET_CRYPTO_rsa_private_key_encode (dki_read.denom_priv.rsa_private_key,
&enc_read);