commit 32c6179920dc7be3c4e8a09be907ab7474097a45
parent c8120134fd650a66deb55ab64c1e77d7e06be529
Author: Christian Grothoff <christian@grothoff.org>
Date: Mon, 2 Feb 2026 09:37:50 +0100
ensure secmod CS anchors all end at the same time (#10892)
Diffstat:
2 files changed, 327 insertions(+), 184 deletions(-)
diff --git a/src/util/secmod_cs.c b/src/util/secmod_cs.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2014-2024 Taler Systems SA
+ Copyright (C) 2014-2026 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
@@ -98,7 +98,12 @@ struct DenominationKey
/**
* Time at which this key is supposed to become valid.
*/
- struct GNUNET_TIME_Timestamp anchor;
+ struct GNUNET_TIME_Timestamp anchor_start;
+
+ /**
+ * Time at which this key is supposed to expire (exclusive).
+ */
+ struct GNUNET_TIME_Timestamp anchor_end;
/**
* Generation when this key was created or revoked.
@@ -384,6 +389,7 @@ generate_response (struct DenominationKey *dk)
struct TALER_CRYPTO_CsKeyAvailableNotification *an;
void *p;
size_t tlen;
+ struct GNUNET_TIME_Relative effective_duration;
GNUNET_assert (sizeof(dk->denom_pub) < UINT16_MAX);
GNUNET_assert (nlen < UINT16_MAX);
@@ -393,13 +399,16 @@ generate_response (struct DenominationKey *dk)
an->header.size = htons ((uint16_t) tlen);
an->header.type = htons (TALER_HELPER_CS_MT_AVAIL);
an->section_name_len = htons ((uint16_t) nlen);
- an->anchor_time = GNUNET_TIME_timestamp_hton (dk->anchor);
- an->duration_withdraw = GNUNET_TIME_relative_hton (denom->duration_withdraw);
+ an->anchor_time = GNUNET_TIME_timestamp_hton (dk->anchor_start);
+ effective_duration = GNUNET_TIME_absolute_get_difference (
+ dk->anchor_start.abs_time,
+ dk->anchor_end.abs_time);
+ an->duration_withdraw = GNUNET_TIME_relative_hton (effective_duration);
an->denom_pub = dk->denom_pub;
TALER_exchange_secmod_cs_sign (&dk->h_cs,
denom->section,
- dk->anchor,
- denom->duration_withdraw,
+ dk->anchor_start,
+ effective_duration,
&TES_smpriv,
&an->secm_sig);
an->secm_pub = TES_smpub;
@@ -440,7 +449,7 @@ do_sign (const struct TALER_CsPubHashP *h_cs,
GNUNET_h2s (&h_cs->hash));
return TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN;
}
- if (GNUNET_TIME_absolute_is_future (dk->anchor.abs_time))
+ if (GNUNET_TIME_absolute_is_future (dk->anchor_start.abs_time))
{
GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
@@ -448,6 +457,18 @@ do_sign (const struct TALER_CsPubHashP *h_cs,
GNUNET_h2s (&h_cs->hash));
return TALER_EC_EXCHANGE_DENOMINATION_HELPER_TOO_EARLY;
}
+ if (GNUNET_TIME_absolute_is_past (dk->anchor_end.abs_time))
+ {
+ /* it is too late; now, usually we should never get here
+ as we delete upon expiration, so this is just conservative */
+ GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Signing request failed, denomination key %s is expired (%llu)\n",
+ GNUNET_h2s (&h_cs->hash),
+ (unsigned long long) dk->anchor_end.abs_time.abs_value_us);
+ /* usually we delete upon expiratoin, hence same EC */
+ return TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN;
+ }
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Received request to sign over bytes with key %s\n",
GNUNET_h2s (&h_cs->hash));
@@ -603,7 +624,7 @@ do_derive (const struct TALER_CsPubHashP *h_cs,
GNUNET_h2s (&h_cs->hash));
return TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN;
}
- if (GNUNET_TIME_absolute_is_future (dk->anchor.abs_time))
+ if (GNUNET_TIME_absolute_is_future (dk->anchor_start.abs_time))
{
GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
@@ -611,6 +632,18 @@ do_derive (const struct TALER_CsPubHashP *h_cs,
GNUNET_h2s (&h_cs->hash));
return TALER_EC_EXCHANGE_DENOMINATION_HELPER_TOO_EARLY;
}
+ if (GNUNET_TIME_absolute_is_past (dk->anchor_end.abs_time))
+ {
+ /* it is too late; now, usually we should never get here
+ as we delete upon expiration, so this is just conservative */
+ GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Signing request failed, denomination key %s is expired (%llu)\n",
+ GNUNET_h2s (&h_cs->hash),
+ (unsigned long long) dk->anchor_end.abs_time.abs_value_us);
+ /* usually we delete upon expiratoin, hence same EC */
+ return TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN;
+ }
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Received request to derive R with key %s\n",
GNUNET_h2s (&h_cs->hash));
@@ -1076,13 +1109,17 @@ setup_key (struct DenominationKey *dk,
GNUNET_CRYPTO_hash (&pub,
sizeof (pub),
&dk->h_cs.hash);
- GNUNET_asprintf (&dk->filename,
- "%s/%s/%llu",
- keydir,
- denom->section,
- (unsigned long long) (dk->anchor.abs_time.abs_value_us
- / GNUNET_TIME_UNIT_SECONDS.rel_value_us
- ));
+ GNUNET_asprintf (
+ &dk->filename,
+ "%s/%s/%llu-%llu",
+ keydir,
+ denom->section,
+ (unsigned long long) (dk->anchor_start.abs_time.abs_value_us
+ / GNUNET_TIME_UNIT_SECONDS.rel_value_us
+ ),
+ (unsigned long long) (dk->anchor_end.abs_time.abs_value_us
+ / GNUNET_TIME_UNIT_SECONDS.rel_value_us
+ ));
if (GNUNET_OK !=
GNUNET_DISK_fn_write (dk->filename,
&priv,
@@ -1097,7 +1134,7 @@ setup_key (struct DenominationKey *dk,
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Setup fresh private key %s at %s in `%s' (generation #%llu)\n",
GNUNET_h2s (&dk->h_cs.hash),
- GNUNET_TIME_timestamp2s (dk->anchor),
+ GNUNET_TIME_timestamp2s (dk->anchor_start),
dk->filename,
(unsigned long long) key_gen);
dk->denom_priv = priv;
@@ -1194,7 +1231,8 @@ handle_revoke_request (struct TES_Client *client,
denom = dk->denom;
ndk = GNUNET_new (struct DenominationKey);
ndk->denom = denom;
- ndk->anchor = dk->anchor;
+ ndk->anchor_start = dk->anchor_start;
+ ndk->anchor_end = dk->anchor_end;
if (GNUNET_OK !=
setup_key (ndk,
dk))
@@ -1485,34 +1523,26 @@ cs_update_client_keys (struct TES_Client *client)
/**
* Create a new denomination key (we do not have enough).
*
- * @param[in] denom denomination key to create
- * @param now current time to use (to get many keys to use the exact same time)
+ * @param[in,out] denom denomination key to create
+ * @param anchor_start when to start key signing validity
+ * @param anchor_end when to end key signing validity
* @return #GNUNET_OK on success
*/
static enum GNUNET_GenericReturnValue
create_key (struct Denomination *denom,
- struct GNUNET_TIME_Timestamp now)
+ struct GNUNET_TIME_Timestamp anchor_start,
+ struct GNUNET_TIME_Timestamp anchor_end)
{
struct DenominationKey *dk;
- struct GNUNET_TIME_Timestamp anchor;
- anchor = now;
- if (NULL != denom->keys_tail)
- {
- struct GNUNET_TIME_Absolute abs;
-
- abs = GNUNET_TIME_absolute_add (denom->keys_tail->anchor.abs_time,
- GNUNET_TIME_relative_subtract (
- denom->duration_withdraw,
- overlap_duration));
- if (GNUNET_TIME_absolute_cmp (now.abs_time,
- <,
- abs))
- anchor = GNUNET_TIME_absolute_to_timestamp (abs);
- }
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Creating new key for `%s' with start date %s\n",
+ denom->section,
+ GNUNET_TIME_timestamp2s (anchor_start));
dk = GNUNET_new (struct DenominationKey);
dk->denom = denom;
- dk->anchor = anchor;
+ dk->anchor_start = anchor_start;
+ dk->anchor_end = anchor_end;
if (GNUNET_OK !=
setup_key (dk,
denom->keys_tail))
@@ -1528,95 +1558,59 @@ create_key (struct Denomination *denom,
/**
- * At what time does this denomination require its next action?
- * Basically, the minimum of the withdraw expiration time of the
- * oldest denomination key, and the withdraw expiration time of
- * the newest denomination key minus the #lookahead_sign time.
+ * Obtain the maximum withdraw duration of all denominations.
*
- * @param denom denomination to compute action time for
+ * Must only be called while the #keys_lock is held.
+ *
+ * @return maximum withdraw duration, zero if there are no denominations
+ */
+static struct GNUNET_TIME_Relative
+get_maximum_duration (void)
+{
+ struct GNUNET_TIME_Relative ret
+ = GNUNET_TIME_UNIT_ZERO;
+
+ for (struct Denomination *denom = denom_head;
+ NULL != denom;
+ denom = denom->next)
+ {
+ ret = GNUNET_TIME_relative_max (ret,
+ denom->duration_withdraw);
+ }
+ return ret;
+}
+
+
+/**
+ * At what time do we need to next create keys if we just did?
+ *
+ * @return time when to next create keys if we just finished key generation
*/
static struct GNUNET_TIME_Absolute
-denomination_action_time (const struct Denomination *denom)
+action_time (void)
{
- struct DenominationKey *head = denom->keys_head;
- struct DenominationKey *tail = denom->keys_tail;
- struct GNUNET_TIME_Absolute tt;
-
- if (NULL == head)
- return GNUNET_TIME_UNIT_ZERO_ABS;
- tt = GNUNET_TIME_absolute_subtract (
- GNUNET_TIME_absolute_subtract (
- GNUNET_TIME_absolute_add (tail->anchor.abs_time,
- denom->duration_withdraw),
- lookahead_sign),
- overlap_duration);
- if (head->rc > 0)
- return tt; /* head expiration does not count due to rc > 0 */
- return GNUNET_TIME_absolute_min (
- GNUNET_TIME_absolute_add (head->anchor.abs_time,
- denom->duration_withdraw),
- tt);
+ struct GNUNET_TIME_Relative md = get_maximum_duration ();
+ struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
+ uint64_t mod;
+
+ mod = now.abs_value_us % md.rel_value_us;
+ now.abs_value_us -= mod;
+ return GNUNET_TIME_absolute_add (now,
+ md);
}
/**
- * Create new keys and expire ancient keys of the given denomination @a denom.
- * Removes the @a denom from the #denom_head DLL and re-insert its at the
- * correct location sorted by next maintenance activity.
+ * Remove all denomination keys of @a denom that have expired.
*
- * @param[in,out] denom denomination to update material for
- * @param now current time to use (to get many keys to use the exact same time)
- * @param[in,out] wake set to true if we should wake the clients
- * @return #GNUNET_OK on success
+ * @param[in,out] denom denomination family to remove keys for
*/
-static enum GNUNET_GenericReturnValue
-update_keys (struct Denomination *denom,
- struct GNUNET_TIME_Timestamp now,
- bool *wake)
+static void
+remove_expired_denomination_keys (struct Denomination *denom)
{
- /* create new denomination keys */
- if (NULL != denom->keys_tail)
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Updating keys of denomination `%s', last key %s valid for another %s\n",
- denom->section,
- GNUNET_h2s (&denom->keys_tail->h_cs.hash),
- GNUNET_TIME_relative2s (
- GNUNET_TIME_absolute_get_remaining (
- GNUNET_TIME_absolute_subtract (
- GNUNET_TIME_absolute_add (
- denom->keys_tail->anchor.abs_time,
- denom->duration_withdraw),
- overlap_duration)),
- GNUNET_YES));
- while ( (NULL == denom->keys_tail) ||
- GNUNET_TIME_absolute_is_past (
- GNUNET_TIME_absolute_subtract (
- GNUNET_TIME_absolute_subtract (
- GNUNET_TIME_absolute_add (denom->keys_tail->anchor.abs_time,
- denom->duration_withdraw),
- lookahead_sign),
- overlap_duration)) )
- {
- if (! *wake)
- {
- key_gen++;
- *wake = true;
- }
- if (GNUNET_OK !=
- create_key (denom,
- now))
- {
- GNUNET_break (0);
- globals->global_ret = EXIT_FAILURE;
- GNUNET_SCHEDULER_shutdown ();
- return GNUNET_SYSERR;
- }
- }
- /* remove expired denomination keys */
while ( (NULL != denom->keys_head) &&
- GNUNET_TIME_absolute_is_past
- (GNUNET_TIME_absolute_add (denom->keys_head->anchor.abs_time,
- denom->duration_withdraw)) )
+ GNUNET_TIME_absolute_is_past (
+ denom->keys_head->anchor_end.abs_time) )
{
struct DenominationKey *key = denom->keys_head;
struct DenominationKey *nxt = key->next;
@@ -1641,70 +1635,154 @@ update_keys (struct Denomination *denom,
GNUNET_free (key);
key = nxt;
}
+}
+
+
+/**
+ * Obtain the end anchor to use at this point. Uses the
+ * #lookahead_sign and then rounds it up by the maximum
+ * duration of any denomination to arrive at a globally
+ * valid end-date.
+ *
+ * Must only be called while the #keys_lock is held.
+ *
+ * @return end anchor
+ */
+static struct GNUNET_TIME_Timestamp
+get_anchor_end (void)
+{
+ struct GNUNET_TIME_Relative md = get_maximum_duration ();
+ struct GNUNET_TIME_Absolute end
+ = GNUNET_TIME_relative_to_absolute (lookahead_sign);
+ uint64_t mod;
+
+ /* Round up 'end' to a multiple of 'md' */
+ mod = end.abs_value_us % md.rel_value_us;
+ end.abs_value_us -= mod;
+ return GNUNET_TIME_absolute_to_timestamp (
+ GNUNET_TIME_absolute_add (end,
+ md));
+}
+
+
+/**
+ * Create all denomination keys that are required for our
+ * desired lookahead and that we do not yet have.
+ *
+ * @param[in,out] opt our options
+ * @param[in,out] wake set to true if we should wake the clients
+ */
+static void
+create_missing_keys (struct TALER_SECMOD_Options *opt,
+ bool *wake)
+{
+ struct GNUNET_TIME_Timestamp start;
+ struct GNUNET_TIME_Timestamp end;
- /* Update position of 'denom' in #denom_head DLL: sort by action time */
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Updating denominations ...\n");
+ start = opt->global_now;
+ GNUNET_assert (0 == pthread_mutex_lock (&keys_lock));
+ end = get_anchor_end ();
+ for (struct Denomination *denom = denom_head;
+ NULL != denom;
+ denom = denom->next)
{
- struct Denomination *before;
- struct GNUNET_TIME_Absolute at;
+ struct GNUNET_TIME_Timestamp anchor_start;
+ struct GNUNET_TIME_Timestamp anchor_end;
+ struct GNUNET_TIME_Timestamp next_end;
+ bool finished = false;
- at = denomination_action_time (denom);
- GNUNET_CONTAINER_DLL_remove (denom_head,
- denom_tail,
- denom);
- before = NULL;
- for (struct Denomination *pos = denom_head;
- NULL != pos;
- pos = pos->next)
+ if (NULL != denom->keys_tail)
{
- if (GNUNET_TIME_absolute_cmp (denomination_action_time (pos), >=, at))
- break;
- before = pos;
+ anchor_start = denom->keys_tail->anchor_end;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Expanding keys of denomination `%s', last key %s valid for another %s\n",
+ denom->section,
+ GNUNET_h2s (&denom->keys_tail->h_cs.hash),
+ GNUNET_TIME_relative2s (
+ GNUNET_TIME_absolute_get_remaining (
+ anchor_start.abs_time),
+ true));
}
- GNUNET_CONTAINER_DLL_insert_after (denom_head,
- denom_tail,
- before,
- denom);
+ else
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Starting keys of denomination `%s'\n",
+ denom->section);
+ anchor_start = start;
+ }
+ finished = GNUNET_TIME_timestamp_cmp (anchor_start,
+ >=,
+ end);
+ while (! finished)
+ {
+ anchor_end = GNUNET_TIME_absolute_to_timestamp (
+ GNUNET_TIME_absolute_add (anchor_start.abs_time,
+ denom->duration_withdraw));
+ next_end = GNUNET_TIME_absolute_to_timestamp (
+ GNUNET_TIME_absolute_add (anchor_end.abs_time,
+ denom->duration_withdraw));
+ if (GNUNET_TIME_timestamp_cmp (next_end,
+ >,
+ end))
+ {
+ anchor_end = end; /* extend period to align end periods */
+ finished = true;
+ }
+ /* adjust start time down to ensure overlap */
+ anchor_start = GNUNET_TIME_absolute_to_timestamp (
+ GNUNET_TIME_absolute_subtract (anchor_start.abs_time,
+ overlap_duration));
+ if (! *wake)
+ {
+ key_gen++;
+ *wake = true;
+ }
+ if (GNUNET_OK !=
+ create_key (denom,
+ anchor_start,
+ anchor_end))
+ {
+ GNUNET_break (0);
+ return;
+ }
+ anchor_start = anchor_end;
+ }
+ remove_expired_denomination_keys (denom);
}
- return GNUNET_OK;
+ GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Updating denominations finished ...\n");
}
/**
* Task run periodically to expire keys and/or generate fresh ones.
*
- * @param cls NULL
+ * @param cls the `struct TALER_SECMOD_Options *`
*/
static void
update_denominations (void *cls)
{
- struct Denomination *denom;
- struct GNUNET_TIME_Absolute now;
- struct GNUNET_TIME_Timestamp t;
+ struct TALER_SECMOD_Options *opt = cls;
+ struct GNUNET_TIME_Absolute at;
bool wake = false;
(void) cls;
keygen_task = NULL;
- now = GNUNET_TIME_absolute_get ();
- t = GNUNET_TIME_absolute_to_timestamp (now);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Updating denominations ...\n");
- GNUNET_assert (0 == pthread_mutex_lock (&keys_lock));
- do {
- denom = denom_head;
- if (GNUNET_OK !=
- update_keys (denom,
- t,
- &wake))
- return;
- } while (denom != denom_head);
- GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Updating denominations finished ...\n");
+ opt->global_now = GNUNET_TIME_timestamp_get ();
+ create_missing_keys (opt,
+ &wake);
if (wake)
TES_wake_clients ();
- keygen_task = GNUNET_SCHEDULER_add_at (denomination_action_time (denom),
+ at = action_time ();
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Next key generation due at %s\n",
+ GNUNET_TIME_absolute2s (at));
+ keygen_task = GNUNET_SCHEDULER_add_at (at,
&update_denominations,
- NULL);
+ opt);
}
@@ -1722,8 +1800,11 @@ parse_key (struct Denomination *denom,
{
char *anchor_s;
char dummy;
- unsigned long long anchor_ll;
- struct GNUNET_TIME_Timestamp anchor;
+ unsigned long long anchor_start_ll;
+ unsigned long long anchor_end_ll;
+ struct GNUNET_TIME_Timestamp anchor_start;
+ struct GNUNET_TIME_Timestamp anchor_end;
+ char *nf = NULL;
anchor_s = strrchr (filename,
'/');
@@ -1734,28 +1815,77 @@ parse_key (struct Denomination *denom,
return;
}
anchor_s++;
- if (1 != sscanf (anchor_s,
- "%llu%c",
- &anchor_ll,
+ if (2 != sscanf (anchor_s,
+ "%llu-%llu%c",
+ &anchor_start_ll,
+ &anchor_end_ll,
&dummy))
{
- /* Filenames in KEYDIR must ONLY be the anchor time in seconds! */
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Filename `%s' invalid for key file, skipping\n",
- filename);
- return;
+ /* try legacy mode */
+ if (1 != sscanf (anchor_s,
+ "%llu%c",
+ &anchor_start_ll,
+ &dummy))
+ {
+ /* Filenames in KEYDIR must ONLY be the anchor time in seconds! */
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Filename `%s' invalid for key file, skipping\n",
+ anchor_s);
+ return;
+ }
+ anchor_start.abs_time.abs_value_us
+ = anchor_start_ll * GNUNET_TIME_UNIT_SECONDS.rel_value_us;
+ if (anchor_start_ll != anchor_start.abs_time.abs_value_us
+ / GNUNET_TIME_UNIT_SECONDS.rel_value_us)
+ {
+ /* Integer overflow. Bad, invalid filename. */
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Integer overflow. Filename `%s' invalid for key file, skipping\n",
+ anchor_s);
+ return;
+ }
+ anchor_end
+ = GNUNET_TIME_absolute_to_timestamp (
+ GNUNET_TIME_absolute_add (anchor_start.abs_time,
+ denom->duration_withdraw));
+ GNUNET_asprintf (
+ &nf,
+ "%s/%s/%llu-%llu",
+ keydir,
+ denom->section,
+ anchor_start_ll,
+ (unsigned long long) (anchor_end.abs_time.abs_value_us
+ / GNUNET_TIME_UNIT_SECONDS.rel_value_us));
+ /* Try to fix the legacy filename */
+ if (0 !=
+ rename (filename,
+ nf))
+ {
+ GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
+ "rename",
+ filename);
+ GNUNET_free (nf);
+ }
}
- anchor.abs_time.abs_value_us
- = anchor_ll * GNUNET_TIME_UNIT_SECONDS.rel_value_us;
- if (anchor_ll != anchor.abs_time.abs_value_us
- / GNUNET_TIME_UNIT_SECONDS.rel_value_us)
+ else
{
- /* Integer overflow. Bad, invalid filename. */
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Filename `%s' invalid for key file, skipping\n",
- filename);
- return;
+ anchor_start.abs_time.abs_value_us
+ = anchor_start_ll * GNUNET_TIME_UNIT_SECONDS.rel_value_us;
+ anchor_end.abs_time.abs_value_us
+ = anchor_end_ll * GNUNET_TIME_UNIT_SECONDS.rel_value_us;
+ if ( (anchor_start_ll != anchor_start.abs_time.abs_value_us
+ / GNUNET_TIME_UNIT_SECONDS.rel_value_us) ||
+ (anchor_end_ll != anchor_end.abs_time.abs_value_us
+ / GNUNET_TIME_UNIT_SECONDS.rel_value_us) )
+ {
+ /* Integer overflow. Bad, invalid filename. */
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Integer overflow. Filename `%s' invalid for key file, skipping\n",
+ anchor_s);
+ return;
+ }
}
+
{
struct DenominationKey *dk;
struct DenominationKey *before;
@@ -1763,8 +1893,9 @@ parse_key (struct Denomination *denom,
dk = GNUNET_new (struct DenominationKey);
dk->denom_priv = *priv;
dk->denom = denom;
- dk->anchor = anchor;
- dk->filename = GNUNET_strdup (filename);
+ dk->anchor_start = anchor_start;
+ dk->anchor_end = anchor_end;
+ dk->filename = (NULL == nf) ? GNUNET_strdup (filename) : nf;
GNUNET_CRYPTO_cs_private_key_get_public (priv,
&dk->denom_pub);
GNUNET_CRYPTO_hash (&dk->denom_pub,
@@ -1791,9 +1922,9 @@ parse_key (struct Denomination *denom,
NULL != pos;
pos = pos->next)
{
- if (GNUNET_TIME_timestamp_cmp (pos->anchor,
+ if (GNUNET_TIME_timestamp_cmp (pos->anchor_start,
>,
- anchor))
+ anchor_start))
break;
before = pos;
}
@@ -1958,6 +2089,17 @@ parse_denomination_cfg (const struct GNUNET_CONFIGURATION_Handle *cfg,
GNUNET_free (secname);
return GNUNET_SYSERR;
}
+ if (GNUNET_TIME_relative_cmp (denom->duration_withdraw,
+ <,
+ GNUNET_TIME_UNIT_SECONDS))
+ {
+ GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
+ ct,
+ "DURATION_WITHDRAW",
+ "less than one second is not supported");
+ GNUNET_free (secname);
+ return GNUNET_SYSERR;
+ }
if (GNUNET_TIME_relative_cmp (overlap_duration,
>=,
denom->duration_withdraw))
@@ -2011,7 +2153,6 @@ load_denominations (void *cls,
{
struct LoadContext *ctx = cls;
struct Denomination *denom;
- bool wake = true;
char *cipher;
if ( (0 != strncasecmp (denomination_alias,
@@ -2069,9 +2210,6 @@ load_denominations (void *cls,
GNUNET_CONTAINER_DLL_insert (denom_head,
denom_tail,
denom);
- update_keys (denom,
- ctx->t,
- &wake);
}
@@ -2225,6 +2363,7 @@ TALER_SECMOD_cs_run (void *cls,
.ret = GNUNET_OK,
.t = opt->global_now
};
+ bool wake = true;
GNUNET_assert (0 == pthread_mutex_lock (&keys_lock));
GNUNET_CONFIGURATION_iterate_sections (cfg,
@@ -2237,6 +2376,8 @@ TALER_SECMOD_cs_run (void *cls,
GNUNET_SCHEDULER_shutdown ();
return;
}
+ create_missing_keys (opt,
+ &wake);
}
if (NULL == denom_head)
{
@@ -2251,5 +2392,5 @@ TALER_SECMOD_cs_run (void *cls,
keygen_task = GNUNET_SCHEDULER_add_with_priority (
GNUNET_SCHEDULER_PRIORITY_URGENT,
&update_denominations,
- NULL);
+ opt);
}
diff --git a/src/util/secmod_rsa.c b/src/util/secmod_rsa.c
@@ -1255,7 +1255,7 @@ rsa_update_client_keys (struct TES_Client *client)
/**
* Create a new denomination key (we do not have enough).
*
- * @param[in] denom denomination key to create
+ * @param[in,out] denom denomination key to create
* @param anchor_start when to start key signing validity
* @param anchor_end when to end key signing validity
* @return #GNUNET_OK on success
@@ -1315,9 +1315,11 @@ get_maximum_duration (void)
/**
* At what time do we need to next create keys if we just did?
+ *
+ * @return time when to next create keys if we just finished key generation
*/
static struct GNUNET_TIME_Absolute
-action_time ()
+action_time (void)
{
struct GNUNET_TIME_Relative md = get_maximum_duration ();
struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();