aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/testing/testing_api_cmd_batch.c84
-rw-r--r--src/testing/testing_api_loop.c175
-rw-r--r--src/util/taler-exchange-secmod-eddsa.c1288
-rw-r--r--src/util/taler-exchange-secmod-rsa.c1540
-rw-r--r--src/util/taler-exchange-secmod-rsa.h6
-rw-r--r--src/util/test_helper_eddsa.c119
-rw-r--r--src/util/test_helper_rsa.c259
7 files changed, 1324 insertions, 2147 deletions
diff --git a/src/testing/testing_api_cmd_batch.c b/src/testing/testing_api_cmd_batch.c
index e8f76ca37..2e880e8df 100644
--- a/src/testing/testing_api_cmd_batch.c
+++ b/src/testing/testing_api_cmd_batch.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2014-2021 Taler Systems SA
+ Copyright (C) 2014-2018 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
@@ -113,15 +113,22 @@ batch_cleanup (void *cls,
* @param index index number of the object to offer.
* @return #GNUNET_OK on success.
*/
-static enum GNUNET_GenericReturnValue
+static int
batch_traits (void *cls,
const void **ret,
const char *trait,
unsigned int index)
{
+#define CURRENT_CMD_INDEX 0
+#define BATCH_INDEX 1
+
struct BatchState *bs = cls;
+
struct TALER_TESTING_Trait traits[] = {
- TALER_TESTING_make_trait_batch_cmds (&bs->batch),
+ TALER_TESTING_make_trait_cmd
+ (CURRENT_CMD_INDEX, &bs->batch[bs->batch_ip]),
+ TALER_TESTING_make_trait_cmd
+ (BATCH_INDEX, bs->batch),
TALER_TESTING_trait_end ()
};
@@ -133,6 +140,18 @@ batch_traits (void *cls,
}
+/**
+ * Create a "batch" command. Such command takes a
+ * end_CMD-terminated array of CMDs and executed them.
+ * Once it hits the end CMD, it passes the control
+ * to the next top-level CMD, regardless of it being
+ * another batch or ordinary CMD.
+ *
+ * @param label the command label.
+ * @param batch array of CMDs to execute.
+ *
+ * @return the command.
+ */
struct TALER_TESTING_Command
TALER_TESTING_cmd_batch (const char *label,
struct TALER_TESTING_Command *batch)
@@ -166,29 +185,68 @@ TALER_TESTING_cmd_batch (const char *label,
}
+/**
+ * Advance internal pointer to next command.
+ *
+ * @param is interpreter state.
+ * @param cmd batch to advance
+ */
void
-TALER_TESTING_cmd_batch_next (struct TALER_TESTING_Interpreter *is)
+TALER_TESTING_cmd_batch_next (struct TALER_TESTING_Interpreter *is,
+ struct TALER_TESTING_Command *par,
+ struct TALER_TESTING_Command *cmd)
{
- struct BatchState *bs = is->commands[is->ip].cls;
+ struct BatchState *bs = cmd->cls;
+ struct TALER_TESTING_Command *chld;
if (NULL == bs->batch[bs->batch_ip].label)
{
- is->commands[is->ip].finish_time = GNUNET_TIME_absolute_get ();
- is->ip++;
+ if (NULL == par)
+ {
+ is->commands[is->ip].finish_time = GNUNET_TIME_absolute_get ();
+ is->ip++;
+ }
+ else
+ {
+ struct BatchState *ps = par->cls;
+
+ cmd->finish_time = GNUNET_TIME_absolute_get ();
+ ps->batch_ip++;
+ }
return;
}
- bs->batch[bs->batch_ip].finish_time = GNUNET_TIME_absolute_get ();
- bs->batch_ip++;
+ chld = &bs->batch[bs->batch_ip];
+ if (TALER_TESTING_cmd_is_batch (chld))
+ {
+ TALER_TESTING_cmd_batch_next (is,
+ cmd,
+ chld);
+ }
+ else
+ {
+ bs->batch[bs->batch_ip].finish_time = GNUNET_TIME_absolute_get ();
+ bs->batch_ip++;
+ }
}
-bool
+/**
+ * Test if this command is a batch command.
+ *
+ * @return false if not, true if it is a batch command
+ */
+int
TALER_TESTING_cmd_is_batch (const struct TALER_TESTING_Command *cmd)
{
return cmd->run == &batch_run;
}
+/**
+ * Obtain what command the batch is at.
+ *
+ * @return cmd current batch command
+ */
struct TALER_TESTING_Command *
TALER_TESTING_cmd_batch_get_current (const struct TALER_TESTING_Command *cmd)
{
@@ -199,6 +257,12 @@ TALER_TESTING_cmd_batch_get_current (const struct TALER_TESTING_Command *cmd)
}
+/**
+ * Set what command the batch should be at.
+ *
+ * @param cmd current batch command
+ * @param new_ip where to move the IP
+ */
void
TALER_TESTING_cmd_batch_set_current (const struct TALER_TESTING_Command *cmd,
unsigned int new_ip)
diff --git a/src/testing/testing_api_loop.c b/src/testing/testing_api_loop.c
index f86c7765b..868a2d750 100644
--- a/src/testing/testing_api_loop.c
+++ b/src/testing/testing_api_loop.c
@@ -36,6 +36,49 @@
*/
static struct GNUNET_DISK_PipeHandle *sigpipe;
+
+const struct TALER_TESTING_Command *
+lookup_helper (const struct TALER_TESTING_Command *cmd,
+ const char *label)
+{
+#define BATCH_INDEX 1
+ struct TALER_TESTING_Command *batch;
+ struct TALER_TESTING_Command *current;
+ struct TALER_TESTING_Command *icmd;
+ const struct TALER_TESTING_Command *match;
+
+ current = TALER_TESTING_cmd_batch_get_current (cmd);
+ GNUNET_assert (GNUNET_OK ==
+ TALER_TESTING_get_trait_cmd (cmd,
+ BATCH_INDEX,
+ &batch));
+ /* We must do the loop forward, but we can find the last match */
+ match = NULL;
+ for (unsigned int j = 0;
+ NULL != (icmd = &batch[j])->label;
+ j++)
+ {
+ if (TALER_TESTING_cmd_is_batch (icmd))
+ {
+ const struct TALER_TESTING_Command *imatch;
+
+ imatch = lookup_helper (icmd,
+ label);
+ if (NULL != imatch)
+ match = imatch;
+ }
+ if ( (current != icmd) &&
+ (NULL != icmd->label) &&
+ (0 == strcmp (icmd->label,
+ label)) )
+ match = icmd;
+ if (current == icmd)
+ break;
+ }
+ return match;
+}
+
+
/**
* Lookup command by label.
*
@@ -66,30 +109,12 @@ TALER_TESTING_interpreter_lookup_command (struct TALER_TESTING_Interpreter *is,
if (TALER_TESTING_cmd_is_batch (cmd))
{
- struct TALER_TESTING_Command **batch;
- struct TALER_TESTING_Command *current;
- struct TALER_TESTING_Command *icmd;
- const struct TALER_TESTING_Command *match;
-
- current = TALER_TESTING_cmd_batch_get_current (cmd);
- GNUNET_assert (GNUNET_OK ==
- TALER_TESTING_get_trait_batch_cmds (cmd,
- &batch));
- /* We must do the loop forward, but we can find the last match */
- match = NULL;
- for (unsigned int j = 0;
- NULL != (icmd = &(*batch)[j])->label;
- j++)
- {
- if (current == icmd)
- break; /* do not go past current command */
- if ( (NULL != icmd->label) &&
- (0 == strcmp (icmd->label,
- label)) )
- match = icmd;
- }
- if (NULL != match)
- return match;
+ const struct TALER_TESTING_Command *ret;
+
+ ret = lookup_helper (cmd,
+ label);
+ if (NULL != ret)
+ return ret;
}
}
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -118,6 +143,15 @@ TALER_TESTING_interpreter_get_fakebank (struct TALER_TESTING_Interpreter *is)
}
+/**
+ * Run tests starting the "fakebank" first. The "fakebank"
+ * is a C minimalist version of the human-oriented Python bank,
+ * which is also part of the Taler project.
+ *
+ * @param is pointer to the interpreter state
+ * @param commands the list of commands to execute
+ * @param bank_url the url the fakebank is supposed to run on
+ */
void
TALER_TESTING_run_with_fakebank (struct TALER_TESTING_Interpreter *is,
struct TALER_TESTING_Command *commands,
@@ -155,6 +189,9 @@ static void
interpreter_run (void *cls);
+/**
+ * Current command is done, run the next one.
+ */
void
TALER_TESTING_interpreter_next (struct TALER_TESTING_Interpreter *is)
{
@@ -166,7 +203,9 @@ TALER_TESTING_interpreter_next (struct TALER_TESTING_Interpreter *is)
return; /* ignore, we already failed! */
if (TALER_TESTING_cmd_is_batch (cmd))
{
- TALER_TESTING_cmd_batch_next (is);
+ TALER_TESTING_cmd_batch_next (is,
+ NULL,
+ cmd);
}
else
{
@@ -189,6 +228,11 @@ TALER_TESTING_interpreter_next (struct TALER_TESTING_Interpreter *is)
}
+/**
+ * Current command failed, clean up and fail the test case.
+ *
+ * @param is interpreter of the test
+ */
void
TALER_TESTING_interpreter_fail (struct TALER_TESTING_Interpreter *is)
{
@@ -209,6 +253,11 @@ TALER_TESTING_interpreter_fail (struct TALER_TESTING_Interpreter *is)
}
+/**
+ * Create command array terminator.
+ *
+ * @return a end-command.
+ */
struct TALER_TESTING_Command
TALER_TESTING_cmd_end (void)
{
@@ -219,6 +268,9 @@ TALER_TESTING_cmd_end (void)
}
+/**
+ * Obtain current label.
+ */
const char *
TALER_TESTING_interpreter_get_current_label (struct
TALER_TESTING_Interpreter *is)
@@ -289,9 +341,8 @@ do_shutdown (void *cls)
for (unsigned int j = 0;
NULL != (cmd = &is->commands[j])->label;
j++)
- if (NULL != cmd->cleanup)
- cmd->cleanup (cmd->cls,
- cmd);
+ cmd->cleanup (cmd->cls,
+ cmd);
if (NULL != is->exchange)
{
@@ -367,8 +418,17 @@ maint_child_death (void *cls)
enum GNUNET_OS_ProcessStatusType type;
unsigned long code;
- while (TALER_TESTING_cmd_is_batch (cmd))
- cmd = TALER_TESTING_cmd_batch_get_current (cmd);
+ if (TALER_TESTING_cmd_is_batch (cmd))
+ {
+ struct TALER_TESTING_Command *batch_cmd;
+
+ GNUNET_assert (GNUNET_OK ==
+ TALER_TESTING_get_trait_cmd (cmd,
+ 0,
+ &batch_cmd));
+ cmd = batch_cmd;
+ }
+
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Got SIGCHLD for `%s'.\n",
cmd->label);
@@ -381,6 +441,7 @@ maint_child_death (void *cls)
sizeof (c)));
if (GNUNET_OK !=
TALER_TESTING_get_trait_process (cmd,
+ 0,
&processp))
{
GNUNET_break (0);
@@ -433,6 +494,12 @@ maint_child_death (void *cls)
}
+/**
+ * Wait until we receive SIGCHLD signal.
+ * Then obtain the process trait of the current
+ * command, wait on the the zombie and continue
+ * with the next command.
+ */
void
TALER_TESTING_wait_for_sigchld (struct TALER_TESTING_Interpreter *is)
{
@@ -449,6 +516,16 @@ TALER_TESTING_wait_for_sigchld (struct TALER_TESTING_Interpreter *is)
}
+/**
+ * Run the testsuite. Note, CMDs are copied into
+ * the interpreter state because they are _usually_
+ * defined into the "run" method that returns after
+ * having scheduled the test interpreter.
+ *
+ * @param is the interpreter state
+ * @param commands the list of command to execute
+ * @param timeout how long to wait
+ */
void
TALER_TESTING_run2 (struct TALER_TESTING_Interpreter *is,
struct TALER_TESTING_Command *commands,
@@ -478,6 +555,15 @@ TALER_TESTING_run2 (struct TALER_TESTING_Interpreter *is,
}
+/**
+ * Run the testsuite. Note, CMDs are copied into
+ * the interpreter state because they are _usually_
+ * defined into the "run" method that returns after
+ * having scheduled the test interpreter.
+ *
+ * @param is the interpreter state
+ * @param commands the list of command to execute
+ */
void
TALER_TESTING_run (struct TALER_TESTING_Interpreter *is,
struct TALER_TESTING_Command *commands)
@@ -536,6 +622,16 @@ sighandler_child_death (void)
}
+/**
+ * "Canonical" cert_cb used when we are connecting to the
+ * Exchange.
+ *
+ * @param cls closure, typically, the "run" method containing
+ * all the commands to be run, and a closure for it.
+ * @param hr HTTP response details
+ * @param keys the exchange's keys.
+ * @param compat protocol compatibility information.
+ */
void
TALER_TESTING_cert_cb (void *cls,
const struct TALER_EXCHANGE_HttpResponse *hr,
@@ -804,6 +900,25 @@ load_urls (struct TALER_TESTING_Interpreter *is)
}
+/**
+ * Install signal handlers plus schedules the main wrapper
+ * around the "run" method.
+ *
+ * @param main_cb the "run" method which contains all the
+ * commands.
+ * @param main_cb_cls a closure for "run", typically NULL.
+ * @param cfg configuration to use
+ * @param exchanged exchange process handle: will be put in the
+ * state as some commands - e.g. revoke - need to send
+ * signal to it, for example to let it know to reload the
+ * key state.. if NULL, the interpreter will run without
+ * trying to connect to the exchange first.
+ * @param exchange_connect #GNUNET_YES if the test should connect
+ * to the exchange, #GNUNET_NO otherwise
+ * @return #GNUNET_OK if all is okay, != #GNUNET_OK otherwise.
+ * non-GNUNET_OK codes are #GNUNET_SYSERR most of the
+ * times.
+ */
int
TALER_TESTING_setup (TALER_TESTING_Main main_cb,
void *main_cb_cls,
diff --git a/src/util/taler-exchange-secmod-eddsa.c b/src/util/taler-exchange-secmod-eddsa.c
index dc2d35d13..3b7ee3ded 100644
--- a/src/util/taler-exchange-secmod-eddsa.c
+++ b/src/util/taler-exchange-secmod-eddsa.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2014-2020 Taler Systems SA
+ Copyright (C) 2014-2021 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
@@ -26,7 +26,7 @@
* and merged with the public keys of the helper by the exchange HTTPD!
* - the main loop of the helper is SINGLE-THREADED, but there are
* threads for crypto-workers which (only) do the signing in parallel,
- * working of a work-queue.
+ * one per client.
* - thread-safety: signing happens in parallel, thus when REMOVING private keys,
* we must ensure that all signers are done before we fully free() the
* private key. This is done by reference counting (as work is always
@@ -41,6 +41,7 @@
#include "taler_error_codes.h"
#include "taler_signatures.h"
#include "secmod_common.h"
+#include <poll.h>
/**
@@ -80,6 +81,11 @@ struct Key
struct GNUNET_TIME_Absolute anchor;
/**
+ * Generation when this key was created or revoked.
+ */
+ uint64_t key_gen;
+
+ /**
* Reference counter. Counts the number of threads that are
* using this key at this time.
*/
@@ -95,92 +101,6 @@ struct Key
/**
- * Information we keep for a client connected to us.
- */
-struct Client
-{
-
- /**
- * Kept in a DLL.
- */
- struct Client *next;
-
- /**
- * Kept in a DLL.
- */
- struct Client *prev;
-
- /**
- * Client address.
- */
- struct sockaddr_un addr;
-
- /**
- * Number of bytes used in @e addr.
- */
- socklen_t addr_size;
-
-};
-
-
-struct WorkItem
-{
-
- /**
- * Kept in a DLL.
- */
- struct WorkItem *next;
-
- /**
- * Kept in a DLL.
- */
- struct WorkItem *prev;
-
- /**
- * Key to be used for this operation.
- */
- struct Key *key;
-
- /**
- * EDDSA signature over @e msg using @e key. Result of doing the work.
- */
- struct TALER_ExchangeSignatureP signature;
-
- /**
- * Message to sign.
- */
- struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
-
- /**
- * Client address.
- */
- struct sockaddr_un addr;
-
- /**
- * Number of bytes used in @e addr.
- */
- socklen_t addr_size;
-
- /**
- * Operation status code.
- */
- enum TALER_ErrorCode ec;
-
-};
-
-
-/**
- * Private key of this security module. Used to sign denomination key
- * announcements.
- */
-static struct TALER_SecurityModulePrivateKeyP smpriv;
-
-/**
- * Public key of this security module.
- */
-static struct TALER_SecurityModulePublicKeyP smpub;
-
-/**
* Head of DLL of actual keys, sorted by anchor.
*/
static struct Key *keys_head;
@@ -201,13 +121,6 @@ static struct GNUNET_TIME_Relative duration;
static int global_ret;
/**
- * Number of worker threads to use. Default (0) is to use one per CPU core
- * available.
- * Length of the #workers array.
- */
-static unsigned int num_workers;
-
-/**
* Time when the key update is executed.
* Either the actual current time, or a pretended time.
*/
@@ -220,11 +133,6 @@ static struct GNUNET_TIME_Absolute now;
static struct GNUNET_TIME_Absolute now_tmp;
/**
- * Handle to the exchange's configuration
- */
-static const struct GNUNET_CONFIGURATION_Handle *kcfg;
-
-/**
* Where do we store the keys?
*/
static char *keydir;
@@ -242,400 +150,19 @@ static struct GNUNET_TIME_Relative overlap_duration;
static struct GNUNET_TIME_Relative lookahead_sign;
/**
- * Our listen socket.
- */
-static struct GNUNET_NETWORK_Handle *unix_sock;
-
-/**
- * Path where we are listening.
- */
-static char *unixpath;
-
-/**
- * Task run to accept new inbound connections.
- */
-static struct GNUNET_SCHEDULER_Task *read_task;
-
-/**
* Task run to generate new keys.
*/
static struct GNUNET_SCHEDULER_Task *keygen_task;
/**
- * Head of DLL of clients connected to us.
- */
-static struct Client *clients_head;
-
-/**
- * Tail of DLL of clients connected to us.
- */
-static struct Client *clients_tail;
-
-/**
- * Head of DLL with pending signing operations.
- */
-static struct WorkItem *work_head;
-
-/**
- * Tail of DLL with pending signing operations.
- */
-static struct WorkItem *work_tail;
-
-/**
- * Lock for the work queue.
- */
-static pthread_mutex_t work_lock;
-
-/**
- * Condition variable for the semaphore of the work queue.
- */
-static pthread_cond_t work_cond = PTHREAD_COND_INITIALIZER;
-
-/**
- * Number of items in the work queue. Also used as the semaphore counter.
- */
-static unsigned long long work_counter;
-
-/**
- * Head of DLL with completed signing operations.
- */
-static struct WorkItem *done_head;
-
-/**
- * Tail of DLL with completed signing operations.
- */
-static struct WorkItem *done_tail;
-
-/**
- * Lock for the done queue.
- */
-static pthread_mutex_t done_lock;
-
-/**
- * Task waiting for work to be done.
- */
-static struct GNUNET_SCHEDULER_Task *done_task;
-
-/**
- * Signal used by threads to notify the #done_task that they
- * completed work that is now in the done queue.
- */
-static struct GNUNET_NETWORK_Handle *done_signal;
-
-/**
- * Set once we are in shutdown and workers should terminate.
- */
-static volatile bool in_shutdown;
-
-/**
- * Array of #num_workers sign_worker() threads.
- */
-static pthread_t *workers;
-
-
-/**
- * Main function of a worker thread that signs.
- *
- * @param cls NULL
- * @return NULL
- */
-static void *
-sign_worker (void *cls)
-{
- (void) cls;
- GNUNET_assert (0 == pthread_mutex_lock (&work_lock));
- while (! in_shutdown)
- {
- struct WorkItem *wi;
-
- while (NULL != (wi = work_head))
- {
- /* take work from queue */
- GNUNET_CONTAINER_DLL_remove (work_head,
- work_tail,
- wi);
- work_counter--;
- GNUNET_assert (0 == pthread_mutex_unlock (&work_lock));
- {
- if (GNUNET_OK !=
- GNUNET_CRYPTO_eddsa_sign_ (&wi->key->exchange_priv.eddsa_priv,
- wi->purpose,
- &wi->signature.eddsa_signature))
- wi->ec = TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
- else
- wi->ec = TALER_EC_NONE;
- }
- /* put completed work into done queue */
- GNUNET_assert (0 == pthread_mutex_lock (&done_lock));
- GNUNET_CONTAINER_DLL_insert (done_head,
- done_tail,
- wi);
- GNUNET_assert (0 == pthread_mutex_unlock (&done_lock));
- {
- uint64_t val = GNUNET_htonll (1);
-
- /* raise #done_signal */
- if (sizeof(val) !=
- write (GNUNET_NETWORK_get_fd (done_signal),
- &val,
- sizeof (val)))
- GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
- "write(eventfd)");
- }
- GNUNET_assert (0 == pthread_mutex_lock (&work_lock));
- }
- if (in_shutdown)
- break;
- /* queue is empty, wait for work */
- GNUNET_assert (0 ==
- pthread_cond_wait (&work_cond,
- &work_lock));
- }
- GNUNET_assert (0 ==
- pthread_mutex_unlock (&work_lock));
- return NULL;
-}
-
-
-/**
- * Free @a client, releasing all (remaining) state.
- *
- * @param[in] client data to free
- */
-static void
-free_client (struct Client *client)
-{
- GNUNET_CONTAINER_DLL_remove (clients_head,
- clients_tail,
- client);
- GNUNET_free (client);
-}
-
-
-/**
- * Function run to read incoming requests from a client.
- *
- * @param cls the `struct Client`
- */
-static void
-read_job (void *cls);
-
-
-/**
- * Free @a key. It must already have been removed from the DLL.
- *
- * @param[in] key the key to free
- */
-static void
-free_key (struct Key *key)
-{
- GNUNET_free (key->filename);
- GNUNET_free (key);
-}
-
-
-/**
- * Send a message starting with @a hdr to @a client. We expect that
- * the client is mostly able to handle everything at whatever speed
- * we have (after all, the crypto should be the slow part). However,
- * especially on startup when we send all of our keys, it is possible
- * that the client cannot keep up. In that case, we throttle when
- * sending fails. This does not work with poll() as we cannot specify
- * the sendto() target address with poll(). So we nanosleep() instead.
- *
- * @param addr address where to send the message
- * @param addr_size number of bytes in @a addr
- * @param hdr beginning of the message, length indicated in size field
- * @return #GNUNET_OK on success
- */
-static int
-transmit (const struct sockaddr_un *addr,
- socklen_t addr_size,
- const struct GNUNET_MessageHeader *hdr)
-{
- for (unsigned int i = 0; i<100; i++)
- {
- ssize_t ret = sendto (GNUNET_NETWORK_get_fd (unix_sock),
- hdr,
- ntohs (hdr->size),
- 0 /* no flags => blocking! */,
- (const struct sockaddr *) addr,
- addr_size);
- if ( (-1 == ret) &&
- (EAGAIN == errno) )
- {
- /* _Maybe_ with blocking sendto(), this should no
- longer be needed; still keeping it just in case. */
- /* Wait a bit, in case client is just too slow */
- struct timespec req = {
- .tv_sec = 0,
- .tv_nsec = 1000
- };
- nanosleep (&req, NULL);
- continue;
- }
- if (ret == ntohs (hdr->size))
- return GNUNET_OK;
- if (ret != ntohs (hdr->size))
- break;
- }
- GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
- "sendto");
- return GNUNET_SYSERR;
-}
-
-
-/**
- * Process completed tasks that are in the #done_head queue, sending
- * the result back to the client (and resuming the client).
- *
- * @param cls NULL
+ * Lock for the keys queue.
*/
-static void
-handle_done (void *cls)
-{
- uint64_t data;
- (void) cls;
-
- /* consume #done_signal */
- if (sizeof (data) !=
- read (GNUNET_NETWORK_get_fd (done_signal),
- &data,
- sizeof (data)))
- GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
- "read(eventfd)");
- done_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
- done_signal,
- &handle_done,
- NULL);
- GNUNET_assert (0 == pthread_mutex_lock (&done_lock));
- while (NULL != done_head)
- {
- struct WorkItem *wi = done_head;
-
- GNUNET_CONTAINER_DLL_remove (done_head,
- done_tail,
- wi);
- GNUNET_assert (0 == pthread_mutex_unlock (&done_lock));
- if (TALER_EC_NONE != wi->ec)
- {
- struct TALER_CRYPTO_EddsaSignFailure sf = {
- .header.size = htons (sizeof (sf)),
- .header.type = htons (TALER_HELPER_EDDSA_MT_RES_SIGN_FAILURE),
- .ec = htonl (wi->ec)
- };
-
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Signing request %p failed, worker failed to produce signature\n",
- wi);
- (void) transmit (&wi->addr,
- wi->addr_size,
- &sf.header);
- }
- else
- {
- struct TALER_CRYPTO_EddsaSignResponse sr = {
- .header.size = htons (sizeof (sr)),
- .header.type = htons (TALER_HELPER_EDDSA_MT_RES_SIGNATURE),
- .exchange_pub = wi->key->exchange_pub,
- .exchange_sig = wi->signature
- };
-
- (void) transmit (&wi->addr,
- wi->addr_size,
- &sr.header);
- }
- {
- struct Key *key = wi->key;
-
- key->rc--;
- if ( (0 == key->rc) &&
- (key->purge) )
- free_key (key);
- }
- GNUNET_free (wi->purpose);
- GNUNET_free (wi);
- GNUNET_assert (0 == pthread_mutex_lock (&done_lock));
- }
- GNUNET_assert (0 == pthread_mutex_unlock (&done_lock));
-
-}
-
+static pthread_mutex_t keys_lock;
/**
- * Handle @a client request @a sr to create signature. Create the
- * signature using the respective key and return the result to
- * the client.
- *
- * @param addr address of the client making the request
- * @param addr_size number of bytes in @a addr
- * @param sr the request details
+ * Current key generation.
*/
-static void
-handle_sign_request (const struct sockaddr_un *addr,
- socklen_t addr_size,
- const struct TALER_CRYPTO_EddsaSignRequest *sr)
-{
- const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose = &sr->purpose;
- struct WorkItem *wi;
- size_t purpose_size = ntohs (sr->header.size) - sizeof (*sr)
- + sizeof (*purpose);
-
- if (purpose_size != htonl (purpose->size))
- {
- struct TALER_CRYPTO_EddsaSignFailure sf = {
- .header.size = htons (sizeof (sr)),
- .header.type = htons (TALER_HELPER_EDDSA_MT_RES_SIGN_FAILURE),
- .ec = htonl (TALER_EC_GENERIC_PARAMETER_MALFORMED)
- };
-
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Signing request failed, request malformed\n");
- (void) transmit (addr,
- addr_size,
- &sf.header);
- return;
- }
- {
- struct GNUNET_TIME_Absolute now;
-
- now = GNUNET_TIME_absolute_get ();
- if ( (now.abs_value_us >= keys_head->anchor.abs_value_us) &&
- (now.abs_value_us < keys_head->anchor.abs_value_us
- + duration.rel_value_us) )
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Signing at %llu with key valid from %llu to %llu\n",
- (unsigned long long) now.abs_value_us,
- (unsigned long long) keys_head->anchor.abs_value_us,
- (unsigned long long) keys_head->anchor.abs_value_us
- + duration.rel_value_us);
- else
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Signing at %llu with key valid from %llu to %llu\n",
- (unsigned long long) now.abs_value_us,
- (unsigned long long) keys_head->anchor.abs_value_us,
- (unsigned long long) keys_head->anchor.abs_value_us
- + duration.rel_value_us);
- }
- wi = GNUNET_new (struct WorkItem);
- wi->addr = *addr;
- wi->addr_size = addr_size;
- wi->key = keys_head;
- keys_head->rc++;
- wi->purpose = GNUNET_memdup (purpose,
- purpose_size);
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Received request to sign over %u bytes, queueing as %p\n",
- (unsigned int) purpose_size,
- wi);
- GNUNET_assert (0 == pthread_mutex_lock (&work_lock));
- work_counter++;
- GNUNET_CONTAINER_DLL_insert (work_head,
- work_tail,
- wi);
- GNUNET_assert (0 == pthread_cond_signal (&work_cond));
- GNUNET_assert (0 == pthread_mutex_unlock (&work_lock));
-}
+static uint64_t key_gen;
/**
@@ -645,8 +172,8 @@ handle_sign_request (const struct sockaddr_un *addr,
* @param key the key to notify @a client about
* @return #GNUNET_OK on success
*/
-static int
-notify_client_key_add (struct Client *client,
+static enum GNUNET_GenericReturnValue
+notify_client_key_add (struct TES_Client *client,
const struct Key *key)
{
struct TALER_CRYPTO_EddsaKeyAvailableNotification an = {
@@ -655,23 +182,21 @@ notify_client_key_add (struct Client *client,
.anchor_time = GNUNET_TIME_absolute_hton (key->anchor),
.duration = GNUNET_TIME_relative_hton (duration),
.exchange_pub = key->exchange_pub,
- .secm_pub = smpub
+ .secm_pub = TES_smpub
};
TALER_exchange_secmod_eddsa_sign (&key->exchange_pub,
key->anchor,
duration,
- &smpriv,
+ &TES_smpriv,
&an.secm_sig);
if (GNUNET_OK !=
- transmit (&client->addr,
- client->addr_size,
- &an.header))
+ TES_transmit (client->csock,
+ &an.header))
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Client %s must have disconnected\n",
- client->addr.sun_path);
- free_client (client);
+ "Client %p must have disconnected\n",
+ client);
return GNUNET_SYSERR;
}
return GNUNET_OK;
@@ -685,8 +210,8 @@ notify_client_key_add (struct Client *client,
* @param key the key to notify @a client about
* @return #GNUNET_OK on success
*/
-static int
-notify_client_key_del (struct Client *client,
+static enum GNUNET_GenericReturnValue
+notify_client_key_del (struct TES_Client *client,
const struct Key *key)
{
struct TALER_CRYPTO_EddsaKeyPurgeNotification pn = {
@@ -696,14 +221,12 @@ notify_client_key_del (struct Client *client,
};
if (GNUNET_OK !=
- transmit (&client->addr,
- client->addr_size,
- &pn.header))
+ TES_transmit (client->csock,
+ &pn.header))
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Client %s must have disconnected\n",
- client->addr.sun_path);
- free_client (client);
+ "Client %p must have disconnected\n",
+ client);
return GNUNET_SYSERR;
}
return GNUNET_OK;
@@ -711,13 +234,116 @@ notify_client_key_del (struct Client *client,
/**
+ * Handle @a client request @a sr to create signature. Create the
+ * signature using the respective key and return the result to
+ * the client.
+ *
+ * @param client the client making the request
+ * @param sr the request details
+ * @return #GNUNET_OK on success
+ */
+static enum GNUNET_GenericReturnValue
+handle_sign_request (struct TES_Client *client,
+ const struct TALER_CRYPTO_EddsaSignRequest *sr)
+{
+ const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose = &sr->purpose;
+ size_t purpose_size = ntohs (sr->header.size) - sizeof (*sr)
+ + sizeof (*purpose);
+ struct Key *key;
+ struct TALER_CRYPTO_EddsaSignResponse sres = {
+ .header.size = htons (sizeof (sres)),
+ .header.type = htons (TALER_HELPER_EDDSA_MT_RES_SIGNATURE)
+ };
+ enum TALER_ErrorCode ec;
+
+ if (purpose_size != htonl (purpose->size))
+ {
+ struct TALER_CRYPTO_EddsaSignFailure sf = {
+ .header.size = htons (sizeof (sr)),
+ .header.type = htons (TALER_HELPER_EDDSA_MT_RES_SIGN_FAILURE),
+ .ec = htonl (TALER_EC_GENERIC_PARAMETER_MALFORMED)
+ };
+
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Signing request failed, request malformed\n");
+ return TES_transmit (client->csock,
+ &sf.header);
+ }
+
+ GNUNET_assert (0 == pthread_mutex_lock (&keys_lock));
+ key = keys_head;
+ while ( (NULL != key) &&
+ (GNUNET_TIME_absolute_is_past (
+ GNUNET_TIME_absolute_add (key->anchor,
+ duration))) )
+ {
+ struct Key *nxt = key->next;
+
+ if (0 != key->rc)
+ break; /* do later */
+ GNUNET_CONTAINER_DLL_remove (keys_head,
+ keys_tail,
+ key);
+ if ( (! key->purge) &&
+ (0 != unlink (key->filename)) )
+ GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
+ "unlink",
+ key->filename);
+ GNUNET_free (key->filename);
+ GNUNET_free (key);
+ key = nxt;
+ }
+ if (NULL == key)
+ {
+ GNUNET_break (0);
+ ec = TALER_EC_EXCHANGE_GENERIC_KEYS_MISSING;
+ }
+ else
+ {
+ GNUNET_assert (key->rc < UINT_MAX);
+ key->rc++;
+ GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
+
+ if (GNUNET_OK !=
+ GNUNET_CRYPTO_eddsa_sign_ (&key->exchange_priv.eddsa_priv,
+ purpose,
+ &sres.exchange_sig.eddsa_signature))
+ ec = TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
+ else
+ ec = TALER_EC_NONE;
+ sres.exchange_pub = key->exchange_pub;
+ GNUNET_assert (0 == pthread_mutex_lock (&keys_lock));
+ GNUNET_assert (key->rc > 0);
+ key->rc--;
+ }
+ GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
+ if (TALER_EC_NONE != ec)
+ {
+ struct TALER_CRYPTO_EddsaSignFailure sf = {
+ .header.size = htons (sizeof (sf)),
+ .header.type = htons (TALER_HELPER_EDDSA_MT_RES_SIGN_FAILURE),
+ .ec = htonl ((uint32_t) ec)
+ };
+
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Signing request %p failed, worker failed to produce signature\n",
+ client);
+ return TES_transmit (client->csock,
+ &sf.header);
+ }
+ return TES_transmit (client->csock,
+ &sres.header);
+}
+
+
+/**
* Initialize key material for key @a key (also on disk).
*
* @param[in,out] key to compute key material for
* @param position where in the DLL will the @a key go
* @return #GNUNET_OK on success
*/
-static int
+static enum GNUNET_GenericReturnValue
setup_key (struct Key *key,
struct Key *position)
{
@@ -746,54 +372,58 @@ setup_key (struct Key *key,
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Setup fresh private key in `%s'\n",
key->filename);
+ key->key_gen = key_gen;
key->exchange_priv.eddsa_priv = priv;
key->exchange_pub.eddsa_pub = pub;
GNUNET_CONTAINER_DLL_insert_after (keys_head,
keys_tail,
position,
key);
+ return GNUNET_OK;
+}
- /* tell clients about new key */
- {
- struct Client *nxt;
- for (struct Client *client = clients_head;
- NULL != client;
- client = nxt)
- {
- nxt = client->next;
- if (GNUNET_OK !=
- notify_client_key_add (client,
- key))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Failed to notify client about new key, client dropped\n");
- }
- }
- }
- return GNUNET_OK;
+/**
+ * The validity period of a key @a key has expired. Purge it.
+ *
+ * @param[in] key expired or revoked key to purge
+ */
+static void
+purge_key (struct Key *key)
+{
+ if (key->purge)
+ return;
+ if (0 != unlink (key->filename))
+ GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
+ "unlink",
+ key->filename);
+ key->purge = true;
+ key->key_gen = key_gen;
+ GNUNET_free (key->filename);
}
/**
- * A client informs us that a key has been revoked.
+ * A @a client informs us that a key has been revoked.
* Check if the key is still in use, and if so replace (!)
* it with a fresh key.
*
- * @param addr address of the client making the request
- * @param addr_size number of bytes in @a addr
+ * @param client the client making the request
* @param rr the revocation request
+ * @return #GNUNET_OK on success
*/
-static void
-handle_revoke_request (const struct sockaddr_un *addr,
- socklen_t addr_size,
+static enum GNUNET_GenericReturnValue
+handle_revoke_request (struct TES_Client *client,
const struct TALER_CRYPTO_EddsaRevokeRequest *rr)
{
struct Key *key;
struct Key *nkey;
key = NULL;
- for (struct Key *pos = keys_head; NULL != pos; pos = pos->next)
+ GNUNET_assert (0 == pthread_mutex_lock (&keys_lock));
+ for (struct Key *pos = keys_head;
+ NULL != pos;
+ pos = pos->next)
if (0 == GNUNET_memcmp (&pos->exchange_pub,
&rr->exchange_pub))
{
@@ -802,16 +432,18 @@ handle_revoke_request (const struct sockaddr_un *addr,
}
if (NULL == key)
{
+ GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"Revocation request ignored, key unknown\n");
- return;
+ return GNUNET_OK;
}
- /* kill existing key, done first to ensure this always happens */
- if (0 != unlink (key->filename))
- GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
- "unlink",
- key->filename);
+ key_gen++;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Revoking key %p, bumping generation to %llu\n",
+ key,
+ (unsigned long long) key_gen);
+ purge_key (key);
/* Setup replacement key */
nkey = GNUNET_new (struct Key);
@@ -820,157 +452,146 @@ handle_revoke_request (const struct sockaddr_un *addr,
setup_key (nkey,
key))
{
+ GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
GNUNET_break (0);
GNUNET_SCHEDULER_shutdown ();
- global_ret = 44;
- return;
+ global_ret = EXIT_FAILURE;
+ return GNUNET_SYSERR;
}
+ GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
+ TES_wake_clients ();
+ return GNUNET_OK;
+}
- /* get rid of the old key */
- key->purge = true;
- GNUNET_CONTAINER_DLL_remove (keys_head,
- keys_tail,
- key);
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Revocation complete\n");
- /* Tell clients this key is gone */
- {
- struct Client *nxt;
+/**
+ * Handle @a hdr message received from @a client.
+ *
+ * @param client the client that received the message
+ * @param hdr message that was received
+ * @return #GNUNET_OK on success
+ */
+static enum GNUNET_GenericReturnValue
+eddsa_work_dispatch (struct TES_Client *client,
+ const struct GNUNET_MessageHeader *hdr)
+{
+ uint16_t msize = ntohs (hdr->size);
- for (struct Client *client = clients_head;
- NULL != client;
- client = nxt)
+ switch (ntohs (hdr->type))
+ {
+ case TALER_HELPER_EDDSA_MT_REQ_SIGN:
+ if (msize < sizeof (struct TALER_CRYPTO_EddsaSignRequest))
{
- nxt = client->next;
- if (GNUNET_OK !=
- notify_client_key_del (client,
- key))
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Failed to notify client about revoked key, client dropped\n");
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
}
+ return handle_sign_request (
+ client,
+ (const struct TALER_CRYPTO_EddsaSignRequest *) hdr);
+ case TALER_HELPER_EDDSA_MT_REQ_REVOKE:
+ if (msize != sizeof (struct TALER_CRYPTO_EddsaRevokeRequest))
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ return handle_revoke_request (
+ client,
+ (const struct TALER_CRYPTO_EddsaRevokeRequest *) hdr);
+ default:
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
}
- if (0 == key->rc)
- free_key (key);
}
-static void
-read_job (void *cls)
+/**
+ * Send our initial key set to @a client together with the
+ * "sync" terminator.
+ *
+ * @param client the client to inform
+ * @return #GNUNET_OK on success
+ */
+static enum GNUNET_GenericReturnValue
+eddsa_client_init (struct TES_Client *client)
{
- struct Client *client = cls;
- char buf[65536];
- ssize_t buf_size;
- const struct GNUNET_MessageHeader *hdr;
- struct sockaddr_un addr;
- socklen_t addr_size = sizeof (addr);
-
- read_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
- unix_sock,
- &read_job,
- NULL);
- buf_size = GNUNET_NETWORK_socket_recvfrom (unix_sock,
- buf,
- sizeof (buf),
- (struct sockaddr *) &addr,
- &addr_size);
- if (-1 == buf_size)
- {
- GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
- "recv");
- return;
- }
- if (0 == buf_size)
+ GNUNET_assert (0 == pthread_mutex_lock (&keys_lock));
+ for (struct Key *key = keys_head;
+ NULL != key;
+ key = key->next)
{
- return;
- }
- if (buf_size < sizeof (struct GNUNET_MessageHeader))
- {
- GNUNET_break_op (0);
- return;
- }
- hdr = (const struct GNUNET_MessageHeader *) buf;
- if (ntohs (hdr->size) != buf_size)
- {
- GNUNET_break_op (0);
- free_client (client);
- return;
+ if (GNUNET_OK !=
+ notify_client_key_add (client,
+ key))
+ {
+ GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
}
- switch (ntohs (hdr->type))
+ client->key_gen = key_gen;
+ GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
{
- case TALER_HELPER_EDDSA_MT_REQ_INIT:
- if (ntohs (hdr->size) != sizeof (struct GNUNET_MessageHeader))
+ struct GNUNET_MessageHeader synced = {
+ .type = htons (TALER_HELPER_EDDSA_SYNCED),
+ .size = htons (sizeof (synced))
+ };
+
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Client %p synced\n",
+ client);
+ if (GNUNET_OK !=
+ TES_transmit (client->csock,
+ &synced))
{
- GNUNET_break_op (0);
- return;
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
}
+ }
+ return GNUNET_OK;
+}
+
+
+/**
+ * Notify @a client about all changes to the keys since
+ * the last generation known to the @a client.
+ *
+ * @param client the client to notify
+ * @return #GNUNET_OK on success
+ */
+static enum GNUNET_GenericReturnValue
+eddsa_update_client_keys (struct TES_Client *client)
+{
+ GNUNET_assert (0 == pthread_mutex_lock (&keys_lock));
+ for (struct Key *key = keys_head;
+ NULL != key;
+ key = key->next)
+ {
+ if (key->key_gen <= client->key_gen)
+ continue;
+ if (key->purge)
{
- struct Client *client;
-
- client = GNUNET_new (struct Client);
- client->addr = addr;
- client->addr_size = addr_size;
- GNUNET_CONTAINER_DLL_insert (clients_head,
- clients_tail,
- client);
- for (struct Key *key = keys_head;
- NULL != key;
- key = key->next)
- {
- if (GNUNET_OK !=
- notify_client_key_add (client,
- key))
- {
- /* client died, skip the rest */
- client = NULL;
- break;
- }
- }
- if (NULL != client)
+ if (GNUNET_OK !=
+ notify_client_key_del (client,
+ key))
{
- struct GNUNET_MessageHeader synced = {
- .type = htons (TALER_HELPER_EDDSA_SYNCED),
- .size = htons (sizeof (synced))
- };
-
- if (GNUNET_OK !=
- transmit (&client->addr,
- client->addr_size,
- &synced))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Client %s must have disconnected\n",
- client->addr.sun_path);
- free_client (client);
- }
+ GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
+ return GNUNET_SYSERR;
}
}
- break;
- case TALER_HELPER_EDDSA_MT_REQ_SIGN:
- if (ntohs (hdr->size) < sizeof (struct TALER_CRYPTO_EddsaSignRequest))
- {
- GNUNET_break_op (0);
- return;
- }
- handle_sign_request (&addr,
- addr_size,
- (const struct TALER_CRYPTO_EddsaSignRequest *) buf);
- break;
- case TALER_HELPER_EDDSA_MT_REQ_REVOKE:
- if (ntohs (hdr->size) != sizeof (struct TALER_CRYPTO_EddsaRevokeRequest))
+ else
{
- GNUNET_break_op (0);
- return;
+ if (GNUNET_OK !=
+ notify_client_key_add (client,
+ key))
+ {
+ GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
+ return GNUNET_SYSERR;
+ }
}
- handle_revoke_request (&addr,
- addr_size,
- (const struct
- TALER_CRYPTO_EddsaRevokeRequest *) buf);
- break;
- default:
- GNUNET_break_op (0);
- return;
}
+ client->key_gen = key_gen;
+ GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
+ return GNUNET_OK;
}
@@ -979,7 +600,7 @@ read_job (void *cls)
*
* @return #GNUNET_OK on success
*/
-static int
+static enum GNUNET_GenericReturnValue
create_key (void)
{
struct Key *key;
@@ -1010,7 +631,7 @@ create_key (void)
GNUNET_break (0);
GNUNET_free (key);
GNUNET_SCHEDULER_shutdown ();
- global_ret = 42;
+ global_ret = EXIT_FAILURE;
return GNUNET_SYSERR;
}
return GNUNET_OK;
@@ -1040,55 +661,6 @@ key_action_time (void)
/**
- * The validity period of a key @a key has expired. Purge it.
- *
- * @param[in] key expired key to purge and free
- */
-static void
-purge_key (struct Key *key)
-{
- struct Client *nxt;
-
- for (struct Client *client = clients_head;
- NULL != client;
- client = nxt)
- {
- nxt = client->next;
- if (GNUNET_OK !=
- notify_client_key_del (client,
- key))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Failed to notify client about purged key, client dropped\n");
- }
- }
- GNUNET_CONTAINER_DLL_remove (keys_head,
- keys_tail,
- key);
- if (0 != unlink (key->filename))
- {
- GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
- "unlink",
- key->filename);
- }
- else
- {
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Purged expired private key `%s'\n",
- key->filename);
- }
- GNUNET_free (key->filename);
- if (0 != key->rc)
- {
- /* delay until all signing threads are done with this key */
- key->purge = true;
- return;
- }
- GNUNET_free (key);
-}
-
-
-/**
* Create new keys and expire ancient keys.
*
* @param cls NULL
@@ -1096,35 +668,52 @@ purge_key (struct Key *key)
static void
update_keys (void *cls)
{
- (void) cls;
+ bool wake = false;
+ (void) cls;
keygen_task = NULL;
+ GNUNET_assert (0 == pthread_mutex_lock (&keys_lock));
/* create new keys */
while ( (NULL == keys_tail) ||
- (0 ==
- GNUNET_TIME_absolute_get_remaining (
- GNUNET_TIME_absolute_subtract (
- GNUNET_TIME_absolute_subtract (
- GNUNET_TIME_absolute_add (keys_tail->anchor,
- duration),
- lookahead_sign),
- overlap_duration)).rel_value_us) )
+ GNUNET_TIME_absolute_is_past (
+ GNUNET_TIME_absolute_subtract (
+ GNUNET_TIME_absolute_subtract (
+ GNUNET_TIME_absolute_add (keys_tail->anchor,
+ duration),
+ lookahead_sign),
+ overlap_duration)) )
{
+ if (! wake)
+ {
+ key_gen++;
+ wake = true;
+ }
if (GNUNET_OK !=
create_key ())
{
+ GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
GNUNET_break (0);
+ global_ret = EXIT_FAILURE;
GNUNET_SCHEDULER_shutdown ();
return;
}
}
/* remove expired keys */
while ( (NULL != keys_head) &&
- (0 ==
- GNUNET_TIME_absolute_get_remaining
- (GNUNET_TIME_absolute_add (keys_head->anchor,
- duration)).rel_value_us) )
+ GNUNET_TIME_absolute_is_past (
+ GNUNET_TIME_absolute_add (keys_head->anchor,
+ duration)))
+ {
+ if (! wake)
+ {
+ key_gen++;
+ wake = true;
+ }
purge_key (keys_head);
+ }
+ GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
+ if (wake)
+ TES_wake_clients ();
keygen_task = GNUNET_SCHEDULER_add_at (key_action_time (),
&update_keys,
NULL);
@@ -1137,8 +726,9 @@ update_keys (void *cls)
* @param filename name of the file we are parsing, for logging
* @param buf key material
* @param buf_size number of bytes in @a buf
+ * @return #GNUNET_OK on success
*/
-static void
+static enum GNUNET_GenericReturnValue
parse_key (const char *filename,
const void *buf,
size_t buf_size)
@@ -1155,7 +745,7 @@ parse_key (const char *filename,
{
/* File in a directory without '/' in the name, this makes no sense. */
GNUNET_break (0);
- return;
+ return GNUNET_SYSERR;
}
anchor_s++;
if (1 != sscanf (anchor_s,
@@ -1167,7 +757,7 @@ parse_key (const char *filename,
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"Filename `%s' invalid for key file, skipping\n",
filename);
- return;
+ return GNUNET_SYSERR;
}
anchor.abs_value_us = anchor_ll * GNUNET_TIME_UNIT_SECONDS.rel_value_us;
if (anchor_ll != anchor.abs_value_us / GNUNET_TIME_UNIT_SECONDS.rel_value_us)
@@ -1176,7 +766,7 @@ parse_key (const char *filename,
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"Filename `%s' invalid for key file, skipping\n",
filename);
- return;
+ return GNUNET_SYSERR;
}
if (buf_size != sizeof (priv))
{
@@ -1184,7 +774,7 @@ parse_key (const char *filename,
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"File `%s' is malformed, skipping\n",
filename);
- return;
+ return GNUNET_SYSERR;
}
memcpy (&priv,
buf,
@@ -1197,11 +787,13 @@ parse_key (const char *filename,
GNUNET_CRYPTO_eddsa_key_get_public (&priv,
&pub);
+ GNUNET_assert (0 == pthread_mutex_lock (&keys_lock));
key = GNUNET_new (struct Key);
key->exchange_priv.eddsa_priv = priv;
key->exchange_pub.eddsa_pub = pub;
key->anchor = anchor;
key->filename = GNUNET_strdup (filename);
+ key->key_gen = key_gen;
before = NULL;
for (struct Key *pos = keys_head;
NULL != pos;
@@ -1215,10 +807,12 @@ parse_key (const char *filename,
keys_tail,
before,
key);
+ GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Imported key from `%s'\n",
filename);
}
+ return GNUNET_OK;
}
@@ -1228,7 +822,7 @@ parse_key (const char *filename,
* @param cls NULL
* @param filename name of a file in the directory
*/
-static int
+static enum GNUNET_GenericReturnValue
import_key (void *cls,
const char *filename)
{
@@ -1326,9 +920,9 @@ import_key (void *cls,
GNUNET_DISK_file_close (fh);
return GNUNET_OK;
}
- parse_key (filename,
- ptr,
- (size_t) sbuf.st_size);
+ (void) parse_key (filename,
+ ptr,
+ (size_t) sbuf.st_size);
GNUNET_DISK_file_unmap (map);
GNUNET_DISK_file_close (fh);
return GNUNET_OK;
@@ -1336,15 +930,16 @@ import_key (void *cls,
/**
- * Load the various duration values from #kcfg.
+ * Load the various duration values from @a kcfg.
*
+ * @param cfg configuration to use
* @return #GNUNET_OK on success
*/
-static int
-load_durations (void)
+static enum GNUNET_GenericReturnValue
+load_durations (const struct GNUNET_CONFIGURATION_Handle *cfg)
{
if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_time (kcfg,
+ GNUNET_CONFIGURATION_get_value_time (cfg,
"taler-exchange-secmod-eddsa",
"OVERLAP_DURATION",
&overlap_duration))
@@ -1355,7 +950,7 @@ load_durations (void)
return GNUNET_SYSERR;
}
if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_time (kcfg,
+ GNUNET_CONFIGURATION_get_value_time (cfg,
"taler-exchange-secmod-eddsa",
"DURATION",
&duration))
@@ -1368,7 +963,7 @@ load_durations (void)
GNUNET_TIME_round_rel (&overlap_duration);
if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_time (kcfg,
+ GNUNET_CONFIGURATION_get_value_time (cfg,
"taler-exchange-secmod-eddsa",
"LOOKAHEAD_SIGN",
&lookahead_sign))
@@ -1392,51 +987,12 @@ static void
do_shutdown (void *cls)
{
(void) cls;
- if (NULL != read_task)
- {
- GNUNET_SCHEDULER_cancel (read_task);
- read_task = NULL;
- }
- if (NULL != unix_sock)
- {
- GNUNET_break (GNUNET_OK ==
- GNUNET_NETWORK_socket_close (unix_sock));
- unix_sock = NULL;
- }
- if (0 != unlink (unixpath))
- {
- GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
- "unlink",
- unixpath);
- }
- GNUNET_free (unixpath);
+ TES_listen_stop ();
if (NULL != keygen_task)
{
GNUNET_SCHEDULER_cancel (keygen_task);
keygen_task = NULL;
}
- if (NULL != done_task)
- {
- GNUNET_SCHEDULER_cancel (done_task);
- done_task = NULL;
- }
- /* shut down worker threads */
- if (NULL != workers)
- {
- GNUNET_assert (0 == pthread_mutex_lock (&work_lock));
- in_shutdown = true;
- GNUNET_assert (0 == pthread_cond_broadcast (&work_cond));
- GNUNET_assert (0 == pthread_mutex_unlock (&work_lock));
- for (unsigned int i = 0; i<num_workers; i++)
- GNUNET_assert (0 == pthread_join (workers[i],
- NULL));
- }
- if (NULL != done_signal)
- {
- GNUNET_break (GNUNET_OK ==
- GNUNET_NETWORK_socket_close (done_signal));
- done_signal = NULL;
- }
}
@@ -1454,10 +1010,15 @@ run (void *cls,
const char *cfgfile,
const struct GNUNET_CONFIGURATION_Handle *cfg)
{
+ static struct TES_Callbacks cb = {
+ .dispatch = eddsa_work_dispatch,
+ .updater = eddsa_update_client_keys,
+ .init = eddsa_client_init
+ };
+
(void) cls;
(void) args;
(void) cfgfile;
- kcfg = cfg;
if (now.abs_value_us != now_tmp.abs_value_us)
{
/* The user gave "--now", use it! */
@@ -1469,48 +1030,14 @@ run (void *cls,
now = GNUNET_TIME_absolute_get ();
}
GNUNET_TIME_round_abs (&now);
-
- {
- char *pfn;
-
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_filename (kcfg,
- "taler-exchange-secmod-eddsa",
- "SM_PRIV_KEY",
- &pfn))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
- "taler-exchange-secmod-eddsa",
- "SM_PRIV_KEY");
- global_ret = 1;
- return;
- }
- if (GNUNET_SYSERR ==
- GNUNET_CRYPTO_eddsa_key_from_file (pfn,
- GNUNET_YES,
- &smpriv.eddsa_priv))
- {
- GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
- "taler-exchange-secmod-rsa",
- "SM_PRIV_KEY",
- "Could not use file to persist private key");
- GNUNET_free (pfn);
- global_ret = 1;
- return;
- }
- GNUNET_free (pfn);
- GNUNET_CRYPTO_eddsa_key_get_public (&smpriv.eddsa_priv,
- &smpub.eddsa_pub);
- }
-
if (GNUNET_OK !=
- load_durations ())
+ load_durations (cfg))
{
- global_ret = 1;
+ global_ret = EXIT_NOTCONFIGURED;
return;
}
if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_filename (kcfg,
+ GNUNET_CONFIGURATION_get_value_filename (cfg,
"taler-exchange-secmod-eddsa",
"KEY_DIR",
&keydir))
@@ -1518,131 +1045,29 @@ run (void *cls,
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
"taler-exchange-secmod-eddsa",
"KEY_DIR");
- global_ret = 1;
+ global_ret = EXIT_NOTCONFIGURED;
return;
}
-
- /* Create client directory and set permissions. */
- {
- char *client_dir;
-
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_filename (kcfg,
- "taler-exchange-secmod-eddsa",
- "CLIENT_DIR",
- &client_dir))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+ global_ret = TES_listen_start (cfg,
"taler-exchange-secmod-eddsa",
- "CLIENT_DIR");
- global_ret = 3;
- return;
- }
-
- if (GNUNET_OK != GNUNET_DISK_directory_create (client_dir))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Can't create client directory (%s)\n",
- client_dir);
- global_ret = 3;
- return;
- }
- /* Set sticky group bit, so that clients will be writeable by the current service. */
- if (0 != chmod (client_dir,
- S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP
- | S_ISGID))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Can't set permissions for client directory (%s)\n",
- client_dir);
- global_ret = 3;
- return;
- }
-
- GNUNET_free (client_dir);
- }
-
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_filename (kcfg,
- "taler-exchange-secmod-eddsa",
- "UNIXPATH",
- &unixpath))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
- "taler-exchange-secmod-eddsa",
- "UNIXPATH");
- global_ret = 3;
- return;
- }
-
- GNUNET_assert (NULL != unixpath);
- unix_sock = TES_open_socket (unixpath);
-
- if (NULL == unix_sock)
- {
- GNUNET_free (unixpath);
- global_ret = 2;
+ &cb);
+ if (0 != global_ret)
return;
- }
-
GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
NULL);
-
/* Load keys */
GNUNET_break (GNUNET_OK ==
GNUNET_DISK_directory_create (keydir));
GNUNET_DISK_directory_scan (keydir,
&import_key,
NULL);
- /* start job to accept incoming requests on 'sock' */
- read_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
- unix_sock,
- &read_job,
- NULL);
- /* start job to keep keys up-to-date; MUST be run before the #read_task,
+
+ /* start job to keep keys up-to-date; MUST be run before the #listen_task,
hence with priority. */
keygen_task = GNUNET_SCHEDULER_add_with_priority (
GNUNET_SCHEDULER_PRIORITY_URGENT,
&update_keys,
NULL);
-
- /* start job to handle completed work */
- {
- int fd;
-
- fd = eventfd (0,
- EFD_NONBLOCK | EFD_CLOEXEC);
- if (-1 == fd)
- {
- GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
- "eventfd");
- global_ret = 6;
- GNUNET_SCHEDULER_shutdown ();
- return;
- }
- done_signal = GNUNET_NETWORK_socket_box_native (fd);
- }
- done_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
- done_signal,
- &handle_done,
- NULL);
-
- /* start crypto workers */
- if (0 == num_workers)
- num_workers = sysconf (_SC_NPROCESSORS_CONF);
- if (0 == num_workers)
- num_workers = 1;
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Starting %u crypto workers\n",
- num_workers);
- workers = GNUNET_new_array (num_workers,
- pthread_t);
- for (unsigned int i = 0; i<num_workers; i++)
- GNUNET_assert (0 ==
- pthread_create (&workers[i],
- NULL,
- &sign_worker,
- NULL));
}
@@ -1660,11 +1085,6 @@ main (int argc,
struct GNUNET_GETOPT_CommandLineOption options[] = {
GNUNET_GETOPT_option_timetravel ('T',
"timetravel"),
- GNUNET_GETOPT_option_uint ('p',
- "parallelism",
- "NUM_WORKERS",
- "number of worker threads to use",
- &num_workers),
GNUNET_GETOPT_option_absolute_time ('t',
"time",
"TIMESTAMP",
@@ -1672,7 +1092,7 @@ main (int argc,
&now_tmp),
GNUNET_GETOPT_OPTION_END
};
- int ret;
+ enum GNUNET_GenericReturnValue ret;
/* Restrict permissions for the key files that we create. */
(void) umask (S_IWGRP | S_IROTH | S_IWOTH | S_IXOTH);
@@ -1689,8 +1109,8 @@ main (int argc,
&run,
NULL);
if (GNUNET_NO == ret)
- return 0;
+ return EXIT_SUCCESS;
if (GNUNET_SYSERR == ret)
- return 1;
+ return EXIT_INVALIDARGUMENT;
return global_ret;
}
diff --git a/src/util/taler-exchange-secmod-rsa.c b/src/util/taler-exchange-secmod-rsa.c
index 6bca58f88..1884ca98c 100644
--- a/src/util/taler-exchange-secmod-rsa.c
+++ b/src/util/taler-exchange-secmod-rsa.c
@@ -25,8 +25,7 @@
* - auditor signatures and master signatures are to be kept in the exchange DB,
* and merged with the public keys of the helper by the exchange HTTPD!
* - the main loop of the helper is SINGLE-THREADED, but there are
- * threads for crypto-workers which (only) do the signing in parallel,
- * working of a work-queue.
+ * threads for crypto-workers which do the signing in parallel, one per client.
* - thread-safety: signing happens in parallel, thus when REMOVING private keys,
* we must ensure that all signers are done before we fully free() the
* private key. This is done by reference counting (as work is always
@@ -41,6 +40,7 @@
#include "taler_error_codes.h"
#include "taler_signatures.h"
#include "secmod_common.h"
+#include <poll.h>
/**
@@ -88,7 +88,7 @@ struct DenominationKey
/**
* Hash of this denomination's public key.
*/
- struct TALER_DenominationHash h_denom_pub;
+ struct GNUNET_HashCode h_denom_pub;
/**
* Time at which this key is supposed to become valid.
@@ -96,6 +96,11 @@ struct DenominationKey
struct GNUNET_TIME_Absolute anchor;
/**
+ * Generation when this key was created or revoked.
+ */
+ uint64_t key_gen;
+
+ /**
* Reference counter. Counts the number of threads that are
* using this key at this time.
*/
@@ -155,111 +160,11 @@ struct Denomination
/**
- * Actively worked on client request.
- */
-struct WorkItem;
-
-
-/**
- * Information we keep for a client connected to us.
- */
-struct Client
-{
-
- /**
- * Kept in a DLL.
- */
- struct Client *next;
-
- /**
- * Kept in a DLL.
- */
- struct Client *prev;
-
- /**
- * Client address.
- */
- struct sockaddr_un addr;
-
- /**
- * Number of bytes used in @e addr.
- */
- socklen_t addr_size;
-
-};
-
-
-struct WorkItem
-{
-
- /**
- * Kept in a DLL.
- */
- struct WorkItem *next;
-
- /**
- * Kept in a DLL.
- */
- struct WorkItem *prev;
-
- /**
- * Key to be used for this operation.
- */
- struct DenominationKey *dk;
-
- /**
- * Signature over @e blinded_msg using @e dk. Result of doing the
- * work. Initially zero.
- */
- struct TALER_BlindedDenominationSignature denom_sig;
-
- /**
- * Coin_ev value to sign.
- */
- void *blinded_msg;
-
- /**
- * Number of bytes in #blinded_msg.
- */
- size_t blinded_msg_size;
-
- /**
- * Client address.
- */
- struct sockaddr_un addr;
-
- /**
- * Number of bytes used in @e addr.
- */
- socklen_t addr_size;
-
-};
-
-
-/**
* Return value from main().
*/
static int global_ret;
/**
- * Private key of this security module. Used to sign denomination key
- * announcements.
- */
-static struct TALER_SecurityModulePrivateKeyP smpriv;
-
-/**
- * Public key of this security module.
- */
-static struct TALER_SecurityModulePublicKeyP smpub;
-
-/**
- * Number of worker threads to use. Default (0) is to use one per CPU core
- * available.
- * Length of the #workers array.
- */
-static unsigned int num_workers;
-
-/**
* Time when the key update is executed.
* Either the actual current time, or a pretended time.
*/
@@ -272,11 +177,6 @@ static struct GNUNET_TIME_Absolute now;
static struct GNUNET_TIME_Absolute now_tmp;
/**
- * Handle to the exchange's configuration
- */
-static const struct GNUNET_CONFIGURATION_Handle *kcfg;
-
-/**
* Where do we store the keys?
*/
static char *keydir;
@@ -310,335 +210,118 @@ static struct Denomination *denom_tail;
static struct GNUNET_CONTAINER_MultiHashMap *keys;
/**
- * Our listen socket.
- */
-static struct GNUNET_NETWORK_Handle *unix_sock;
-
-/**
- * Path where we are listening.
- */
-static char *unixpath;
-
-/**
- * Task run to accept new inbound connections.
- */
-static struct GNUNET_SCHEDULER_Task *read_task;
-
-/**
* Task run to generate new keys.
*/
static struct GNUNET_SCHEDULER_Task *keygen_task;
-/**
- * Head of DLL of clients connected to us.
- */
-static struct Client *clients_head;
-
-/**
- * Tail of DLL of clients connected to us.
- */
-static struct Client *clients_tail;
-
-/**
- * Head of DLL with pending signing operations.
- */
-static struct WorkItem *work_head;
-
-/**
- * Tail of DLL with pending signing operations.
- */
-static struct WorkItem *work_tail;
-
-/**
- * Lock for the work queue.
- */
-static pthread_mutex_t work_lock;
-
-/**
- * Condition variable for the semaphore of the work queue.
- */
-static pthread_cond_t work_cond = PTHREAD_COND_INITIALIZER;
-
-/**
- * Number of items in the work queue. Also used as the semaphore counter.
- */
-static unsigned long long work_counter;
-
-/**
- * Head of DLL with completed signing operations.
- */
-static struct WorkItem *done_head;
-
-/**
- * Tail of DLL with completed signing operations.
- */
-static struct WorkItem *done_tail;
-
-/**
- * Lock for the done queue.
- */
-static pthread_mutex_t done_lock;
-
-/**
- * Task waiting for work to be done.
- */
-static struct GNUNET_SCHEDULER_Task *done_task;
-
-/**
- * Signal used by threads to notify the #done_task that they
- * completed work that is now in the done queue.
- */
-static struct GNUNET_NETWORK_Handle *done_signal;
-
-/**
- * Set once we are in shutdown and workers should terminate.
- */
-static volatile bool in_shutdown;
-
-/**
- * Array of #num_workers sign_worker() threads.
- */
-static pthread_t *workers;
-
-
-/**
- * Main function of a worker thread that signs.
- *
- * @param cls NULL
- * @return NULL
- */
-static void *
-sign_worker (void *cls)
-{
- (void) cls;
- GNUNET_assert (0 == pthread_mutex_lock (&work_lock));
- while (! in_shutdown)
- {
- struct WorkItem *wi;
-
- while (NULL != (wi = work_head))
- {
- /* take work from queue */
- GNUNET_CONTAINER_DLL_remove (work_head,
- work_tail,
- wi);
- work_counter--;
- GNUNET_assert (0 == pthread_mutex_unlock (&work_lock));
- GNUNET_break (GNUNET_OK ==
- TALER_denom_sign_blinded (&wi->denom_sig,
- &wi->dk->denom_priv,
- wi->blinded_msg,
- wi->blinded_msg_size));
- /* put completed work into done queue */
- GNUNET_assert (0 == pthread_mutex_lock (&done_lock));
- GNUNET_CONTAINER_DLL_insert (done_head,
- done_tail,
- wi);
- GNUNET_assert (0 == pthread_mutex_unlock (&done_lock));
- {
- uint64_t val = GNUNET_htonll (1);
-
- /* raise #done_signal */
- if (sizeof(val) !=
- write (GNUNET_NETWORK_get_fd (done_signal),
- &val,
- sizeof (val)))
- GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
- "write(eventfd)");
- }
- GNUNET_assert (0 == pthread_mutex_lock (&work_lock));
- }
- if (in_shutdown)
- break;
- /* queue is empty, wait for work */
- GNUNET_assert (0 ==
- pthread_cond_wait (&work_cond,
- &work_lock));
- }
- GNUNET_assert (0 ==
- pthread_mutex_unlock (&work_lock));
- return NULL;
-}
-
/**
- * Free @a client, releasing all (remaining) state.
- *
- * @param[in] client data to free
- */
-static void
-free_client (struct Client *client)
-{
- GNUNET_CONTAINER_DLL_remove (clients_head,
- clients_tail,
- client);
- GNUNET_free (client);
-}
-
-
-/**
- * Function run to read incoming requests from a client.
- *
- * @param cls the `struct Client`
+ * Lock for the keys queue.
*/
-static void
-read_job (void *cls);
-
+static pthread_mutex_t keys_lock;
/**
- * Free @a dk. It must already have been removed from #keys and the
- * denomination's DLL.
- *
- * @param[in] dk key to free
+ * Current key generation.
*/
-static void
-free_dk (struct DenominationKey *dk)
-{
- GNUNET_free (dk->filename);
- TALER_denom_priv_free (&dk->denom_priv);
- TALER_denom_pub_free (&dk->denom_pub);
- GNUNET_free (dk);
-}
+static uint64_t key_gen;
/**
- * Send a message starting with @a hdr to @a client. We expect that
- * the client is mostly able to handle everything at whatever speed
- * we have (after all, the crypto should be the slow part). However,
- * especially on startup when we send all of our keys, it is possible
- * that the client cannot keep up. In that case, we throttle when
- * sending fails. This does not work with poll() as we cannot specify
- * the sendto() target address with poll(). So we nanosleep() instead.
+ * Notify @a client about @a dk becoming available.
*
- * @param addr address where to send the message
- * @param addr_size number of bytes in @a addr
- * @param hdr beginning of the message, length indicated in size field
+ * @param[in,out] client the client to notify; possible freed if transmission fails
+ * @param dk the key to notify @a client about
* @return #GNUNET_OK on success
*/
-static int
-transmit (const struct sockaddr_un *addr,
- socklen_t addr_size,
- const struct GNUNET_MessageHeader *hdr)
+static enum GNUNET_GenericReturnValue
+notify_client_dk_add (struct TES_Client *client,
+ const struct DenominationKey *dk)
{
- for (unsigned int i = 0; i<100; i++)
+ struct Denomination *denom = dk->denom;
+ size_t nlen = strlen (denom->section) + 1;
+ struct TALER_CRYPTO_RsaKeyAvailableNotification *an;
+ size_t buf_len;
+ void *buf;
+ void *p;
+ size_t tlen;
+
+ buf_len = GNUNET_CRYPTO_rsa_public_key_encode (dk->denom_pub.rsa_public_key,
+ &buf);
+ GNUNET_assert (buf_len < UINT16_MAX);
+ GNUNET_assert (nlen < UINT16_MAX);
+ tlen = buf_len + nlen + sizeof (*an);
+ GNUNET_assert (tlen < UINT16_MAX);
+ an = GNUNET_malloc (tlen);
+ an->header.size = htons ((uint16_t) tlen);
+ an->header.type = htons (TALER_HELPER_RSA_MT_AVAIL);
+ an->pub_size = htons ((uint16_t) buf_len);
+ an->section_name_len = htons ((uint16_t) nlen);
+ an->anchor_time = GNUNET_TIME_absolute_hton (dk->anchor);
+ an->duration_withdraw = GNUNET_TIME_relative_hton (denom->duration_withdraw);
+ TALER_exchange_secmod_rsa_sign (&dk->h_denom_pub,
+ denom->section,
+ dk->anchor,
+ denom->duration_withdraw,
+ &TES_smpriv,
+ &an->secm_sig);
+ an->secm_pub = TES_smpub;
+ p = (void *) &an[1];
+ memcpy (p,
+ buf,
+ buf_len);
+ GNUNET_free (buf);
+ memcpy (p + buf_len,
+ denom->section,
+ nlen);
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Sending RSA denomination key %s (%s)\n",
+ GNUNET_h2s (&dk->h_denom_pub),
+ denom->section);
+ if (GNUNET_OK !=
+ TES_transmit (client->csock,
+ &an->header))
{
- ssize_t ret = sendto (GNUNET_NETWORK_get_fd (unix_sock),
- hdr,
- ntohs (hdr->size),
- 0 /* no flags => blocking! */,
- (const struct sockaddr *) addr,
- addr_size);
- if ( (-1 == ret) &&
- (EAGAIN == errno) )
- {
- /* _Maybe_ with blocking sendto(), this should no
- longer be needed; still keeping it just in case. */
- /* Wait a bit, in case client is just too slow */
- struct timespec req = {
- .tv_sec = 0,
- .tv_nsec = 1000
- };
- nanosleep (&req, NULL);
- continue;
- }
- if (ret == ntohs (hdr->size))
- return GNUNET_OK;
- if (ret != ntohs (hdr->size))
- break;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Client %p must have disconnected\n",
+ client);
+ GNUNET_free (an);
+ return GNUNET_SYSERR;
}
- GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
- "sendto");
- return GNUNET_SYSERR;
+ GNUNET_free (an);
+ return GNUNET_OK;
}
/**
- * Process completed tasks that are in the #done_head queue, sending
- * the result back to the client (and resuming the client).
+ * Notify @a client about @a dk being purged.
*
- * @param cls NULL
+ * @param[in,out] client the client to notify; possible freed if transmission fails
+ * @param dk the key to notify @a client about
+ * @return #GNUNET_OK on success
*/
-static void
-handle_done (void *cls)
+static enum GNUNET_GenericReturnValue
+notify_client_dk_del (struct TES_Client *client,
+ const struct DenominationKey *dk)
{
- uint64_t data;
- (void) cls;
+ struct TALER_CRYPTO_RsaKeyPurgeNotification pn = {
+ .header.type = htons (TALER_HELPER_RSA_MT_PURGE),
+ .header.size = htons (sizeof (pn)),
+ .h_denom_pub = dk->h_denom_pub
+ };
- /* consume #done_signal */
- if (sizeof (data) !=
- read (GNUNET_NETWORK_get_fd (done_signal),
- &data,
- sizeof (data)))
- GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
- "read(eventfd)");
- done_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
- done_signal,
- &handle_done,
- NULL);
- GNUNET_assert (0 == pthread_mutex_lock (&done_lock));
- while (NULL != done_head)
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Sending RSA denomination expiration %s\n",
+ GNUNET_h2s (&dk->h_denom_pub));
+ if (GNUNET_OK !=
+ TES_transmit (client->csock,
+ &pn.header))
{
- struct WorkItem *wi = done_head;
-
- GNUNET_CONTAINER_DLL_remove (done_head,
- done_tail,
- wi);
- GNUNET_assert (0 == pthread_mutex_unlock (&done_lock));
- if (TALER_DENOMINATION_INVALID == wi->denom_sig.cipher)
- {
- struct TALER_CRYPTO_SignFailure sf = {
- .header.size = htons (sizeof (sf)),
- .header.type = htons (TALER_HELPER_RSA_MT_RES_SIGN_FAILURE),
- .ec = htonl (TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE)
- };
-
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Signing request failed, worker failed to produce signature\n");
- (void) transmit (&wi->addr,
- wi->addr_size,
- &sf.header);
- }
- else
- {
- struct TALER_CRYPTO_SignResponse *sr;
- void *buf;
- size_t buf_size;
- size_t tsize;
-
- buf_size = GNUNET_CRYPTO_rsa_signature_encode (
- wi->denom_sig.details.blinded_rsa_signature,
- &buf);
- TALER_blinded_denom_sig_free (&wi->denom_sig);
- tsize = sizeof (*sr) + buf_size;
- GNUNET_assert (tsize < UINT16_MAX);
- sr = GNUNET_malloc (tsize);
- sr->header.size = htons (tsize);
- sr->header.type = htons (TALER_HELPER_RSA_MT_RES_SIGNATURE);
- memcpy (&sr[1],
- buf,
- buf_size);
- GNUNET_free (buf);
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Sending RSA signature\n");
- (void) transmit (&wi->addr,
- wi->addr_size,
- &sr->header);
- GNUNET_free (sr);
- }
- {
- struct DenominationKey *dk = wi->dk;
-
- dk->rc--;
- if ( (0 == dk->rc) &&
- (dk->purge) )
- free_dk (dk);
- }
- GNUNET_free (wi->blinded_msg);
- GNUNET_free (wi);
- GNUNET_assert (0 == pthread_mutex_lock (&done_lock));
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Client %p must have disconnected\n",
+ client);
+ return GNUNET_SYSERR;
}
- GNUNET_assert (0 == pthread_mutex_unlock (&done_lock));
-
+ return GNUNET_OK;
}
@@ -647,22 +330,22 @@ handle_done (void *cls)
* signature using the respective key and return the result to
* the client.
*
- * @param addr address of the client making the request
- * @param addr_size number of bytes in @a addr
+ * @param client the client making the request
* @param sr the request details
+ * @return #GNUNET_OK on success
*/
-static void
-handle_sign_request (const struct sockaddr_un *addr,
- socklen_t addr_size,
+static enum GNUNET_GenericReturnValue
+handle_sign_request (struct TES_Client *client,
const struct TALER_CRYPTO_SignRequest *sr)
{
struct DenominationKey *dk;
- struct WorkItem *wi;
const void *blinded_msg = &sr[1];
size_t blinded_msg_size = ntohs (sr->header.size) - sizeof (*sr);
+ struct GNUNET_CRYPTO_RsaSignature *rsa_signature;
+ GNUNET_assert (0 == pthread_mutex_lock (&keys_lock));
dk = GNUNET_CONTAINER_multihashmap_get (keys,
- &sr->h_denom_pub.hash);
+ &sr->h_denom_pub);
if (NULL == dk)
{
struct TALER_CRYPTO_SignFailure sf = {
@@ -671,13 +354,12 @@ handle_sign_request (const struct sockaddr_un *addr,
.ec = htonl (TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN)
};
+ GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Signing request failed, denomination key %s unknown\n",
- GNUNET_h2s (&sr->h_denom_pub.hash));
- (void) transmit (addr,
- addr_size,
- &sf.header);
- return;
+ GNUNET_h2s (&sr->h_denom_pub));
+ return TES_transmit (client->csock,
+ &sf.header);
}
if (0 !=
GNUNET_TIME_absolute_get_remaining (dk->anchor).rel_value_us)
@@ -689,141 +371,68 @@ handle_sign_request (const struct sockaddr_un *addr,
.ec = htonl (TALER_EC_EXCHANGE_DENOMINATION_HELPER_TOO_EARLY)
};
+ GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Signing request failed, denomination key %s is not yet valid\n",
- GNUNET_h2s (&sr->h_denom_pub.hash));
- (void) transmit (addr,
- addr_size,
- &sf.header);
- return;
+ GNUNET_h2s (&sr->h_denom_pub));
+ return TES_transmit (client->csock,
+ &sf.header);
}
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Received request to sign over %u bytes with key %s\n",
(unsigned int) blinded_msg_size,
- GNUNET_h2s (&sr->h_denom_pub.hash));
- wi = GNUNET_new (struct WorkItem);
- wi->addr = *addr;
- wi->addr_size = addr_size;
- wi->dk = dk;
+ GNUNET_h2s (&sr->h_denom_pub));
+ GNUNET_assert (dk->rc < UINT_MAX);
dk->rc++;
- wi->blinded_msg = GNUNET_memdup (blinded_msg,
- blinded_msg_size);
- wi->blinded_msg_size = blinded_msg_size;
- GNUNET_assert (0 == pthread_mutex_lock (&work_lock));
- work_counter++;
- GNUNET_CONTAINER_DLL_insert (work_head,
- work_tail,
- wi);
- GNUNET_assert (0 == pthread_cond_signal (&work_cond));
- GNUNET_assert (0 == pthread_mutex_unlock (&work_lock));
-}
-
-
-/**
- * Notify @a client about @a dk becoming available.
- *
- * @param[in,out] client the client to notify; possible freed if transmission fails
- * @param dk the key to notify @a client about
- * @return #GNUNET_OK on success
- */
-static enum GNUNET_GenericReturnValue
-notify_client_dk_add (struct Client *client,
- const struct DenominationKey *dk)
-{
- struct Denomination *denom = dk->denom;
- size_t nlen = strlen (denom->section) + 1;
- struct TALER_CRYPTO_RsaKeyAvailableNotification *an;
- size_t buf_len;
- void *buf;
- void *p;
- size_t tlen;
-
- buf_len = GNUNET_CRYPTO_rsa_public_key_encode (
- dk->denom_pub.details.rsa_public_key,
- &buf);
- GNUNET_assert (buf_len < UINT16_MAX);
- GNUNET_assert (nlen < UINT16_MAX);
- tlen = buf_len + nlen + sizeof (*an);
- GNUNET_assert (tlen < UINT16_MAX);
- an = GNUNET_malloc (tlen);
- an->header.size = htons ((uint16_t) tlen);
- an->header.type = htons (TALER_HELPER_RSA_MT_AVAIL);
- an->pub_size = htons ((uint16_t) buf_len);
- an->section_name_len = htons ((uint16_t) nlen);
- an->anchor_time = GNUNET_TIME_absolute_hton (dk->anchor);
- an->duration_withdraw = GNUNET_TIME_relative_hton (denom->duration_withdraw);
- TALER_exchange_secmod_denom_sign (&dk->h_denom_pub,
- denom->section,
- dk->anchor,
- denom->duration_withdraw,
- &smpriv,
- &an->secm_sig);
- an->secm_pub = smpub;
- p = (void *) &an[1];
- memcpy (p,
- buf,
- buf_len);
- GNUNET_free (buf);
- memcpy (p + buf_len,
- denom->section,
- nlen);
+ GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
+ rsa_signature
+ = GNUNET_CRYPTO_rsa_sign_blinded (dk->denom_priv.rsa_private_key,
+ blinded_msg,
+ blinded_msg_size);
+ GNUNET_assert (0 == pthread_mutex_lock (&keys_lock));
+ GNUNET_assert (dk->rc > 0);
+ dk->rc--;
+ GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
+ if (NULL == rsa_signature)
{
- enum GNUNET_GenericReturnValue ret = GNUNET_OK;
+ struct TALER_CRYPTO_SignFailure sf = {
+ .header.size = htons (sizeof (sf)),
+ .header.type = htons (TALER_HELPER_RSA_MT_RES_SIGN_FAILURE),
+ .ec = htonl (TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE)
+ };
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Sending RSA denomination key %s (%s)\n",
- GNUNET_h2s (&dk->h_denom_pub.hash),
- denom->section);
- if (GNUNET_OK !=
- transmit (&client->addr,
- client->addr_size,
- &an->header))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Client %s must have disconnected\n",
- client->addr.sun_path);
- free_client (client);
- ret = GNUNET_SYSERR;
- }
- GNUNET_free (an);
- return ret;
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Signing request failed, worker failed to produce signature\n");
+ return TES_transmit (client->csock,
+ &sf.header);
}
-}
-
-
-/**
- * Notify @a client about @a dk being purged.
- *
- * @param[in,out] client the client to notify; possible freed if transmission fails
- * @param dk the key to notify @a client about
- * @return #GNUNET_OK on success
- */
-static int
-notify_client_dk_del (struct Client *client,
- const struct DenominationKey *dk)
-{
- struct TALER_CRYPTO_RsaKeyPurgeNotification pn = {
- .header.type = htons (TALER_HELPER_RSA_MT_PURGE),
- .header.size = htons (sizeof (pn)),
- .h_denom_pub = dk->h_denom_pub
- };
-
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Sending RSA denomination expiration %s\n",
- GNUNET_h2s (&dk->h_denom_pub.hash));
- if (GNUNET_OK !=
- transmit (&client->addr,
- client->addr_size,
- &pn.header))
{
+ struct TALER_CRYPTO_SignResponse *sr;
+ void *buf;
+ size_t buf_size;
+ size_t tsize;
+ enum GNUNET_GenericReturnValue ret;
+
+ buf_size = GNUNET_CRYPTO_rsa_signature_encode (rsa_signature,
+ &buf);
+ GNUNET_CRYPTO_rsa_signature_free (rsa_signature);
+ tsize = sizeof (*sr) + buf_size;
+ GNUNET_assert (tsize < UINT16_MAX);
+ sr = GNUNET_malloc (tsize);
+ sr->header.size = htons (tsize);
+ sr->header.type = htons (TALER_HELPER_RSA_MT_RES_SIGNATURE);
+ memcpy (&sr[1],
+ buf,
+ buf_size);
+ GNUNET_free (buf);
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Client %s must have disconnected\n",
- client->addr.sun_path);
- free_client (client);
- return GNUNET_SYSERR;
+ "Sending RSA signature\n");
+ ret = TES_transmit (client->csock,
+ &sr->header);
+ GNUNET_free (sr);
+ return ret;
}
- return GNUNET_OK;
}
@@ -834,31 +443,35 @@ notify_client_dk_del (struct Client *client,
* @param position where in the DLL will the @a dk go
* @return #GNUNET_OK on success
*/
-static int
+static enum GNUNET_GenericReturnValue
setup_key (struct DenominationKey *dk,
struct DenominationKey *position)
{
struct Denomination *denom = dk->denom;
- struct TALER_DenominationPrivateKey priv;
- struct TALER_DenominationPublicKey pub;
+ struct GNUNET_CRYPTO_RsaPrivateKey *priv;
+ struct GNUNET_CRYPTO_RsaPublicKey *pub;
size_t buf_size;
void *buf;
- if (GNUNET_OK !=
- TALER_denom_priv_create (&priv,
- &pub,
- TALER_DENOMINATION_RSA,
- (unsigned int) denom->rsa_keysize))
+ priv = GNUNET_CRYPTO_rsa_private_key_create (denom->rsa_keysize);
+ if (NULL == priv)
{
GNUNET_break (0);
GNUNET_SCHEDULER_shutdown ();
- global_ret = 40;
+ global_ret = EXIT_FAILURE;
return GNUNET_SYSERR;
}
- buf_size = GNUNET_CRYPTO_rsa_private_key_encode (priv.details.rsa_private_key,
+ pub = GNUNET_CRYPTO_rsa_private_key_get_public (priv);
+ if (NULL == pub)
+ {
+ GNUNET_break (0);
+ GNUNET_CRYPTO_rsa_private_key_free (priv);
+ return GNUNET_SYSERR;
+ }
+ buf_size = GNUNET_CRYPTO_rsa_private_key_encode (priv,
&buf);
- TALER_denom_pub_hash (&pub,
- &dk->h_denom_pub);
+ GNUNET_CRYPTO_rsa_public_key_hash (pub,
+ &dk->h_denom_pub);
GNUNET_asprintf (&dk->filename,
"%s/%s/%llu",
keydir,
@@ -875,30 +488,31 @@ setup_key (struct DenominationKey *dk,
"write",
dk->filename);
GNUNET_free (buf);
- TALER_denom_priv_free (&priv);
- TALER_denom_pub_free (&pub);
+ GNUNET_CRYPTO_rsa_private_key_free (priv);
+ GNUNET_CRYPTO_rsa_public_key_free (pub);
return GNUNET_SYSERR;
}
GNUNET_free (buf);
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Setup fresh private key %s at %s in `%s'\n",
- GNUNET_h2s (&dk->h_denom_pub.hash),
+ "Setup fresh private key %s at %s in `%s' (generation #%llu)\n",
+ GNUNET_h2s (&dk->h_denom_pub),
GNUNET_STRINGS_absolute_time_to_string (dk->anchor),
- dk->filename);
- dk->denom_priv = priv;
- dk->denom_pub = pub;
-
+ dk->filename,
+ (unsigned long long) key_gen);
+ dk->denom_priv.rsa_private_key = priv;
+ dk->denom_pub.rsa_public_key = pub;
+ dk->key_gen = key_gen;
if (GNUNET_OK !=
GNUNET_CONTAINER_multihashmap_put (
keys,
- &dk->h_denom_pub.hash,
+ &dk->h_denom_pub,
dk,
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Duplicate private key created! Terminating.\n");
- TALER_denom_priv_free (&dk->denom_priv);
- TALER_denom_pub_free (&dk->denom_pub);
+ GNUNET_CRYPTO_rsa_private_key_free (dk->denom_priv.rsa_private_key);
+ GNUNET_CRYPTO_rsa_public_key_free (dk->denom_pub.rsa_public_key);
GNUNET_free (dk->filename);
GNUNET_free (dk);
return GNUNET_SYSERR;
@@ -907,62 +521,65 @@ setup_key (struct DenominationKey *dk,
denom->keys_tail,
position,
dk);
+ return GNUNET_OK;
+}
- /* tell clients about new key */
- {
- struct Client *nxt;
- for (struct Client *client = clients_head;
- NULL != client;
- client = nxt)
- {
- nxt = client->next;
- if (GNUNET_OK !=
- notify_client_dk_add (client,
- dk))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Failed to notify client about new key, client dropped\n");
- }
- }
- }
- return GNUNET_OK;
+/**
+ * The withdraw period of a key @a dk has expired. Purge it.
+ *
+ * @param[in] dk expired denomination key to purge
+ */
+static void
+purge_key (struct DenominationKey *dk)
+{
+ if (dk->purge)
+ return;
+ if (0 != unlink (dk->filename))
+ GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
+ "unlink",
+ dk->filename);
+ GNUNET_free (dk->filename);
+ dk->purge = true;
+ dk->key_gen = key_gen;
}
/**
- * A client informs us that a key has been revoked.
+ * A @a client informs us that a key has been revoked.
* Check if the key is still in use, and if so replace (!)
* it with a fresh key.
*
- * @param addr address of the client making the request
- * @param addr_size number of bytes in @a addr
+ * @param client the client making the request
* @param rr the revocation request
*/
-static void
-handle_revoke_request (const struct sockaddr_un *addr,
- socklen_t addr_size,
+static enum GNUNET_GenericReturnValue
+handle_revoke_request (struct TES_Client *client,
const struct TALER_CRYPTO_RevokeRequest *rr)
{
struct DenominationKey *dk;
struct DenominationKey *ndk;
struct Denomination *denom;
+ GNUNET_assert (0 == pthread_mutex_lock (&keys_lock));
dk = GNUNET_CONTAINER_multihashmap_get (keys,
- &rr->h_denom_pub.hash);
+ &rr->h_denom_pub);
if (NULL == dk)
{
+ GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"Revocation request ignored, denomination key %s unknown\n",
- GNUNET_h2s (&rr->h_denom_pub.hash));
- return;
+ GNUNET_h2s (&rr->h_denom_pub));
+ return GNUNET_OK;
}
- /* kill existing key, done first to ensure this always happens */
- if (0 != unlink (dk->filename))
- GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
- "unlink",
- dk->filename);
+ key_gen++;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Revoking key %p, bumping generation to %llu\n",
+ dk,
+ (unsigned long long) key_gen);
+ purge_key (dk);
+
/* Setup replacement key */
denom = dk->denom;
ndk = GNUNET_new (struct DenominationKey);
@@ -972,171 +589,158 @@ handle_revoke_request (const struct sockaddr_un *addr,
setup_key (ndk,
dk))
{
+ GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
GNUNET_break (0);
GNUNET_SCHEDULER_shutdown ();
- global_ret = 44;
- return;
+ global_ret = EXIT_FAILURE;
+ return GNUNET_SYSERR;
}
+ GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
+ TES_wake_clients ();
+ return GNUNET_OK;
+}
- /* get rid of the old key */
- dk->purge = true;
- GNUNET_assert (GNUNET_OK ==
- GNUNET_CONTAINER_multihashmap_remove (
- keys,
- &dk->h_denom_pub.hash,
- dk));
- GNUNET_CONTAINER_DLL_remove (denom->keys_head,
- denom->keys_tail,
- dk);
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Revocation of denomination key %s complete\n",
- GNUNET_h2s (&rr->h_denom_pub.hash));
- /* Tell clients this key is gone */
- {
- struct Client *nxt;
+/**
+ * Handle @a hdr message received from @a client.
+ *
+ * @param client the client that received the message
+ * @param hdr message that was received
+ * @return #GNUNET_OK on success
+ */
+static enum GNUNET_GenericReturnValue
+rsa_work_dispatch (struct TES_Client *client,
+ const struct GNUNET_MessageHeader *hdr)
+{
+ uint16_t msize = ntohs (hdr->size);
- for (struct Client *client = clients_head;
- NULL != client;
- client = nxt)
+ switch (ntohs (hdr->type))
+ {
+ case TALER_HELPER_RSA_MT_REQ_SIGN:
+ if (msize <= sizeof (struct TALER_CRYPTO_SignRequest))
{
- nxt = client->next;
- if (GNUNET_OK !=
- notify_client_dk_del (client,
- dk))
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Failed to notify client about revoked key, client dropped\n");
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ return handle_sign_request (
+ client,
+ (const struct TALER_CRYPTO_SignRequest *) hdr);
+ case TALER_HELPER_RSA_MT_REQ_REVOKE:
+ if (msize != sizeof (struct TALER_CRYPTO_RevokeRequest))
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
}
+ return handle_revoke_request (
+ client,
+ (const struct TALER_CRYPTO_RevokeRequest *) hdr);
+ default:
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
}
- if (0 == dk->rc)
- free_dk (dk);
}
-static void
-read_job (void *cls)
+/**
+ * Send our initial key set to @a client together with the
+ * "sync" terminator.
+ *
+ * @param client the client to inform
+ * @return #GNUNET_OK on success
+ */
+static enum GNUNET_GenericReturnValue
+rsa_client_init (struct TES_Client *client)
{
- struct Client *client = cls;
- char buf[65536];
- ssize_t buf_size;
- const struct GNUNET_MessageHeader *hdr;
- struct sockaddr_un addr;
- socklen_t addr_size = sizeof (addr);
-
- read_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
- unix_sock,
- &read_job,
- NULL);
- buf_size = GNUNET_NETWORK_socket_recvfrom (unix_sock,
- buf,
- sizeof (buf),
- (struct sockaddr *) &addr,
- &addr_size);
- if (-1 == buf_size)
- {
- GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
- "recv");
- return;
- }
- if (0 == buf_size)
- {
- return;
- }
- if (buf_size < sizeof (struct GNUNET_MessageHeader))
- {
- GNUNET_break_op (0);
- return;
- }
- hdr = (const struct GNUNET_MessageHeader *) buf;
- if (ntohs (hdr->size) != buf_size)
- {
- GNUNET_break_op (0);
- free_client (client);
- return;
+ GNUNET_assert (0 == pthread_mutex_lock (&keys_lock));
+ for (struct Denomination *denom = denom_head;
+ NULL != denom;
+ denom = denom->next)
+ {
+ for (struct DenominationKey *dk = denom->keys_head;
+ NULL != dk;
+ dk = dk->next)
+ {
+ if (GNUNET_OK !=
+ notify_client_dk_add (client,
+ dk))
+ {
+ GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Client %p must have disconnected\n",
+ client);
+ return GNUNET_SYSERR;
+ }
+ }
}
- switch (ntohs (hdr->type))
+ client->key_gen = key_gen;
+ GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
{
- case TALER_HELPER_RSA_MT_REQ_INIT:
- if (ntohs (hdr->size) != sizeof (struct GNUNET_MessageHeader))
+ struct GNUNET_MessageHeader synced = {
+ .type = htons (TALER_HELPER_RSA_SYNCED),
+ .size = htons (sizeof (synced))
+ };
+
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Sending RSA SYNCED message to %p\n",
+ client);
+ if (GNUNET_OK !=
+ TES_transmit (client->csock,
+ &synced))
{
- GNUNET_break_op (0);
- return;
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
}
+ }
+ return GNUNET_OK;
+}
+
+
+/**
+ * Notify @a client about all changes to the keys since
+ * the last generation known to the @a client.
+ *
+ * @param client the client to notify
+ * @return #GNUNET_OK on success
+ */
+static enum GNUNET_GenericReturnValue
+rsa_update_client_keys (struct TES_Client *client)
+{
+ GNUNET_assert (0 == pthread_mutex_lock (&keys_lock));
+ for (struct Denomination *denom = denom_head;
+ NULL != denom;
+ denom = denom->next)
+ {
+ for (struct DenominationKey *key = denom->keys_head;
+ NULL != key;
+ key = key->next)
{
- struct Client *client;
-
- client = GNUNET_new (struct Client);
- client->addr = addr;
- client->addr_size = addr_size;
- GNUNET_CONTAINER_DLL_insert (clients_head,
- clients_tail,
- client);
- for (struct Denomination *denom = denom_head;
- NULL != denom;
- denom = denom->next)
+ if (key->key_gen <= client->key_gen)
+ continue;
+ if (key->purge)
{
- for (struct DenominationKey *dk = denom->keys_head;
- NULL != dk;
- dk = dk->next)
+ if (GNUNET_OK !=
+ notify_client_dk_del (client,
+ key))
{
- if (GNUNET_OK !=
- notify_client_dk_add (client,
- dk))
- {
- /* client died, skip the rest */
- client = NULL;
- break;
- }
+ GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
+ return GNUNET_SYSERR;
}
- if (NULL == client)
- break;
}
- if (NULL != client)
+ else
{
- struct GNUNET_MessageHeader synced = {
- .type = htons (TALER_HELPER_RSA_SYNCED),
- .size = htons (sizeof (synced))
- };
-
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Sending RSA SYNCED message\n");
if (GNUNET_OK !=
- transmit (&client->addr,
- client->addr_size,
- &synced))
+ notify_client_dk_add (client,
+ key))
{
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Client %s must have disconnected\n",
- client->addr.sun_path);
- free_client (client);
+ GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
+ return GNUNET_SYSERR;
}
}
}
- break;
- case TALER_HELPER_RSA_MT_REQ_SIGN:
- if (ntohs (hdr->size) <= sizeof (struct TALER_CRYPTO_SignRequest))
- {
- GNUNET_break_op (0);
- return;
- }
- handle_sign_request (&addr,
- addr_size,
- (const struct TALER_CRYPTO_SignRequest *) buf);
- break;
- case TALER_HELPER_RSA_MT_REQ_REVOKE:
- if (ntohs (hdr->size) != sizeof (struct TALER_CRYPTO_RevokeRequest))
- {
- GNUNET_break_op (0);
- return;
- }
- handle_revoke_request (&addr,
- addr_size,
- (const struct TALER_CRYPTO_RevokeRequest *) buf);
- break;
- default:
- GNUNET_break_op (0);
- return;
}
+ client->key_gen = key_gen;
+ GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
+ return GNUNET_OK;
}
@@ -1147,7 +751,7 @@ read_job (void *cls)
* @param now current time to use (to get many keys to use the exact same time)
* @return #GNUNET_OK on success
*/
-static int
+static enum GNUNET_GenericReturnValue
create_key (struct Denomination *denom,
struct GNUNET_TIME_Absolute now)
{
@@ -1174,12 +778,12 @@ create_key (struct Denomination *denom,
setup_key (dk,
denom->keys_tail))
{
+ GNUNET_break (0);
GNUNET_free (dk);
GNUNET_SCHEDULER_shutdown ();
- global_ret = 42;
+ global_ret = EXIT_FAILURE;
return GNUNET_SYSERR;
}
-
return GNUNET_OK;
}
@@ -1195,72 +799,24 @@ create_key (struct Denomination *denom,
static struct GNUNET_TIME_Absolute
denomination_action_time (const struct Denomination *denom)
{
- if (NULL == denom->keys_head)
+ 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,
+ 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 (denom->keys_head->anchor,
+ GNUNET_TIME_absolute_add (head->anchor,
denom->duration_withdraw),
- GNUNET_TIME_absolute_subtract (
- GNUNET_TIME_absolute_subtract (
- GNUNET_TIME_absolute_add (denom->keys_tail->anchor,
- denom->duration_withdraw),
- lookahead_sign),
- overlap_duration));
-}
-
-
-/**
- * The withdraw period of a key @a dk has expired. Purge it.
- *
- * @param[in] dk expired denomination key to purge and free
- */
-static void
-purge_key (struct DenominationKey *dk)
-{
- struct Denomination *denom = dk->denom;
- struct Client *nxt;
-
- for (struct Client *client = clients_head;
- NULL != client;
- client = nxt)
- {
- nxt = client->next;
- if (GNUNET_OK !=
- notify_client_dk_del (client,
- dk))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Failed to notify client about purged key, client dropped\n");
- }
- }
- GNUNET_CONTAINER_DLL_remove (denom->keys_head,
- denom->keys_tail,
- dk);
- GNUNET_assert (GNUNET_OK ==
- GNUNET_CONTAINER_multihashmap_remove (keys,
- &dk->h_denom_pub.hash,
- dk));
- if (0 != unlink (dk->filename))
- {
- GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
- "unlink",
- dk->filename);
- }
- else
- {
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Purged expired private key `%s'\n",
- dk->filename);
- }
- GNUNET_free (dk->filename);
- if (0 != dk->rc)
- {
- /* delay until all signing threads are done with this key */
- dk->purge = true;
- return;
- }
- TALER_denom_priv_free (&dk->denom_priv);
- GNUNET_free (dk);
+ tt);
}
@@ -1271,37 +827,69 @@ purge_key (struct DenominationKey *dk)
*
* @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
*/
-static void
+static enum GNUNET_GenericReturnValue
update_keys (struct Denomination *denom,
- struct GNUNET_TIME_Absolute now)
+ struct GNUNET_TIME_Absolute now,
+ bool *wake)
{
/* create new denomination keys */
while ( (NULL == denom->keys_tail) ||
- (0 ==
- GNUNET_TIME_absolute_get_remaining (
- GNUNET_TIME_absolute_subtract (
- GNUNET_TIME_absolute_subtract (
- GNUNET_TIME_absolute_add (denom->keys_tail->anchor,
- denom->duration_withdraw),
- lookahead_sign),
- overlap_duration)).rel_value_us) )
+ GNUNET_TIME_absolute_is_past (
+ GNUNET_TIME_absolute_subtract (
+ GNUNET_TIME_absolute_subtract (
+ GNUNET_TIME_absolute_add (denom->keys_tail->anchor,
+ denom->duration_withdraw),
+ lookahead_sign),
+ overlap_duration)) )
+ {
+ if (! *wake)
+ {
+ key_gen++;
+ *wake = true;
+ }
if (GNUNET_OK !=
create_key (denom,
now))
{
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to create keys for `%s'\n",
- denom->section);
- return;
+ GNUNET_break (0);
+ global_ret = EXIT_FAILURE;
+ GNUNET_SCHEDULER_shutdown ();
+ return GNUNET_SYSERR;
}
+ }
/* remove expired denomination keys */
while ( (NULL != denom->keys_head) &&
- (0 ==
- GNUNET_TIME_absolute_get_remaining
- (GNUNET_TIME_absolute_add (denom->keys_head->anchor,
- denom->duration_withdraw)).rel_value_us) )
- purge_key (denom->keys_head);
+ GNUNET_TIME_absolute_is_past
+ (GNUNET_TIME_absolute_add (denom->keys_head->anchor,
+ denom->duration_withdraw)) )
+ {
+ struct DenominationKey *key = denom->keys_head;
+ struct DenominationKey *nxt = key->next;
+
+ if (0 != key->rc)
+ break; /* later */
+ GNUNET_CONTAINER_DLL_remove (denom->keys_head,
+ denom->keys_tail,
+ key);
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_CONTAINER_multihashmap_remove (
+ keys,
+ &key->h_denom_pub,
+ key));
+ if ( (! key->purge) &&
+ (0 != unlink (key->filename)) )
+ GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
+ "unlink",
+ key->filename);
+ GNUNET_free (key->filename);
+ GNUNET_CRYPTO_rsa_private_key_free (key->denom_priv.rsa_private_key);
+ GNUNET_CRYPTO_rsa_public_key_free (key->denom_pub.rsa_public_key);
+ GNUNET_free (key);
+ key = nxt;
+ }
/* Update position of 'denom' in #denom_head DLL: sort by action time */
{
@@ -1321,12 +909,12 @@ update_keys (struct Denomination *denom,
break;
before = pos;
}
-
GNUNET_CONTAINER_DLL_insert_after (denom_head,
denom_tail,
before,
denom);
}
+ return GNUNET_OK;
}
@@ -1340,16 +928,24 @@ update_denominations (void *cls)
{
struct Denomination *denom;
struct GNUNET_TIME_Absolute now;
+ bool wake = false;
(void) cls;
keygen_task = NULL;
now = GNUNET_TIME_absolute_get ();
(void) GNUNET_TIME_round_abs (&now);
+ GNUNET_assert (0 == pthread_mutex_lock (&keys_lock));
do {
denom = denom_head;
- update_keys (denom,
- now);
+ if (GNUNET_OK !=
+ update_keys (denom,
+ now,
+ &wake))
+ return;
} while (denom != denom_head);
+ GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
+ if (wake)
+ TES_wake_clients ();
keygen_task = GNUNET_SCHEDULER_add_at (denomination_action_time (denom),
&update_denominations,
NULL);
@@ -1370,7 +966,7 @@ parse_key (struct Denomination *denom,
const void *buf,
size_t buf_size)
{
- struct TALER_DenominationPrivateKey priv;
+ struct GNUNET_CRYPTO_RsaPrivateKey *priv;
char *anchor_s;
char dummy;
unsigned long long anchor_ll;
@@ -1405,11 +1001,9 @@ parse_key (struct Denomination *denom,
filename);
return;
}
- priv.cipher = TALER_DENOMINATION_RSA;
- priv.details.rsa_private_key
- = GNUNET_CRYPTO_rsa_private_key_decode (buf,
- buf_size);
- if (NULL == priv.details.rsa_private_key)
+ priv = GNUNET_CRYPTO_rsa_private_key_decode (buf,
+ buf_size);
+ if (NULL == priv)
{
/* Parser failure. */
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
@@ -1419,34 +1013,38 @@ parse_key (struct Denomination *denom,
}
{
- struct TALER_DenominationPublicKey pub;
+ struct GNUNET_CRYPTO_RsaPublicKey *pub;
struct DenominationKey *dk;
struct DenominationKey *before;
- TALER_denom_priv_to_pub (&priv,
- (struct TALER_AgeMask) { .mask = 0 }, /* FIXME-Oec */
- &pub);
+ pub = GNUNET_CRYPTO_rsa_private_key_get_public (priv);
+ if (NULL == pub)
+ {
+ GNUNET_break (0);
+ GNUNET_CRYPTO_rsa_private_key_free (priv);
+ return;
+ }
dk = GNUNET_new (struct DenominationKey);
- dk->denom_priv = priv;
+ dk->denom_priv.rsa_private_key = priv;
dk->denom = denom;
dk->anchor = anchor;
dk->filename = GNUNET_strdup (filename);
- TALER_denom_pub_hash (&pub,
- &dk->h_denom_pub);
- dk->denom_pub = pub;
+ GNUNET_CRYPTO_rsa_public_key_hash (pub,
+ &dk->h_denom_pub);
+ dk->denom_pub.rsa_public_key = pub;
if (GNUNET_OK !=
GNUNET_CONTAINER_multihashmap_put (
keys,
- &dk->h_denom_pub.hash,
+ &dk->h_denom_pub,
dk,
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Duplicate private key %s detected in file `%s'. Skipping.\n",
- GNUNET_h2s (&dk->h_denom_pub.hash),
+ GNUNET_h2s (&dk->h_denom_pub),
filename);
- TALER_denom_priv_free (&priv);
- TALER_denom_pub_free (&pub);
+ GNUNET_CRYPTO_rsa_private_key_free (priv);
+ GNUNET_CRYPTO_rsa_public_key_free (pub);
GNUNET_free (dk);
return;
}
@@ -1465,7 +1063,7 @@ parse_key (struct Denomination *denom,
dk);
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Imported key %s from `%s'\n",
- GNUNET_h2s (&dk->h_denom_pub.hash),
+ GNUNET_h2s (&dk->h_denom_pub),
filename);
}
}
@@ -1477,8 +1075,9 @@ parse_key (struct Denomination *denom,
*
* @param[in,out] cls a `struct Denomiantion`
* @param filename name of a file in the directory
+ * @return #GNUNET_OK (always, continue to iterate)
*/
-static int
+static enum GNUNET_GenericReturnValue
import_key (void *cls,
const char *filename)
{
@@ -1591,18 +1190,20 @@ import_key (void *cls,
* Parse configuration for denomination type parameters. Also determines
* our anchor by looking at the existing denominations of the same type.
*
+ * @param cfg configuration to use
* @param ct section in the configuration file giving the denomination type parameters
* @param[out] denom set to the denomination parameters from the configuration
* @return #GNUNET_OK on success, #GNUNET_SYSERR if the configuration is invalid
*/
-static int
-parse_denomination_cfg (const char *ct,
+static enum GNUNET_GenericReturnValue
+parse_denomination_cfg (const struct GNUNET_CONFIGURATION_Handle *cfg,
+ const char *ct,
struct Denomination *denom)
{
unsigned long long rsa_keysize;
if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_time (kcfg,
+ GNUNET_CONFIGURATION_get_value_time (cfg,
ct,
"DURATION_WITHDRAW",
&denom->duration_withdraw))
@@ -1623,7 +1224,7 @@ parse_denomination_cfg (const char *ct,
return GNUNET_SYSERR;
}
if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_number (kcfg,
+ GNUNET_CONFIGURATION_get_value_number (cfg,
ct,
"RSA_KEYSIZE",
&rsa_keysize))
@@ -1653,6 +1254,12 @@ parse_denomination_cfg (const char *ct,
*/
struct LoadContext
{
+
+ /**
+ * Configuration to use.
+ */
+ const struct GNUNET_CONFIGURATION_Handle *cfg;
+
/**
* Current time to use.
*/
@@ -1661,7 +1268,7 @@ struct LoadContext
/**
* Status, to be set to #GNUNET_SYSERR on failure
*/
- int ret;
+ enum GNUNET_GenericReturnValue ret;
};
@@ -1678,6 +1285,7 @@ load_denominations (void *cls,
{
struct LoadContext *ctx = cls;
struct Denomination *denom;
+ bool wake;
if ( (0 != strncasecmp (denomination_alias,
"coin_",
@@ -1688,7 +1296,8 @@ load_denominations (void *cls,
return; /* not a denomination type definition */
denom = GNUNET_new (struct Denomination);
if (GNUNET_OK !=
- parse_denomination_cfg (denomination_alias,
+ parse_denomination_cfg (ctx->cfg,
+ denomination_alias,
denom))
{
ctx->ret = GNUNET_SYSERR;
@@ -1716,20 +1325,22 @@ load_denominations (void *cls,
denom_tail,
denom);
update_keys (denom,
- ctx->now);
+ ctx->now,
+ &wake);
}
/**
- * Load the various duration values from #kcfg.
+ * Load the various duration values from @a cfg
*
+ * @param cfg configuration to use
* @return #GNUNET_OK on success
*/
-static int
-load_durations (void)
+static enum GNUNET_GenericReturnValue
+load_durations (const struct GNUNET_CONFIGURATION_Handle *cfg)
{
if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_time (kcfg,
+ GNUNET_CONFIGURATION_get_value_time (cfg,
"taler-exchange-secmod-rsa",
"OVERLAP_DURATION",
&overlap_duration))
@@ -1742,7 +1353,7 @@ load_durations (void)
GNUNET_TIME_round_rel (&overlap_duration);
if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_time (kcfg,
+ GNUNET_CONFIGURATION_get_value_time (cfg,
"taler-exchange-secmod-rsa",
"LOOKAHEAD_SIGN",
&lookahead_sign))
@@ -1766,51 +1377,12 @@ static void
do_shutdown (void *cls)
{
(void) cls;
- if (NULL != read_task)
- {
- GNUNET_SCHEDULER_cancel (read_task);
- read_task = NULL;
- }
- if (NULL != unix_sock)
- {
- GNUNET_break (GNUNET_OK ==
- GNUNET_NETWORK_socket_close (unix_sock));
- unix_sock = NULL;
- }
- if (0 != unlink (unixpath))
- {
- GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
- "unlink",
- unixpath);
- }
- GNUNET_free (unixpath);
+ TES_listen_stop ();
if (NULL != keygen_task)
{
GNUNET_SCHEDULER_cancel (keygen_task);
keygen_task = NULL;
}
- if (NULL != done_task)
- {
- GNUNET_SCHEDULER_cancel (done_task);
- done_task = NULL;
- }
- /* shut down worker threads */
- if (NULL != workers)
- {
- GNUNET_assert (0 == pthread_mutex_lock (&work_lock));
- in_shutdown = true;
- GNUNET_assert (0 == pthread_cond_broadcast (&work_cond));
- GNUNET_assert (0 == pthread_mutex_unlock (&work_lock));
- for (unsigned int i = 0; i<num_workers; i++)
- GNUNET_assert (0 == pthread_join (workers[i],
- NULL));
- }
- if (NULL != done_signal)
- {
- GNUNET_break (GNUNET_OK ==
- GNUNET_NETWORK_socket_close (done_signal));
- done_signal = NULL;
- }
}
@@ -1828,10 +1400,14 @@ run (void *cls,
const char *cfgfile,
const struct GNUNET_CONFIGURATION_Handle *cfg)
{
+ static struct TES_Callbacks cb = {
+ .dispatch = rsa_work_dispatch,
+ .updater = rsa_update_client_keys,
+ .init = rsa_client_init
+ };
(void) cls;
(void) args;
(void) cfgfile;
- kcfg = cfg;
if (now.abs_value_us != now_tmp.abs_value_us)
{
/* The user gave "--now", use it! */
@@ -1843,48 +1419,8 @@ run (void *cls,
now = GNUNET_TIME_absolute_get ();
}
GNUNET_TIME_round_abs (&now);
-
- {
- char *pfn;
-
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_filename (kcfg,
- "taler-exchange-secmod-rsa",
- "SM_PRIV_KEY",
- &pfn))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
- "taler-exchange-secmod-rsa",
- "SM_PRIV_KEY");
- global_ret = 1;
- return;
- }
- if (GNUNET_SYSERR ==
- GNUNET_CRYPTO_eddsa_key_from_file (pfn,
- GNUNET_YES,
- &smpriv.eddsa_priv))
- {
- GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
- "taler-exchange-secmod-rsa",
- "SM_PRIV_KEY",
- "Could not use file to persist private key");
- GNUNET_free (pfn);
- global_ret = 1;
- return;
- }
- GNUNET_free (pfn);
- GNUNET_CRYPTO_eddsa_key_get_public (&smpriv.eddsa_priv,
- &smpub.eddsa_pub);
- }
-
if (GNUNET_OK !=
- load_durations ())
- {
- global_ret = 1;
- return;
- }
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_filename (kcfg,
+ GNUNET_CONFIGURATION_get_value_filename (cfg,
"taler-exchange-secmod-rsa",
"KEY_DIR",
&keydir))
@@ -1892,92 +1428,41 @@ run (void *cls,
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
"taler-exchange-secmod-rsa",
"KEY_DIR");
- global_ret = 1;
+ global_ret = EXIT_NOTCONFIGURED;
return;
}
-
- /* Create client directory and set permissions. */
- {
- char *client_dir;
-
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_filename (kcfg,
- "taler-exchange-secmod-rsa",
- "CLIENT_DIR",
- &client_dir))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
- "taler-exchange-secmod-rsa",
- "CLIENT_DIR");
- global_ret = 3;
- return;
- }
-
- if (GNUNET_OK != GNUNET_DISK_directory_create (client_dir))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Can't create client directory (%s)\n",
- client_dir);
- global_ret = 3;
- return;
- }
- /* Set sticky group bit, so that clients will be writeable by the current service. */
- if (0 != chmod (client_dir,
- S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP
- | S_ISGID))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Can't set permissions for client directory (%s)\n",
- client_dir);
- global_ret = 3;
- return;
- }
-
- GNUNET_free (client_dir);
- }
-
if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_filename (kcfg,
- "taler-exchange-secmod-rsa",
- "UNIXPATH",
- &unixpath))
+ load_durations (cfg))
{
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
- "taler-exchange-secmod-rsa",
- "UNIXPATH");
- global_ret = 3;
+ global_ret = EXIT_NOTCONFIGURED;
return;
}
-
- GNUNET_assert (NULL != unixpath);
- unix_sock = TES_open_socket (unixpath);
-
- if (NULL == unix_sock)
- {
- GNUNET_free (unixpath);
- global_ret = 2;
+ global_ret = TES_listen_start (cfg,
+ "taler-exchange-secmod-rsa",
+ &cb);
+ if (0 != global_ret)
return;
- }
-
GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
NULL);
-
/* Load denominations */
keys = GNUNET_CONTAINER_multihashmap_create (65536,
GNUNET_YES);
{
struct LoadContext lc = {
+ .cfg = cfg,
.ret = GNUNET_OK,
- .now = GNUNET_TIME_absolute_get ()
+ .now = now
};
(void) GNUNET_TIME_round_abs (&lc.now);
- GNUNET_CONFIGURATION_iterate_sections (kcfg,
+ GNUNET_assert (0 == pthread_mutex_lock (&keys_lock));
+ GNUNET_CONFIGURATION_iterate_sections (cfg,
&load_denominations,
&lc);
+ GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
if (GNUNET_OK != lc.ret)
{
- global_ret = 4;
+ global_ret = EXIT_FAILURE;
GNUNET_SCHEDULER_shutdown ();
return;
}
@@ -1986,60 +1471,16 @@ run (void *cls,
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"No denominations configured\n");
- global_ret = 5;
+ global_ret = EXIT_NOTCONFIGURED;
GNUNET_SCHEDULER_shutdown ();
return;
}
-
- /* start job to accept incoming requests on 'sock' */
- read_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
- unix_sock,
- &read_job,
- NULL);
- /* start job to keep keys up-to-date; MUST be run before the #read_task,
+ /* start job to keep keys up-to-date; MUST be run before the #listen_task,
hence with priority. */
keygen_task = GNUNET_SCHEDULER_add_with_priority (
GNUNET_SCHEDULER_PRIORITY_URGENT,
&update_denominations,
NULL);
-
- /* start job to handle completed work */
- {
- int fd;
-
- fd = eventfd (0,
- EFD_NONBLOCK | EFD_CLOEXEC);
- if (-1 == fd)
- {
- GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
- "eventfd");
- global_ret = 6;
- GNUNET_SCHEDULER_shutdown ();
- return;
- }
- done_signal = GNUNET_NETWORK_socket_box_native (fd);
- }
- done_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
- done_signal,
- &handle_done,
- NULL);
-
- /* start crypto workers */
- if (0 == num_workers)
- num_workers = sysconf (_SC_NPROCESSORS_CONF);
- if (0 == num_workers)
- num_workers = 1;
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Starting %u crypto workers\n",
- num_workers);
- workers = GNUNET_new_array (num_workers,
- pthread_t);
- for (unsigned int i = 0; i<num_workers; i++)
- GNUNET_assert (0 ==
- pthread_create (&workers[i],
- NULL,
- &sign_worker,
- NULL));
}
@@ -2057,11 +1498,6 @@ main (int argc,
struct GNUNET_GETOPT_CommandLineOption options[] = {
GNUNET_GETOPT_option_timetravel ('T',
"timetravel"),
- GNUNET_GETOPT_option_uint ('p',
- "parallelism",
- "NUM_WORKERS",
- "number of worker threads to use",
- &num_workers),
GNUNET_GETOPT_option_absolute_time ('t',
"time",
"TIMESTAMP",
@@ -2069,7 +1505,7 @@ main (int argc,
&now_tmp),
GNUNET_GETOPT_OPTION_END
};
- int ret;
+ enum GNUNET_GenericReturnValue ret;
/* Restrict permissions for the key files that we create. */
(void) umask (S_IWGRP | S_IROTH | S_IWOTH | S_IXOTH);
@@ -2086,8 +1522,8 @@ main (int argc,
&run,
NULL);
if (GNUNET_NO == ret)
- return 0;
+ return EXIT_SUCCESS;
if (GNUNET_SYSERR == ret)
- return 1;
+ return EXIT_INVALIDARGUMENT;
return global_ret;
}
diff --git a/src/util/taler-exchange-secmod-rsa.h b/src/util/taler-exchange-secmod-rsa.h
index cf439e261..146b6948f 100644
--- a/src/util/taler-exchange-secmod-rsa.h
+++ b/src/util/taler-exchange-secmod-rsa.h
@@ -102,7 +102,7 @@ struct TALER_CRYPTO_RsaKeyPurgeNotification
/**
* Hash of the public key of the purged RSA key.
*/
- struct TALER_DenominationHash h_denom_pub;
+ struct GNUNET_HashCode h_denom_pub;
};
@@ -125,7 +125,7 @@ struct TALER_CRYPTO_SignRequest
/**
* Hash of the public key of the RSA key to use for the signature.
*/
- struct TALER_DenominationHash h_denom_pub;
+ struct GNUNET_HashCode h_denom_pub;
/* followed by message to sign */
};
@@ -149,7 +149,7 @@ struct TALER_CRYPTO_RevokeRequest
/**
* Hash of the public key of the revoked RSA key.
*/
- struct TALER_DenominationHash h_denom_pub;
+ struct GNUNET_HashCode h_denom_pub;
};
diff --git a/src/util/test_helper_eddsa.c b/src/util/test_helper_eddsa.c
index 4b44f6041..48c14491a 100644
--- a/src/util/test_helper_eddsa.c
+++ b/src/util/test_helper_eddsa.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- (C) 2020 Taler Systems SA
+ (C) 2020, 2021 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
@@ -36,7 +36,7 @@
/**
* How many iterations of the successful signing test should we run
- * during the benchmark phase?
+ * during the test phase?
*/
#define NUM_SIGN_TESTS 3
@@ -46,6 +46,11 @@
*/
#define NUM_SIGN_PERFS 100
+/**
+ * How many parallel clients should we use for the parallel
+ * benchmark? (> 500 may cause problems with the max open FD number limit).
+ */
+#define NUM_CORES 8
/**
* Number of keys currently in #keys.
@@ -270,7 +275,8 @@ test_signing (struct TALER_CRYPTO_ExchangeSignHelper *esh)
* @return 0 on success
*/
static int
-perf_signing (struct TALER_CRYPTO_ExchangeSignHelper *esh)
+perf_signing (struct TALER_CRYPTO_ExchangeSignHelper *esh,
+ const char *type)
{
struct GNUNET_CRYPTO_EccSignaturePurpose purpose = {
.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TEST),
@@ -303,8 +309,69 @@ perf_signing (struct TALER_CRYPTO_ExchangeSignHelper *esh)
delay);
} /* for j */
fprintf (stderr,
- "%u (sequential) signature operations took %s\n",
- (unsigned int) NUM_SIGN_TESTS,
+ "%u (%s) signature operations took %s\n",
+ (unsigned int) NUM_SIGN_PERFS,
+ type,
+ GNUNET_STRINGS_relative_time_to_string (duration,
+ GNUNET_YES));
+ return 0;
+}
+
+
+/**
+ * Parallel signing logic.
+ *
+ * @param esh handle to the helper
+ * @return 0 on success
+ */
+static int
+par_signing (struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+ struct GNUNET_TIME_Absolute start;
+ struct GNUNET_TIME_Relative duration;
+ pid_t pids[NUM_CORES];
+ struct TALER_CRYPTO_ExchangeSignHelper *esh;
+
+ memset (keys,
+ 0,
+ sizeof (keys));
+ num_keys = 0;
+ start = GNUNET_TIME_absolute_get ();
+ for (unsigned int i = 0; i<NUM_CORES; i++)
+ {
+ pids[i] = fork ();
+ GNUNET_assert (-1 != pids[i]);
+ if (0 == pids[i])
+ {
+ int ret;
+
+ esh = TALER_CRYPTO_helper_esign_connect (cfg,
+ &key_cb,
+ NULL);
+ if (NULL == esh)
+ {
+ GNUNET_break (0);
+ exit (EXIT_FAILURE);
+ }
+ ret = perf_signing (esh,
+ "parallel");
+ TALER_CRYPTO_helper_esign_disconnect (esh);
+ exit (ret);
+ }
+ }
+ for (unsigned int i = 0; i<NUM_CORES; i++)
+ {
+ int wstatus;
+
+ GNUNET_assert (pids[i] ==
+ waitpid (pids[i],
+ &wstatus,
+ 0));
+ }
+ duration = GNUNET_TIME_absolute_get_duration (start);
+ fprintf (stderr,
+ "%u (parallel) signature operations took %s (total real time)\n",
+ (unsigned int) NUM_SIGN_PERFS * NUM_CORES,
GNUNET_STRINGS_relative_time_to_string (duration,
GNUNET_YES));
return 0;
@@ -319,10 +386,10 @@ run_test (void)
{
struct GNUNET_CONFIGURATION_Handle *cfg;
struct TALER_CRYPTO_ExchangeSignHelper *esh;
+ int ret;
struct timespec req = {
.tv_nsec = 250000000
};
- int ret;
cfg = GNUNET_CONFIGURATION_create ();
if (GNUNET_OK !=
@@ -334,54 +401,47 @@ run_test (void)
}
/* wait for helper to start and give us keys */
- fprintf (stderr, "Waiting for helper client directory to become available ");
- for (unsigned int i = 0; i<1000; i++)
+ fprintf (stderr, "Waiting for helper to start ... ");
+ for (unsigned int i = 0; i<100; i++)
{
+ nanosleep (&req,
+ NULL);
esh = TALER_CRYPTO_helper_esign_connect (cfg,
&key_cb,
NULL);
if (NULL != esh)
break;
- nanosleep (&req, NULL);
fprintf (stderr, ".");
}
- GNUNET_CONFIGURATION_destroy (cfg);
if (NULL == esh)
{
- GNUNET_break (0);
+ fprintf (stderr,
+ "\nFAILED: timeout trying to connect to helper\n");
+ GNUNET_CONFIGURATION_destroy (cfg);
return 1;
}
- fprintf (stderr, " done.\n");
-
- /* wait for helper to start and give us keys */
- fprintf (stderr, "Waiting for helper to start ");
- for (unsigned int i = 0; i<1000; i++)
- {
- TALER_CRYPTO_helper_esign_poll (esh);
- if (0 != num_keys)
- break;
- nanosleep (&req, NULL);
- fprintf (stderr, ".");
- }
if (0 == num_keys)
{
fprintf (stderr,
- "\nFAILED: timeout trying to connect to helper\n");
+ "\nFAILED: no keys returend by helper\n");
TALER_CRYPTO_helper_esign_disconnect (esh);
+ GNUNET_CONFIGURATION_destroy (cfg);
return 1;
}
fprintf (stderr,
- "\nOK: Helper ready (%u keys)\n",
+ " Done (%u keys)\n",
num_keys);
-
ret = 0;
if (0 == ret)
ret = test_revocation (esh);
if (0 == ret)
ret = test_signing (esh);
if (0 == ret)
- ret = perf_signing (esh);
+ ret = perf_signing (esh,
+ "sequential");
TALER_CRYPTO_helper_esign_disconnect (esh);
+ if (0 == ret)
+ ret = par_signing (cfg);
/* clean up our state */
for (unsigned int i = 0; i<MAX_KEYS; i++)
if (keys[i].valid)
@@ -390,6 +450,7 @@ run_test (void)
GNUNET_assert (num_keys > 0);
num_keys--;
}
+ GNUNET_CONFIGURATION_destroy (cfg);
return ret;
}
@@ -408,7 +469,7 @@ main (int argc,
(void) argc;
(void) argv;
GNUNET_log_setup ("test-helper-eddsa",
- "INFO",
+ "WARNING",
NULL);
GNUNET_OS_init (TALER_project_data_default ());
libexec_dir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_BINDIR);
@@ -424,7 +485,7 @@ main (int argc,
"-c",
"test_helper_eddsa.conf",
"-L",
- "INFO",
+ "WARNING",
NULL);
if (NULL == helper)
{
diff --git a/src/util/test_helper_rsa.c b/src/util/test_helper_rsa.c
index e4c0bf6fd..97844001d 100644
--- a/src/util/test_helper_rsa.c
+++ b/src/util/test_helper_rsa.c
@@ -22,11 +22,12 @@
#include "taler_util.h"
/**
- * Configuration has 1 minute duration and 5 minutes lookahead, so
- * we should never have more than 6 active keys, plus for during
- * key expiration / revocation.
+ * Configuration has 1 minute duration and 5 minutes lookahead, but
+ * we do not get 'revocations' for expired keys. So this must be
+ * large enough to deal with key rotation during the runtime of
+ * the benchmark.
*/
-#define MAX_KEYS 7
+#define MAX_KEYS 1024
/**
* How many random key revocations should we test?
@@ -38,6 +39,17 @@
*/
#define NUM_SIGN_TESTS 5
+/**
+ * How many iterations of the successful signing test should we run
+ * during the benchmark phase?
+ */
+#define NUM_SIGN_PERFS 100
+
+/**
+ * How many parallel clients should we use for the parallel
+ * benchmark? (> 500 may cause problems with the max open FD number limit).
+ */
+#define NUM_CORES 8
/**
* Number of keys currently in #keys.
@@ -62,7 +74,7 @@ struct KeyData
/**
* Hash of the public key.
*/
- struct TALER_DenominationHash h_denom_pub;
+ struct GNUNET_HashCode h_denom_pub;
/**
* Full public key.
@@ -110,7 +122,7 @@ key_cb (void *cls,
const char *section_name,
struct GNUNET_TIME_Absolute start_time,
struct GNUNET_TIME_Relative validity_duration,
- const struct TALER_DenominationHash *h_denom_pub,
+ const struct GNUNET_HashCode *h_denom_pub,
const struct TALER_DenominationPublicKey *denom_pub,
const struct TALER_SecurityModulePublicKeyP *sm_pub,
const struct TALER_SecurityModuleSignatureP *sm_sig)
@@ -119,7 +131,7 @@ key_cb (void *cls,
(void) sm_sig;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Key notification about key %s in `%s'\n",
- GNUNET_h2s (&h_denom_pub->hash),
+ GNUNET_h2s (h_denom_pub),
section_name);
if (0 == validity_duration.rel_value_us)
{
@@ -133,7 +145,8 @@ key_cb (void *cls,
{
keys[i].valid = false;
keys[i].revoked = false;
- TALER_denom_pub_free (&keys[i].denom_pub);
+ GNUNET_CRYPTO_rsa_public_key_free (keys[i].denom_pub.rsa_public_key);
+ keys[i].denom_pub.rsa_public_key = NULL;
GNUNET_assert (num_keys > 0);
num_keys--;
found = true;
@@ -154,9 +167,8 @@ key_cb (void *cls,
keys[i].h_denom_pub = *h_denom_pub;
keys[i].start_time = start_time;
keys[i].validity_duration = validity_duration;
- keys[i].denom_pub = *denom_pub;
- TALER_denom_pub_deep_copy (&keys[i].denom_pub,
- denom_pub);
+ keys[i].denom_pub.rsa_public_key
+ = GNUNET_CRYPTO_rsa_public_key_dup (denom_pub->rsa_public_key);
num_keys++;
return;
}
@@ -199,7 +211,7 @@ test_revocation (struct TALER_CRYPTO_DenominationHelper *dh)
keys[j].revoked = true;
fprintf (stderr,
"Revoking key %s ...",
- GNUNET_h2s (&keys[j].h_denom_pub.hash));
+ GNUNET_h2s (&keys[j].h_denom_pub));
TALER_CRYPTO_helper_denom_revoke (dh,
&keys[j].h_denom_pub);
for (unsigned int k = 0; k<1000; k++)
@@ -235,35 +247,42 @@ test_revocation (struct TALER_CRYPTO_DenominationHelper *dh)
static int
test_signing (struct TALER_CRYPTO_DenominationHelper *dh)
{
- struct TALER_BlindedDenominationSignature ds;
+ struct TALER_DenominationSignature ds;
enum TALER_ErrorCode ec;
bool success = false;
- struct TALER_PlanchetSecretsP ps;
- struct TALER_CoinPubHash c_hash;
-
- TALER_planchet_setup_random (&ps);
+ struct GNUNET_HashCode m_hash;
+ struct GNUNET_CRYPTO_RsaBlindingKeySecret bks;
+
+ GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
+ &bks,
+ sizeof (bks));
+ GNUNET_CRYPTO_hash ("Hello",
+ strlen ("Hello"),
+ &m_hash);
for (unsigned int i = 0; i<MAX_KEYS; i++)
{
if (! keys[i].valid)
continue;
{
- struct TALER_PlanchetDetail pd;
+ void *buf;
+ size_t buf_size;
GNUNET_assert (GNUNET_YES ==
- TALER_planchet_prepare (&keys[i].denom_pub,
- &ps,
- &c_hash,
- &pd));
+ TALER_rsa_blind (&m_hash,
+ &bks,
+ keys[i].denom_pub.rsa_public_key,
+ &buf,
+ &buf_size));
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Requesting signature over %u bytes with key %s\n",
- (unsigned int) pd.coin_ev_size,
- GNUNET_h2s (&keys[i].h_denom_pub.hash));
+ (unsigned int) buf_size,
+ GNUNET_h2s (&keys[i].h_denom_pub));
ds = TALER_CRYPTO_helper_denom_sign (dh,
&keys[i].h_denom_pub,
- pd.coin_ev,
- pd.coin_ev_size,
+ buf,
+ buf_size,
&ec);
- GNUNET_free (pd.coin_ev);
+ GNUNET_free (buf);
}
switch (ec)
{
@@ -283,33 +302,32 @@ test_signing (struct TALER_CRYPTO_DenominationHelper *dh)
return 5;
}
{
- struct TALER_DenominationSignature rs;
+ struct GNUNET_CRYPTO_RsaSignature *rs;
- if (GNUNET_OK !=
- TALER_denom_sig_unblind (&rs,
- &ds,
- &ps.blinding_key,
- &keys[i].denom_pub))
+ rs = TALER_rsa_unblind (ds.rsa_signature,
+ &bks,
+ keys[i].denom_pub.rsa_public_key);
+ if (NULL == rs)
{
GNUNET_break (0);
return 6;
}
- TALER_blinded_denom_sig_free (&ds);
+ GNUNET_CRYPTO_rsa_signature_free (ds.rsa_signature);
if (GNUNET_OK !=
- TALER_denom_pub_verify (&keys[i].denom_pub,
- &rs,
- &c_hash))
+ GNUNET_CRYPTO_rsa_verify (&m_hash,
+ rs,
+ keys[i].denom_pub.rsa_public_key))
{
/* signature invalid */
GNUNET_break (0);
- TALER_denom_sig_free (&rs);
+ GNUNET_CRYPTO_rsa_signature_free (rs);
return 7;
}
- TALER_denom_sig_free (&rs);
+ GNUNET_CRYPTO_rsa_signature_free (rs);
}
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Received valid signature for key %s\n",
- GNUNET_h2s (&keys[i].h_denom_pub.hash));
+ GNUNET_h2s (&keys[i].h_denom_pub));
success = true;
break;
case TALER_EC_EXCHANGE_DENOMINATION_HELPER_TOO_EARLY:
@@ -344,24 +362,27 @@ test_signing (struct TALER_CRYPTO_DenominationHelper *dh)
/* check signing does not work if the key is unknown */
{
- struct TALER_DenominationHash rnd;
+ struct GNUNET_HashCode rnd;
+ struct TALER_DenominationSignature ds;
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
&rnd,
sizeof (rnd));
- (void) TALER_CRYPTO_helper_denom_sign (dh,
- &rnd,
- "Hello",
- strlen ("Hello"),
- &ec);
+ ds = TALER_CRYPTO_helper_denom_sign (dh,
+ &rnd,
+ "Hello",
+ strlen ("Hello"),
+ &ec);
if (TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN != ec)
{
+ if (TALER_EC_NONE == ec)
+ GNUNET_CRYPTO_rsa_signature_free (ds.rsa_signature);
GNUNET_break (0);
return 17;
}
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Signing with invalid key %s failed as desired\n",
- GNUNET_h2s (&rnd.hash));
+ GNUNET_h2s (&rnd));
}
return 0;
}
@@ -374,18 +395,25 @@ test_signing (struct TALER_CRYPTO_DenominationHelper *dh)
* @return 0 on success
*/
static int
-perf_signing (struct TALER_CRYPTO_DenominationHelper *dh)
+perf_signing (struct TALER_CRYPTO_DenominationHelper *dh,
+ const char *type)
{
- struct TALER_BlindedDenominationSignature ds;
+ struct TALER_DenominationSignature ds;
enum TALER_ErrorCode ec;
+ struct GNUNET_HashCode m_hash;
+ struct GNUNET_CRYPTO_RsaBlindingKeySecret bks;
struct GNUNET_TIME_Relative duration;
- struct TALER_PlanchetSecretsP ps;
- TALER_planchet_setup_random (&ps);
+ GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
+ &bks,
+ sizeof (bks));
+ GNUNET_CRYPTO_hash ("Hello",
+ strlen ("Hello"),
+ &m_hash);
duration = GNUNET_TIME_UNIT_ZERO;
- for (unsigned int j = 0; j<NUM_SIGN_TESTS;)
+ TALER_CRYPTO_helper_denom_poll (dh);
+ for (unsigned int j = 0; j<NUM_SIGN_PERFS;)
{
- TALER_CRYPTO_helper_denom_poll (dh);
for (unsigned int i = 0; i<MAX_KEYS; i++)
{
if (! keys[i].valid)
@@ -397,14 +425,15 @@ perf_signing (struct TALER_CRYPTO_DenominationHelper *dh)
keys[i].validity_duration.rel_value_us)
continue;
{
- struct TALER_CoinPubHash c_hash;
- struct TALER_PlanchetDetail pd;
+ void *buf;
+ size_t buf_size;
GNUNET_assert (GNUNET_YES ==
- TALER_planchet_prepare (&keys[i].denom_pub,
- &ps,
- &c_hash,
- &pd));
+ TALER_rsa_blind (&m_hash,
+ &bks,
+ keys[i].denom_pub.rsa_public_key,
+ &buf,
+ &buf_size));
/* use this key as long as it works */
while (1)
{
@@ -413,26 +442,83 @@ perf_signing (struct TALER_CRYPTO_DenominationHelper *dh)
ds = TALER_CRYPTO_helper_denom_sign (dh,
&keys[i].h_denom_pub,
- pd.coin_ev,
- pd.coin_ev_size,
+ buf,
+ buf_size,
&ec);
if (TALER_EC_NONE != ec)
break;
delay = GNUNET_TIME_absolute_get_duration (start);
duration = GNUNET_TIME_relative_add (duration,
delay);
- TALER_blinded_denom_sig_free (&ds);
+ GNUNET_CRYPTO_rsa_signature_free (ds.rsa_signature);
j++;
- if (NUM_SIGN_TESTS == j)
+ if (NUM_SIGN_PERFS <= j)
break;
}
- GNUNET_free (pd.coin_ev);
+ GNUNET_free (buf);
}
} /* for i */
} /* for j */
fprintf (stderr,
- "%u (sequential) signature operations took %s\n",
- (unsigned int) NUM_SIGN_TESTS,
+ "%u (%s) signature operations took %s\n",
+ (unsigned int) NUM_SIGN_PERFS,
+ type,
+ GNUNET_STRINGS_relative_time_to_string (duration,
+ GNUNET_YES));
+ return 0;
+}
+
+
+/**
+ * Parallel signing logic.
+ *
+ * @param esh handle to the helper
+ * @return 0 on success
+ */
+static int
+par_signing (struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+ struct GNUNET_TIME_Absolute start;
+ struct GNUNET_TIME_Relative duration;
+ pid_t pids[NUM_CORES];
+ struct TALER_CRYPTO_DenominationHelper *dh;
+
+ start = GNUNET_TIME_absolute_get ();
+ for (unsigned int i = 0; i<NUM_CORES; i++)
+ {
+ pids[i] = fork ();
+ memset (keys,
+ 0,
+ sizeof (keys));
+ num_keys = 0;
+ GNUNET_assert (-1 != pids[i]);
+ if (0 == pids[i])
+ {
+ int ret;
+
+ dh = TALER_CRYPTO_helper_denom_connect (cfg,
+ &key_cb,
+ NULL);
+ GNUNET_assert (NULL != dh);
+ ret = perf_signing (dh,
+ "parallel");
+ TALER_CRYPTO_helper_denom_disconnect (dh);
+ exit (ret);
+ }
+ }
+ for (unsigned int i = 0; i<NUM_CORES; i++)
+ {
+ int wstatus;
+
+ GNUNET_assert (pids[i] ==
+ waitpid (pids[i],
+ &wstatus,
+ 0));
+ }
+ duration = GNUNET_TIME_absolute_get_duration (start);
+ fprintf (stderr,
+ "%u (parallel) signature operations took %s (total real time)\n",
+ (unsigned int) NUM_SIGN_PERFS * NUM_CORES,
GNUNET_STRINGS_relative_time_to_string (duration,
GNUNET_YES));
return 0;
@@ -461,62 +547,57 @@ run_test (void)
return 77;
}
- fprintf (stderr, "Waiting for helper client directory to become available ");
- for (unsigned int i = 0; i<1000; i++)
+ fprintf (stderr, "Waiting for helper to start ... ");
+ for (unsigned int i = 0; i<100; i++)
{
+ nanosleep (&req,
+ NULL);
dh = TALER_CRYPTO_helper_denom_connect (cfg,
&key_cb,
NULL);
if (NULL != dh)
break;
- nanosleep (&req, NULL);
fprintf (stderr, ".");
}
- GNUNET_CONFIGURATION_destroy (cfg);
if (NULL == dh)
{
- GNUNET_break (0);
+ fprintf (stderr,
+ "\nFAILED: timeout trying to connect to helper\n");
+ GNUNET_CONFIGURATION_destroy (cfg);
return 1;
}
- fprintf (stderr, " done.\n");
-
- /* wait for helper to start and give us keys */
- fprintf (stderr, "Waiting for helper to start ");
- for (unsigned int i = 0; i<1000; i++)
- {
- TALER_CRYPTO_helper_denom_poll (dh);
- if (0 != num_keys)
- break;
- nanosleep (&req, NULL);
- fprintf (stderr, ".");
- }
if (0 == num_keys)
{
fprintf (stderr,
"\nFAILED: timeout trying to connect to helper\n");
TALER_CRYPTO_helper_denom_disconnect (dh);
+ GNUNET_CONFIGURATION_destroy (cfg);
return 1;
}
fprintf (stderr,
- "\nOK: Helper ready (%u keys)\n",
+ " Done (%u keys)\n",
num_keys);
-
ret = 0;
if (0 == ret)
ret = test_revocation (dh);
if (0 == ret)
ret = test_signing (dh);
if (0 == ret)
- ret = perf_signing (dh);
+ ret = perf_signing (dh,
+ "sequential");
TALER_CRYPTO_helper_denom_disconnect (dh);
+ if (0 == ret)
+ ret = par_signing (cfg);
/* clean up our state */
for (unsigned int i = 0; i<MAX_KEYS; i++)
if (keys[i].valid)
{
- TALER_denom_pub_free (&keys[i].denom_pub);
+ GNUNET_CRYPTO_rsa_public_key_free (keys[i].denom_pub.rsa_public_key);
+ keys[i].denom_pub.rsa_public_key = NULL;
GNUNET_assert (num_keys > 0);
num_keys--;
}
+ GNUNET_CONFIGURATION_destroy (cfg);
return ret;
}
@@ -535,7 +616,7 @@ main (int argc,
(void) argc;
(void) argv;
GNUNET_log_setup ("test-helper-rsa",
- "INFO",
+ "WARNING",
NULL);
GNUNET_OS_init (TALER_project_data_default ());
libexec_dir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_BINDIR);
@@ -551,7 +632,7 @@ main (int argc,
"-c",
"test_helper_rsa.conf",
"-L",
- "INFO",
+ "WARNING",
NULL);
if (NULL == helper)
{