gnunet-svn
[Top][All Lists]
Advanced

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

[taler-exchange] branch master updated: [age restriction] progress 18/n


From: gnunet
Subject: [taler-exchange] branch master updated: [age restriction] progress 18/n - attestation tested
Date: Thu, 03 Mar 2022 19:39:22 +0100

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

oec pushed a commit to branch master
in repository exchange.

The following commit(s) were added to refs/heads/master by this push:
     new 4c53d42e [age restriction] progress 18/n - attestation tested
4c53d42e is described below

commit 4c53d42e44cbab55194b2f0fb71ffc3cb082b56a
Author: Özgür Kesim <oec-taler@kesim.org>
AuthorDate: Thu Mar 3 19:35:24 2022 +0100

    [age restriction] progress 18/n - attestation tested
    
    - Unit-tests for commit, derive, attest and verify added, with multiple
      combinations of minimum age and commited age.
    - Fixed crypto implementation (eddsa -> ecdsa)
    - Using now standard functionality from GNUNET:
      GNUNET_CRYPTO_ecdsa_{private,public}_key_derive
    
    All tests pass (unit tests in util/ and 'make check' in testing).
---
 .gitignore                                         |   1 +
 .../taler-exchange-httpd_refreshes_reveal.c        |   4 +-
 src/include/taler_crypto_lib.h                     |  14 +-
 src/lib/exchange_api_refreshes_reveal.c            |   9 +-
 src/util/Makefile.am                               |   6 +
 src/util/age_restriction.c                         | 229 +++++++--------------
 src/util/test_age_restriction.c                    | 135 ++++++++++++
 7 files changed, 235 insertions(+), 163 deletions(-)

diff --git a/.gitignore b/.gitignore
index 9fbf5b05..ace3682e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -88,6 +88,7 @@ src/wire-plugins/test_wire_plugin
 src/wire-plugins/test_wire_plugin_transactions_taler_bank
 src/pq/test_pq
 src/sq/test_sq
+src/util/test_age_restriction
 src/util/test_amount
 src/util/test_crypto
 src/util/test_json
diff --git a/src/exchange/taler-exchange-httpd_refreshes_reveal.c 
b/src/exchange/taler-exchange-httpd_refreshes_reveal.c
index caba557c..d5cb2e47 100644
--- a/src/exchange/taler-exchange-httpd_refreshes_reveal.c
+++ b/src/exchange/taler-exchange-httpd_refreshes_reveal.c
@@ -620,14 +620,14 @@ resolve_refreshes_reveal_denominations (struct 
MHD_Connection *connection,
     oac = rctx->old_age_commitment;
     oac->mask  =  TEH_age_mask;
     oac->num = ng;
-    oac->pub = GNUNET_new_array (ng, struct TALER_AgeCommitmentPublicKeyP);
+    oac->keys = GNUNET_new_array (ng, struct TALER_AgeCommitmentPublicKeyP);
 
     /* Extract old age commitment */
     for (unsigned int i = 0; i< ng; i++)
     {
       struct GNUNET_JSON_Specification ac_spec[] = {
         GNUNET_JSON_spec_fixed_auto (NULL,
-                                     &oac->pub[i]),
+                                     &oac->keys[i]),
         GNUNET_JSON_spec_end ()
       };
 
diff --git a/src/include/taler_crypto_lib.h b/src/include/taler_crypto_lib.h
index ea1a73af..e114ef83 100644
--- a/src/include/taler_crypto_lib.h
+++ b/src/include/taler_crypto_lib.h
@@ -339,9 +339,9 @@ struct TALER_CoinSpendPrivateKeyP
 struct TALER_AgeCommitmentPrivateKeyP
 {
   /**
-   * Taler uses EdDSA for coins when signing age verification attestation.
+   * Taler uses EcDSA for coins when signing age verification attestation.
    */
-  struct GNUNET_CRYPTO_EddsaPrivateKey eddsa_priv;
+  struct GNUNET_CRYPTO_EcdsaPrivateKey priv;
 };
 
 
@@ -351,9 +351,9 @@ struct TALER_AgeCommitmentPrivateKeyP
 struct TALER_AgeCommitmentPublicKeyP
 {
   /**
-   * Taler uses EdDSA for coins when signing age verification attestation.
+   * Taler uses EcDSA for coins when signing age verification attestation.
    */
-  struct GNUNET_CRYPTO_EddsaPublicKey eddsa_pub;
+  struct GNUNET_CRYPTO_EcdsaPublicKey pub;
 };
 
 
@@ -869,7 +869,7 @@ struct TALER_AgeCommitmentHash
  */
 struct TALER_AgeAttestation
 {
-  struct GNUNET_CRYPTO_EddsaSignature eddsa_signature;
+  struct GNUNET_CRYPTO_EcdsaSignature signature;
 };
 
 extern const struct TALER_AgeCommitmentHash TALER_ZeroAgeCommitmentHash;
@@ -3326,7 +3326,7 @@ struct TALER_AgeCommitment
    *
    * The list has been allocated via GNUNET_malloc.
    */
-  struct TALER_AgeCommitmentPublicKeyP *pub;
+  struct TALER_AgeCommitmentPublicKeyP *keys;
 };
 
 struct TALER_AgeProof
@@ -3347,7 +3347,7 @@ struct TALER_AgeProof
    *
    * The list has been allocated via GNUNET_malloc.
    */
-  struct TALER_AgeCommitmentPrivateKeyP *priv;
+  struct TALER_AgeCommitmentPrivateKeyP *keys;
 };
 
 struct TALER_AgeCommitmentProof
diff --git a/src/lib/exchange_api_refreshes_reveal.c 
b/src/lib/exchange_api_refreshes_reveal.c
index 6427c637..cd2a1d1f 100644
--- a/src/lib/exchange_api_refreshes_reveal.c
+++ b/src/lib/exchange_api_refreshes_reveal.c
@@ -438,10 +438,11 @@ TALER_EXCHANGE_refreshes_reveal (
     for (size_t i = 0; i < rd->melt_age_commitment_proof->commitment.num; i++)
     {
       GNUNET_assert (0 ==
-                     json_array_append_new (old_age_commitment,
-                                            GNUNET_JSON_from_data_auto (
-                                              &rd->melt_age_commitment_proof->
-                                              commitment.pub[i])));
+                     json_array_append_new (
+                       old_age_commitment,
+                       GNUNET_JSON_from_data_auto (
+                         &rd->melt_age_commitment_proof->
+                         commitment.keys[i])));
     }
   }
 
diff --git a/src/util/Makefile.am b/src/util/Makefile.am
index 022d0611..a24f081b 100644
--- a/src/util/Makefile.am
+++ b/src/util/Makefile.am
@@ -116,6 +116,7 @@ libtalerutil_la_LDFLAGS = \
 AM_TESTS_ENVIRONMENT=export TALER_PREFIX=$${TALER_PREFIX:-@libdir@};export 
PATH=$${TALER_PREFIX:-@prefix@}/bin:$$PATH;
 
 check_PROGRAMS = \
+ test_age_restriction \
  test_amount \
  test_crypto \
  test_helper_eddsa \
@@ -127,6 +128,11 @@ check_PROGRAMS = \
 TESTS = \
  $(check_PROGRAMS)
 
+test_age_restriction_SOURCES = \
+  test_age_restriction.c
+test_age_restriction_LDADD = \
+  -lgnunetutil \
+  libtalerutil.la
 
 test_amount_SOURCES = \
   test_amount.c
diff --git a/src/util/age_restriction.c b/src/util/age_restriction.c
index 8e088a40..58db2341 100644
--- a/src/util/age_restriction.c
+++ b/src/util/age_restriction.c
@@ -46,9 +46,9 @@ TALER_age_commitment_hash (
   for (size_t i = 0; i < commitment->num; i++)
   {
     GNUNET_CRYPTO_hash_context_read (hash_context,
-                                     &commitment->pub[i],
+                                     &commitment->keys[i],
                                      sizeof(struct
-                                            GNUNET_CRYPTO_EddsaPublicKey));
+                                            GNUNET_CRYPTO_EcdsaPublicKey));
   }
 
   GNUNET_CRYPTO_hash_context_finish (hash_context,
@@ -62,7 +62,7 @@ TALER_age_commitment_hash (
 /* To a given age value between 0 and 31, returns the index of the age group
  * defined by the given mask.
  */
-static uint8_t
+uint8_t
 get_age_group (
   const struct TALER_AgeMask *mask,
   uint8_t age)
@@ -102,14 +102,14 @@ TALER_age_restriction_commit (
   new->commitment.mask.bits = mask->bits;
   new->commitment.num = num_pub;
   new->proof.num = num_priv;
-  new->proof.priv = NULL;
+  new->proof.keys = NULL;
 
-  new->commitment.pub = GNUNET_new_array (
+  new->commitment.keys = GNUNET_new_array (
     num_pub,
     struct TALER_AgeCommitmentPublicKeyP);
 
   if (0 < num_priv)
-    new->proof.priv = GNUNET_new_array (
+    new->proof.keys = GNUNET_new_array (
       num_priv,
       struct TALER_AgeCommitmentPrivateKeyP);
 
@@ -119,35 +119,40 @@ TALER_age_restriction_commit (
    * elliptic curve, so we can't simply fill the struct with random values. */
   for (i = 0; i < num_pub; i++)
   {
-    uint64_t saltBE = htonl (salt + i);
+    uint64_t salti = salt + i;
     struct TALER_AgeCommitmentPrivateKeyP key = {0};
-    struct TALER_AgeCommitmentPrivateKeyP *priv = &key;
+    struct TALER_AgeCommitmentPrivateKeyP *pkey = &key;
+
 
     /* Only save the private keys for age groups less than num_priv */
     if (i < num_priv)
-      priv = &new->proof.priv[i];
+      pkey = &new->proof.keys[i];
 
     if  (GNUNET_OK !=
-         GNUNET_CRYPTO_kdf (priv,
-                            sizeof (*priv),
-                            &saltBE,
-                            sizeof (saltBE),
-                            "taler-age-commitment-derivation",
-                            strlen (
-                              "taler-age-commitment-derivation"),
+         GNUNET_CRYPTO_kdf (pkey,
+                            sizeof (*pkey),
+                            &salti,
+                            sizeof (salti),
+                            "age commitment",
+                            strlen ("age derivation"),
                             NULL, 0))
       goto FAIL;
 
-    GNUNET_CRYPTO_eddsa_key_get_public (&priv->eddsa_priv,
-                                        &new->commitment.pub[i].eddsa_pub);
+    /* See GNUNET_CRYPTO_ecdsa_key_create */
+    pkey->priv.d[0] &= 248;
+    pkey->priv.d[31] &= 127;
+    pkey->priv.d[31] |= 64;
+
+    GNUNET_CRYPTO_ecdsa_key_get_public (&pkey->priv,
+                                        &new->commitment.keys[i].pub);
   }
 
   return GNUNET_OK;
 
 FAIL:
-  GNUNET_free (new->commitment.pub);
-  if (NULL != new->proof.priv)
-    GNUNET_free (new->proof.priv);
+  GNUNET_free (new->commitment.keys);
+  if (NULL != new->proof.keys)
+    GNUNET_free (new->proof.keys);
   return GNUNET_SYSERR;
 }
 
@@ -158,128 +163,52 @@ TALER_age_commitment_derive (
   const uint64_t salt,
   struct TALER_AgeCommitmentProof *new)
 {
-  struct GNUNET_CRYPTO_EccScalar scalar;
-  uint64_t saltBT = htonl (salt);
-  int64_t factor;
-
-  GNUNET_assert (GNUNET_OK ==
-                 GNUNET_CRYPTO_kdf (
-                   &factor,
-                   sizeof (factor),
-                   &saltBT,
-                   sizeof (saltBT),
-                   "taler-age-restriction-derivation",
-                   strlen ("taler-age-restriction-derivation"),
-                   NULL, 0));
-
-  GNUNET_CRYPTO_ecc_scalar_from_int (factor, &scalar);
-
-  /*
-  * age commitment consists of GNUNET_CRYPTO_Eddsa{Private,Public}Key
-  *
-  * GNUNET_CRYPTO_EddsaPrivateKey is a
-  *   unsigned char d[256 / 8];
-  *
-  * GNUNET_CRYPTO_EddsaPublicKey is a
-  *   unsigned char q_y[256 / 8];
-  *
-  * We want to multiply, both, the Private Key by an integer factor and the
-  * public key (point on curve) with the equivalent scalar.
-  *
-  * From the salt we will derive
-  *   1. a scalar to multiply the public keys with
-  *   2. a factor to multiply the private key with
-  *
-  * Invariants:
-  *   point*scalar == public(private*factor)
-  *
-  * A point on a curve is GNUNET_CRYPTO_EccPoint which is
-  *   unsigned char v[256 / 8];
-  *
-  * A ECC scalar for use in point multiplications is a
-  * GNUNET_CRYPTO_EccScalar which is a
-  *   unsigned char v[256 / 8];
-  * */
+  char label[sizeof(uint64_t) + 1] = {0};
 
   GNUNET_assert (NULL != new);
-  GNUNET_assert (orig->commitment.num== __builtin_popcount (
-                   orig->commitment.mask.bits) - 1);
-  GNUNET_assert (orig->proof.num <= orig->commitment.num);
+  GNUNET_assert (orig->proof.num <=
+                 orig->commitment.num);
+  GNUNET_assert (orig->commitment.num ==
+                 __builtin_popcount (orig->commitment.mask.bits) - 1);
 
   new->commitment.mask = orig->commitment.mask;
   new->commitment.num = orig->commitment.num;
-  new->proof.num = orig->proof.num;
-  new->commitment.pub = GNUNET_new_array (
+  new->commitment.keys = GNUNET_new_array (
     new->commitment.num,
     struct TALER_AgeCommitmentPublicKeyP);
-  new->proof.priv = GNUNET_new_array (
-    new->proof.num,
-    struct TALER_AgeCommitmentPrivateKeyP);
 
-  /* scalar multiply the public keys on the curve */
+  new->proof.num = orig->proof.num;
+  new->proof.keys = NULL;
+  if (0 != new->proof.num)
+    new->proof.keys = GNUNET_new_array (
+      new->proof.num,
+      struct TALER_AgeCommitmentPrivateKeyP);
+
+  memcpy (label, &salt, sizeof(salt));
+
+  /* 1. Derive the public keys */
   for (size_t i = 0; i < orig->commitment.num; i++)
   {
-    /* We shift all keys by the same scalar */
-    struct GNUNET_CRYPTO_EccPoint *p = (struct
-                                        GNUNET_CRYPTO_EccPoint *) &orig->
-                                       commitment.pub[i];
-    struct GNUNET_CRYPTO_EccPoint *np = (struct
-                                         GNUNET_CRYPTO_EccPoint *) &new->
-                                        commitment.pub[i];
-    if (GNUNET_OK !=
-        GNUNET_CRYPTO_ecc_pmul_mpi (
-          p,
-          &scalar,
-          np))
-      goto FAIL;
-
+    GNUNET_CRYPTO_ecdsa_public_key_derive (
+      &orig->commitment.keys[i].pub,
+      label,
+      "age commitment derive",
+      &new->commitment.keys[i].pub);
   }
 
-  /* multiply the private keys */
-  /* we borough ideas from GNUNET_CRYPTO_ecdsa_private_key_derive */
+  /* 2. Derive the private keys */
+  for (size_t i = 0; i < orig->proof.num; i++)
   {
-    for (size_t i = 0; i < orig->proof.num; i++)
-    {
-      uint8_t dc[32];
-      gcry_mpi_t f, x, d, n;
-      gcry_ctx_t ctx;
-
-      GNUNET_assert (0==gcry_mpi_ec_new (&ctx, NULL, "Ed25519"));
-      n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
-
-      GNUNET_CRYPTO_mpi_scan_unsigned (&f, (unsigned char*) &factor,
-                                       sizeof(factor));
-
-      for (size_t j = 0; j < 32; j++)
-        dc[i] = orig->proof.priv[i].eddsa_priv.d[31 - j];
-      GNUNET_CRYPTO_mpi_scan_unsigned (&x, dc, sizeof(dc));
-
-      d = gcry_mpi_new (256);
-      gcry_mpi_mulm (d, f, x, n);
-      GNUNET_CRYPTO_mpi_print_unsigned (dc, sizeof(dc), d);
-
-      for (size_t j = 0; j <32; j++)
-        new->proof.priv[i].eddsa_priv.d[j] = dc[31 - 1];
-
-      sodium_memzero (dc, sizeof(dc));
-      gcry_mpi_release (d);
-      gcry_mpi_release (x);
-      gcry_mpi_release (n);
-      gcry_mpi_release (f);
-      gcry_ctx_release (ctx);
-
-      /* TODO: add test to make sure that the calculated private key generate
-       * the same public keys */
-    }
-
+    struct GNUNET_CRYPTO_EcdsaPrivateKey *priv;
+    priv = GNUNET_CRYPTO_ecdsa_private_key_derive (
+      &orig->proof.keys[i].priv,
+      label,
+      "age commitment derive");
+    new->proof.keys[i].priv = *priv;
+    GNUNET_free (priv);
   }
 
   return GNUNET_OK;
-
-FAIL:
-  GNUNET_free (new->commitment.pub);
-  GNUNET_free (new->proof.priv);
-  return GNUNET_SYSERR;
 }
 
 
@@ -309,7 +238,7 @@ TALER_age_commitment_attest (
     return GNUNET_OK;
   }
 
-  if (group >= cp->proof.num)
+  if (group > cp->proof.num)
     return GNUNET_NO;
 
   {
@@ -320,9 +249,9 @@ TALER_age_commitment_attest (
       .age = age
     };
 
-    GNUNET_CRYPTO_eddsa_sign (&cp->proof.priv[group - 1].eddsa_priv,
+    GNUNET_CRYPTO_ecdsa_sign (&cp->proof.keys[group - 1].priv,
                               &at,
-                              &attest->eddsa_signature);
+                              &attest->signature);
   }
 
   return GNUNET_OK;
@@ -349,7 +278,7 @@ TALER_age_commitment_verify (
   if (0 == group)
     return GNUNET_OK;
 
-  if (group >= comm->num)
+  if (group > comm->num)
     return GNUNET_NO;
 
   {
@@ -361,10 +290,10 @@ TALER_age_commitment_verify (
     };
 
     return
-      GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_AGE_ATTESTATION,
+      GNUNET_CRYPTO_ecdsa_verify (TALER_SIGNATURE_WALLET_AGE_ATTESTATION,
                                   &at,
-                                  &attest->eddsa_signature,
-                                  &comm->pub[group - 1].eddsa_pub);
+                                  &attest->signature,
+                                  &comm->keys[group - 1].pub);
   }
 }
 
@@ -376,10 +305,10 @@ TALER_age_commitment_free (
   if (NULL == commitment)
     return;
 
-  if (NULL != commitment->pub)
+  if (NULL != commitment->keys)
   {
-    GNUNET_free (commitment->pub);
-    commitment->pub = NULL;
+    GNUNET_free (commitment->keys);
+    commitment->keys = NULL;
   }
   GNUNET_free (commitment);
 }
@@ -389,14 +318,14 @@ void
 TALER_age_proof_free (
   struct TALER_AgeProof *proof)
 {
-  if (NULL != proof->priv)
+  if (NULL != proof->keys)
   {
     GNUNET_CRYPTO_zero_keys (
-      proof->priv,
-      sizeof(*proof->priv) * proof->num);
+      proof->keys,
+      sizeof(*proof->keys) * proof->num);
 
-    GNUNET_free (proof->priv);
-    proof->priv = NULL;
+    GNUNET_free (proof->keys);
+    proof->keys = NULL;
   }
   GNUNET_free (proof);
 }
@@ -406,19 +335,19 @@ void
 TALER_age_commitment_proof_free (
   struct TALER_AgeCommitmentProof *cp)
 {
-  if (NULL != cp->proof.priv)
+  if (NULL != cp->proof.keys)
   {
     GNUNET_CRYPTO_zero_keys (
-      cp->proof.priv,
-      sizeof(*cp->proof.priv) * cp->proof.num);
+      cp->proof.keys,
+      sizeof(*cp->proof.keys) * cp->proof.num);
 
-    GNUNET_free (cp->proof.priv);
-    cp->proof.priv = NULL;
+    GNUNET_free (cp->proof.keys);
+    cp->proof.keys = NULL;
   }
 
-  if (NULL != cp->commitment.pub)
+  if (NULL != cp->commitment.keys)
   {
-    GNUNET_free (cp->commitment.pub);
-    cp->commitment.pub = NULL;
+    GNUNET_free (cp->commitment.keys);
+    cp->commitment.keys = NULL;
   }
 }
diff --git a/src/util/test_age_restriction.c b/src/util/test_age_restriction.c
new file mode 100644
index 00000000..a047714f
--- /dev/null
+++ b/src/util/test_age_restriction.c
@@ -0,0 +1,135 @@
+/*
+  This file is part of TALER
+  (C) 2022 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
+  Foundation; either version 3, or (at your option) any later version.
+
+  TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+  A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License along with
+  TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+*/
+
+/**
+ * @file util/test_age_restriction.c
+ * @brief Tests for age restriction specific logic
+ * @author Özgür Kesim
+ */
+#include "platform.h"
+#include "taler_util.h"
+#include "taler_crypto_lib.h"
+
+static struct TALER_AgeMask age_mask = {
+  .bits = 1 | 1 << 8 | 1 << 10 | 1 << 12 | 1 << 14 | 1 << 16 | 1 << 18 | 1 << 
21
+};
+
+extern uint8_t
+get_age_group (
+  const struct TALER_AgeMask *mask,
+  uint8_t age);
+
+enum GNUNET_GenericReturnValue
+test_attestation (void)
+{
+  uint8_t age;
+  for (age = 0; age < 35; age++)
+  {
+    enum GNUNET_GenericReturnValue ret;
+    struct TALER_AgeCommitmentProof acp[3] = {0};
+    struct TALER_AgeAttestation at = {0};
+    uint8_t age_group = get_age_group (&age_mask, age);
+    uint64_t salt = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
+                                              UINT64_MAX);
+
+    ret = TALER_age_restriction_commit (&age_mask,
+                                        age,
+                                        salt,
+                                        &acp[0]);
+
+    printf (
+      "commit(age:%d) == %d; proof.num: %ld; age_group: %d\n",
+      age,
+      ret,
+      acp[0].proof.num,
+      age_group);
+
+    for (uint8_t i = 0; i<2; i++)
+    {
+      /* Also derive another commitment right away */
+      salt = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
+                                       UINT64_MAX);
+      GNUNET_assert (GNUNET_OK ==
+                     TALER_age_commitment_derive (&acp[i],
+                                                  salt,
+                                                  &acp[i + 1]));
+    }
+
+    for (uint8_t i = 0; i < 3; i++)
+    {
+      for (uint8_t min = 0; min < 22; min++)
+      {
+        uint8_t min_group = get_age_group (&age_mask, min);
+
+        ret = TALER_age_commitment_attest (&acp[i],
+                                           min,
+                                           &at);
+
+        printf (
+          "[%s]: attest(min:%d, age:%d) == %d; age_group: %d, min_group: %d\n",
+          i == 0 ? "commit" : "derive",
+          min,
+          age,
+          ret,
+          age_group,
+          min_group);
+
+        if (min_group <= age_group &&
+            GNUNET_OK != ret)
+          return GNUNET_SYSERR;
+
+        if (min_group > age_group &&
+            GNUNET_NO != ret)
+          return GNUNET_SYSERR;
+
+        if (min_group > age_group)
+          continue;
+
+        ret = TALER_age_commitment_verify (&acp[i].commitment,
+                                           min,
+                                           &at);
+
+        printf (
+          "[%s]: verify(min:%d, age:%d) == %d; age_group:%d, min_group: %d\n",
+          i == 0 ? "commit" : "derive",
+          min,
+          age,
+          ret,
+          age_group,
+          min_group);
+
+        if (GNUNET_OK != ret)
+          return ret;
+      }
+    }
+  }
+  return GNUNET_OK;
+}
+
+
+int
+main (int argc,
+      const char *const argv[])
+{
+  (void) argc;
+  (void) argv;
+  if (GNUNET_OK != test_attestation ())
+    return 1;
+  return 0;
+}
+
+
+/* end of test_age_restriction.c */

-- 
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]