summaryrefslogtreecommitdiff
path: root/src/util/age_restriction.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/age_restriction.c')
-rw-r--r--src/util/age_restriction.c242
1 files changed, 174 insertions, 68 deletions
diff --git a/src/util/age_restriction.c b/src/util/age_restriction.c
index beb68e5a6..c2a7fc07c 100644
--- a/src/util/age_restriction.c
+++ b/src/util/age_restriction.c
@@ -23,6 +23,7 @@
#include "taler_signatures.h"
#include <gnunet/gnunet_json_lib.h>
#include <gcrypt.h>
+#include <stdint.h>
struct
#ifndef AGE_RESTRICTION_WITH_ECDSA
@@ -31,10 +32,10 @@ GNUNET_CRYPTO_Edx25519PublicKey
GNUNET_CRYPTO_EcdsaPublicKey
#endif
TALER_age_commitment_base_public_key = {
- .q_y = { 0x6f, 0xe5, 0x87, 0x9a, 0x3d, 0xa9, 0x44, 0x20,
- 0x80, 0xbd, 0x6a, 0xb9, 0x44, 0x56, 0x91, 0x19,
- 0xaf, 0xb4, 0xc8, 0x7b, 0x89, 0xce, 0x23, 0x17,
- 0x97, 0x20, 0x5c, 0xbb, 0x9c, 0xd7, 0xcc, 0xd9},
+ .q_y = { 0x64, 0x41, 0xb9, 0xbd, 0xbf, 0x14, 0x39, 0x8e,
+ 0x46, 0xeb, 0x5c, 0x1d, 0x34, 0xd3, 0x9b, 0x2f,
+ 0x9b, 0x7d, 0xc8, 0x18, 0xeb, 0x9c, 0x09, 0xfb,
+ 0x43, 0xad, 0x16, 0x64, 0xbc, 0x18, 0x49, 0xb5},
};
void
@@ -76,7 +77,7 @@ TALER_age_commitment_hash (
* defined by the given mask.
*/
uint8_t
-get_age_group (
+TALER_get_age_group (
const struct TALER_AgeMask *mask,
uint8_t age)
{
@@ -95,47 +96,66 @@ get_age_group (
}
+uint8_t
+TALER_get_lowest_age (
+ const struct TALER_AgeMask *mask,
+ uint8_t age)
+{
+ uint32_t m = mask->bits;
+ uint8_t group = TALER_get_age_group (mask, age);
+ uint8_t lowest = 0;
+
+ while (group > 0)
+ {
+ m = m >> 1;
+ if (m & 1)
+ group--;
+ lowest++;
+ }
+
+ return lowest;
+}
+
+
#ifdef AGE_RESTRICTION_WITH_ECDSA
-/* @brief Helper function to generate a ECDSA private key
+/**
+ * @brief Helper function to generate a ECDSA private key
*
* @param seed Input seed
* @param size Size of the seed in bytes
* @param[out] pkey ECDSA private key
- * @return GNUNET_OK on success
*/
-static enum GNUNET_GenericReturnValue
+static void
ecdsa_create_from_seed (
const void *seed,
size_t seed_size,
struct GNUNET_CRYPTO_EcdsaPrivateKey *key)
{
enum GNUNET_GenericReturnValue ret;
- ret = GNUNET_CRYPTO_kdf (key,
- sizeof (*key),
- &seed,
- seed_size,
- "age commitment",
- sizeof ("age commitment") - 1,
- NULL, 0);
- if (GNUNET_OK != ret)
- return ret;
+ GNUNET_assert (
+ GNUNET_OK ==
+ GNUNET_CRYPTO_kdf (key,
+ sizeof (*key),
+ &seed,
+ seed_size,
+ "age commitment",
+ sizeof ("age commitment") - 1,
+ NULL, 0));
/* See GNUNET_CRYPTO_ecdsa_key_create */
key->d[0] &= 248;
key->d[31] &= 127;
key->d[31] |= 64;
-
- return GNUNET_OK;
}
#endif
-enum GNUNET_GenericReturnValue
+void
TALER_age_restriction_commit (
const struct TALER_AgeMask *mask,
- const uint8_t age,
+ uint8_t age,
const struct GNUNET_HashCode *seed,
struct TALER_AgeCommitmentProof *ncp)
{
@@ -147,10 +167,10 @@ TALER_age_restriction_commit (
GNUNET_assert (NULL != mask);
GNUNET_assert (NULL != seed);
GNUNET_assert (NULL != ncp);
- GNUNET_assert (mask->bits & 1); /* fist bit must have been set */
+ GNUNET_assert (mask->bits & 1); /* first bit must have been set */
num_pub = __builtin_popcount (mask->bits) - 1;
- num_priv = get_age_group (mask, age);
+ num_priv = TALER_get_age_group (mask, age);
GNUNET_assert (31 > num_priv);
GNUNET_assert (num_priv <= num_pub);
@@ -190,24 +210,15 @@ TALER_age_restriction_commit (
GNUNET_CRYPTO_edx25519_key_get_public (&pkey->priv,
&ncp->commitment.keys[i].pub);
#else
- if (GNUNET_OK !=
- ecdsa_create_from_seed (&seed_i,
- sizeof(seed_i),
- &pkey->priv))
- {
- GNUNET_free (ncp->commitment.keys);
- GNUNET_free (ncp->proof.keys);
- return GNUNET_SYSERR;
- }
-
+ ecdsa_create_from_seed (&seed_i,
+ sizeof(seed_i),
+ &pkey->priv);
GNUNET_CRYPTO_ecdsa_key_get_public (&pkey->priv,
&ncp->commitment.keys[i].pub);
#endif
seed_i.bits[0] += 1;
}
-
- return GNUNET_OK;
}
@@ -335,8 +346,8 @@ TALER_age_commitment_attest (
GNUNET_assert (NULL != attest);
GNUNET_assert (NULL != cp);
- group = get_age_group (&cp->commitment.mask,
- age);
+ group = TALER_get_age_group (&cp->commitment.mask,
+ age);
GNUNET_assert (group < 32);
@@ -370,6 +381,7 @@ TALER_age_commitment_attest (
&at,
&attest->signature);
}
+#undef sign
return GNUNET_OK;
}
@@ -386,8 +398,8 @@ TALER_age_commitment_verify (
GNUNET_assert (NULL != attest);
GNUNET_assert (NULL != comm);
- group = get_age_group (&comm->mask,
- age);
+ group = TALER_get_age_group (&comm->mask,
+ age);
GNUNET_assert (group < 32);
@@ -419,6 +431,7 @@ TALER_age_commitment_verify (
&attest->signature,
&comm->keys[group - 1].pub);
}
+#undef verify
}
@@ -442,6 +455,9 @@ void
TALER_age_proof_free (
struct TALER_AgeProof *proof)
{
+ if (NULL == proof)
+ return;
+
if (NULL != proof->keys)
{
GNUNET_CRYPTO_zero_keys (
@@ -457,26 +473,71 @@ TALER_age_proof_free (
void
TALER_age_commitment_proof_free (
- struct TALER_AgeCommitmentProof *cp)
+ struct TALER_AgeCommitmentProof *acp)
{
- if (NULL != cp->proof.keys)
+ if (NULL == acp)
+ return;
+
+ if (NULL != acp->proof.keys)
{
GNUNET_CRYPTO_zero_keys (
- cp->proof.keys,
- sizeof(*cp->proof.keys) * cp->proof.num);
+ acp->proof.keys,
+ sizeof(*acp->proof.keys) * acp->proof.num);
- GNUNET_free (cp->proof.keys);
- cp->proof.keys = NULL;
+ GNUNET_free (acp->proof.keys);
+ acp->proof.keys = NULL;
}
- if (NULL != cp->commitment.keys)
+ if (NULL != acp->commitment.keys)
{
- GNUNET_free (cp->commitment.keys);
- cp->commitment.keys = NULL;
+ GNUNET_free (acp->commitment.keys);
+ acp->commitment.keys = NULL;
}
}
+struct TALER_AgeCommitmentProof *
+TALER_age_commitment_proof_duplicate (
+ const struct TALER_AgeCommitmentProof *acp)
+{
+ struct TALER_AgeCommitmentProof *nacp;
+
+ GNUNET_assert (NULL != acp);
+ GNUNET_assert (__builtin_popcount (acp->commitment.mask.bits) - 1 ==
+ (int) acp->commitment.num);
+
+ nacp = GNUNET_new (struct TALER_AgeCommitmentProof);
+
+ TALER_age_commitment_proof_deep_copy (acp,nacp);
+ return nacp;
+}
+
+
+void
+TALER_age_commitment_proof_deep_copy (
+ const struct TALER_AgeCommitmentProof *acp,
+ struct TALER_AgeCommitmentProof *nacp)
+{
+ GNUNET_assert (NULL != acp);
+ GNUNET_assert (__builtin_popcount (acp->commitment.mask.bits) - 1 ==
+ (int) acp->commitment.num);
+
+ *nacp = *acp;
+ nacp->commitment.keys =
+ GNUNET_new_array (acp->commitment.num,
+ struct TALER_AgeCommitmentPublicKeyP);
+ nacp->proof.keys =
+ GNUNET_new_array (acp->proof.num,
+ struct TALER_AgeCommitmentPrivateKeyP);
+
+ for (size_t i = 0; i < acp->commitment.num; i++)
+ nacp->commitment.keys[i] = acp->commitment.keys[i];
+
+ for (size_t i = 0; i < acp->proof.num; i++)
+ nacp->proof.keys[i] = acp->proof.keys[i];
+}
+
+
enum GNUNET_GenericReturnValue
TALER_JSON_parse_age_groups (const json_t *root,
struct TALER_AgeMask *mask)
@@ -513,6 +574,9 @@ TALER_parse_age_group_string (
unsigned int val = 0;
char c;
+ /* reset mask */
+ mask->bits = 0;
+
while (*pos)
{
c = *pos++;
@@ -546,19 +610,16 @@ TALER_parse_age_group_string (
}
-char *
+const char *
TALER_age_mask_to_string (
const struct TALER_AgeMask *mask)
{
+ static char buf[256] = {0};
uint32_t bits = mask->bits;
unsigned int n = 0;
- char *buf = GNUNET_malloc (32 * 3); // max characters possible
char *pos = buf;
- if (NULL == buf)
- {
- return buf;
- }
+ memset (buf, 0, sizeof(buf));
while (bits != 0)
{
@@ -584,7 +645,7 @@ TALER_age_mask_to_string (
}
-enum GNUNET_GenericReturnValue
+void
TALER_age_restriction_from_secret (
const struct TALER_PlanchetMasterSecretP *secret,
const struct TALER_AgeMask *mask,
@@ -601,7 +662,7 @@ TALER_age_restriction_from_secret (
GNUNET_assert (mask->bits & 1); /* fist bit must have been set */
num_pub = __builtin_popcount (mask->bits) - 1;
- num_priv = get_age_group (mask, max_age);
+ num_priv = TALER_get_age_group (mask, max_age);
GNUNET_assert (31 > num_priv);
GNUNET_assert (num_priv <= num_pub);
@@ -610,11 +671,9 @@ TALER_age_restriction_from_secret (
ncp->commitment.num = num_pub;
ncp->proof.num = num_priv;
ncp->proof.keys = NULL;
-
ncp->commitment.keys = GNUNET_new_array (
num_pub,
struct TALER_AgeCommitmentPublicKeyP);
-
if (0 < num_priv)
ncp->proof.keys = GNUNET_new_array (
num_priv,
@@ -622,7 +681,7 @@ TALER_age_restriction_from_secret (
/* Create as many private keys as allow with max_age and derive the
* corresponding public keys. The rest of the needed public keys are created
- * by scalar mulitplication with the TALER_age_commitment_base_public_key. */
+ * by scalar multiplication with the TALER_age_commitment_base_public_key. */
for (size_t i = 0; i < num_pub; i++)
{
enum GNUNET_GenericReturnValue ret;
@@ -648,14 +707,9 @@ TALER_age_restriction_from_secret (
GNUNET_CRYPTO_edx25519_key_get_public (&pkey->priv,
&ncp->commitment.keys[i].pub);
#else
- if (GNUNET_OK != ecdsa_create_from_seed (&seed_i,
- sizeof(seed_i),
- &pkey->priv))
- {
- GNUNET_free (ncp->commitment.keys);
- GNUNET_free (ncp->proof.keys);
- return GNUNET_SYSERR;
- }
+ ecdsa_create_from_seed (&seed_i,
+ sizeof(seed_i),
+ &pkey->priv);
GNUNET_CRYPTO_ecdsa_key_get_public (&pkey->priv,
&ncp->commitment.keys[i].pub);
#endif
@@ -680,9 +734,61 @@ TALER_age_restriction_from_secret (
#endif
}
}
+}
- return GNUNET_OK;
+enum GNUNET_GenericReturnValue
+TALER_parse_coarse_date (
+ const char *in,
+ const struct TALER_AgeMask *mask,
+ uint32_t *out)
+{
+ struct tm date = {0};
+ struct tm limit = {0};
+ time_t seconds;
+
+ if (NULL == in)
+ {
+ /* FIXME[oec]: correct behaviour? */
+ *out = 0;
+ return GNUNET_OK;
+ }
+
+ GNUNET_assert (NULL !=mask);
+ GNUNET_assert (NULL !=out);
+
+ if (NULL == strptime (in, "%Y-%m-%d", &date))
+ {
+ if (NULL == strptime (in, "%Y-%m-00", &date))
+ if (NULL == strptime (in, "%Y-00-00", &date))
+ return GNUNET_SYSERR;
+ /* turns out that the day is off by one in the last two cases */
+ date.tm_mday += 1;
+ }
+
+ seconds = timegm (&date);
+ if (-1 == seconds)
+ return GNUNET_SYSERR;
+
+ /* calculate the limit date for the largest age group */
+ {
+ time_t l = time (NULL);
+ localtime_r (&l, &limit);
+ }
+ limit.tm_year -= TALER_adult_age (mask);
+ GNUNET_assert (-1 != timegm (&limit));
+
+ if ((limit.tm_year < date.tm_year)
+ || ((limit.tm_year == date.tm_year)
+ && (limit.tm_mon < date.tm_mon))
+ || ((limit.tm_year == date.tm_year)
+ && (limit.tm_mon == date.tm_mon)
+ && (limit.tm_mday < date.tm_mday)))
+ *out = seconds / 60 / 60 / 24;
+ else
+ *out = 0;
+
+ return GNUNET_OK;
}