This commit is contained in:
Christian Grothoff 2021-11-17 13:03:47 +01:00
parent 0f5fc95ecf
commit 6e86a3c43c
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
7 changed files with 1339 additions and 2162 deletions

View File

@ -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)
{
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;
}
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)

View File

@ -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;
const struct TALER_TESTING_Command *ret;
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;
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,7 +341,6 @@ 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);
@ -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,

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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;
};

View File

@ -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)
{

View File

@ -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;
struct GNUNET_HashCode m_hash;
struct GNUNET_CRYPTO_RsaBlindingKeySecret bks;
TALER_planchet_setup_random (&ps);
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,
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;)
{
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)
{