gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-exchange] branch master updated: add test for batch CS derive/sig


From: gnunet
Subject: [taler-exchange] branch master updated: add test for batch CS derive/sign logic
Date: Sun, 13 Nov 2022 21:45:45 +0100

This is an automated email from the git hooks/post-receive script.

grothoff pushed a commit to branch master
in repository exchange.

The following commit(s) were added to refs/heads/master by this push:
     new 231cdaf4 add test for batch CS derive/sign logic
231cdaf4 is described below

commit 231cdaf4f777165c3858d737f0b7b799d39758ce
Author: Christian Grothoff <christian@grothoff.org>
AuthorDate: Sun Nov 13 21:45:43 2022 +0100

    add test for batch CS derive/sign logic
---
 src/util/taler-exchange-secmod-cs.c  |  78 ++++++++----
 src/util/taler-exchange-secmod-rsa.c |   3 +
 src/util/test_helper_cs.c            | 238 ++++++++++++++++++++++++++++++++++-
 3 files changed, 290 insertions(+), 29 deletions(-)

diff --git a/src/util/taler-exchange-secmod-cs.c 
b/src/util/taler-exchange-secmod-cs.c
index 13148a16..231a8cd8 100644
--- a/src/util/taler-exchange-secmod-cs.c
+++ b/src/util/taler-exchange-secmod-cs.c
@@ -512,6 +512,28 @@ fail_sign (struct TES_Client *client,
 }
 
 
+/**
+ * Generate error response that deriving failed.
+ *
+ * @param client client to send response to
+ * @param ec error code to include
+ * @return #GNUNET_OK on success
+ */
+static enum GNUNET_GenericReturnValue
+fail_derive (struct TES_Client *client,
+             enum TALER_ErrorCode ec)
+{
+  struct TALER_CRYPTO_RDeriveFailure sf = {
+    .header.size = htons (sizeof (sf)),
+    .header.type = htons (TALER_HELPER_CS_MT_RES_RDERIVE_FAILURE),
+    .ec = htonl (ec)
+  };
+
+  return TES_transmit (client->csock,
+                       &sf.header);
+}
+
+
 /**
  * Generate signature response.
  *
@@ -842,19 +864,25 @@ finish_job (struct TES_Client *client,
 {
   sem_down (&bj->sem);
   sem_done (&bj->sem);
-  if (TALER_EC_NONE != bj->ec)
-  {
-    fail_sign (client,
-               bj->ec);
-    return;
-  }
   switch (bj->type)
   {
   case TYPE_SIGN:
+    if (TALER_EC_NONE != bj->ec)
+    {
+      fail_sign (client,
+                 bj->ec);
+      return;
+    }
     send_signature (client,
                     &bj->details.sign.cs_answer);
     break;
   case TYPE_RDERIVE:
+    if (TALER_EC_NONE != bj->ec)
+    {
+      fail_derive (client,
+                   bj->ec);
+      return;
+    }
     send_derivation (client,
                      &bj->details.rderive.rpairp);
     break;
@@ -878,16 +906,19 @@ handle_batch_sign_request (struct TES_Client *client,
   uint16_t size = ntohs (bsr->header.size) - sizeof (*bsr);
   const void *off = (const void *) &bsr[1];
   unsigned int idx = 0;
-  struct BatchJob jobs[bs];
+  struct BatchJob jobs[GNUNET_NZL (bs)];
   bool failure = false;
 
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Handling batch sign request of size %u\n",
+              (unsigned int) bs);
   if (bs > TALER_MAX_FRESH_COINS)
   {
     GNUNET_break_op (0);
     return GNUNET_SYSERR;
   }
   while ( (bs > 0) &&
-          (size > sizeof (struct TALER_CRYPTO_CsSignRequestMessage)) )
+          (size >= sizeof (struct TALER_CRYPTO_CsSignRequestMessage)) )
   {
     const struct TALER_CRYPTO_CsSignRequestMessage *sr = off;
     uint16_t s = ntohs (sr->header.size);
@@ -903,6 +934,9 @@ handle_batch_sign_request (struct TES_Client *client,
     off += s;
     size -= s;
   }
+  GNUNET_break_op (0 == size);
+  bs = GNUNET_MIN (bs,
+                   idx);
   for (unsigned int i = 0; i<bs; i++)
     finish_job (client,
                 &jobs[i]);
@@ -941,13 +975,16 @@ handle_batch_derive_request (struct TES_Client *client,
   struct BatchJob jobs[bs];
   bool failure = false;
 
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Handling batch derivation request of size %u\n",
+              (unsigned int) bs);
   if (bs > TALER_MAX_FRESH_COINS)
   {
     GNUNET_break_op (0);
     return GNUNET_SYSERR;
   }
   while ( (bs > 0) &&
-          (size > sizeof (struct TALER_CRYPTO_CsRDeriveRequest)) )
+          (size >= sizeof (struct TALER_CRYPTO_CsRDeriveRequest)) )
   {
     const struct TALER_CRYPTO_CsRDeriveRequest *rdr = off;
     uint16_t s = ntohs (rdr->header.size);
@@ -964,20 +1001,17 @@ handle_batch_derive_request (struct TES_Client *client,
     off += s;
     size -= s;
   }
+  GNUNET_break_op (0 == size);
+  bs = GNUNET_MIN (bs,
+                   idx);
   for (unsigned int i = 0; i<bs; i++)
     finish_job (client,
                 &jobs[i]);
   if (failure)
   {
-    struct TALER_CRYPTO_SignFailure sf = {
-      .header.size = htons (sizeof (sf)),
-      .header.type = htons (TALER_HELPER_CS_MT_RES_BATCH_RDERIVE_FAILURE),
-      .ec = htonl (TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE)
-    };
-
     GNUNET_break (0);
-    return TES_transmit (client->csock,
-                         &sf.header);
+    return fail_derive (client,
+                        TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE);
   }
   return GNUNET_OK;
 }
@@ -1219,14 +1253,8 @@ handle_r_derive_request (struct TES_Client *client,
                   &r_pub);
   if (TALER_EC_NONE != ec)
   {
-    struct TALER_CRYPTO_RDeriveFailure rdf = {
-      .header.size = htons (sizeof (rdf)),
-      .header.type = htons (TALER_HELPER_CS_MT_RES_RDERIVE_FAILURE),
-      .ec = htonl (ec)
-    };
-
-    return TES_transmit (client->csock,
-                         &rdf.header);
+    return fail_derive (client,
+                        ec);
   }
 
   ret = send_derivation (client,
diff --git a/src/util/taler-exchange-secmod-rsa.c 
b/src/util/taler-exchange-secmod-rsa.c
index 779e1252..d5106c8a 100644
--- a/src/util/taler-exchange-secmod-rsa.c
+++ b/src/util/taler-exchange-secmod-rsa.c
@@ -766,6 +766,9 @@ handle_batch_sign_request (struct TES_Client *client,
     off += s;
     size -= s;
   }
+  GNUNET_break_op (0 == size);
+  bs = GNUNET_MIN (bs,
+                   idx);
   for (unsigned int i = 0; i<bs; i++)
     finish_job (client,
                 &jobs[i]);
diff --git a/src/util/test_helper_cs.c b/src/util/test_helper_cs.c
index 7c57d50c..fdfc5c36 100644
--- a/src/util/test_helper_cs.c
+++ b/src/util/test_helper_cs.c
@@ -439,8 +439,6 @@ test_signing (struct TALER_CRYPTO_CsDenominationHelper *dh)
       };
 
       pd.blinded_planchet.cipher = TALER_DENOMINATION_CS;
-      // keys[i].denom_pub.cipher = TALER_DENOMINATION_CS;
-
       TALER_cs_withdraw_nonce_derive (&ps,
                                       &pd.blinded_planchet.details.
                                       cs_blinded_planchet.nonce);
@@ -592,6 +590,209 @@ test_signing (struct TALER_CRYPTO_CsDenominationHelper 
*dh)
 }
 
 
+/**
+ * Test batch signing logic.
+ *
+ * @param dh handle to the helper
+ * @param batch_size how large should the batch be
+ * @param check_sigs also check unknown key and signatures
+ * @return 0 on success
+ */
+static int
+test_batch_signing (struct TALER_CRYPTO_CsDenominationHelper *dh,
+                    unsigned int batch_size,
+                    bool check_sigs)
+{
+  struct TALER_BlindedDenominationSignature ds[batch_size];
+  enum TALER_ErrorCode ec;
+  bool success = false;
+  struct TALER_PlanchetMasterSecretP ps[batch_size];
+  struct TALER_CoinSpendPrivateKeyP coin_priv[batch_size];
+  union TALER_DenominationBlindingKeyP bks[batch_size];
+  struct TALER_CoinPubHashP c_hash[batch_size];
+  struct TALER_ExchangeWithdrawValues alg_values[batch_size];
+
+  for (unsigned int i = 0; i<batch_size; i++)
+    TALER_planchet_master_setup_random (&ps[i]);
+  for (unsigned int k = 0; k<MAX_KEYS; k++)
+  {
+    if (! keys[k].valid)
+      continue;
+    {
+      struct TALER_PlanchetDetail pd[batch_size];
+      struct TALER_CRYPTO_CsSignRequest csr[batch_size];
+      struct TALER_CRYPTO_CsDeriveRequest cdr[batch_size];
+      struct TALER_DenominationCSPublicRPairP crps[batch_size];
+
+      for (unsigned int i = 0; i<batch_size; i++)
+      {
+        cdr[i].h_cs = &keys[k].h_cs;
+        cdr[i].nonce =
+          &pd[i].blinded_planchet.details.cs_blinded_planchet.nonce;
+        pd[i].blinded_planchet.cipher = TALER_DENOMINATION_CS;
+        TALER_cs_withdraw_nonce_derive (
+          &ps[i],
+          &pd[i].blinded_planchet.details.cs_blinded_planchet.nonce);
+        alg_values[i].cipher = TALER_DENOMINATION_CS;
+      }
+      ec = TALER_CRYPTO_helper_cs_r_batch_derive_withdraw (
+        dh,
+        cdr,
+        batch_size,
+        crps);
+      if (TALER_EC_NONE != ec)
+        continue;
+      for (unsigned int i = 0; i<batch_size; i++)
+      {
+        alg_values[i].details.cs_values = crps[i];
+        TALER_planchet_setup_coin_priv (&ps[i],
+                                        &alg_values[i],
+                                        &coin_priv[i]);
+        TALER_planchet_blinding_secret_create (&ps[i],
+                                               &alg_values[i],
+                                               &bks[i]);
+        GNUNET_assert (GNUNET_YES ==
+                       TALER_planchet_prepare (&keys[k].denom_pub,
+                                               &alg_values[i],
+                                               &bks[i],
+                                               &coin_priv[i],
+                                               NULL, /* no age commitment */
+                                               &c_hash[i],
+                                               &pd[i]));
+        GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                    "Requesting signature with key %s\n",
+                    GNUNET_h2s (&keys[k].h_cs.hash));
+        csr[i].h_cs = &keys[k].h_cs;
+        csr[i].blinded_planchet
+          = &pd[i].blinded_planchet.details.cs_blinded_planchet;
+      }
+      ec = TALER_CRYPTO_helper_cs_batch_sign_withdraw (
+        dh,
+        csr,
+        batch_size,
+        ds);
+    }
+    switch (ec)
+    {
+    case TALER_EC_NONE:
+      if (GNUNET_TIME_relative_cmp (GNUNET_TIME_absolute_get_remaining (
+                                      keys[k].start_time.abs_time),
+                                    >,
+                                    GNUNET_TIME_UNIT_SECONDS))
+      {
+        /* key worked too early */
+        GNUNET_break (0);
+        return 4;
+      }
+      if (GNUNET_TIME_relative_cmp (GNUNET_TIME_absolute_get_duration (
+                                      keys[k].start_time.abs_time),
+                                    >,
+                                    keys[k].validity_duration))
+      {
+        /* key worked too later */
+        GNUNET_break (0);
+        return 5;
+      }
+      if (check_sigs)
+      {
+        for (unsigned int i = 0; i<batch_size; i++)
+        {
+          struct TALER_FreshCoin coin;
+
+          if (GNUNET_OK !=
+              TALER_planchet_to_coin (&keys[k].denom_pub,
+                                      &ds[i],
+                                      &bks[i],
+                                      &coin_priv[i],
+                                      NULL, /* no age commitment */
+                                      &c_hash[i],
+                                      &alg_values[i],
+                                      &coin))
+          {
+            GNUNET_break (0);
+            return 6;
+          }
+        }
+        GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                    "Received valid signature for key %s\n",
+                    GNUNET_h2s (&keys[k].h_cs.hash));
+      }
+      success = true;
+      break;
+    case TALER_EC_EXCHANGE_DENOMINATION_HELPER_TOO_EARLY:
+      /* This 'failure' is expected, we're testing also for the
+         error handling! */
+      if ( (GNUNET_TIME_relative_is_zero (
+              GNUNET_TIME_absolute_get_remaining (
+                keys[k].start_time.abs_time))) &&
+           (GNUNET_TIME_relative_cmp (
+              GNUNET_TIME_absolute_get_duration (
+                keys[k].start_time.abs_time),
+              <,
+              keys[k].validity_duration)) )
+      {
+        /* key should have worked! */
+        GNUNET_break (0);
+        return 6;
+      }
+      break;
+    default:
+      /* unexpected error */
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Unexpected error %d\n",
+                  ec);
+      return 7;
+    }
+  }
+  if (! success)
+  {
+    /* no valid key for signing found, also bad */
+    GNUNET_break (0);
+    return 16;
+  }
+
+  /* check signing does not work if the key is unknown */
+  if (check_sigs)
+  {
+    struct TALER_PlanchetDetail pd;
+    struct TALER_CsPubHashP rnd;
+    struct TALER_CRYPTO_CsSignRequest csr;
+
+    GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
+                                &rnd,
+                                sizeof (rnd));
+    pd.blinded_planchet.cipher = TALER_DENOMINATION_CS;
+    GNUNET_assert (GNUNET_YES ==
+                   TALER_planchet_prepare (&keys[0].denom_pub,
+                                           &alg_values[0],
+                                           &bks[0],
+                                           &coin_priv[0],
+                                           NULL, /* no age commitment */
+                                           &c_hash[0],
+                                           &pd));
+    csr.h_cs = &rnd;
+    csr.blinded_planchet
+      = &pd.blinded_planchet.details.cs_blinded_planchet;
+    ec = TALER_CRYPTO_helper_cs_batch_sign_withdraw (
+      dh,
+      &csr,
+      1,
+      &ds[0]);
+    if (TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN != ec)
+    {
+      if (TALER_EC_NONE == ec)
+        TALER_blinded_denom_sig_free (ds);
+      GNUNET_break (0);
+      return 17;
+    }
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Signing with invalid key %s failed as desired\n",
+                GNUNET_h2s (&rnd.hash));
+  }
+  return 0;
+}
+
+
 /**
  * Benchmark signing logic.
  *
@@ -812,6 +1013,34 @@ run_test (void)
     ret = test_r_derive (dh);
   if (0 == ret)
     ret = test_signing (dh);
+  if (0 == ret)
+    ret = test_batch_signing (dh,
+                              2,
+                              true);
+  if (0 == ret)
+    ret = test_batch_signing (dh,
+                              256,
+                              true);
+  for (unsigned int i = 0; i<5; i++)
+  {
+    static unsigned int batches[] = { 1, 4, 16, 64, 256 };
+    unsigned int batch_size = batches[i];
+    struct GNUNET_TIME_Absolute start;
+    struct GNUNET_TIME_Relative duration;
+
+    start = GNUNET_TIME_absolute_get ();
+    if (0 != ret)
+      break;
+    ret = test_batch_signing (dh,
+                              batch_size,
+                              false);
+    duration = GNUNET_TIME_absolute_get_duration (start);
+    fprintf (stderr,
+             "%4u (batch) signature operations took %s (total real time)\n",
+             (unsigned int) batch_size,
+             GNUNET_STRINGS_relative_time_to_string (duration,
+                                                     GNUNET_YES));
+  }
   if (0 == ret)
     ret = perf_signing (dh,
                         "sequential");
@@ -835,13 +1064,14 @@ main (int argc,
   int ret;
   enum GNUNET_OS_ProcessStatusType type;
   unsigned long code;
+  const char *loglev = "WARNING";
 
   (void) argc;
   (void) argv;
   unsetenv ("XDG_DATA_HOME");
   unsetenv ("XDG_CONFIG_HOME");
   GNUNET_log_setup ("test-helper-cs",
-                    "WARNING",
+                    loglev,
                     NULL);
   GNUNET_OS_init (TALER_project_data_default ());
   libexec_dir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_BINDIR);
@@ -857,7 +1087,7 @@ main (int argc,
                                     "-c",
                                     "test_helper_cs.conf",
                                     "-L",
-                                    "WARNING",
+                                    loglev,
                                     NULL);
   if (NULL == helper)
   {

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]