summaryrefslogtreecommitdiff
path: root/src/include
diff options
context:
space:
mode:
Diffstat (limited to 'src/include')
-rw-r--r--src/include/taler_crypto_lib.h213
-rw-r--r--src/include/taler_exchange_service.h10
-rw-r--r--src/include/taler_exchangedb_plugin.h28
-rw-r--r--src/include/taler_extensions.h78
-rw-r--r--src/include/taler_json_lib.h11
-rw-r--r--src/include/taler_signatures.h18
-rw-r--r--src/include/taler_testing_lib.h37
7 files changed, 318 insertions, 77 deletions
diff --git a/src/include/taler_crypto_lib.h b/src/include/taler_crypto_lib.h
index ab5202baa..9bbf29de4 100644
--- a/src/include/taler_crypto_lib.h
+++ b/src/include/taler_crypto_lib.h
@@ -306,37 +306,6 @@ struct TALER_MasterSignatureP
struct GNUNET_CRYPTO_EddsaSignature eddsa_signature;
};
-/*
- * @brief Type of a list of age groups, represented as bit mask.
- *
- * The bits set in the mask mark the edges at the beginning of a next age
- * group. F.e. for the age groups
- * 0-7, 8-9, 10-11, 12-14, 14-15, 16-17, 18-21, 21-*
- * the following bits are set:
- *
- * 31 24 16 8 0
- * | | | | |
- * oooooooo oo1oo1o1 o1o1o1o1 ooooooo1
- *
- * A value of 0 means that the exchange does not support the extension for
- * age-restriction.
- */
-struct TALER_AgeMask
-{
- uint32_t mask;
-};
-
-/**
- * @brief Age restriction commitment of a coin.
- */
-struct TALER_AgeHash
-{
- /**
- * The commitment is a SHA-256 hash code.
- */
- struct GNUNET_ShortHashCode shash;
-};
-
/**
* @brief Type of public keys for Taler coins. The same key material is used
@@ -364,6 +333,29 @@ struct TALER_CoinSpendPrivateKeyP
struct GNUNET_CRYPTO_EddsaPrivateKey eddsa_priv;
};
+/**
+ * @brief Type of private keys for age commitment in coins.
+ */
+struct TALER_AgeCommitmentPrivateKeyP
+{
+ /**
+ * Taler uses EdDSA for coins when signing age verification attestation.
+ */
+ struct GNUNET_CRYPTO_EddsaPrivateKey eddsa_priv;
+};
+
+
+/**
+ * @brief Type of public keys for age commitment in coins.
+ */
+struct TALER_AgeCommitmentPublicKeyP
+{
+ /**
+ * Taler uses EdDSA for coins when signing age verification attestation.
+ */
+ struct GNUNET_CRYPTO_EddsaPublicKey eddsa_pub;
+};
+
/**
* @brief Type of signatures made with Taler coins.
@@ -765,6 +757,46 @@ struct TALER_BlindedDenominationSignature
};
+/* *************** Age Restriction *********************************** */
+
+/*
+ * @brief Type of a list of age groups, represented as bit mask.
+ *
+ * The bits set in the mask mark the edges at the beginning of a next age
+ * group. F.e. for the age groups
+ * 0-7, 8-9, 10-11, 12-14, 14-15, 16-17, 18-21, 21-*
+ * the following bits are set:
+ *
+ * 31 24 16 8 0
+ * | | | | |
+ * oooooooo oo1oo1o1 o1o1o1o1 ooooooo1
+ *
+ * A value of 0 means that the exchange does not support the extension for
+ * age-restriction.
+ */
+struct TALER_AgeMask
+{
+ uint32_t mask;
+};
+
+/**
+ * @brief Age commitment of a coin.
+ */
+struct TALER_AgeCommitmentHash
+{
+ /**
+ * The commitment is a SHA-256 hash code.
+ */
+ struct GNUNET_ShortHashCode shash;
+};
+
+extern const struct TALER_AgeCommitmentHash TALER_ZeroAgeCommitmentHash;
+#define TALER_AgeCommitmentHash_isNullOrZero(ph) ((NULL == ph) || \
+ (0 == memcmp (ph, \
+ & \
+ TALER_ZeroAgeCommitmentHash, \
+ sizeof(struct \
+ TALER_AgeCommitmentHash))))
/**
* @brief Type of public signing keys for verifying blindly signed coins.
@@ -944,9 +976,10 @@ struct TALER_CoinPublicInfo
struct TALER_DenominationHash denom_pub_hash;
/**
- * Hash of the age commitment.
+ * Hash of the age commitment. If no age commitment was provided, it must be
+ * set to all zeroes.
*/
- struct TALER_AgeHash age_commitment_hash;
+ struct TALER_AgeCommitmentHash age_commitment_hash;
/**
* (Unblinded) signature over @e coin_pub with @e denom_pub,
@@ -1117,7 +1150,7 @@ TALER_denom_sig_free (struct TALER_DenominationSignature *denom_sig);
enum GNUNET_GenericReturnValue
TALER_denom_blind (const struct TALER_DenominationPublicKey *dk,
const union TALER_DenominationBlindingKeyP *coin_bks,
- const struct TALER_AgeHash *age_commitment_hash,
+ const struct TALER_AgeCommitmentHash *age_commitment_hash,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
const struct TALER_ExchangeWithdrawValues *alg_values,
struct TALER_CoinPubHash *c_hash,
@@ -1349,7 +1382,7 @@ TALER_withdraw_request_hash (
*/
void
TALER_coin_pub_hash (const struct TALER_CoinSpendPublicKeyP *coin_pub,
- const struct TALER_AgeHash *age_commitment_hash,
+ const struct TALER_AgeCommitmentHash *age_commitment_hash,
struct TALER_CoinPubHash *coin_h);
@@ -1402,8 +1435,9 @@ struct TALER_FreshCoin
struct TALER_CoinSpendPrivateKeyP coin_priv;
/**
- * FIXME-Oec: Age-verification vector, as pointer: Dyn alloc!
+ * Optional hash of an age commitment bound to this coin, maybe NULL.
*/
+ const struct TALER_AgeCommitmentHash *h_age_commitment;
};
@@ -1571,6 +1605,7 @@ TALER_planchet_blinding_secret_create (
* @param alg_values algorithm specific values
* @param bks blinding secrets
* @param coin_priv coin private key
+ * @param ach hash of age commitment to bind to this coin, maybe NULL
* @param[out] c_hash set to the hash of the public key of the coin (needed later)
* @param[out] pd set to the planchet detail for TALER_MERCHANT_tip_pickup() and
* other withdraw operations, `pd->blinded_planchet.cipher` will be set
@@ -1582,6 +1617,7 @@ TALER_planchet_prepare (const struct TALER_DenominationPublicKey *dk,
const struct TALER_ExchangeWithdrawValues *alg_values,
const union TALER_DenominationBlindingKeyP *bks,
const struct TALER_CoinSpendPrivateKeyP *coin_priv,
+ const struct TALER_AgeCommitmentHash *ach,
struct TALER_CoinPubHash *c_hash,
struct TALER_PlanchetDetail *pd);
@@ -1613,6 +1649,7 @@ TALER_planchet_detail_free (struct TALER_PlanchetDetail *pd);
* @param blind_sig blind signature from the exchange
* @param bks blinding key secret
* @param coin_priv private key of the coin
+ * @param ach hash of age commitment that is bound to this coin, maybe NULL
* @param c_hash hash of the coin's public key for verification of the signature
* @param alg_values values obtained from the exchange for the withdrawal
* @param[out] coin set to the details of the fresh coin
@@ -1624,6 +1661,7 @@ TALER_planchet_to_coin (
const struct TALER_BlindedDenominationSignature *blind_sig,
const union TALER_DenominationBlindingKeyP *bks,
const struct TALER_CoinSpendPrivateKeyP *coin_priv,
+ const struct TALER_AgeCommitmentHash *ach,
const struct TALER_CoinPubHash *c_hash,
const struct TALER_ExchangeWithdrawValues *alg_values,
struct TALER_FreshCoin *coin);
@@ -2202,6 +2240,7 @@ TALER_wallet_account_setup_sign (
* @param deposit_fee the deposit fee we expect to pay
* @param h_wire hash of the merchant’s account details
* @param h_contract_terms hash of the contact of the merchant with the customer (further details are never disclosed to the exchange)
+ * @param h_age_commitment hash over the age commitment, if applicable to the denomination (maybe NULL)
* @param h_extensions hash over the extensions
* @param h_denom_pub hash of the coin denomination's public key
* @param coin_priv coin’s private key
@@ -2216,6 +2255,7 @@ TALER_wallet_deposit_sign (
const struct TALER_Amount *deposit_fee,
const struct TALER_MerchantWireHash *h_wire,
const struct TALER_PrivateContractHash *h_contract_terms,
+ const struct TALER_AgeCommitmentHash *h_age_commitment,
const struct TALER_ExtensionContractHash *h_extensions,
const struct TALER_DenominationHash *h_denom_pub,
struct GNUNET_TIME_Timestamp wallet_timestamp,
@@ -2232,6 +2272,7 @@ TALER_wallet_deposit_sign (
* @param deposit_fee the deposit fee we expect to pay
* @param h_wire hash of the merchant’s account details
* @param h_contract_terms hash of the contact of the merchant with the customer (further details are never disclosed to the exchange)
+ * @param h_age_commitment hash over the age commitment (maybe all zeroes, if not applicable to the denomination)
* @param h_extensions hash over the extensions
* @param h_denom_pub hash of the coin denomination's public key
* @param wallet_timestamp timestamp when the contract was finalized, must not be too far in the future
@@ -2247,6 +2288,7 @@ TALER_wallet_deposit_verify (
const struct TALER_Amount *deposit_fee,
const struct TALER_MerchantWireHash *h_wire,
const struct TALER_PrivateContractHash *h_contract_terms,
+ const struct TALER_AgeCommitmentHash *h_commitment_hash,
const struct TALER_ExtensionContractHash *h_extensions,
const struct TALER_DenominationHash *h_denom_pub,
struct GNUNET_TIME_Timestamp wallet_timestamp,
@@ -2283,6 +2325,7 @@ TALER_wallet_melt_sign (
* @param melt_fee the melt fee we expect to pay
* @param rc refresh session we are committed to
* @param h_denom_pub hash of the coin denomination's public key
+ * @param h_age_commitment hash of the age commitment (may be NULL)
* @param coin_pub coin’s public key
* @param coin_sig the signature made with purpose #TALER_SIGNATURE_WALLET_COIN_MELT
* @return #GNUNET_OK if the signature is valid
@@ -2293,6 +2336,7 @@ TALER_wallet_melt_verify (
const struct TALER_Amount *melt_fee,
const struct TALER_RefreshCommitmentP *rc,
const struct TALER_DenominationHash *h_denom_pub,
+ const struct TALER_AgeCommitmentHash *h_age_commitment,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
const struct TALER_CoinSpendSignatureP *coin_sig);
@@ -2321,6 +2365,7 @@ TALER_wallet_link_sign (const struct TALER_DenominationHash *h_denom_pub,
* @param transfer_pub transfer public key
* @param h_coin_ev hash of the coin envelope
* @param old_coin_pub old coin key that the link signature is for
+ * @param h_age_commitment hash of age commitment. Maybe NULL, if not applicable.
* @param coin_sig resulting signature
* @return #GNUNET_OK if the signature is valid
*/
@@ -2330,6 +2375,7 @@ TALER_wallet_link_verify (
const struct TALER_TransferPublicKeyP *transfer_pub,
const struct TALER_BlindedCoinHash *h_coin_ev,
const struct TALER_CoinSpendPublicKeyP *old_coin_pub,
+ const struct TALER_AgeCommitmentHash *h_age_commitment,
const struct TALER_CoinSpendSignatureP *coin_sig);
@@ -3149,5 +3195,100 @@ TALER_exchange_offline_extension_config_hash_verify (
const struct TALER_MasterSignatureP *master_sig
);
+/*
+ * @brief Representation of an age commitment: one public key per age group.
+ *
+ * The number of keys must be be the same as the number of bits set in the
+ * corresponding age mask.
+ */
+struct TALER_AgeCommitment
+{
+
+ /* The age mask defines the age groups that were a parameter during the
+ * generation of this age commitment */
+ struct TALER_AgeMask mask;
+
+ /* The number of public keys, which must be the same as the number of
+ * groups in the mask.
+ */
+ size_t num_pub;
+
+ /* The list of #num_pub public keys. In must have same size as the number of
+ * age groups defined in the mask.
+ *
+ * A hash of this list is the hashed commitment that goes into FDC
+ * calculation during the withdraw and refresh operations for new coins. That
+ * way, the particular age commitment becomes mandatory and bound to a coin.
+ *
+ * The list has been allocated via GNUNET_malloc.
+ */
+ struct TALER_AgeCommitmentPublicKeyP *pub;
+
+ /* The number of private keys, which must be at most num_pub_keys. One minus
+ * this number corresponds to the largest age group that is supported with
+ * this age commitment.
+ */
+ size_t num_priv;
+
+ /* List of #num_priv private keys.
+ *
+ * Note that the list can be _smaller_ than the corresponding list of public
+ * keys. In that case, the wallet can sign off only for a subset of the age
+ * groups.
+ *
+ * The list has been allocated via GNUNET_malloc.
+ */
+ struct TALER_AgeCommitmentPrivateKeyP *priv;
+};
+
+/*
+ * @brief Generates a hash of the public keys in the age commitment.
+ *
+ * @param commitment the age commitment - one public key per age group
+ * @param[out] hash resulting hash
+ */
+void
+TALER_age_commitment_hash (
+ const struct TALER_AgeCommitment *commitment,
+ struct TALER_AgeCommitmentHash *hash);
+
+/*
+ * @brief Generates an age commitent for the given age.
+ *
+ * @param mask The age mask the defines the age groups
+ * @param age The actual age for which an age commitment is generated
+ * @param seed The seed that goes into the key generation. MUST be choosen uniformly random.
+ * @param commitment[out] The generated age commitment, ->priv and ->pub allocated via GNUNET_malloc on success
+ * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
+ */
+enum GNUNET_GenericReturnValue
+TALER_age_restriction_commit (
+ const struct TALER_AgeMask *mask,
+ const uint8_t age,
+ const uint32_t seed,
+ struct TALER_AgeCommitment *commitment);
+
+/*
+ * @brief Derives another, equivalent age commitment for a given one.
+ *
+ * @param orig Original age commitment
+ * @param seed Used to move the points on the elliptic curve in order to generate another, equivalent commitment.
+ * @param derived[out] The resulting age commitment, ->priv and ->pub allocated via GNUNET_malloc on success.
+ * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
+ */
+enum GNUNET_GenericReturnValue
+TALER_age_commitment_derive (
+ const struct TALER_AgeCommitment *orig,
+ const uint32_t seed,
+ struct TALER_AgeCommitment *derived);
+
+/*
+ * @brief helper function to free memory inside a struct TALER_AgeCommitment
+ * @param cmt the commitment from which internal memory should be freed. Note
+ * that cmt itself is NOT freed!
+ */
+void
+TALER_age_restriction_commitment_free_inside (
+ struct TALER_AgeCommitment *cmt);
#endif
diff --git a/src/include/taler_exchange_service.h b/src/include/taler_exchange_service.h
index 8c1b4bde2..fef09f721 100644
--- a/src/include/taler_exchange_service.h
+++ b/src/include/taler_exchange_service.h
@@ -159,11 +159,6 @@ struct TALER_EXCHANGE_DenomPublicKey
* revoked by the exchange.
*/
bool revoked;
-
- /**
- * Is the denomination age-restricted?
- */
- bool age_restricted;
};
@@ -785,6 +780,7 @@ TALER_EXCHANGE_wire_cancel (struct TALER_EXCHANGE_WireHandle *wh);
* @param h_extensions hash over the extensions
* @param h_denom_pub hash of the coin denomination's public key
* @param coin_priv coin’s private key
+ * @param age_commitment age commitment that went into the making of the coin, might be NULL
* @param wallet_timestamp timestamp when the contract was finalized, must not be too far in the future
* @param merchant_pub the public key of the merchant (used to identify the merchant for refund requests)
* @param refund_deadline date until which the merchant can issue a refund to the customer via the exchange (can be zero if refunds are not allowed); must not be after the @a wire_deadline
@@ -799,6 +795,7 @@ TALER_EXCHANGE_deposit_permission_sign (
const struct TALER_ExtensionContractHash *h_extensions,
const struct TALER_DenominationHash *h_denom_pub,
const struct TALER_CoinSpendPrivateKeyP *coin_priv,
+ const struct TALER_AgeCommitment *age_commitment,
struct GNUNET_TIME_Timestamp wallet_timestamp,
const struct TALER_MerchantPublicKeyP *merchant_pub,
struct GNUNET_TIME_Timestamp refund_deadline,
@@ -924,6 +921,7 @@ TALER_EXCHANGE_deposit (
const char *merchant_payto_uri,
const struct TALER_WireSaltP *wire_salt,
const struct TALER_PrivateContractHash *h_contract_terms,
+ const struct TALER_AgeCommitmentHash *h_age_commitment,
const json_t *extension_details,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
const struct TALER_DenominationSignature *denom_sig,
@@ -1496,6 +1494,7 @@ typedef void
* @param reserve_priv private key of the reserve to withdraw from
* @param ps secrets of the planchet
* caller must have committed this value to disk before the call (with @a pk)
+ * @param ach hash of the age commitment that should be bound to this coin. Maybe NULL.
* @param res_cb the callback to call when the final result for this request is available
* @param res_cb_cls closure for @a res_cb
* @return NULL
@@ -1508,6 +1507,7 @@ TALER_EXCHANGE_withdraw (
const struct TALER_EXCHANGE_DenomPublicKey *pk,
const struct TALER_ReservePrivateKeyP *reserve_priv,
const struct TALER_PlanchetMasterSecretP *ps,
+ const struct TALER_AgeCommitmentHash *ach,
TALER_EXCHANGE_WithdrawCallback res_cb,
void *res_cb_cls);
diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h
index ec647e9c6..f0a6f8bd6 100644
--- a/src/include/taler_exchangedb_plugin.h
+++ b/src/include/taler_exchangedb_plugin.h
@@ -70,6 +70,12 @@ struct TALER_EXCHANGEDB_DenominationKeyInformationP
* Signed properties of the denomination key.
*/
struct TALER_DenominationKeyValidityPS properties;
+
+ /**
+ * If denomination was setup for age restriction, non-zero age mask.
+ * Note that the mask is not part of the signature.
+ */
+ struct TALER_AgeMask age_mask;
};
@@ -295,7 +301,7 @@ struct TALER_EXCHANGEDB_TableData
struct
{
struct TALER_CoinSpendPublicKeyP coin_pub;
- struct TALER_AgeHash age_hash;
+ struct TALER_AgeCommitmentHash age_hash;
uint64_t denominations_serial;
struct TALER_DenominationSignature denom_sig;
} known_coins;
@@ -644,7 +650,7 @@ struct TALER_EXCHANGEDB_DenominationKeyMetaData
* A value of 0 means that the denomination does not support the extension for
* age-restriction.
*/
- struct TALER_AgeMask age_restrictions;
+ struct TALER_AgeMask age_mask;
};
@@ -1262,6 +1268,13 @@ struct TALER_EXCHANGEDB_Refresh
struct TALER_CoinSpendSignatureP coin_sig;
/**
+ * Hash of the age commitment used to sign the coin, if age restriction was
+ * applicable to the denomination. May be all zeroes if no age restriction
+ * applies.
+ */
+ struct TALER_AgeCommitmentHash h_age_commitment;
+
+ /**
* Refresh commitment this coin is melted into.
*/
struct TALER_RefreshCommitmentP rc;
@@ -1307,6 +1320,13 @@ struct TALER_EXCHANGEDB_MeltListEntry
struct TALER_DenominationHash h_denom_pub;
/**
+ * Hash of the age commitment used to sign the coin, if age restriction was
+ * applicable to the denomination. May be all zeroes if no age restriction
+ * applies.
+ */
+ struct TALER_AgeCommitmentHash h_age_commitment;
+
+ /**
* How much value is being melted? This amount includes the fees,
* so the final amount contributed to the melt is this value minus
* the fee for melting the coin. We include the fee in what is
@@ -1606,6 +1626,7 @@ typedef enum GNUNET_GenericReturnValue
* @param cls closure
* @param rowid unique serial ID for the refresh session in our DB
* @param denom_pub denomination public key of @a coin_pub
+ * @param h_age_commitment age commitment that went into the signing of the coin, may be NULL
* @param coin_pub public key of the coin
* @param coin_sig signature from the coin
* @param amount_with_fee amount that was deposited including fee
@@ -1618,6 +1639,7 @@ typedef enum GNUNET_GenericReturnValue
void *cls,
uint64_t rowid,
const struct TALER_DenominationPublicKey *denom_pub,
+ const struct TALER_AgeCommitmentHash *h_age_commitment,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
const struct TALER_CoinSpendSignatureP *coin_sig,
const struct TALER_Amount *amount_with_fee,
@@ -2758,7 +2780,7 @@ struct TALER_EXCHANGEDB_Plugin
const struct TALER_CoinPublicInfo *coin,
uint64_t *known_coin_id,
struct TALER_DenominationHash *denom_pub_hash,
- struct TALER_AgeHash *age_hash);
+ struct TALER_AgeCommitmentHash *age_hash);
/**
diff --git a/src/include/taler_extensions.h b/src/include/taler_extensions.h
index f00f3ed56..b7b93e178 100644
--- a/src/include/taler_extensions.h
+++ b/src/include/taler_extensions.h
@@ -86,6 +86,31 @@ TALER_extensions_load_taler_config (
const struct GNUNET_CONFIGURATION_Handle *cfg);
/*
+ * Check the given obj to be a valid extension object and fill the fields
+ * accordingly.
+ */
+enum GNUNET_GenericReturnValue
+TALER_extensions_is_json_config (
+ json_t *obj,
+ int *critical,
+ const char **version,
+ json_t **config);
+
+/*
+ * Sets the configuration of the extensions from a given JSON object.
+ *
+ * he JSON object must be of type ExchangeKeysResponse as described in
+ * https://docs.taler.net/design-documents/006-extensions.html#exchange
+ *
+ * @param cfg JSON object containting the configuration for all extensions
+ * @return GNUNET_OK on success, GNUNET_SYSERR if unknown extensions were found
+ * or any particular configuration couldn't be parsed.
+ */
+enum GNUNET_GenericReturnValue
+TALER_extensions_load_json_config (
+ json_t *cfg);
+
+/*
* Returns the head of the linked list of extensions
*/
const struct TALER_Extension *
@@ -156,20 +181,6 @@ TALER_extensions_verify_json_config_signature (
struct TALER_MasterSignatureP *extensions_sig,
struct TALER_MasterPublicKeyP *master_pub);
-/*
- * Sets the configuration of the extensions from a given JSON object.
- *
- * The JSON object must be of type ExchangeKeysResponse as described in
- * https://docs.taler.net/design-documents/006-extensions.html#exchange
- *
- * @param cfg Handle to the TALER configuration
- * @return GNUNET_OK on success, GNUNET_SYSERR if unknown extensions were found
- * or any particular configuration couldn't be parsed.
- */
-enum GNUNET_GenericReturnValue
-TALER_extensions_load_json_config (
- json_t *extensions);
-
/*
* TALER Age Restriction Extension
@@ -221,6 +232,45 @@ char *
TALER_age_mask_to_string (
const struct TALER_AgeMask *mask);
+/**
+ * Returns true when age restriction is configured and enabled.
+ */
+bool
+TALER_extensions_age_restriction_is_enabled ();
+
+/**
+ * Returns true when age restriction is configured (might not be _enabled_,
+ * though).
+ */
+bool
+TALER_extensions_age_restriction_is_configured ();
+
+/**
+ * Returns the currently set age mask. Note that even if age restriction is
+ * not enabled, the age mask might be have a non-zero value.
+ */
+struct TALER_AgeMask
+TALER_extensions_age_restriction_ageMask ();
+
+
+/**
+ * Returns the amount of age groups defined. 0 means no age restriction
+ * enabled.
+ */
+size_t
+TALER_extensions_age_restriction_num_groups ();
+
+/**
+ * Parses a JSON object { "age_groups": "a:b:...y:z" }.
+ *
+ * @param root is the json object
+ * @param[out] mask on succes, will contain the age mask
+ * @return #GNUNET_OK on success and #GNUNET_SYSERR on failure.
+ */
+enum GNUNET_GenericReturnValue
+TALER_JSON_parse_age_groups (const json_t *root,
+ struct TALER_AgeMask *mask);
+
/*
* TODO: Add Peer2Peer Extension
diff --git a/src/include/taler_json_lib.h b/src/include/taler_json_lib.h
index b7bcd845f..e3e47222b 100644
--- a/src/include/taler_json_lib.h
+++ b/src/include/taler_json_lib.h
@@ -608,17 +608,6 @@ TALER_JSON_extensions_config_hash (const json_t *config,
struct TALER_ExtensionConfigHash *eh);
/**
- * Parses a JSON object `{ "extension": "age_restriction", "mask": uint32 }`.
- *
- * @param root is the json object
- * @param[out] mask on succes, will contain the age mask
- * @return #GNUNET_OK on success and #GNUNET_SYSERR on failure.
- */
-enum GNUNET_GenericReturnValue
-TALER_JSON_parse_agemask (const json_t *root,
- struct TALER_AgeMask *mask);
-
-/**
* Canonicalize a JSON input to a string according to RFC 8785.
*/
char *
diff --git a/src/include/taler_signatures.h b/src/include/taler_signatures.h
index 17ed4b57a..e3d9a8939 100644
--- a/src/include/taler_signatures.h
+++ b/src/include/taler_signatures.h
@@ -419,6 +419,11 @@ struct TALER_LinkDataPS
struct TALER_TransferPublicKeyP transfer_pub;
/**
+ * Hash of the age commitment, if applicable. Can be all zero
+ */
+ struct TALER_AgeCommitmentHash h_age_commitment;
+
+ /**
* Hash of the blinded new coin.
*/
struct TALER_BlindedCoinHash coin_envelope_hash;
@@ -477,6 +482,12 @@ struct TALER_DepositRequestPS
struct TALER_PrivateContractHash h_contract_terms GNUNET_PACKED;
/**
+ * Hash over the age commitment that went into the coin. Maybe all zero, if
+ * age commitment isn't applicable to the denomination.
+ */
+ struct TALER_AgeCommitmentHash h_age_commitment GNUNET_PACKED;
+
+ /**
* Hash over extension attributes shared with the exchange.
*/
struct TALER_ExtensionContractHash h_extensions GNUNET_PACKED;
@@ -710,6 +721,13 @@ struct TALER_RefreshMeltCoinAffirmationPS
struct TALER_DenominationHash h_denom_pub GNUNET_PACKED;
/**
+ * If age commitment was provided during the withdrawal of the coin, this is
+ * the hash of the age commitment vector. It must be all zeroes if no age
+ * commitment was provided.
+ */
+ struct TALER_AgeCommitmentHash h_age_commitment GNUNET_PACKED;
+
+ /**
* How much of the value of the coin should be melted? This amount
* includes the fees, so the final amount contributed to the melt is
* this value minus the fee for melting the coin. We include the
diff --git a/src/include/taler_testing_lib.h b/src/include/taler_testing_lib.h
index 69cb9f68f..ab8b64fc5 100644
--- a/src/include/taler_testing_lib.h
+++ b/src/include/taler_testing_lib.h
@@ -66,11 +66,13 @@ TALER_TESTING_make_wire_details (const char *payto);
*
* @param keys array of keys to search
* @param amount coin value to look for
+ * @param age_restricted must the denomination be age restricted?
* @return NULL if no matching key was found
*/
const struct TALER_EXCHANGE_DenomPublicKey *
TALER_TESTING_find_pk (const struct TALER_EXCHANGE_Keys *keys,
- const struct TALER_Amount *amount);
+ const struct TALER_Amount *amount,
+ bool age_restricted);
/**
@@ -1278,6 +1280,7 @@ TALER_TESTING_cmd_exec_transfer (const char *label,
* @param label command label.
* @param reserve_reference command providing us with a reserve to withdraw from
* @param amount how much we withdraw.
+ * @param age if > 0, age restriction applies
* @param expected_response_code which HTTP response code
* we expect from the exchange.
* @return the withdraw command to be executed by the interpreter.
@@ -1286,6 +1289,7 @@ struct TALER_TESTING_Command
TALER_TESTING_cmd_withdraw_amount (const char *label,
const char *reserve_reference,
const char *amount,
+ uint8_t age,
unsigned int expected_response_code);
@@ -1298,6 +1302,7 @@ TALER_TESTING_cmd_withdraw_amount (const char *label,
* @param label command label.
* @param reserve_reference command providing us with a reserve to withdraw from
* @param amount how much we withdraw.
+ * @param age if > 0, age restriction applies.
* @param coin_ref reference to (withdraw/reveal) command of a coin
* from which we should re-use the private key
* @param expected_response_code which HTTP response code
@@ -1309,6 +1314,7 @@ TALER_TESTING_cmd_withdraw_amount_reuse_key (
const char *label,
const char *reserve_reference,
const char *amount,
+ uint8_t age,
const char *coin_ref,
unsigned int expected_response_code);
@@ -2138,6 +2144,19 @@ TALER_TESTING_cmd_wire_del (const char *label,
unsigned int expected_http_status,
bool bad_sig);
+/**
+ * Sign all extensions that the exchange has to offer, f. e. the extension for
+ * age restriction. This has to be run before any withdrawal of age restricted
+ * can be performed.
+ *
+ * @param label command label.
+ * @param config_filename configuration filename.
+ * @return the command
+ */
+struct TALER_TESTING_Command
+TALER_TESTING_cmd_exec_offline_sign_extensions (const char *label,
+ const char *config_filename);
+
/**
* Sign all exchange denomination and online signing keys
@@ -2422,10 +2441,10 @@ TALER_TESTING_get_trait (const struct TALER_TESTING_Trait *traits,
*/
#define TALER_TESTING_SIMPLE_TRAITS(op) \
op (bank_row, const uint64_t) \
- op (reserve_priv, const struct TALER_ReservePrivateKeyP) \
- op (planchet_secret, const struct TALER_PlanchetMasterSecretP) \
- op (refresh_secret, const struct TALER_RefreshMasterSecretP) \
- op (reserve_pub, const struct TALER_ReservePublicKeyP) \
+ op (reserve_priv, const struct TALER_ReservePrivateKeyP) \
+ op (planchet_secret, const struct TALER_PlanchetMasterSecretP) \
+ op (refresh_secret, const struct TALER_RefreshMasterSecretP) \
+ op (reserve_pub, const struct TALER_ReservePublicKeyP) \
op (merchant_priv, const struct TALER_MerchantPrivateKeyP) \
op (merchant_pub, const struct TALER_MerchantPublicKeyP) \
op (merchant_sig, const struct TALER_MerchantSignatureP) \
@@ -2438,8 +2457,8 @@ TALER_TESTING_get_trait (const struct TALER_TESTING_Trait *traits,
op (exchange_bank_account_url, const char *) \
op (taler_uri, const char *) \
op (payto_uri, const char *) \
- op (kyc_url, const char *) \
- op (web_url, const char *) \
+ op (kyc_url, const char *) \
+ op (web_url, const char *) \
op (row, const uint64_t) \
op (payment_target_uuid, const uint64_t) \
op (array_length, const unsigned int) \
@@ -2464,7 +2483,9 @@ TALER_TESTING_get_trait (const struct TALER_TESTING_Trait *traits,
#define TALER_TESTING_INDEXED_TRAITS(op) \
op (denom_pub, const struct TALER_EXCHANGE_DenomPublicKey) \
op (denom_sig, const struct TALER_DenominationSignature) \
- op (planchet_secrets, const struct TALER_PlanchetMasterSecretP) \
+ op (age_commitment, struct TALER_AgeCommitment) \
+ op (h_age_commitment, struct TALER_AgeCommitmentHash) \
+ op (planchet_secrets, const struct TALER_PlanchetMasterSecretP) \
op (exchange_wd_value, const struct TALER_ExchangeWithdrawValues) \
op (coin_priv, const struct TALER_CoinSpendPrivateKeyP) \
op (coin_pub, const struct TALER_CoinSpendPublicKeyP) \