2015-01-08 18:37:20 +01:00
|
|
|
/*
|
|
|
|
This file is part of TALER
|
2016-04-10 17:10:20 +02:00
|
|
|
Copyright (C) 2014, 2015, 2016 GNUnet e.V.
|
2015-01-08 18:37:20 +01:00
|
|
|
|
|
|
|
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
|
|
|
|
Foundation; either version 3, or (at your option) any later version.
|
|
|
|
|
|
|
|
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
|
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
|
|
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License along with
|
2016-07-07 17:55:25 +02:00
|
|
|
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
2015-01-08 18:37:20 +01:00
|
|
|
*/
|
|
|
|
/**
|
2016-03-01 15:35:04 +01:00
|
|
|
* @file taler-exchange-keyup.c
|
|
|
|
* @brief Update the exchange's keys for coins and signatures,
|
|
|
|
* using the exchange's offline master key.
|
2015-01-08 18:37:20 +01:00
|
|
|
* @author Florian Dold
|
|
|
|
* @author Benedikt Mueller
|
2015-03-17 11:37:21 +01:00
|
|
|
* @author Christian Grothoff
|
2015-01-08 18:37:20 +01:00
|
|
|
*/
|
|
|
|
#include <platform.h>
|
2016-03-01 15:35:04 +01:00
|
|
|
#include "taler_exchangedb_lib.h"
|
2015-01-08 18:37:20 +01:00
|
|
|
|
2015-01-27 14:55:05 +01:00
|
|
|
/**
|
2015-03-17 11:37:21 +01:00
|
|
|
* When generating filenames from a cryptographic hash, we do not use
|
|
|
|
* all 512 bits but cut off after this number of characters (in
|
|
|
|
* base32-encoding). Base32 is 5 bit per character, and given that we
|
|
|
|
* have very few coin types we hash, at 100 bits the chance of
|
|
|
|
* collision (by accident over tiny set -- birthday paradox does not
|
|
|
|
* apply here!) is negligible.
|
2015-03-15 22:33:28 +01:00
|
|
|
*/
|
2015-01-08 18:37:20 +01:00
|
|
|
#define HASH_CUTOFF 20
|
|
|
|
|
|
|
|
|
|
|
|
GNUNET_NETWORK_STRUCT_BEGIN
|
|
|
|
|
2015-03-15 22:33:28 +01:00
|
|
|
/**
|
2015-03-17 10:48:12 +01:00
|
|
|
* Struct with all of the key information for a kind of coin. Hashed
|
|
|
|
* to generate a unique directory name per coin type.
|
2015-03-15 22:33:28 +01:00
|
|
|
*/
|
2015-03-27 19:58:40 +01:00
|
|
|
struct CoinTypeNBOP
|
2015-01-08 18:37:20 +01:00
|
|
|
{
|
2015-03-28 18:23:45 +01:00
|
|
|
/**
|
|
|
|
* How long are the signatures legally valid?
|
|
|
|
*/
|
|
|
|
struct GNUNET_TIME_RelativeNBO duration_legal;
|
|
|
|
|
2015-03-15 22:33:28 +01:00
|
|
|
/**
|
2015-03-17 10:48:12 +01:00
|
|
|
* How long can the coin be spend?
|
2015-03-15 22:33:28 +01:00
|
|
|
*/
|
2015-01-08 18:37:20 +01:00
|
|
|
struct GNUNET_TIME_RelativeNBO duration_spend;
|
2015-03-15 22:33:28 +01:00
|
|
|
|
|
|
|
/**
|
2015-03-17 10:48:12 +01:00
|
|
|
* How long can the coin be withdrawn (generated)?
|
2015-03-15 22:33:28 +01:00
|
|
|
*/
|
2015-01-08 18:37:20 +01:00
|
|
|
struct GNUNET_TIME_RelativeNBO duration_withdraw;
|
2015-03-15 22:33:28 +01:00
|
|
|
|
|
|
|
/**
|
2015-03-17 10:48:12 +01:00
|
|
|
* What is the value of the coin?
|
2015-03-15 22:33:28 +01:00
|
|
|
*/
|
2015-01-08 18:37:20 +01:00
|
|
|
struct TALER_AmountNBO value;
|
2015-03-15 22:33:28 +01:00
|
|
|
|
|
|
|
/**
|
2015-03-17 10:48:12 +01:00
|
|
|
* What is the fee charged for withdrawl?
|
2015-03-15 22:33:28 +01:00
|
|
|
*/
|
2015-01-08 18:37:20 +01:00
|
|
|
struct TALER_AmountNBO fee_withdraw;
|
2015-03-15 22:33:28 +01:00
|
|
|
|
|
|
|
/**
|
2015-03-17 10:48:12 +01:00
|
|
|
* What is the fee charged for deposits?
|
2015-03-15 22:33:28 +01:00
|
|
|
*/
|
2015-01-08 18:37:20 +01:00
|
|
|
struct TALER_AmountNBO fee_deposit;
|
2015-03-15 22:33:28 +01:00
|
|
|
|
|
|
|
/**
|
2015-03-17 10:48:12 +01:00
|
|
|
* What is the fee charged for melting?
|
2015-03-15 22:33:28 +01:00
|
|
|
*/
|
2015-01-08 18:37:20 +01:00
|
|
|
struct TALER_AmountNBO fee_refresh;
|
2015-03-17 11:37:21 +01:00
|
|
|
|
2016-04-20 01:50:26 +02:00
|
|
|
/**
|
|
|
|
* What is the fee charged for refunds?
|
|
|
|
*/
|
|
|
|
struct TALER_AmountNBO fee_refund;
|
|
|
|
|
2015-03-17 11:37:21 +01:00
|
|
|
/**
|
|
|
|
* Key size in NBO.
|
|
|
|
*/
|
|
|
|
uint32_t rsa_keysize;
|
2015-01-08 18:37:20 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
GNUNET_NETWORK_STRUCT_END
|
|
|
|
|
2015-03-15 22:33:28 +01:00
|
|
|
/**
|
2015-03-17 11:37:21 +01:00
|
|
|
* Set of all of the parameters that chracterize a coin.
|
2015-03-15 22:33:28 +01:00
|
|
|
*/
|
2015-01-08 18:37:20 +01:00
|
|
|
struct CoinTypeParams
|
|
|
|
{
|
2015-03-15 22:33:28 +01:00
|
|
|
|
2015-03-28 18:23:45 +01:00
|
|
|
/**
|
|
|
|
* How long are the signatures legally valid? Should be
|
|
|
|
* significantly larger than @e duration_spend (i.e. years).
|
|
|
|
*/
|
|
|
|
struct GNUNET_TIME_Relative duration_legal;
|
|
|
|
|
|
|
|
|
2015-03-15 22:33:28 +01:00
|
|
|
/**
|
2015-03-17 11:37:21 +01:00
|
|
|
* How long can the coin be spend? Should be significantly
|
|
|
|
* larger than @e duration_withdraw (i.e. years).
|
2015-03-15 22:33:28 +01:00
|
|
|
*/
|
2015-01-08 18:37:20 +01:00
|
|
|
struct GNUNET_TIME_Relative duration_spend;
|
2015-03-15 22:33:28 +01:00
|
|
|
|
|
|
|
/**
|
2015-03-17 11:37:21 +01:00
|
|
|
* How long can the coin be withdrawn (generated)? Should be small
|
|
|
|
* enough to limit how many coins will be signed into existence with
|
|
|
|
* the same key, but large enough to still provide a reasonable
|
|
|
|
* anonymity set.
|
2015-03-15 22:33:28 +01:00
|
|
|
*/
|
2015-01-08 18:37:20 +01:00
|
|
|
struct GNUNET_TIME_Relative duration_withdraw;
|
2015-03-15 22:33:28 +01:00
|
|
|
|
|
|
|
/**
|
2015-03-17 11:37:21 +01:00
|
|
|
* How much should coin creation (@e duration_withdraw) duration
|
|
|
|
* overlap with the next coin? Basically, the starting time of two
|
|
|
|
* coins is always @e duration_withdraw - @e duration_overlap apart.
|
2015-03-15 22:33:28 +01:00
|
|
|
*/
|
2015-01-08 18:37:20 +01:00
|
|
|
struct GNUNET_TIME_Relative duration_overlap;
|
2015-03-15 22:33:28 +01:00
|
|
|
|
|
|
|
/**
|
2015-03-17 11:37:21 +01:00
|
|
|
* What is the value of the coin?
|
2015-03-15 22:33:28 +01:00
|
|
|
*/
|
2015-01-08 18:37:20 +01:00
|
|
|
struct TALER_Amount value;
|
2015-03-15 22:33:28 +01:00
|
|
|
|
|
|
|
/**
|
2015-03-17 11:37:21 +01:00
|
|
|
* What is the fee charged for withdrawl?
|
2015-03-15 22:33:28 +01:00
|
|
|
*/
|
2015-01-08 18:37:20 +01:00
|
|
|
struct TALER_Amount fee_withdraw;
|
2015-03-15 22:33:28 +01:00
|
|
|
|
|
|
|
/**
|
2015-03-17 11:37:21 +01:00
|
|
|
* What is the fee charged for deposits?
|
2015-03-15 22:33:28 +01:00
|
|
|
*/
|
2015-01-08 18:37:20 +01:00
|
|
|
struct TALER_Amount fee_deposit;
|
2015-03-15 22:33:28 +01:00
|
|
|
|
|
|
|
/**
|
2015-03-17 11:37:21 +01:00
|
|
|
* What is the fee charged for melting?
|
2015-03-15 22:33:28 +01:00
|
|
|
*/
|
2015-01-08 18:37:20 +01:00
|
|
|
struct TALER_Amount fee_refresh;
|
2015-03-15 22:33:28 +01:00
|
|
|
|
2016-04-20 01:50:26 +02:00
|
|
|
/**
|
|
|
|
* What is the fee charged for refunds?
|
|
|
|
*/
|
|
|
|
struct TALER_Amount fee_refund;
|
|
|
|
|
2015-03-15 22:33:28 +01:00
|
|
|
/**
|
2015-03-17 11:37:21 +01:00
|
|
|
* Time at which this coin is supposed to become valid.
|
2015-03-15 22:33:28 +01:00
|
|
|
*/
|
2015-01-08 18:37:20 +01:00
|
|
|
struct GNUNET_TIME_Absolute anchor;
|
2015-03-17 11:37:21 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Length of the RSA key in bits.
|
|
|
|
*/
|
|
|
|
uint32_t rsa_keysize;
|
2015-01-08 18:37:20 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Filename of the master private key.
|
|
|
|
*/
|
|
|
|
static char *masterkeyfile;
|
|
|
|
|
2015-09-16 18:48:05 +02:00
|
|
|
/**
|
|
|
|
* Filename where to write denomination key signing
|
|
|
|
* requests for the auditor (optional, can be NULL).
|
|
|
|
*/
|
|
|
|
static char *auditorrequestfile;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Handle for writing the output for the auditor.
|
|
|
|
*/
|
|
|
|
static FILE *auditor_output_file;
|
|
|
|
|
2015-01-08 18:37:20 +01:00
|
|
|
/**
|
2016-03-01 15:35:04 +01:00
|
|
|
* Director of the exchange, containing the keys.
|
2015-01-08 18:37:20 +01:00
|
|
|
*/
|
2016-03-01 15:35:04 +01:00
|
|
|
static char *exchange_directory;
|
2015-01-08 18:37:20 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Time to pretend when the key update is executed.
|
|
|
|
*/
|
|
|
|
static char *pretend_time_str;
|
|
|
|
|
|
|
|
/**
|
2016-03-01 15:35:04 +01:00
|
|
|
* Handle to the exchange's configuration
|
2015-01-08 18:37:20 +01:00
|
|
|
*/
|
2016-04-16 12:37:37 +02:00
|
|
|
static const struct GNUNET_CONFIGURATION_Handle *kcfg;
|
2015-01-08 18:37:20 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Time when the key update is executed. Either the actual current time, or a
|
|
|
|
* pretended time.
|
|
|
|
*/
|
|
|
|
static struct GNUNET_TIME_Absolute now;
|
|
|
|
|
|
|
|
/**
|
2016-03-01 15:35:04 +01:00
|
|
|
* Master private key of the exchange.
|
2015-01-08 18:37:20 +01:00
|
|
|
*/
|
2015-03-27 19:58:40 +01:00
|
|
|
static struct TALER_MasterPrivateKeyP master_priv;
|
2015-01-08 18:37:20 +01:00
|
|
|
|
|
|
|
/**
|
2016-03-01 15:35:04 +01:00
|
|
|
* Master public key of the exchange.
|
2015-01-08 18:37:20 +01:00
|
|
|
*/
|
2015-03-27 19:58:40 +01:00
|
|
|
static struct TALER_MasterPublicKeyP master_public_key;
|
2015-01-08 18:37:20 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Until what time do we provide keys?
|
|
|
|
*/
|
|
|
|
static struct GNUNET_TIME_Absolute lookahead_sign_stamp;
|
|
|
|
|
2016-04-16 12:37:37 +02:00
|
|
|
/**
|
|
|
|
* Return value from main().
|
|
|
|
*/
|
|
|
|
static int global_ret;
|
|
|
|
|
|
|
|
|
2015-01-08 18:37:20 +01:00
|
|
|
/**
|
2015-03-17 10:48:12 +01:00
|
|
|
* Hash the data defining the coin type. Exclude information that may
|
|
|
|
* not be the same for all instances of the coin type (i.e. the
|
|
|
|
* anchor, overlap).
|
2015-03-15 22:33:28 +01:00
|
|
|
*
|
2015-03-17 10:48:12 +01:00
|
|
|
* @param p coin parameters to convert to a hash
|
2015-03-28 15:42:07 +01:00
|
|
|
* @param[out] hash set to the hash matching @a p
|
2015-01-08 18:37:20 +01:00
|
|
|
*/
|
2015-01-26 12:22:26 +01:00
|
|
|
static void
|
2015-03-15 22:33:28 +01:00
|
|
|
hash_coin_type (const struct CoinTypeParams *p,
|
|
|
|
struct GNUNET_HashCode *hash)
|
2015-01-08 18:37:20 +01:00
|
|
|
{
|
2015-03-27 19:58:40 +01:00
|
|
|
struct CoinTypeNBOP p_nbo;
|
2015-01-08 18:37:20 +01:00
|
|
|
|
2015-03-15 22:33:28 +01:00
|
|
|
memset (&p_nbo,
|
|
|
|
0,
|
2015-03-27 19:58:40 +01:00
|
|
|
sizeof (struct CoinTypeNBOP));
|
2015-01-08 18:37:20 +01:00
|
|
|
p_nbo.duration_spend = GNUNET_TIME_relative_hton (p->duration_spend);
|
2015-03-28 18:23:45 +01:00
|
|
|
p_nbo.duration_legal = GNUNET_TIME_relative_hton (p->duration_legal);
|
2015-01-08 18:37:20 +01:00
|
|
|
p_nbo.duration_withdraw = GNUNET_TIME_relative_hton (p->duration_withdraw);
|
2015-03-18 18:55:41 +01:00
|
|
|
TALER_amount_hton (&p_nbo.value,
|
|
|
|
&p->value);
|
|
|
|
TALER_amount_hton (&p_nbo.fee_withdraw,
|
|
|
|
&p->fee_withdraw);
|
|
|
|
TALER_amount_hton (&p_nbo.fee_deposit,
|
|
|
|
&p->fee_deposit);
|
|
|
|
TALER_amount_hton (&p_nbo.fee_refresh,
|
|
|
|
&p->fee_refresh);
|
2016-04-20 01:50:26 +02:00
|
|
|
TALER_amount_hton (&p_nbo.fee_refund,
|
|
|
|
&p->fee_refund);
|
2015-03-17 11:37:21 +01:00
|
|
|
p_nbo.rsa_keysize = htonl (p->rsa_keysize);
|
2015-03-15 22:33:28 +01:00
|
|
|
GNUNET_CRYPTO_hash (&p_nbo,
|
2015-03-27 19:58:40 +01:00
|
|
|
sizeof (struct CoinTypeNBOP),
|
2015-03-15 22:33:28 +01:00
|
|
|
hash);
|
2015-01-08 18:37:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-03-15 22:33:28 +01:00
|
|
|
/**
|
2015-03-17 10:48:12 +01:00
|
|
|
* Obtain the name of the directory we should use to store coins of
|
|
|
|
* the given type. The directory name has the format
|
2016-03-01 15:35:04 +01:00
|
|
|
* "$EXCHANGEDIR/$VALUE/$HASH/" where "$VALUE" represents the value of the
|
2015-03-17 10:48:12 +01:00
|
|
|
* coin and "$HASH" encodes all of the coin's parameters, generating a
|
|
|
|
* unique string for each type of coin. Note that the "$HASH"
|
|
|
|
* includes neither the absolute creation time nor the key of the
|
|
|
|
* coin, thus the files in the subdirectory really just refer to the
|
|
|
|
* same type of coins, not the same coin.
|
2015-03-15 22:33:28 +01:00
|
|
|
*
|
2015-03-17 10:48:12 +01:00
|
|
|
* @param p coin parameters to convert to a directory name
|
|
|
|
* @return directory name (valid until next call to this function)
|
2015-03-15 22:33:28 +01:00
|
|
|
*/
|
2015-01-08 18:37:20 +01:00
|
|
|
static const char *
|
|
|
|
get_cointype_dir (const struct CoinTypeParams *p)
|
|
|
|
{
|
|
|
|
static char dir[4096];
|
|
|
|
struct GNUNET_HashCode hash;
|
|
|
|
char *hash_str;
|
|
|
|
char *val_str;
|
2015-03-17 11:37:21 +01:00
|
|
|
size_t i;
|
2015-01-08 18:37:20 +01:00
|
|
|
|
|
|
|
hash_coin_type (p, &hash);
|
2015-01-28 20:31:28 +01:00
|
|
|
hash_str = GNUNET_STRINGS_data_to_string_alloc (&hash,
|
|
|
|
sizeof (struct GNUNET_HashCode));
|
2015-01-08 18:37:20 +01:00
|
|
|
GNUNET_assert (NULL != hash_str);
|
2015-03-17 11:37:21 +01:00
|
|
|
GNUNET_assert (HASH_CUTOFF <= strlen (hash_str) + 1);
|
2015-01-08 18:37:20 +01:00
|
|
|
hash_str[HASH_CUTOFF] = 0;
|
|
|
|
|
2015-03-18 18:55:41 +01:00
|
|
|
val_str = TALER_amount_to_string (&p->value);
|
2015-01-08 18:37:20 +01:00
|
|
|
for (i = 0; i < strlen (val_str); i++)
|
2015-03-17 11:37:21 +01:00
|
|
|
if ( (':' == val_str[i]) ||
|
|
|
|
('.' == val_str[i]) )
|
2015-01-08 18:37:20 +01:00
|
|
|
val_str[i] = '_';
|
|
|
|
|
2015-03-15 22:33:28 +01:00
|
|
|
GNUNET_snprintf (dir,
|
|
|
|
sizeof (dir),
|
2016-03-01 15:35:04 +01:00
|
|
|
"%s" DIR_SEPARATOR_STR TALER_EXCHANGEDB_DIR_DENOMINATION_KEYS DIR_SEPARATOR_STR "%s-%s",
|
|
|
|
exchange_directory,
|
2015-03-15 22:33:28 +01:00
|
|
|
val_str,
|
|
|
|
hash_str);
|
2015-01-08 18:37:20 +01:00
|
|
|
GNUNET_free (hash_str);
|
2015-03-17 11:37:21 +01:00
|
|
|
GNUNET_free (val_str);
|
2015-01-08 18:37:20 +01:00
|
|
|
return dir;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-03-15 22:33:28 +01:00
|
|
|
/**
|
2015-03-17 11:37:21 +01:00
|
|
|
* Obtain the name of the file we would use to store the key
|
|
|
|
* information for a coin of the given type @a p and validity
|
|
|
|
* start time @a start
|
2015-03-15 22:33:28 +01:00
|
|
|
*
|
2015-03-17 11:37:21 +01:00
|
|
|
* @param p parameters for the coin
|
|
|
|
* @param start when would the coin begin to be issued
|
|
|
|
* @return name of the file to use for this coin
|
|
|
|
* (valid until next call to this function)
|
2015-03-15 22:33:28 +01:00
|
|
|
*/
|
2015-01-08 18:37:20 +01:00
|
|
|
static const char *
|
2015-03-17 11:37:21 +01:00
|
|
|
get_cointype_file (const struct CoinTypeParams *p,
|
2015-01-08 18:37:20 +01:00
|
|
|
struct GNUNET_TIME_Absolute start)
|
|
|
|
{
|
|
|
|
static char filename[4096];
|
2015-03-17 11:37:21 +01:00
|
|
|
const char *dir;
|
2015-03-15 22:33:28 +01:00
|
|
|
|
2015-01-08 18:37:20 +01:00
|
|
|
dir = get_cointype_dir (p);
|
2015-03-15 22:33:28 +01:00
|
|
|
GNUNET_snprintf (filename,
|
|
|
|
sizeof (filename),
|
|
|
|
"%s" DIR_SEPARATOR_STR "%llu",
|
|
|
|
dir,
|
|
|
|
(unsigned long long) start.abs_value_us);
|
2015-01-08 18:37:20 +01:00
|
|
|
return filename;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2015-03-17 11:37:21 +01:00
|
|
|
* Get the latest key file from a past run of the key generation
|
|
|
|
* tool. Used to calculate the starting time for the keys we
|
2015-03-17 14:34:55 +01:00
|
|
|
* generate during this invocation. This function is used to
|
|
|
|
* handle both signing keys and coin keys, as in both cases
|
|
|
|
* the filenames correspond to the timestamps we need.
|
2015-01-08 18:37:20 +01:00
|
|
|
*
|
2015-03-17 11:37:21 +01:00
|
|
|
* @param cls closure, a `struct GNUNET_TIME_Absolute *`, updated
|
|
|
|
* to contain the highest timestamp (below #now)
|
|
|
|
* that was found
|
2015-01-08 18:37:20 +01:00
|
|
|
* @param filename complete filename (absolute path)
|
2015-03-17 11:37:21 +01:00
|
|
|
* @return #GNUNET_OK (to continue to iterate)
|
2015-01-08 18:37:20 +01:00
|
|
|
*/
|
|
|
|
static int
|
|
|
|
get_anchor_iter (void *cls,
|
|
|
|
const char *filename)
|
|
|
|
{
|
|
|
|
struct GNUNET_TIME_Absolute *anchor = cls;
|
2015-03-15 22:33:28 +01:00
|
|
|
struct GNUNET_TIME_Absolute stamp;
|
2015-01-08 18:37:20 +01:00
|
|
|
const char *base;
|
|
|
|
char *end = NULL;
|
|
|
|
|
|
|
|
base = GNUNET_STRINGS_get_short_name (filename);
|
2015-03-15 22:33:28 +01:00
|
|
|
stamp.abs_value_us = strtol (base,
|
|
|
|
&end,
|
|
|
|
10);
|
2015-01-08 18:37:20 +01:00
|
|
|
if ((NULL == end) || (0 != *end))
|
|
|
|
{
|
2015-03-15 22:33:28 +01:00
|
|
|
fprintf(stderr,
|
2015-03-17 11:37:21 +01:00
|
|
|
"Ignoring unexpected file `%s'.\n",
|
2015-03-15 22:33:28 +01:00
|
|
|
filename);
|
2015-01-08 18:37:20 +01:00
|
|
|
return GNUNET_OK;
|
|
|
|
}
|
2015-06-18 14:14:14 +02:00
|
|
|
*anchor = GNUNET_TIME_absolute_max (stamp,
|
|
|
|
*anchor);
|
2015-01-08 18:37:20 +01:00
|
|
|
return GNUNET_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the timestamp where the first new key should be generated.
|
2015-03-17 11:37:21 +01:00
|
|
|
* Relies on correctly named key files (as we do not parse them,
|
|
|
|
* but just look at the filenames to "guess" at their contents).
|
2015-01-08 18:37:20 +01:00
|
|
|
*
|
2015-03-17 11:37:21 +01:00
|
|
|
* @param dir directory that should contain the existing keys
|
|
|
|
* @param duration how long is one key valid (for signing)?
|
2015-01-08 18:37:20 +01:00
|
|
|
* @param overlap what's the overlap between the keys validity period?
|
|
|
|
* @param[out] anchor the timestamp where the first new key should be generated
|
|
|
|
*/
|
2015-01-26 12:22:26 +01:00
|
|
|
static void
|
2015-01-08 18:37:20 +01:00
|
|
|
get_anchor (const char *dir,
|
|
|
|
struct GNUNET_TIME_Relative duration,
|
|
|
|
struct GNUNET_TIME_Relative overlap,
|
|
|
|
struct GNUNET_TIME_Absolute *anchor)
|
|
|
|
{
|
|
|
|
GNUNET_assert (0 == duration.rel_value_us % 1000000);
|
|
|
|
GNUNET_assert (0 == overlap.rel_value_us % 1000000);
|
2015-03-15 22:33:28 +01:00
|
|
|
if (GNUNET_YES !=
|
2015-03-17 11:37:21 +01:00
|
|
|
GNUNET_DISK_directory_test (dir,
|
|
|
|
GNUNET_YES))
|
2015-01-08 18:37:20 +01:00
|
|
|
{
|
|
|
|
*anchor = now;
|
2015-03-17 11:37:21 +01:00
|
|
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
|
|
|
"No existing keys found, starting with fresh key set.\n");
|
2015-01-08 18:37:20 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
*anchor = GNUNET_TIME_UNIT_ZERO_ABS;
|
2015-03-15 22:33:28 +01:00
|
|
|
if (-1 ==
|
|
|
|
GNUNET_DISK_directory_scan (dir,
|
|
|
|
&get_anchor_iter,
|
|
|
|
anchor))
|
2015-01-08 18:37:20 +01:00
|
|
|
{
|
|
|
|
*anchor = now;
|
2015-03-17 11:37:21 +01:00
|
|
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
|
|
|
"No existing keys found, starting with fresh key set.\n");
|
2015-01-08 18:37:20 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-03-15 22:33:28 +01:00
|
|
|
if ((GNUNET_TIME_absolute_add (*anchor,
|
|
|
|
duration)).abs_value_us < now.abs_value_us)
|
2015-01-08 18:37:20 +01:00
|
|
|
{
|
2015-03-17 11:37:21 +01:00
|
|
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
|
|
|
"Existing keys are way too old, starting with fresh key set.\n");
|
2015-01-08 18:37:20 +01:00
|
|
|
*anchor = now;
|
|
|
|
}
|
2015-06-18 14:14:14 +02:00
|
|
|
else if (anchor->abs_value_us != now.abs_value_us)
|
2015-01-08 18:37:20 +01:00
|
|
|
{
|
2015-03-17 11:37:21 +01:00
|
|
|
/* Real starting time is the last start time + duration - overlap */
|
|
|
|
*anchor = GNUNET_TIME_absolute_add (*anchor,
|
|
|
|
duration);
|
|
|
|
*anchor = GNUNET_TIME_absolute_subtract (*anchor,
|
|
|
|
overlap);
|
2015-01-08 18:37:20 +01:00
|
|
|
}
|
2015-03-17 11:37:21 +01:00
|
|
|
/* anchor is now the stamp where we need to create a new key */
|
2015-01-08 18:37:20 +01:00
|
|
|
}
|
|
|
|
|
2015-01-26 12:22:26 +01:00
|
|
|
|
2015-03-15 22:33:28 +01:00
|
|
|
/**
|
2016-03-01 15:35:04 +01:00
|
|
|
* Create a exchange signing key (for signing exchange messages, not for coins)
|
2015-03-17 12:17:42 +01:00
|
|
|
* and assert its correctness by signing it with the master key.
|
2015-03-15 22:33:28 +01:00
|
|
|
*
|
2015-03-17 12:17:42 +01:00
|
|
|
* @param start start time of the validity period for the key
|
|
|
|
* @param duration how long should the key be valid
|
2015-03-28 18:18:38 +01:00
|
|
|
* @param end when do all signatures by this key expire
|
2015-03-28 15:42:07 +01:00
|
|
|
* @param[out] pi set to the signing key information
|
2015-03-15 22:33:28 +01:00
|
|
|
*/
|
2015-01-08 18:37:20 +01:00
|
|
|
static void
|
2015-01-09 18:18:59 +01:00
|
|
|
create_signkey_issue_priv (struct GNUNET_TIME_Absolute start,
|
|
|
|
struct GNUNET_TIME_Relative duration,
|
2015-03-28 18:18:38 +01:00
|
|
|
struct GNUNET_TIME_Absolute end,
|
2016-03-01 15:35:04 +01:00
|
|
|
struct TALER_EXCHANGEDB_PrivateSigningKeyInformationP *pi)
|
2015-01-08 18:37:20 +01:00
|
|
|
{
|
|
|
|
struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
|
2016-03-01 15:35:04 +01:00
|
|
|
struct TALER_ExchangeSigningKeyValidityPS *issue = &pi->issue;
|
2015-01-08 18:37:20 +01:00
|
|
|
|
|
|
|
priv = GNUNET_CRYPTO_eddsa_key_create ();
|
2015-03-22 22:14:30 +01:00
|
|
|
pi->signkey_priv.eddsa_priv = *priv;
|
2015-01-08 18:37:20 +01:00
|
|
|
GNUNET_free (priv);
|
2015-03-27 19:58:40 +01:00
|
|
|
issue->master_public_key = master_public_key;
|
2015-01-08 18:37:20 +01:00
|
|
|
issue->start = GNUNET_TIME_absolute_hton (start);
|
2015-03-15 22:33:28 +01:00
|
|
|
issue->expire = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_add (start,
|
|
|
|
duration));
|
2015-03-28 18:18:38 +01:00
|
|
|
issue->end = GNUNET_TIME_absolute_hton (end);
|
2015-03-22 22:14:30 +01:00
|
|
|
GNUNET_CRYPTO_eddsa_key_get_public (&pi->signkey_priv.eddsa_priv,
|
|
|
|
&issue->signkey_pub.eddsa_pub);
|
2015-03-28 14:22:21 +01:00
|
|
|
issue->purpose.purpose = htonl (TALER_SIGNATURE_MASTER_SIGNING_KEY_VALIDITY);
|
2016-03-01 15:35:04 +01:00
|
|
|
issue->purpose.size = htonl (sizeof (struct TALER_ExchangeSigningKeyValidityPS) -
|
|
|
|
offsetof (struct TALER_ExchangeSigningKeyValidityPS,
|
2015-03-15 22:33:28 +01:00
|
|
|
purpose));
|
2015-01-08 18:37:20 +01:00
|
|
|
|
2015-03-09 11:24:35 +01:00
|
|
|
GNUNET_assert (GNUNET_OK ==
|
2015-03-22 22:14:30 +01:00
|
|
|
GNUNET_CRYPTO_eddsa_sign (&master_priv.eddsa_priv,
|
2015-03-09 11:24:35 +01:00
|
|
|
&issue->purpose,
|
2015-03-22 22:14:30 +01:00
|
|
|
&issue->signature.eddsa_signature));
|
2015-01-08 18:37:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-03-15 22:33:28 +01:00
|
|
|
/**
|
2015-03-17 14:34:55 +01:00
|
|
|
* Generate signing keys starting from the last key found to
|
|
|
|
* the lookahead time.
|
2015-03-15 22:33:28 +01:00
|
|
|
*
|
2015-03-17 11:37:21 +01:00
|
|
|
* @return #GNUNET_OK on success, #GNUNET_SYSERR on error
|
2015-03-15 22:33:28 +01:00
|
|
|
*/
|
2015-01-26 12:22:26 +01:00
|
|
|
static int
|
2016-03-01 15:35:04 +01:00
|
|
|
exchange_keys_update_signkeys ()
|
2015-01-08 18:37:20 +01:00
|
|
|
{
|
|
|
|
struct GNUNET_TIME_Relative signkey_duration;
|
2015-03-28 18:18:38 +01:00
|
|
|
struct GNUNET_TIME_Relative legal_duration;
|
2015-01-08 18:37:20 +01:00
|
|
|
struct GNUNET_TIME_Absolute anchor;
|
|
|
|
char *signkey_dir;
|
|
|
|
|
2015-03-15 22:33:28 +01:00
|
|
|
if (GNUNET_OK !=
|
|
|
|
GNUNET_CONFIGURATION_get_value_time (kcfg,
|
2016-03-01 15:35:04 +01:00
|
|
|
"exchange_keys",
|
2015-03-15 22:33:28 +01:00
|
|
|
"signkey_duration",
|
|
|
|
&signkey_duration))
|
2015-01-08 18:37:20 +01:00
|
|
|
{
|
2015-03-17 12:17:42 +01:00
|
|
|
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
|
2016-03-01 15:35:04 +01:00
|
|
|
"exchange_keys",
|
2015-03-17 12:17:42 +01:00
|
|
|
"signkey_duration");
|
2015-01-08 18:37:20 +01:00
|
|
|
return GNUNET_SYSERR;
|
|
|
|
}
|
2015-03-28 18:18:38 +01:00
|
|
|
if (GNUNET_OK !=
|
|
|
|
GNUNET_CONFIGURATION_get_value_time (kcfg,
|
2016-03-01 15:35:04 +01:00
|
|
|
"exchange_keys",
|
2015-03-28 18:18:38 +01:00
|
|
|
"legal_duration",
|
|
|
|
&legal_duration))
|
|
|
|
{
|
2015-06-18 14:04:42 +02:00
|
|
|
GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
|
2016-03-01 15:35:04 +01:00
|
|
|
"exchange_keys",
|
2015-06-18 14:04:42 +02:00
|
|
|
"legal_duration",
|
|
|
|
"fails to specify valid timeframe");
|
2015-03-28 18:18:38 +01:00
|
|
|
return GNUNET_SYSERR;
|
|
|
|
}
|
2015-06-18 14:04:42 +02:00
|
|
|
if (signkey_duration.rel_value_us > legal_duration.rel_value_us)
|
2015-03-28 18:18:38 +01:00
|
|
|
{
|
|
|
|
GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
|
2016-03-01 15:35:04 +01:00
|
|
|
"exchange_keys",
|
2015-03-28 18:18:38 +01:00
|
|
|
"legal_duration",
|
|
|
|
"must be longer than signkey_duration");
|
|
|
|
return GNUNET_SYSERR;
|
|
|
|
}
|
2016-03-19 15:23:11 +01:00
|
|
|
GNUNET_TIME_round_rel (&signkey_duration);
|
2015-03-17 10:48:12 +01:00
|
|
|
GNUNET_asprintf (&signkey_dir,
|
2016-03-01 15:35:04 +01:00
|
|
|
"%s" DIR_SEPARATOR_STR TALER_EXCHANGEDB_DIR_SIGNING_KEYS,
|
|
|
|
exchange_directory);
|
2015-03-17 14:34:55 +01:00
|
|
|
/* make sure the directory exists */
|
2015-03-15 22:33:28 +01:00
|
|
|
if (GNUNET_OK !=
|
|
|
|
GNUNET_DISK_directory_create (signkey_dir))
|
2015-01-08 18:37:20 +01:00
|
|
|
{
|
2015-03-15 22:33:28 +01:00
|
|
|
fprintf (stderr,
|
|
|
|
"Failed to create signing key directory\n");
|
2016-06-11 17:11:38 +02:00
|
|
|
GNUNET_free (signkey_dir);
|
2015-01-08 18:37:20 +01:00
|
|
|
return GNUNET_SYSERR;
|
|
|
|
}
|
|
|
|
|
2015-03-15 22:33:28 +01:00
|
|
|
get_anchor (signkey_dir,
|
|
|
|
signkey_duration,
|
2015-03-17 14:34:55 +01:00
|
|
|
GNUNET_TIME_UNIT_ZERO /* no overlap for signing keys */,
|
2015-03-15 22:33:28 +01:00
|
|
|
&anchor);
|
2016-06-11 17:11:38 +02:00
|
|
|
GNUNET_free (signkey_dir);
|
2015-01-08 18:37:20 +01:00
|
|
|
|
2015-03-15 22:33:28 +01:00
|
|
|
while (anchor.abs_value_us < lookahead_sign_stamp.abs_value_us)
|
|
|
|
{
|
2016-03-01 15:35:04 +01:00
|
|
|
struct TALER_EXCHANGEDB_PrivateSigningKeyInformationP signkey_issue;
|
2015-03-28 18:18:38 +01:00
|
|
|
struct GNUNET_TIME_Absolute end;
|
2015-03-15 22:33:28 +01:00
|
|
|
|
2015-03-28 18:18:38 +01:00
|
|
|
end = GNUNET_TIME_absolute_add (anchor,
|
|
|
|
legal_duration);
|
2015-03-17 14:34:55 +01:00
|
|
|
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
|
|
|
"Generating signing key for %s.\n",
|
|
|
|
GNUNET_STRINGS_absolute_time_to_string (anchor));
|
|
|
|
create_signkey_issue_priv (anchor,
|
|
|
|
signkey_duration,
|
2015-03-28 18:18:38 +01:00
|
|
|
end,
|
2015-03-17 14:34:55 +01:00
|
|
|
&signkey_issue);
|
2016-05-06 18:33:02 +02:00
|
|
|
if (GNUNET_OK !=
|
|
|
|
TALER_EXCHANGEDB_signing_key_write (exchange_directory,
|
|
|
|
anchor,
|
|
|
|
&signkey_issue))
|
2015-03-17 14:34:55 +01:00
|
|
|
return GNUNET_SYSERR;
|
2015-03-17 11:37:21 +01:00
|
|
|
anchor = GNUNET_TIME_absolute_add (anchor,
|
|
|
|
signkey_duration);
|
2015-01-08 18:37:20 +01:00
|
|
|
}
|
|
|
|
return GNUNET_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-03-15 22:33:28 +01:00
|
|
|
/**
|
2015-03-17 11:37:21 +01:00
|
|
|
* Parse configuration for coin type parameters. Also determines
|
|
|
|
* our anchor by looking at the existing coins of the same type.
|
2015-03-15 22:33:28 +01:00
|
|
|
*
|
2015-03-17 11:37:21 +01:00
|
|
|
* @param ct section in the configuration file giving the coin type parameters
|
2015-03-28 15:42:07 +01:00
|
|
|
* @param[out] params set to the coin parameters from the configuration
|
2015-03-17 11:37:21 +01:00
|
|
|
* @return #GNUNET_OK on success, #GNUNET_SYSERR if the configuration is invalid
|
2015-03-15 22:33:28 +01:00
|
|
|
*/
|
2015-01-26 12:22:26 +01:00
|
|
|
static int
|
2015-03-15 22:33:28 +01:00
|
|
|
get_cointype_params (const char *ct,
|
|
|
|
struct CoinTypeParams *params)
|
2015-01-08 18:37:20 +01:00
|
|
|
{
|
|
|
|
const char *dir;
|
2015-03-17 11:37:21 +01:00
|
|
|
unsigned long long rsa_keysize;
|
2015-03-15 22:33:28 +01:00
|
|
|
|
|
|
|
if (GNUNET_OK !=
|
|
|
|
GNUNET_CONFIGURATION_get_value_time (kcfg,
|
|
|
|
ct,
|
2015-03-17 14:34:55 +01:00
|
|
|
"duration_withdraw",
|
2015-03-15 22:33:28 +01:00
|
|
|
¶ms->duration_withdraw))
|
2015-01-08 18:37:20 +01:00
|
|
|
{
|
2015-03-17 12:17:42 +01:00
|
|
|
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
|
|
|
|
ct,
|
2015-03-17 14:34:55 +01:00
|
|
|
"duration_withdraw");
|
2015-01-08 18:37:20 +01:00
|
|
|
return GNUNET_SYSERR;
|
|
|
|
}
|
2016-03-19 15:23:11 +01:00
|
|
|
GNUNET_TIME_round_rel (¶ms->duration_withdraw);
|
2015-03-15 22:33:28 +01:00
|
|
|
if (GNUNET_OK !=
|
|
|
|
GNUNET_CONFIGURATION_get_value_time (kcfg,
|
|
|
|
ct,
|
2015-03-17 14:34:55 +01:00
|
|
|
"duration_spend",
|
2015-03-15 22:33:28 +01:00
|
|
|
¶ms->duration_spend))
|
2015-01-08 18:37:20 +01:00
|
|
|
{
|
2015-03-17 12:17:42 +01:00
|
|
|
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
|
|
|
|
ct,
|
2015-03-17 14:34:55 +01:00
|
|
|
"duration_spend");
|
2015-01-08 18:37:20 +01:00
|
|
|
return GNUNET_SYSERR;
|
|
|
|
}
|
2016-03-19 15:23:11 +01:00
|
|
|
GNUNET_TIME_round_rel (¶ms->duration_spend);
|
2015-03-28 18:23:45 +01:00
|
|
|
if (GNUNET_OK !=
|
|
|
|
GNUNET_CONFIGURATION_get_value_time (kcfg,
|
|
|
|
ct,
|
|
|
|
"duration_legal",
|
|
|
|
¶ms->duration_legal))
|
|
|
|
{
|
|
|
|
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
|
|
|
|
ct,
|
|
|
|
"duration_legal");
|
|
|
|
return GNUNET_SYSERR;
|
|
|
|
}
|
2016-03-19 15:23:11 +01:00
|
|
|
GNUNET_TIME_round_rel (¶ms->duration_legal);
|
2015-03-15 22:33:28 +01:00
|
|
|
if (GNUNET_OK !=
|
|
|
|
GNUNET_CONFIGURATION_get_value_time (kcfg,
|
|
|
|
ct,
|
2015-03-17 14:34:55 +01:00
|
|
|
"duration_overlap",
|
2015-03-15 22:33:28 +01:00
|
|
|
¶ms->duration_overlap))
|
2015-01-08 18:37:20 +01:00
|
|
|
{
|
2015-03-17 12:17:42 +01:00
|
|
|
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
|
|
|
|
ct,
|
2016-03-01 15:35:04 +01:00
|
|
|
"exchange_denom_duration_overlap");
|
2015-01-08 18:37:20 +01:00
|
|
|
return GNUNET_SYSERR;
|
|
|
|
}
|
2016-03-19 15:23:11 +01:00
|
|
|
GNUNET_TIME_round_rel (¶ms->duration_overlap);
|
2015-03-17 11:37:21 +01:00
|
|
|
if (GNUNET_OK !=
|
|
|
|
GNUNET_CONFIGURATION_get_value_number (kcfg,
|
|
|
|
ct,
|
2015-03-17 14:34:55 +01:00
|
|
|
"rsa_keysize",
|
2015-03-17 11:37:21 +01:00
|
|
|
&rsa_keysize))
|
|
|
|
{
|
2015-03-17 12:17:42 +01:00
|
|
|
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
|
|
|
|
ct,
|
2015-03-17 14:34:55 +01:00
|
|
|
"rsa_keysize");
|
2015-03-17 11:37:21 +01:00
|
|
|
return GNUNET_SYSERR;
|
|
|
|
}
|
|
|
|
if ( (rsa_keysize > 4 * 2048) ||
|
|
|
|
(rsa_keysize < 1024) )
|
|
|
|
{
|
|
|
|
fprintf (stderr,
|
|
|
|
"Given RSA keysize %llu outside of permitted range\n",
|
|
|
|
rsa_keysize);
|
|
|
|
return GNUNET_SYSERR;
|
|
|
|
}
|
|
|
|
params->rsa_keysize = (unsigned int) rsa_keysize;
|
2015-03-15 22:33:28 +01:00
|
|
|
if (GNUNET_OK !=
|
2015-03-17 10:48:12 +01:00
|
|
|
TALER_config_get_denom (kcfg,
|
|
|
|
ct,
|
2015-03-17 14:34:55 +01:00
|
|
|
"value",
|
2015-03-17 10:48:12 +01:00
|
|
|
¶ms->value))
|
2015-01-08 18:37:20 +01:00
|
|
|
{
|
2015-03-17 12:17:42 +01:00
|
|
|
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
|
|
|
|
ct,
|
2015-03-17 14:34:55 +01:00
|
|
|
"value");
|
2015-01-08 18:37:20 +01:00
|
|
|
return GNUNET_SYSERR;
|
|
|
|
}
|
2015-03-15 22:33:28 +01:00
|
|
|
if (GNUNET_OK !=
|
2015-03-17 10:48:12 +01:00
|
|
|
TALER_config_get_denom (kcfg,
|
|
|
|
ct,
|
2015-03-17 14:34:55 +01:00
|
|
|
"fee_withdraw",
|
2015-03-17 10:48:12 +01:00
|
|
|
¶ms->fee_withdraw))
|
2015-01-08 18:37:20 +01:00
|
|
|
{
|
2015-03-17 12:17:42 +01:00
|
|
|
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
|
|
|
|
ct,
|
2015-03-17 14:34:55 +01:00
|
|
|
"fee_withdraw");
|
2015-01-08 18:37:20 +01:00
|
|
|
return GNUNET_SYSERR;
|
|
|
|
}
|
2015-03-15 22:33:28 +01:00
|
|
|
if (GNUNET_OK !=
|
2015-03-17 10:48:12 +01:00
|
|
|
TALER_config_get_denom (kcfg,
|
|
|
|
ct,
|
2015-03-17 14:34:55 +01:00
|
|
|
"fee_deposit",
|
2015-03-17 10:48:12 +01:00
|
|
|
¶ms->fee_deposit))
|
2015-01-08 18:37:20 +01:00
|
|
|
{
|
2015-03-17 12:17:42 +01:00
|
|
|
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
|
|
|
|
ct,
|
2015-03-17 14:34:55 +01:00
|
|
|
"fee_deposit");
|
2015-01-08 18:37:20 +01:00
|
|
|
return GNUNET_SYSERR;
|
|
|
|
}
|
2015-03-15 22:33:28 +01:00
|
|
|
if (GNUNET_OK !=
|
2015-03-17 10:48:12 +01:00
|
|
|
TALER_config_get_denom (kcfg,
|
|
|
|
ct,
|
2015-03-17 14:34:55 +01:00
|
|
|
"fee_refresh",
|
2015-03-17 10:48:12 +01:00
|
|
|
¶ms->fee_refresh))
|
2015-01-08 18:37:20 +01:00
|
|
|
{
|
2015-03-17 12:17:42 +01:00
|
|
|
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
|
|
|
|
ct,
|
2015-03-17 14:34:55 +01:00
|
|
|
"fee_refresh");
|
2015-01-08 18:37:20 +01:00
|
|
|
return GNUNET_SYSERR;
|
|
|
|
}
|
2016-04-20 01:50:26 +02:00
|
|
|
if (GNUNET_OK !=
|
|
|
|
TALER_config_get_denom (kcfg,
|
|
|
|
ct,
|
|
|
|
"fee_refund",
|
|
|
|
¶ms->fee_refund))
|
|
|
|
{
|
|
|
|
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
|
|
|
|
ct,
|
|
|
|
"fee_refund");
|
|
|
|
return GNUNET_SYSERR;
|
|
|
|
}
|
2015-01-08 18:37:20 +01:00
|
|
|
|
|
|
|
dir = get_cointype_dir (params);
|
2015-03-17 11:37:21 +01:00
|
|
|
get_anchor (dir,
|
2015-07-05 11:49:33 +02:00
|
|
|
params->duration_withdraw,
|
2015-03-17 11:37:21 +01:00
|
|
|
params->duration_overlap,
|
|
|
|
¶ms->anchor);
|
2015-01-08 18:37:20 +01:00
|
|
|
return GNUNET_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-03-15 22:33:28 +01:00
|
|
|
/**
|
2015-03-17 11:37:21 +01:00
|
|
|
* Initialize the private and public key information structure for
|
|
|
|
* signing coins into existence. Generates the private signing key
|
|
|
|
* and signes it together with the coin's meta data using the master
|
|
|
|
* signing key.
|
2015-03-15 22:33:28 +01:00
|
|
|
*
|
2015-03-17 11:37:21 +01:00
|
|
|
* @param params parameters used to initialize the @a dki
|
2015-03-28 15:42:07 +01:00
|
|
|
* @param[out] dki initialized according to @a params
|
2015-03-15 22:33:28 +01:00
|
|
|
*/
|
2015-01-08 18:37:20 +01:00
|
|
|
static void
|
2015-03-17 11:37:21 +01:00
|
|
|
create_denomkey_issue (const struct CoinTypeParams *params,
|
2016-03-01 15:35:04 +01:00
|
|
|
struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki)
|
2015-01-08 18:37:20 +01:00
|
|
|
{
|
2015-03-22 22:14:30 +01:00
|
|
|
dki->denom_priv.rsa_private_key
|
|
|
|
= GNUNET_CRYPTO_rsa_private_key_create (params->rsa_keysize);
|
|
|
|
GNUNET_assert (NULL != dki->denom_priv.rsa_private_key);
|
|
|
|
dki->denom_pub.rsa_public_key
|
|
|
|
= GNUNET_CRYPTO_rsa_private_key_get_public (dki->denom_priv.rsa_private_key);
|
|
|
|
GNUNET_CRYPTO_rsa_public_key_hash (dki->denom_pub.rsa_public_key,
|
2015-07-06 10:16:49 +02:00
|
|
|
&dki->issue.properties.denom_hash);
|
|
|
|
dki->issue.properties.master = master_public_key;
|
|
|
|
dki->issue.properties.start = GNUNET_TIME_absolute_hton (params->anchor);
|
|
|
|
dki->issue.properties.expire_withdraw =
|
2015-01-09 18:18:59 +01:00
|
|
|
GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_add (params->anchor,
|
2015-01-08 18:37:20 +01:00
|
|
|
params->duration_withdraw));
|
2016-05-02 05:10:40 +02:00
|
|
|
dki->issue.properties.expire_deposit =
|
2015-01-09 18:18:59 +01:00
|
|
|
GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_add (params->anchor,
|
2015-03-28 18:23:45 +01:00
|
|
|
params->duration_spend));
|
2015-07-06 10:16:49 +02:00
|
|
|
dki->issue.properties.expire_legal =
|
2015-03-28 18:23:45 +01:00
|
|
|
GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_add (params->anchor,
|
|
|
|
params->duration_legal));
|
2015-07-06 10:16:49 +02:00
|
|
|
TALER_amount_hton (&dki->issue.properties.value,
|
2015-03-18 18:55:41 +01:00
|
|
|
¶ms->value);
|
2015-07-06 10:16:49 +02:00
|
|
|
TALER_amount_hton (&dki->issue.properties.fee_withdraw,
|
2015-03-18 18:55:41 +01:00
|
|
|
¶ms->fee_withdraw);
|
2015-07-06 10:16:49 +02:00
|
|
|
TALER_amount_hton (&dki->issue.properties.fee_deposit,
|
2015-03-18 18:55:41 +01:00
|
|
|
¶ms->fee_deposit);
|
2015-07-06 10:16:49 +02:00
|
|
|
TALER_amount_hton (&dki->issue.properties.fee_refresh,
|
2015-03-18 18:55:41 +01:00
|
|
|
¶ms->fee_refresh);
|
2016-04-20 01:50:26 +02:00
|
|
|
TALER_amount_hton (&dki->issue.properties.fee_refund,
|
|
|
|
¶ms->fee_refund);
|
2015-07-06 10:16:49 +02:00
|
|
|
dki->issue.properties.purpose.purpose
|
2015-06-19 22:24:02 +02:00
|
|
|
= htonl (TALER_SIGNATURE_MASTER_DENOMINATION_KEY_VALIDITY);
|
2015-07-06 10:16:49 +02:00
|
|
|
dki->issue.properties.purpose.size
|
|
|
|
= htonl (sizeof (struct TALER_DenominationKeyValidityPS));
|
2015-03-09 11:24:35 +01:00
|
|
|
GNUNET_assert (GNUNET_OK ==
|
2015-03-22 22:14:30 +01:00
|
|
|
GNUNET_CRYPTO_eddsa_sign (&master_priv.eddsa_priv,
|
2015-07-06 10:16:49 +02:00
|
|
|
&dki->issue.properties.purpose,
|
2015-03-22 22:14:30 +01:00
|
|
|
&dki->issue.signature.eddsa_signature));
|
2015-01-08 18:37:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-03-15 22:33:28 +01:00
|
|
|
/**
|
2015-03-17 11:37:21 +01:00
|
|
|
* Generate new coin signing keys for the coin type of the given @a
|
|
|
|
* coin_alias.
|
2015-03-15 22:33:28 +01:00
|
|
|
*
|
2015-03-17 14:45:31 +01:00
|
|
|
* @param cls a `int *`, to be set to #GNUNET_SYSERR on failure
|
2015-03-17 11:37:21 +01:00
|
|
|
* @param coin_alias name of the coin's section in the configuration
|
2015-03-15 22:33:28 +01:00
|
|
|
*/
|
2015-03-17 14:45:31 +01:00
|
|
|
static void
|
2016-03-01 15:35:04 +01:00
|
|
|
exchange_keys_update_cointype (void *cls,
|
2016-04-20 01:50:26 +02:00
|
|
|
const char *coin_alias)
|
2015-01-08 18:37:20 +01:00
|
|
|
{
|
2015-03-17 14:45:31 +01:00
|
|
|
int *ret = cls;
|
2015-01-08 18:37:20 +01:00
|
|
|
struct CoinTypeParams p;
|
2015-03-17 14:45:31 +01:00
|
|
|
const char *dkf;
|
2016-03-01 15:35:04 +01:00
|
|
|
struct TALER_EXCHANGEDB_DenominationKeyIssueInformation denomkey_issue;
|
2015-01-08 18:37:20 +01:00
|
|
|
|
2015-03-17 14:45:31 +01:00
|
|
|
if (0 != strncasecmp (coin_alias,
|
|
|
|
"coin_",
|
|
|
|
strlen ("coin_")))
|
|
|
|
return; /* not a coin definition */
|
|
|
|
if (GNUNET_OK !=
|
|
|
|
get_cointype_params (coin_alias,
|
|
|
|
&p))
|
|
|
|
{
|
|
|
|
*ret = GNUNET_SYSERR;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (GNUNET_OK !=
|
|
|
|
GNUNET_DISK_directory_create (get_cointype_dir (&p)))
|
|
|
|
{
|
|
|
|
*ret = GNUNET_SYSERR;
|
|
|
|
return;
|
|
|
|
}
|
2015-01-08 18:37:20 +01:00
|
|
|
|
2015-03-15 22:33:28 +01:00
|
|
|
while (p.anchor.abs_value_us < lookahead_sign_stamp.abs_value_us)
|
|
|
|
{
|
2015-03-17 14:45:31 +01:00
|
|
|
dkf = get_cointype_file (&p,
|
|
|
|
p.anchor);
|
|
|
|
GNUNET_break (GNUNET_YES != GNUNET_DISK_file_test (dkf));
|
|
|
|
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
|
|
|
"Generating denomination key for type `%s', start %s at %s\n",
|
|
|
|
coin_alias,
|
|
|
|
GNUNET_STRINGS_absolute_time_to_string (p.anchor),
|
|
|
|
dkf);
|
|
|
|
create_denomkey_issue (&p,
|
|
|
|
&denomkey_issue);
|
|
|
|
if (GNUNET_OK !=
|
2016-03-01 15:35:04 +01:00
|
|
|
TALER_EXCHANGEDB_denomination_key_write (dkf,
|
2016-06-15 18:42:00 +02:00
|
|
|
&denomkey_issue))
|
2015-01-08 18:37:20 +01:00
|
|
|
{
|
2015-03-17 14:45:31 +01:00
|
|
|
fprintf (stderr,
|
|
|
|
"Failed to write denomination key information to file `%s'.\n",
|
|
|
|
dkf);
|
|
|
|
*ret = GNUNET_SYSERR;
|
2015-03-22 22:14:30 +01:00
|
|
|
GNUNET_CRYPTO_rsa_private_key_free (denomkey_issue.denom_priv.rsa_private_key);
|
2016-06-15 18:42:00 +02:00
|
|
|
GNUNET_CRYPTO_rsa_public_key_free (denomkey_issue.denom_pub.rsa_public_key);
|
2015-03-17 14:45:31 +01:00
|
|
|
return;
|
2015-01-08 18:37:20 +01:00
|
|
|
}
|
2015-09-16 18:48:05 +02:00
|
|
|
if ( (NULL != auditor_output_file) &&
|
|
|
|
(sizeof (denomkey_issue.issue.properties) !=
|
|
|
|
fwrite (&denomkey_issue.issue.properties,
|
|
|
|
sizeof (struct TALER_DenominationKeyValidityPS),
|
|
|
|
1,
|
|
|
|
auditor_output_file)) )
|
|
|
|
{
|
|
|
|
fprintf (stderr,
|
|
|
|
"Failed to write denomination key information to %s: %s\n",
|
|
|
|
auditorrequestfile,
|
|
|
|
STRERROR (errno));
|
|
|
|
*ret = GNUNET_SYSERR;
|
2016-06-15 18:42:00 +02:00
|
|
|
GNUNET_CRYPTO_rsa_private_key_free (denomkey_issue.denom_priv.rsa_private_key);
|
|
|
|
GNUNET_CRYPTO_rsa_public_key_free (denomkey_issue.denom_pub.rsa_public_key);
|
2015-09-16 18:48:05 +02:00
|
|
|
return;
|
|
|
|
}
|
2015-03-22 22:14:30 +01:00
|
|
|
GNUNET_CRYPTO_rsa_private_key_free (denomkey_issue.denom_priv.rsa_private_key);
|
2016-06-15 18:42:00 +02:00
|
|
|
GNUNET_CRYPTO_rsa_public_key_free (denomkey_issue.denom_pub.rsa_public_key);
|
2015-03-17 14:45:31 +01:00
|
|
|
p.anchor = GNUNET_TIME_absolute_add (p.anchor,
|
|
|
|
p.duration_spend);
|
|
|
|
p.anchor = GNUNET_TIME_absolute_subtract (p.anchor,
|
|
|
|
p.duration_overlap);
|
2015-01-08 18:37:20 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-03-15 22:33:28 +01:00
|
|
|
/**
|
2016-03-01 15:35:04 +01:00
|
|
|
* Update all of the denomination keys of the exchange.
|
2015-03-15 22:33:28 +01:00
|
|
|
*
|
2015-03-17 12:17:42 +01:00
|
|
|
* @return #GNUNET_OK on success, #GNUNET_SYSERR on error
|
2015-03-15 22:33:28 +01:00
|
|
|
*/
|
2015-01-26 12:22:26 +01:00
|
|
|
static int
|
2016-03-01 15:35:04 +01:00
|
|
|
exchange_keys_update_denomkeys ()
|
2015-01-08 18:37:20 +01:00
|
|
|
{
|
2015-03-17 14:45:31 +01:00
|
|
|
int ok;
|
2015-01-08 18:37:20 +01:00
|
|
|
|
2015-03-17 14:45:31 +01:00
|
|
|
ok = GNUNET_OK;
|
|
|
|
GNUNET_CONFIGURATION_iterate_sections (kcfg,
|
2016-03-01 15:35:04 +01:00
|
|
|
&exchange_keys_update_cointype,
|
2015-03-17 14:45:31 +01:00
|
|
|
&ok);
|
|
|
|
return ok;
|
2015-01-08 18:37:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2016-04-16 12:37:37 +02:00
|
|
|
* Main function that will be run.
|
2015-01-08 18:37:20 +01:00
|
|
|
*
|
2016-04-16 12:37:37 +02:00
|
|
|
* @param cls closure
|
|
|
|
* @param args remaining command-line arguments
|
|
|
|
* @param cfgfile name of the configuration file used (for saving, can be NULL!)
|
2016-04-16 13:10:29 +02:00
|
|
|
* @param cfg configuration
|
2015-01-08 18:37:20 +01:00
|
|
|
*/
|
2016-04-16 12:37:37 +02:00
|
|
|
static void
|
|
|
|
run (void *cls,
|
|
|
|
char *const *args,
|
|
|
|
const char *cfgfile,
|
|
|
|
const struct GNUNET_CONFIGURATION_Handle *cfg)
|
2015-01-08 18:37:20 +01:00
|
|
|
{
|
2015-03-17 12:27:26 +01:00
|
|
|
struct GNUNET_TIME_Relative lookahead_sign;
|
2015-03-22 22:14:30 +01:00
|
|
|
struct GNUNET_CRYPTO_EddsaPrivateKey *eddsa_priv;
|
2015-01-08 18:37:20 +01:00
|
|
|
|
2016-04-16 12:37:37 +02:00
|
|
|
kcfg = cfg;
|
2015-01-08 18:37:20 +01:00
|
|
|
if (NULL != pretend_time_str)
|
|
|
|
{
|
2015-03-15 22:33:28 +01:00
|
|
|
if (GNUNET_OK !=
|
|
|
|
GNUNET_STRINGS_fancy_time_to_absolute (pretend_time_str,
|
|
|
|
&now))
|
2015-01-08 18:37:20 +01:00
|
|
|
{
|
2015-03-15 22:33:28 +01:00
|
|
|
fprintf (stderr,
|
2015-03-17 12:27:26 +01:00
|
|
|
"timestamp `%s' invalid\n",
|
|
|
|
pretend_time_str);
|
2016-04-16 12:37:37 +02:00
|
|
|
global_ret = 1;
|
|
|
|
return;
|
2015-01-08 18:37:20 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
now = GNUNET_TIME_absolute_get ();
|
|
|
|
}
|
2016-03-19 15:23:11 +01:00
|
|
|
GNUNET_TIME_round_abs (&now);
|
2016-04-10 17:10:20 +02:00
|
|
|
if ( (NULL == masterkeyfile) &&
|
|
|
|
(GNUNET_OK !=
|
|
|
|
GNUNET_CONFIGURATION_get_value_filename (kcfg,
|
|
|
|
"exchange",
|
|
|
|
"MASTER_PRIV_FILE",
|
|
|
|
&masterkeyfile)) )
|
2015-01-08 18:37:20 +01:00
|
|
|
{
|
2015-03-15 22:33:28 +01:00
|
|
|
fprintf (stderr,
|
2016-04-10 17:10:20 +02:00
|
|
|
"Master key file not given in neither configuration nor command-line\n");
|
2016-04-16 12:37:37 +02:00
|
|
|
global_ret = 1;
|
|
|
|
return;
|
2015-01-08 18:37:20 +01:00
|
|
|
}
|
2016-04-10 17:10:20 +02:00
|
|
|
if (GNUNET_OK !=
|
|
|
|
GNUNET_CONFIGURATION_get_value_filename (kcfg,
|
|
|
|
"exchange",
|
|
|
|
"KEYDIR",
|
|
|
|
&exchange_directory))
|
2015-01-08 18:37:20 +01:00
|
|
|
{
|
2016-04-10 17:10:20 +02:00
|
|
|
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
|
|
|
|
"exchange",
|
|
|
|
"KEYDIR");
|
2016-04-16 12:37:37 +02:00
|
|
|
global_ret = 1;
|
|
|
|
return;
|
2015-01-08 18:37:20 +01:00
|
|
|
}
|
2016-05-05 15:03:43 +02:00
|
|
|
if (GNUNET_YES != GNUNET_DISK_file_test (masterkeyfile))
|
|
|
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
|
|
|
"Exchange master private key `%s' does not exist yet, creating it!\n",
|
|
|
|
masterkeyfile);
|
2015-03-22 22:14:30 +01:00
|
|
|
eddsa_priv = GNUNET_CRYPTO_eddsa_key_create_from_file (masterkeyfile);
|
|
|
|
if (NULL == eddsa_priv)
|
2015-01-08 18:37:20 +01:00
|
|
|
{
|
2015-03-15 22:33:28 +01:00
|
|
|
fprintf (stderr,
|
|
|
|
"Failed to initialize master key from file `%s'\n",
|
|
|
|
masterkeyfile);
|
2016-04-16 12:37:37 +02:00
|
|
|
global_ret = 1;
|
|
|
|
return;
|
2015-01-08 18:37:20 +01:00
|
|
|
}
|
2015-03-22 22:14:30 +01:00
|
|
|
master_priv.eddsa_priv = *eddsa_priv;
|
|
|
|
GNUNET_free (eddsa_priv);
|
|
|
|
GNUNET_CRYPTO_eddsa_key_get_public (&master_priv.eddsa_priv,
|
2015-03-27 19:58:40 +01:00
|
|
|
&master_public_key.eddsa_pub);
|
2015-01-08 18:37:20 +01:00
|
|
|
|
2015-09-16 18:48:05 +02:00
|
|
|
if (NULL != auditorrequestfile)
|
|
|
|
{
|
|
|
|
auditor_output_file = FOPEN (auditorrequestfile,
|
|
|
|
"w");
|
|
|
|
if (NULL == auditor_output_file)
|
|
|
|
{
|
|
|
|
fprintf (stderr,
|
|
|
|
"Failed to open `%s' for writing: %s\n",
|
|
|
|
auditorrequestfile,
|
|
|
|
STRERROR (errno));
|
2016-04-16 12:37:37 +02:00
|
|
|
global_ret = 1;
|
|
|
|
return;
|
2015-09-16 18:48:05 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-17 12:27:26 +01:00
|
|
|
/* check if key from file matches the one from the configuration */
|
2015-01-08 18:37:20 +01:00
|
|
|
{
|
2015-03-27 19:58:40 +01:00
|
|
|
struct GNUNET_CRYPTO_EddsaPublicKey master_public_key_from_cfg;
|
2015-03-15 22:33:28 +01:00
|
|
|
|
2015-01-27 18:35:17 +01:00
|
|
|
if (GNUNET_OK !=
|
2015-03-15 22:33:28 +01:00
|
|
|
GNUNET_CONFIGURATION_get_data (kcfg,
|
2016-03-01 15:35:04 +01:00
|
|
|
"exchange",
|
2015-03-27 19:58:40 +01:00
|
|
|
"master_public_key",
|
|
|
|
&master_public_key_from_cfg,
|
2015-01-27 18:35:17 +01:00
|
|
|
sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)))
|
2015-01-08 18:37:20 +01:00
|
|
|
{
|
2015-03-17 12:17:42 +01:00
|
|
|
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
|
2016-03-01 15:35:04 +01:00
|
|
|
"exchange",
|
2015-03-27 19:58:40 +01:00
|
|
|
"master_public_key");
|
2016-04-16 12:37:37 +02:00
|
|
|
global_ret = 1;
|
|
|
|
return;
|
2015-01-08 18:37:20 +01:00
|
|
|
}
|
2015-03-15 22:33:28 +01:00
|
|
|
if (0 !=
|
2015-03-27 19:58:40 +01:00
|
|
|
memcmp (&master_public_key,
|
|
|
|
&master_public_key_from_cfg,
|
2015-03-15 22:33:28 +01:00
|
|
|
sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)))
|
2015-01-08 18:37:20 +01:00
|
|
|
{
|
2015-03-17 12:17:42 +01:00
|
|
|
GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
|
2016-03-01 15:35:04 +01:00
|
|
|
"exchange",
|
2015-03-27 19:58:40 +01:00
|
|
|
"master_public_key",
|
2015-03-17 12:17:42 +01:00
|
|
|
_("does not match with private key"));
|
2016-04-16 12:37:37 +02:00
|
|
|
global_ret = 1;
|
|
|
|
return;
|
2015-01-08 18:37:20 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-17 12:27:26 +01:00
|
|
|
if (GNUNET_OK !=
|
|
|
|
GNUNET_CONFIGURATION_get_value_time (kcfg,
|
2016-03-01 15:35:04 +01:00
|
|
|
"exchange_keys",
|
2015-03-17 12:27:26 +01:00
|
|
|
"lookahead_sign",
|
|
|
|
&lookahead_sign))
|
|
|
|
{
|
|
|
|
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
|
2016-03-01 15:35:04 +01:00
|
|
|
"exchange_keys",
|
2015-03-17 12:27:26 +01:00
|
|
|
"lookahead_sign");
|
2016-04-16 12:37:37 +02:00
|
|
|
global_ret = 1;
|
|
|
|
return;
|
2015-03-17 12:27:26 +01:00
|
|
|
}
|
|
|
|
if (0 == lookahead_sign.rel_value_us)
|
|
|
|
{
|
|
|
|
GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
|
2016-03-01 15:35:04 +01:00
|
|
|
"exchange_keys",
|
2015-03-17 12:27:26 +01:00
|
|
|
"lookahead_sign",
|
|
|
|
_("must not be zero"));
|
2016-04-16 12:37:37 +02:00
|
|
|
global_ret = 1;
|
|
|
|
return;
|
2015-03-17 12:27:26 +01:00
|
|
|
}
|
2016-03-19 15:23:11 +01:00
|
|
|
GNUNET_TIME_round_rel (&lookahead_sign);
|
2015-03-17 12:27:26 +01:00
|
|
|
lookahead_sign_stamp = GNUNET_TIME_absolute_add (now,
|
|
|
|
lookahead_sign);
|
|
|
|
|
|
|
|
|
|
|
|
/* finally, do actual work */
|
2016-03-01 15:35:04 +01:00
|
|
|
if (GNUNET_OK != exchange_keys_update_signkeys ())
|
2016-04-16 12:37:37 +02:00
|
|
|
{
|
|
|
|
global_ret = 1;
|
|
|
|
return;
|
|
|
|
}
|
2016-03-01 15:35:04 +01:00
|
|
|
if (GNUNET_OK != exchange_keys_update_denomkeys ())
|
2016-04-16 12:37:37 +02:00
|
|
|
{
|
|
|
|
global_ret = 1;
|
|
|
|
return;
|
|
|
|
}
|
2015-09-16 18:48:05 +02:00
|
|
|
if (NULL != auditor_output_file)
|
|
|
|
{
|
|
|
|
FCLOSE (auditor_output_file);
|
|
|
|
auditor_output_file = NULL;
|
|
|
|
}
|
2016-04-16 12:37:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The main function of the taler-exchange-keyup tool. This tool is used
|
|
|
|
* to create the signing and denomination keys for the exchange. It uses
|
|
|
|
* the long-term offline private key and writes the (additional) key
|
|
|
|
* files to the respective exchange directory (from where they can then be
|
|
|
|
* copied to the online server). Note that we need (at least) the
|
|
|
|
* most recent generated previous keys so as to align the validity
|
|
|
|
* periods.
|
|
|
|
*
|
|
|
|
* @param argc number of arguments from the command line
|
|
|
|
* @param argv command line arguments
|
|
|
|
* @return 0 ok, 1 on error
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
main (int argc,
|
|
|
|
char *const *argv)
|
|
|
|
{
|
|
|
|
const struct GNUNET_GETOPT_CommandLineOption options[] = {
|
2016-04-16 13:10:29 +02:00
|
|
|
{'m', "master-key", "FILE",
|
2016-04-16 12:37:37 +02:00
|
|
|
"master key file (private key)", 1,
|
|
|
|
&GNUNET_GETOPT_set_filename, &masterkeyfile},
|
|
|
|
{'o', "output", "FILE",
|
|
|
|
"auditor denomination key signing request file to create", 1,
|
|
|
|
&GNUNET_GETOPT_set_filename, &auditorrequestfile},
|
|
|
|
{'t', "time", "TIMESTAMP",
|
|
|
|
"pretend it is a different time for the update", 0,
|
|
|
|
&GNUNET_GETOPT_set_string, &pretend_time_str},
|
|
|
|
GNUNET_GETOPT_OPTION_END
|
|
|
|
};
|
|
|
|
|
|
|
|
GNUNET_assert (GNUNET_OK ==
|
|
|
|
GNUNET_log_setup ("taler-exchange-keyup",
|
|
|
|
"WARNING",
|
|
|
|
NULL));
|
2016-04-16 13:57:22 +02:00
|
|
|
|
2016-04-16 12:37:37 +02:00
|
|
|
if (GNUNET_OK !=
|
|
|
|
GNUNET_PROGRAM_run (argc, argv,
|
|
|
|
"taler-exchange-keyup",
|
|
|
|
"Setup signing and denomination keys for a Taler exchange",
|
|
|
|
options,
|
|
|
|
&run, NULL))
|
|
|
|
return 1;
|
|
|
|
return global_ret;
|
2015-01-08 18:37:20 +01:00
|
|
|
}
|
2015-03-15 22:33:28 +01:00
|
|
|
|
2016-03-01 15:35:04 +01:00
|
|
|
/* end of taler-exchange-keyup.c */
|