gnunet-svn
[Top][All Lists]
Advanced

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

[taler-exchange] 18/37: implement TALER_CRYPTO_helper_cs_r_derive and re


From: gnunet
Subject: [taler-exchange] 18/37: implement TALER_CRYPTO_helper_cs_r_derive and related tests
Date: Fri, 04 Feb 2022 16:53:48 +0100

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

gian-demarmels pushed a commit to branch master
in repository exchange.

commit 106664ed0c50621bd20568c948ad30fccd0689ea
Author: Lucien Heuzeveldt <lucienclaude.heuzeveldt@students.bfh.ch>
AuthorDate: Tue Jan 4 17:26:01 2022 +0100

    implement TALER_CRYPTO_helper_cs_r_derive and related tests
---
 src/include/taler_crypto_lib.h      |  28 +++++-
 src/util/crypto_helper_cs.c         | 195 ++++++++++++++++++++++++++++++++++++
 src/util/taler-exchange-secmod-cs.c |   3 +-
 src/util/test_helper_cs.c           | 132 +++++++++++++++++++++++-
 4 files changed, 353 insertions(+), 5 deletions(-)

diff --git a/src/include/taler_crypto_lib.h b/src/include/taler_crypto_lib.h
index bd889b35..a20e5120 100644
--- a/src/include/taler_crypto_lib.h
+++ b/src/include/taler_crypto_lib.h
@@ -1800,7 +1800,7 @@ TALER_CRYPTO_helper_cs_sign (
 
 
 /**
- * Ask the helper to revoke the public key associated with @param h_denom_pub .
+ * Ask the helper to revoke the public key associated with @param h_cs .
  * Will cause the helper to tell all clients that the key is now unavailable,
  * and to create a replacement key.
  *
@@ -1812,7 +1812,7 @@ TALER_CRYPTO_helper_cs_sign (
  * callback.
  *
  * @param dh helper to process connection
- * @param h_rsa hash of the RSA public key to revoke
+ * @param h_cs hash of the CS public key to revoke
  */
 void
 TALER_CRYPTO_helper_cs_revoke (
@@ -1820,6 +1820,30 @@ TALER_CRYPTO_helper_cs_revoke (
   const struct TALER_CsPubHashP *h_cs);
 
 
+/**
+ * Ask the helper to derive R using the @param nonce and denomination key
+ * associated with @param h_cs.
+ *
+ * This operation will block until the R has been obtained.  Should
+ * this process receive a signal (that is not ignored) while the operation is
+ * pending, the operation will fail.  Note that the helper may still believe
+ * that it created the signature. Thus, signals may result in a small
+ * differences in the signature counters.  Retrying in this case may work.
+ *
+ * @param dh helper to process connection
+ * @param h_cs hash of the CS public key to revoke
+ * @param nonce witdhraw nonce
+ * @param[out] ec set to the error code (or #TALER_EC_NONE on success)
+ * @return R, the value inside the structure will be NULL on failure,
+ *         see @a ec for details about the failure
+ */
+struct TALER_DenominationCsPublicR
+TALER_CRYPTO_helper_cs_r_derive (struct TALER_CRYPTO_CsDenominationHelper *dh,
+                                 const struct TALER_CsPubHashP *h_cs,
+                                 const struct TALER_WithdrawNonce *nonce,
+                                 enum TALER_ErrorCode *ec);
+
+
 /**
  * Close connection to @a dh.
  *
diff --git a/src/util/crypto_helper_cs.c b/src/util/crypto_helper_cs.c
index 95050a1f..5b299934 100644
--- a/src/util/crypto_helper_cs.c
+++ b/src/util/crypto_helper_cs.c
@@ -633,6 +633,201 @@ TALER_CRYPTO_helper_cs_revoke (
 }
 
 
+struct TALER_DenominationCsPublicR
+TALER_CRYPTO_helper_cs_r_derive (struct TALER_CRYPTO_CsDenominationHelper *dh,
+                                 const struct TALER_CsPubHashP *h_cs,
+                                 const struct TALER_WithdrawNonce *nonce,
+                                 enum TALER_ErrorCode *ec)
+{
+  struct TALER_DenominationCsPublicR r_pub;
+
+  memset (&r_pub,
+          0,
+          sizeof (r_pub));
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Starting R derivation process\n");
+  if (GNUNET_OK !=
+      try_connect (dh))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Failed to connect to helper\n");
+    *ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
+    return r_pub;
+  }
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Requesting R\n");
+  {
+    struct TALER_CRYPTO_CsRDeriveRequest rdr;
+
+    rdr.header.size = htons (sizeof (rdr));
+    rdr.header.type = htons (TALER_HELPER_CS_MT_REQ_RDERIVE);
+    rdr.reserved = htonl (0);
+    rdr.h_cs = *h_cs;
+    rdr.nonce = *nonce;
+    if (GNUNET_OK !=
+        TALER_crypto_helper_send_all (dh->sock,
+                                      &rdr,
+                                      sizeof (rdr)))
+    {
+      GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
+                           "send");
+      do_disconnect (dh);
+      *ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
+      return r_pub;
+    }
+  }
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Awaiting reply\n");
+  {
+    char buf[UINT16_MAX];
+    size_t off = 0;
+    const struct GNUNET_MessageHeader *hdr
+      = (const struct GNUNET_MessageHeader *) buf;
+    bool finished = false;
+
+    *ec = TALER_EC_INVALID;
+    while (1)
+    {
+      uint16_t msize;
+      ssize_t ret;
+
+      ret = recv (dh->sock,
+                  &buf[off],
+                  sizeof (buf) - off,
+                  (finished && (0 == off))
+                  ? MSG_DONTWAIT
+                  : 0);
+      if (ret < 0)
+      {
+        if (EINTR == errno)
+          continue;
+        if (EAGAIN == errno)
+        {
+          GNUNET_assert (finished);
+          GNUNET_assert (0 == off);
+          return r_pub;
+        }
+        GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
+                             "recv");
+        do_disconnect (dh);
+        *ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
+        break;
+      }
+      if (0 == ret)
+      {
+        GNUNET_break (0 == off);
+        if (! finished)
+          *ec = TALER_EC_EXCHANGE_SIGNKEY_HELPER_BUG;
+        return r_pub;
+      }
+      off += ret;
+more:
+      if (off < sizeof (struct GNUNET_MessageHeader))
+        continue;
+      msize = ntohs (hdr->size);
+      if (off < msize)
+        continue;
+      switch (ntohs (hdr->type))
+      {
+      case TALER_HELPER_CS_MT_RES_RDERIVE:
+        if (msize != sizeof (struct TALER_CRYPTO_RDeriveResponse))
+        {
+          GNUNET_break_op (0);
+          do_disconnect (dh);
+          *ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
+          goto end;
+        }
+        if (finished)
+        {
+          GNUNET_break_op (0);
+          do_disconnect (dh);
+          *ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
+          goto end;
+        }
+        {
+          const struct TALER_CRYPTO_RDeriveResponse *rdr =
+            (const struct TALER_CRYPTO_RDeriveResponse *) buf;
+
+          GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                      "Received R\n");
+          *ec = TALER_EC_NONE;
+          finished = true;
+          r_pub = rdr->r_pub;
+          break;
+        }
+      case TALER_HELPER_CS_MT_RES_RDERIVE_FAILURE:
+        if (msize != sizeof (struct TALER_CRYPTO_RDeriveFailure))
+        {
+          GNUNET_break_op (0);
+          do_disconnect (dh);
+          *ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
+          goto end;
+        }
+        {
+          const struct TALER_CRYPTO_RDeriveFailure *rdf =
+            (const struct TALER_CRYPTO_RDeriveFailure *) buf;
+
+          *ec = (enum TALER_ErrorCode) ntohl (rdf->ec);
+          GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                      "R derivation failed!\n");
+          finished = true;
+          break;
+        }
+      case TALER_HELPER_CS_MT_AVAIL:
+        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                    "Received new key!\n");
+        if (GNUNET_OK !=
+            handle_mt_avail (dh,
+                             hdr))
+        {
+          GNUNET_break_op (0);
+          do_disconnect (dh);
+          *ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
+          goto end;
+        }
+        break; /* while(1) loop ensures we recvfrom() again */
+      case TALER_HELPER_CS_MT_PURGE:
+        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                    "Received revocation!\n");
+        if (GNUNET_OK !=
+            handle_mt_purge (dh,
+                             hdr))
+        {
+          GNUNET_break_op (0);
+          do_disconnect (dh);
+          *ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
+          goto end;
+        }
+        break; /* while(1) loop ensures we recvfrom() again */
+      case TALER_HELPER_CS_SYNCED:
+        GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                    "Synchronized add odd time with CS helper!\n");
+        dh->synced = true;
+        break;
+      default:
+        GNUNET_break_op (0);
+        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                    "Received unexpected message of type %u\n",
+                    ntohs (hdr->type));
+        do_disconnect (dh);
+        *ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
+        goto end;
+      }
+      memmove (buf,
+               &buf[msize],
+               off - msize);
+      off -= msize;
+      goto more;
+    } /* while(1) */
+end:
+    return r_pub;
+  }
+}
+
+
 void
 TALER_CRYPTO_helper_cs_disconnect (
   struct TALER_CRYPTO_CsDenominationHelper *dh)
diff --git a/src/util/taler-exchange-secmod-cs.c 
b/src/util/taler-exchange-secmod-cs.c
index 14f0a5d1..0df7c3dd 100644
--- a/src/util/taler-exchange-secmod-cs.c
+++ b/src/util/taler-exchange-secmod-cs.c
@@ -618,7 +618,6 @@ handle_r_derive_request (struct TES_Client *client,
                          &rdf.header);
   }
 
-  // TODO: print nonce too?
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               "Received request to derive R with key %s\n",
               GNUNET_h2s (&rdr->h_cs.hash));
@@ -692,7 +691,7 @@ cs_work_dispatch (struct TES_Client *client,
     return handle_revoke_request (
       client,
       (const struct TALER_CRYPTO_CsRevokeRequest *) hdr);
-  case TALER_HELPER_CS_MT_RES_RDERIVE:
+  case TALER_HELPER_CS_MT_REQ_RDERIVE:
     if (msize != sizeof (struct TALER_CRYPTO_CsRDeriveRequest))
     {
       GNUNET_break_op (0);
diff --git a/src/util/test_helper_cs.c b/src/util/test_helper_cs.c
index 41d363fd..d59c2163 100644
--- a/src/util/test_helper_cs.c
+++ b/src/util/test_helper_cs.c
@@ -255,6 +255,133 @@ test_revocation (struct TALER_CRYPTO_CsDenominationHelper 
*dh)
 }
 
 
+/**
+ * Test R derivation logic.
+ *
+ * @param dh handle to the helper
+ * @return 0 on success
+ */
+static int
+test_r_derive (struct TALER_CRYPTO_CsDenominationHelper *dh)
+{
+  struct TALER_DenominationCsPublicR r_pub;
+  enum TALER_ErrorCode ec;
+  bool success = false;
+  struct TALER_PlanchetSecretsP ps;
+  struct TALER_CoinPubHash c_hash;
+
+  TALER_planchet_setup_random (&ps, TALER_DENOMINATION_RSA);
+  for (unsigned int i = 0; i<MAX_KEYS; i++)
+  {
+    if (! keys[i].valid)
+      continue;
+    // TODO: insert assertion into other checks
+    GNUNET_assert (TALER_DENOMINATION_CS == keys[i].denom_pub.cipher);
+    {
+      struct TALER_PlanchetDetail pd;
+      pd.blinded_planchet.cipher = TALER_DENOMINATION_CS;
+
+      TALER_cs_withdraw_nonce_derive (&ps.coin_priv,
+                                      &pd.blinded_planchet.details.
+                                      cs_blinded_planchet.nonce);
+      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                  "Requesting R derivation with key %s\n",
+                  GNUNET_h2s (&keys[i].h_cs.hash));
+      r_pub = TALER_CRYPTO_helper_cs_r_derive (dh,
+                                               &keys[i].h_cs,
+                                               &pd.blinded_planchet.details.
+                                               cs_blinded_planchet.nonce,
+                                               &ec);
+    }
+    switch (ec)
+    {
+    case TALER_EC_NONE:
+      if (GNUNET_TIME_relative_cmp (GNUNET_TIME_absolute_get_remaining (
+                                      keys[i].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[i].start_time.abs_time),
+                                    >,
+                                    keys[i].validity_duration))
+      {
+        /* key worked too later */
+        GNUNET_break (0);
+        return 5;
+      }
+
+      // since R is part of the signature creation process, it can't be tested 
fully here
+      // instead it will be further tested in the signature creation process
+      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                  "Received valid R for key %s\n",
+                  GNUNET_h2s (&keys[i].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[i].start_time.abs_time))) &&
+           (GNUNET_TIME_relative_cmp (
+              GNUNET_TIME_absolute_get_duration (
+                keys[i].start_time.abs_time),
+              <,
+              keys[i].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 R derivation does not work if the key is unknown */
+  {
+    struct TALER_CsPubHashP rnd;
+    struct TALER_WithdrawNonce nonce;
+
+    GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
+                                &rnd,
+                                sizeof (rnd));
+    GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
+                                &nonce,
+                                sizeof (nonce));
+    r_pub = TALER_CRYPTO_helper_cs_r_derive (dh,
+                                             &rnd,
+                                             &nonce,
+                                             &ec);
+    if (TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN != ec)
+    {
+      GNUNET_break (0);
+      return 17;
+    }
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "R derivation with invalid key %s failed as desired\n",
+                GNUNET_h2s (&rnd.hash));
+  }
+  return 0;
+}
+
+
 /**
  * Test signing logic.
  *
@@ -600,9 +727,11 @@ run_test (void)
            " Done (%u keys)\n",
            num_keys);
   ret = 0;
-  // TODO: implement other tests
   if (0 == ret)
     ret = test_revocation (dh);
+  if (0 == ret)
+    ret = test_r_derive (dh);
+  // TODO: implement other tests
   // if (0 == ret)
   //   ret = test_signing (dh);
   // if (0 == ret)
@@ -685,6 +814,7 @@ main (int argc,
                 (int) code);
     ret = 5;
   }
+  // TODO: remove
   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
               "I am here");
   GNUNET_OS_process_destroy (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]