diff options
Diffstat (limited to 'src/util/age_restriction.c')
-rw-r--r-- | src/util/age_restriction.c | 242 |
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; } |