exchange

Base system with REST service to issue digital coins, run by the payment service provider
Log | Files | Refs | Submodules | README | LICENSE

wallet_signatures.c (61792B)


      1 /*
      2   This file is part of TALER
      3   Copyright (C) 2021-2023 Taler Systems SA
      4 
      5   TALER is free software; you can redistribute it and/or modify it under the
      6   terms of the GNU General Public License as published by the Free Software
      7   Foundation; either version 3, or (at your option) any later version.
      8 
      9   TALER is distributed in the hope that it will be useful, but WITHOUT ANY
     10   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
     11   A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
     12 
     13   You should have received a copy of the GNU General Public License along with
     14   TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
     15 */
     16 /**
     17  * @file wallet_signatures.c
     18  * @brief Utility functions for Taler wallet signatures
     19  * @author Christian Grothoff
     20  * @author Özgür Kesim
     21  */
     22 #include "taler/platform.h"
     23 #include "taler/taler_util.h"
     24 #include "taler/taler_signatures.h"
     25 #include <gnunet/gnunet_common.h>
     26 #include <stdint.h>
     27 
     28 
     29 GNUNET_NETWORK_STRUCT_BEGIN
     30 
     31 /**
     32  * @brief Format used to generate the signature on a request to deposit
     33  * a coin into the account of a merchant.
     34  */
     35 struct TALER_DepositRequestPS
     36 {
     37   /**
     38    * Purpose must be #TALER_SIGNATURE_WALLET_COIN_DEPOSIT.
     39    * Used for an EdDSA signature with the `struct TALER_CoinSpendPublicKeyP`.
     40    */
     41   struct GNUNET_CRYPTO_SignaturePurpose purpose;
     42 
     43   /**
     44    * Hash over the contract for which this deposit is made.
     45    */
     46   struct TALER_PrivateContractHashP h_contract_terms GNUNET_PACKED;
     47 
     48   /**
     49    * Hash over the age commitment that went into the coin. Maybe all zero, if
     50    * age commitment isn't applicable to the denomination.
     51    */
     52   struct TALER_AgeCommitmentHashP h_age_commitment GNUNET_PACKED;
     53 
     54   /**
     55    * Hash over optional policy extension attributes shared with the exchange.
     56    */
     57   struct TALER_ExtensionPolicyHashP h_policy GNUNET_PACKED;
     58 
     59   /**
     60    * Hash over the wiring information of the merchant.
     61    */
     62   struct TALER_MerchantWireHashP h_wire GNUNET_PACKED;
     63 
     64   /**
     65    * Hash over the denomination public key used to sign the coin.
     66    */
     67   struct TALER_DenominationHashP h_denom_pub GNUNET_PACKED;
     68 
     69   /**
     70    * Time when this request was generated.  Used, for example, to
     71    * assess when (roughly) the income was achieved for tax purposes.
     72    * Note that the Exchange will only check that the timestamp is not "too
     73    * far" into the future (i.e. several days).  The fact that the
     74    * timestamp falls within the validity period of the coin's
     75    * denomination key is irrelevant for the validity of the deposit
     76    * request, as obviously the customer and merchant could conspire to
     77    * set any timestamp.  Also, the Exchange must accept very old deposit
     78    * requests, as the merchant might have been unable to transmit the
     79    * deposit request in a timely fashion (so back-dating is not
     80    * prevented).
     81    */
     82   struct GNUNET_TIME_TimestampNBO wallet_timestamp;
     83 
     84   /**
     85    * How much time does the merchant have to issue a refund request?
     86    * Zero if refunds are not allowed.  After this time, the coin
     87    * cannot be refunded.
     88    */
     89   struct GNUNET_TIME_TimestampNBO refund_deadline;
     90 
     91   /**
     92    * Amount to be deposited, including deposit fee charged by the
     93    * exchange.  This is the total amount that the coin's value at the exchange
     94    * will be reduced by.
     95    */
     96   struct TALER_AmountNBO amount_with_fee;
     97 
     98   /**
     99    * Depositing fee charged by the exchange.  This must match the Exchange's
    100    * denomination key's depositing fee.  If the client puts in an
    101    * invalid deposit fee (too high or too low) that does not match the
    102    * Exchange's denomination key, the deposit operation is invalid and
    103    * will be rejected by the exchange.  The @e amount_with_fee minus the
    104    * @e deposit_fee is the amount that will be transferred to the
    105    * account identified by @e h_wire.
    106    */
    107   struct TALER_AmountNBO deposit_fee;
    108 
    109   /**
    110    * The Merchant's public key.  Allows the merchant to later refund
    111    * the transaction or to inquire about the wire transfer identifier.
    112    */
    113   struct TALER_MerchantPublicKeyP merchant;
    114 
    115   /**
    116    * Hash over a JSON containing data provided by the
    117    * wallet to complete the contract upon payment.
    118    */
    119   struct GNUNET_HashCode wallet_data_hash;
    120 
    121 };
    122 
    123 GNUNET_NETWORK_STRUCT_END
    124 
    125 void
    126 TALER_wallet_deposit_sign (
    127   const struct TALER_Amount *amount,
    128   const struct TALER_Amount *deposit_fee,
    129   const struct TALER_MerchantWireHashP *h_wire,
    130   const struct TALER_PrivateContractHashP *h_contract_terms,
    131   const struct GNUNET_HashCode *wallet_data_hash,
    132   const struct TALER_AgeCommitmentHashP *h_age_commitment,
    133   const struct TALER_ExtensionPolicyHashP *h_policy,
    134   const struct TALER_DenominationHashP *h_denom_pub,
    135   const struct GNUNET_TIME_Timestamp wallet_timestamp,
    136   const struct TALER_MerchantPublicKeyP *merchant_pub,
    137   const struct GNUNET_TIME_Timestamp refund_deadline,
    138   const struct TALER_CoinSpendPrivateKeyP *coin_priv,
    139   struct TALER_CoinSpendSignatureP *coin_sig)
    140 {
    141   struct TALER_DepositRequestPS dr = {
    142     .purpose.size = htonl (sizeof (dr)),
    143     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_DEPOSIT),
    144     .h_contract_terms = *h_contract_terms,
    145     .h_wire = *h_wire,
    146     .h_denom_pub = *h_denom_pub,
    147     .wallet_timestamp = GNUNET_TIME_timestamp_hton (wallet_timestamp),
    148     .refund_deadline = GNUNET_TIME_timestamp_hton (refund_deadline),
    149     .merchant = *merchant_pub
    150   };
    151 
    152   if (NULL != wallet_data_hash)
    153     dr.wallet_data_hash = *wallet_data_hash;
    154   if (NULL != h_age_commitment)
    155     dr.h_age_commitment = *h_age_commitment;
    156   if (NULL != h_policy)
    157     dr.h_policy = *h_policy;
    158   TALER_amount_hton (&dr.amount_with_fee,
    159                      amount);
    160   TALER_amount_hton (&dr.deposit_fee,
    161                      deposit_fee);
    162   GNUNET_CRYPTO_eddsa_sign (&coin_priv->eddsa_priv,
    163                             &dr,
    164                             &coin_sig->eddsa_signature);
    165 }
    166 
    167 
    168 enum GNUNET_GenericReturnValue
    169 TALER_wallet_deposit_verify (
    170   const struct TALER_Amount *amount,
    171   const struct TALER_Amount *deposit_fee,
    172   const struct TALER_MerchantWireHashP *h_wire,
    173   const struct TALER_PrivateContractHashP *h_contract_terms,
    174   const struct GNUNET_HashCode *wallet_data_hash,
    175   const struct TALER_AgeCommitmentHashP *h_age_commitment,
    176   const struct TALER_ExtensionPolicyHashP *h_policy,
    177   const struct TALER_DenominationHashP *h_denom_pub,
    178   struct GNUNET_TIME_Timestamp wallet_timestamp,
    179   const struct TALER_MerchantPublicKeyP *merchant_pub,
    180   struct GNUNET_TIME_Timestamp refund_deadline,
    181   const struct TALER_CoinSpendPublicKeyP *coin_pub,
    182   const struct TALER_CoinSpendSignatureP *coin_sig)
    183 {
    184   struct TALER_DepositRequestPS dr = {
    185     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_DEPOSIT),
    186     .purpose.size = htonl (sizeof (dr)),
    187     .h_contract_terms = *h_contract_terms,
    188     .h_wire = *h_wire,
    189     .h_denom_pub = *h_denom_pub,
    190     .wallet_timestamp = GNUNET_TIME_timestamp_hton (wallet_timestamp),
    191     .refund_deadline = GNUNET_TIME_timestamp_hton (refund_deadline),
    192     .merchant = *merchant_pub,
    193   };
    194 
    195   if (NULL != wallet_data_hash)
    196     dr.wallet_data_hash = *wallet_data_hash;
    197   if (NULL != h_age_commitment)
    198     dr.h_age_commitment = *h_age_commitment;
    199   if (NULL != h_policy)
    200     dr.h_policy = *h_policy;
    201   TALER_amount_hton (&dr.amount_with_fee,
    202                      amount);
    203   TALER_amount_hton (&dr.deposit_fee,
    204                      deposit_fee);
    205   if (GNUNET_OK !=
    206       GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_COIN_DEPOSIT,
    207                                   &dr,
    208                                   &coin_sig->eddsa_signature,
    209                                   &coin_pub->eddsa_pub))
    210   {
    211     GNUNET_break_op (0);
    212     return GNUNET_SYSERR;
    213   }
    214   return GNUNET_OK;
    215 }
    216 
    217 
    218 GNUNET_NETWORK_STRUCT_BEGIN
    219 
    220 /**
    221  * @brief Format used for to allow the wallet to authenticate
    222  * link data provided by the exchange.
    223  */
    224 struct TALER_LinkDataPS
    225 {
    226 
    227   /**
    228    * Purpose must be #TALER_SIGNATURE_WALLET_COIN_LINK.
    229    * Used with an EdDSA signature of a `struct TALER_CoinPublicKeyP`.
    230    */
    231   struct GNUNET_CRYPTO_SignaturePurpose purpose;
    232 
    233   /**
    234    * Hash of the denomination public key of the new coin.
    235    */
    236   struct TALER_DenominationHashP h_denom_pub;
    237 
    238   /**
    239    * Transfer public key (for which the private key was not revealed)
    240    */
    241   struct TALER_TransferPublicKeyP transfer_pub;
    242 
    243   /**
    244    * Hash of the age commitment, if applicable.  Can be all zero
    245    */
    246   struct TALER_AgeCommitmentHashP h_age_commitment;
    247 
    248   /**
    249    * Hash of the blinded new coin.
    250    */
    251   struct TALER_BlindedCoinHashP coin_envelope_hash;
    252 };
    253 
    254 GNUNET_NETWORK_STRUCT_END
    255 
    256 void
    257 TALER_wallet_link_sign (const struct TALER_DenominationHashP *h_denom_pub,
    258                         const struct TALER_TransferPublicKeyP *transfer_pub,
    259                         const struct TALER_BlindedCoinHashP *bch,
    260                         const struct TALER_CoinSpendPrivateKeyP *old_coin_priv,
    261                         struct TALER_CoinSpendSignatureP *coin_sig)
    262 {
    263   struct TALER_LinkDataPS ldp = {
    264     .purpose.size = htonl (sizeof (ldp)),
    265     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_LINK),
    266     .h_denom_pub = *h_denom_pub,
    267     .transfer_pub = *transfer_pub,
    268     .coin_envelope_hash = *bch
    269   };
    270 
    271   GNUNET_CRYPTO_eddsa_sign (&old_coin_priv->eddsa_priv,
    272                             &ldp,
    273                             &coin_sig->eddsa_signature);
    274 }
    275 
    276 
    277 enum GNUNET_GenericReturnValue
    278 TALER_wallet_link_verify (
    279   const struct TALER_DenominationHashP *h_denom_pub,
    280   const struct TALER_TransferPublicKeyP *transfer_pub,
    281   const struct TALER_BlindedCoinHashP *h_coin_ev,
    282   const struct TALER_CoinSpendPublicKeyP *old_coin_pub,
    283   const struct TALER_CoinSpendSignatureP *coin_sig)
    284 {
    285   struct TALER_LinkDataPS ldp = {
    286     .purpose.size = htonl (sizeof (ldp)),
    287     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_LINK),
    288     .h_denom_pub = *h_denom_pub,
    289     .transfer_pub = *transfer_pub,
    290     .coin_envelope_hash = *h_coin_ev,
    291   };
    292 
    293   return
    294     GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_COIN_LINK,
    295                                 &ldp,
    296                                 &coin_sig->eddsa_signature,
    297                                 &old_coin_pub->eddsa_pub);
    298 }
    299 
    300 
    301 GNUNET_NETWORK_STRUCT_BEGIN
    302 
    303 /**
    304  * Signed data to request that a coin should be refunded as part of
    305  * the "emergency" /recoup protocol.  The refund will go back to the bank
    306  * account that created the reserve.
    307  */
    308 struct TALER_RecoupRequestPS
    309 {
    310   /**
    311    * Purpose is #TALER_SIGNATURE_WALLET_COIN_RECOUP
    312    * or #TALER_SIGNATURE_WALLET_COIN_RECOUP_REFRESH.
    313    */
    314   struct GNUNET_CRYPTO_SignaturePurpose purpose;
    315 
    316   /**
    317    * Hash of the (revoked) denomination public key of the coin.
    318    */
    319   struct TALER_DenominationHashP h_denom_pub;
    320 
    321   /**
    322    * Blinding factor that was used to withdraw the coin.
    323    */
    324   union GNUNET_CRYPTO_BlindingSecretP coin_blind;
    325 
    326 };
    327 
    328 GNUNET_NETWORK_STRUCT_END
    329 
    330 
    331 enum GNUNET_GenericReturnValue
    332 TALER_wallet_recoup_verify (
    333   const struct TALER_DenominationHashP *h_denom_pub,
    334   const union GNUNET_CRYPTO_BlindingSecretP *coin_bks,
    335   const struct TALER_CoinSpendPublicKeyP *coin_pub,
    336   const struct TALER_CoinSpendSignatureP *coin_sig)
    337 {
    338   struct TALER_RecoupRequestPS pr = {
    339     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_RECOUP),
    340     .purpose.size = htonl (sizeof (pr)),
    341     .h_denom_pub = *h_denom_pub,
    342     .coin_blind = *coin_bks
    343   };
    344 
    345   return GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_COIN_RECOUP,
    346                                      &pr,
    347                                      &coin_sig->eddsa_signature,
    348                                      &coin_pub->eddsa_pub);
    349 }
    350 
    351 
    352 void
    353 TALER_wallet_recoup_sign (
    354   const struct TALER_DenominationHashP *h_denom_pub,
    355   const union GNUNET_CRYPTO_BlindingSecretP *coin_bks,
    356   const struct TALER_CoinSpendPrivateKeyP *coin_priv,
    357   struct TALER_CoinSpendSignatureP *coin_sig)
    358 {
    359   struct TALER_RecoupRequestPS pr = {
    360     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_RECOUP),
    361     .purpose.size = htonl (sizeof (pr)),
    362     .h_denom_pub = *h_denom_pub,
    363     .coin_blind = *coin_bks
    364   };
    365 
    366   GNUNET_CRYPTO_eddsa_sign (&coin_priv->eddsa_priv,
    367                             &pr,
    368                             &coin_sig->eddsa_signature);
    369 }
    370 
    371 
    372 enum GNUNET_GenericReturnValue
    373 TALER_wallet_recoup_refresh_verify (
    374   const struct TALER_DenominationHashP *h_denom_pub,
    375   const union GNUNET_CRYPTO_BlindingSecretP *coin_bks,
    376   const struct TALER_CoinSpendPublicKeyP *coin_pub,
    377   const struct TALER_CoinSpendSignatureP *coin_sig)
    378 {
    379   struct TALER_RecoupRequestPS pr = {
    380     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_RECOUP_REFRESH),
    381     .purpose.size = htonl (sizeof (pr)),
    382     .h_denom_pub = *h_denom_pub,
    383     .coin_blind = *coin_bks
    384   };
    385 
    386   return GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_COIN_RECOUP_REFRESH,
    387                                      &pr,
    388                                      &coin_sig->eddsa_signature,
    389                                      &coin_pub->eddsa_pub);
    390 }
    391 
    392 
    393 void
    394 TALER_wallet_recoup_refresh_sign (
    395   const struct TALER_DenominationHashP *h_denom_pub,
    396   const union GNUNET_CRYPTO_BlindingSecretP *coin_bks,
    397   const struct TALER_CoinSpendPrivateKeyP *coin_priv,
    398   struct TALER_CoinSpendSignatureP *coin_sig)
    399 {
    400   struct TALER_RecoupRequestPS pr = {
    401     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_RECOUP_REFRESH),
    402     .purpose.size = htonl (sizeof (struct TALER_RecoupRequestPS)),
    403     .h_denom_pub = *h_denom_pub,
    404     .coin_blind = *coin_bks
    405   };
    406 
    407   GNUNET_CRYPTO_eddsa_sign (&coin_priv->eddsa_priv,
    408                             &pr,
    409                             &coin_sig->eddsa_signature);
    410 }
    411 
    412 
    413 GNUNET_NETWORK_STRUCT_BEGIN
    414 
    415 /**
    416  * @brief Message signed by a coin to indicate that the coin should be
    417  * melted.
    418  */
    419 struct TALER_RefreshMeltCoinAffirmationPS
    420 {
    421   /**
    422    * Purpose is #TALER_SIGNATURE_WALLET_COIN_MELT.
    423    * Used for an EdDSA signature with the `struct TALER_CoinSpendPublicKeyP`.
    424    */
    425   struct GNUNET_CRYPTO_SignaturePurpose purpose;
    426 
    427   /**
    428    * Which melt commitment is made by the wallet.
    429    */
    430   struct TALER_RefreshCommitmentP rc GNUNET_PACKED;
    431 
    432   /**
    433    * Hash over the denomination public key used to sign the coin.
    434    */
    435   struct TALER_DenominationHashP h_denom_pub GNUNET_PACKED;
    436 
    437   /**
    438    * If age commitment was provided during the withdrawal of the coin, this is
    439    * the hash of the age commitment vector.  It must be all zeroes if no age
    440    * commitment was provided.
    441    */
    442   struct TALER_AgeCommitmentHashP h_age_commitment GNUNET_PACKED;
    443 
    444   /**
    445    * How much of the value of the coin should be melted?  This amount
    446    * includes the fees, so the final amount contributed to the melt is
    447    * this value minus the fee for melting the coin.  We include the
    448    * fee in what is being signed so that we can verify a reserve's
    449    * remaining total balance without needing to access the respective
    450    * denomination key information each time.
    451    */
    452   struct TALER_AmountNBO amount_with_fee;
    453 
    454   /**
    455    * Melting fee charged by the exchange.  This must match the Exchange's
    456    * denomination key's melting fee.  If the client puts in an invalid
    457    * melting fee (too high or too low) that does not match the Exchange's
    458    * denomination key, the melting operation is invalid and will be
    459    * rejected by the exchange.  The @e amount_with_fee minus the @e
    460    * melt_fee is the amount that will be credited to the melting
    461    * session.
    462    */
    463   struct TALER_AmountNBO melt_fee;
    464 };
    465 
    466 GNUNET_NETWORK_STRUCT_END
    467 
    468 void
    469 TALER_wallet_melt_sign (
    470   const struct TALER_Amount *amount_with_fee,
    471   const struct TALER_Amount *melt_fee,
    472   const struct TALER_RefreshCommitmentP *rc,
    473   const struct TALER_DenominationHashP *h_denom_pub,
    474   const struct TALER_AgeCommitmentHashP *h_age_commitment,
    475   const struct TALER_CoinSpendPrivateKeyP *coin_priv,
    476   struct TALER_CoinSpendSignatureP *coin_sig)
    477 {
    478   struct TALER_RefreshMeltCoinAffirmationPS melt = {
    479     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_MELT),
    480     .purpose.size = htonl (sizeof (melt)),
    481     .rc = *rc,
    482     .h_denom_pub = *h_denom_pub
    483   };
    484 
    485   if (NULL != h_age_commitment)
    486     melt.h_age_commitment = *h_age_commitment;
    487   TALER_amount_hton (&melt.amount_with_fee,
    488                      amount_with_fee);
    489   TALER_amount_hton (&melt.melt_fee,
    490                      melt_fee);
    491   GNUNET_CRYPTO_eddsa_sign (&coin_priv->eddsa_priv,
    492                             &melt,
    493                             &coin_sig->eddsa_signature);
    494 }
    495 
    496 
    497 enum GNUNET_GenericReturnValue
    498 TALER_wallet_melt_verify (
    499   const struct TALER_Amount *amount_with_fee,
    500   const struct TALER_Amount *melt_fee,
    501   const struct TALER_RefreshCommitmentP *rc,
    502   const struct TALER_DenominationHashP *h_denom_pub,
    503   const struct TALER_AgeCommitmentHashP *h_age_commitment,
    504   const struct TALER_CoinSpendPublicKeyP *coin_pub,
    505   const struct TALER_CoinSpendSignatureP *coin_sig)
    506 {
    507   struct TALER_RefreshMeltCoinAffirmationPS melt = {
    508     .purpose.size = htonl (sizeof (melt)),
    509     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_MELT),
    510     .rc = *rc,
    511     .h_denom_pub = *h_denom_pub
    512   };
    513 
    514   if (NULL != h_age_commitment)
    515     melt.h_age_commitment = *h_age_commitment;
    516   TALER_amount_hton (&melt.amount_with_fee,
    517                      amount_with_fee);
    518   TALER_amount_hton (&melt.melt_fee,
    519                      melt_fee);
    520   return GNUNET_CRYPTO_eddsa_verify (
    521     TALER_SIGNATURE_WALLET_COIN_MELT,
    522     &melt,
    523     &coin_sig->eddsa_signature,
    524     &coin_pub->eddsa_pub);
    525 }
    526 
    527 
    528 GNUNET_NETWORK_STRUCT_BEGIN
    529 
    530 /**
    531  * @brief Format used for to generate the signature on a refresh nonce,
    532  *  a) to prove ownership of the old coin's private key and
    533  *  b) to derive the planchet master secrets for the batch of fresh coins
    534  */
    535 struct TALER_RefreshNonceSignaturePS
    536 {
    537 
    538   /**
    539    * Purpose must be #TALER_SIGNATURE_WALLET_COIN_LINK
    540    */
    541   struct GNUNET_CRYPTO_SignaturePurpose purpose;
    542 
    543   /**
    544    * The nonce to sign
    545    */
    546   struct TALER_PublicRefreshNonceP nonce GNUNET_PACKED;
    547 
    548   /**
    549    * The running hash of the (hashes of) denomination public keys
    550    */
    551   struct GNUNET_HashCode h_denoms_h GNUNET_PACKED;
    552 
    553   /**
    554    * The kappa index for this signature, in NBO
    555    */
    556   uint32_t kappa_index GNUNET_PACKED;
    557 };
    558 
    559 GNUNET_NETWORK_STRUCT_END
    560 
    561 
    562 void
    563 TALER_wallet_refresh_nonce_sign (
    564   const struct TALER_CoinSpendPrivateKeyP *old_coin_priv,
    565   const struct TALER_PublicRefreshNonceP *nonce,
    566   size_t num_denoms_h,
    567   const struct TALER_DenominationHashP *denoms_h[static num_denoms_h],
    568   uint8_t kappa_index,
    569   struct TALER_PrivateRefreshNonceSignatureP *sig)
    570 {
    571   struct TALER_RefreshNonceSignaturePS req = {
    572     .purpose.size = htonl (sizeof (req)),
    573     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_LINK),
    574     .nonce = *nonce,
    575     .kappa_index = htonl (kappa_index),
    576   };
    577   struct GNUNET_HashContext *ctx = GNUNET_CRYPTO_hash_context_start ();
    578   GNUNET_assert (ctx);
    579 
    580   for (size_t i = 0; i<num_denoms_h; i++)
    581     GNUNET_CRYPTO_hash_context_read (ctx,
    582                                      denoms_h[i],
    583                                      sizeof(*denoms_h[i]));
    584 
    585   GNUNET_CRYPTO_hash_context_finish (ctx,
    586                                      &req.h_denoms_h);
    587   GNUNET_CRYPTO_eddsa_sign (&old_coin_priv->eddsa_priv,
    588                             &req,
    589                             &sig->coin_sig.eddsa_signature);
    590 }
    591 
    592 
    593 enum GNUNET_GenericReturnValue
    594 TALER_wallet_refresh_nonce_verify (
    595   const struct TALER_CoinSpendPublicKeyP *old_coin_pub,
    596   const struct TALER_PublicRefreshNonceP *nonce,
    597   size_t num_denoms_h,
    598   struct TALER_DenominationHashP *const denoms_h[static num_denoms_h],
    599   uint8_t kappa_index,
    600   const struct TALER_PrivateRefreshNonceSignatureP *sig)
    601 {
    602   struct TALER_RefreshNonceSignaturePS req = {
    603     .purpose.size = htonl (sizeof (req)),
    604     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_LINK),
    605     .nonce = *nonce,
    606     .kappa_index = htonl (kappa_index),
    607   };
    608   struct GNUNET_HashContext *ctx = GNUNET_CRYPTO_hash_context_start ();
    609   GNUNET_assert (ctx);
    610 
    611   for (size_t i = 0; i<num_denoms_h; i++)
    612     GNUNET_CRYPTO_hash_context_read (ctx,
    613                                      denoms_h[i],
    614                                      sizeof(*denoms_h[i]));
    615 
    616   GNUNET_CRYPTO_hash_context_finish (ctx,
    617                                      &req.h_denoms_h);
    618   return GNUNET_CRYPTO_eddsa_verify (
    619     TALER_SIGNATURE_WALLET_COIN_LINK,
    620     &req,
    621     &sig->coin_sig.eddsa_signature,
    622     &old_coin_pub->eddsa_pub);
    623 }
    624 
    625 
    626 GNUNET_NETWORK_STRUCT_BEGIN
    627 
    628 
    629 /**
    630  * @brief Format used for to generate the signature on a request to withdraw
    631  * coins from a reserve.
    632  * @note: deprecated.  Will be removed at some point after v24 of the protocol.
    633  */
    634 struct TALER_WithdrawCommitmentPre24PS
    635 {
    636 
    637   /**
    638    * Purpose must be #TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW.
    639    * Used with an EdDSA signature of a `struct TALER_ReservePublicKeyP`.
    640    */
    641   struct GNUNET_CRYPTO_SignaturePurpose purpose;
    642 
    643   /**
    644    * Value of the coin being exchanged (matching the denomination key)
    645    * plus the transaction fee.  We include this in what is being
    646    * signed so that we can verify a reserve's remaining total balance
    647    * without needing to access the respective denomination key
    648    * information each time.
    649    */
    650   struct TALER_AmountNBO amount_with_fee;
    651 
    652   /**
    653    * Hash of the denomination public key for the coin that is withdrawn.
    654    */
    655   struct TALER_DenominationHashP h_denomination_pub GNUNET_PACKED;
    656 
    657   /**
    658    * Hash of the (blinded) message to be signed by the Exchange.
    659    */
    660   struct TALER_BlindedCoinHashP h_coin_envelope GNUNET_PACKED;
    661 };
    662 
    663 
    664 GNUNET_NETWORK_STRUCT_END
    665 
    666 void
    667 TALER_wallet_withdraw_sign_pre26 (
    668   const struct TALER_DenominationHashP *h_denom_pub,
    669   const struct TALER_Amount *amount_with_fee,
    670   const struct TALER_BlindedCoinHashP *bch,
    671   const struct TALER_ReservePrivateKeyP *reserve_priv,
    672   struct TALER_ReserveSignatureP *reserve_sig)
    673 {
    674   struct TALER_WithdrawCommitmentPre24PS req = {
    675     .purpose.size = htonl (sizeof (req)),
    676     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW),
    677     .h_denomination_pub = *h_denom_pub,
    678     .h_coin_envelope = *bch
    679   };
    680 
    681   TALER_amount_hton (&req.amount_with_fee,
    682                      amount_with_fee);
    683   GNUNET_CRYPTO_eddsa_sign (&reserve_priv->eddsa_priv,
    684                             &req,
    685                             &reserve_sig->eddsa_signature);
    686 }
    687 
    688 
    689 enum GNUNET_GenericReturnValue
    690 TALER_wallet_withdraw_verify_pre26 (
    691   const struct TALER_DenominationHashP *h_denom_pub,
    692   const struct TALER_Amount *amount_with_fee,
    693   const struct TALER_BlindedCoinHashP *bch,
    694   const struct TALER_ReservePublicKeyP *reserve_pub,
    695   const struct TALER_ReserveSignatureP *reserve_sig)
    696 {
    697   struct TALER_WithdrawCommitmentPre24PS req = {
    698     .purpose.size = htonl (sizeof (req)),
    699     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW),
    700     .h_denomination_pub = *h_denom_pub,
    701     .h_coin_envelope = *bch
    702   };
    703 
    704   TALER_amount_hton (&req.amount_with_fee,
    705                      amount_with_fee);
    706   return GNUNET_CRYPTO_eddsa_verify (
    707     TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW,
    708     &req,
    709     &reserve_sig->eddsa_signature,
    710     &reserve_pub->eddsa_pub);
    711 }
    712 
    713 
    714 GNUNET_NETWORK_STRUCT_BEGIN
    715 
    716 /**
    717  * @brief Format used for to generate the signature on a request to withdraw
    718  * coins from a reserve.
    719  *
    720  */
    721 struct TALER_WithdrawRequestPS
    722 {
    723   /**
    724    * Purpose is #TALER_SIGNATURE_WALLET_WITHDRAW
    725    */
    726   struct GNUNET_CRYPTO_SignaturePurpose purpose;
    727 
    728   /**
    729    * Total value of all coins being exchanged (matching the denomination keys),
    730    * without the fee.
    731    * Note that the reserve must have a value of at least amount+fee.
    732    */
    733   struct TALER_AmountNBO amount;
    734 
    735   /**
    736    * Total fee for the withdrawal.
    737    * Note that the reserve must have a value of at least amount+fee.
    738    */
    739   struct TALER_AmountNBO fee;
    740 
    741   /**
    742    * Running SHA512 hash of all TALER_BlindedCoinHashP's
    743    * of the of n coins, or n*kappa candidate coins in case of age restriction.
    744    * In the later case, the coins' hashes are arranged [0..num_coins)...[0..num_coins),
    745    * i.e. the coins are grouped per kappa-index.
    746    * Note that each coin's TALER_BlindedCoinHashP also captures
    747    * the hash of the public key of the corresponding denomination.
    748    */
    749   struct TALER_HashBlindedPlanchetsP h_planchets GNUNET_PACKED;
    750 
    751   /**
    752    * If any of the denominations is of cipher type Clause-Schnorr,
    753    * the client had to call /blinding-prepare prior to the withdraw
    754    * to retrieve public R-values for the CS signature scheme.
    755    * The input seed for that request must be provided here.
    756    * Otherwise, if no CS denomination is used, the struct must be all zeros.
    757    */
    758   struct TALER_BlindingMasterSeedP blinding_seed;
    759 
    760   /**
    761    * Maximum age group that the coins are going to be restricted to.
    762    * MUST be 0 if no age restriction applies.
    763    */
    764   uint32_t max_age_group;
    765 
    766   /**
    767    * The mask that defines the age groups.
    768    * MUST be the same for all denominations.
    769    * MUST be 0 if no age restriction applies.
    770    */
    771   struct TALER_AgeMask mask;
    772 
    773 };
    774 
    775 
    776 GNUNET_NETWORK_STRUCT_END
    777 
    778 void
    779 TALER_wallet_blinded_planchets_hash (
    780   size_t num_planchets,
    781   const struct TALER_BlindedPlanchet blinded_planchets[static num_planchets],
    782   const struct TALER_DenominationHashP h_denom_pubs[static num_planchets],
    783   struct TALER_HashBlindedPlanchetsP *h_planchets)
    784 {
    785   struct TALER_BlindedCoinHashP bch;
    786   struct GNUNET_HashContext *coins_hctx;
    787 
    788   GNUNET_assert (num_planchets > 0);
    789   GNUNET_assert (NULL != h_planchets);
    790 
    791   coins_hctx = GNUNET_CRYPTO_hash_context_start ();
    792   GNUNET_assert (NULL != coins_hctx);
    793 
    794   for (size_t i = 0; i < num_planchets; i++)
    795   {
    796     TALER_coin_ev_hash (
    797       &blinded_planchets[i],
    798       &h_denom_pubs[i],
    799       &bch);
    800     GNUNET_CRYPTO_hash_context_read (
    801       coins_hctx,
    802       &bch,
    803       sizeof(bch));
    804   }
    805 
    806   GNUNET_CRYPTO_hash_context_finish (
    807     coins_hctx,
    808     &h_planchets->hash);
    809 }
    810 
    811 
    812 void
    813 TALER_wallet_blinded_planchet_details_hash (
    814   size_t num_planchets,
    815   const struct TALER_PlanchetDetail planchet_details[static num_planchets],
    816   struct TALER_HashBlindedPlanchetsP *h_planchets)
    817 {
    818   struct TALER_BlindedCoinHashP bch;
    819   struct GNUNET_HashContext *coins_hctx;
    820 
    821   GNUNET_assert (num_planchets > 0);
    822   GNUNET_assert (NULL != h_planchets);
    823 
    824   coins_hctx = GNUNET_CRYPTO_hash_context_start ();
    825   GNUNET_assert (NULL != coins_hctx);
    826 
    827   for (size_t i = 0; i < num_planchets; i++)
    828   {
    829     TALER_coin_ev_hash (
    830       &planchet_details[i].blinded_planchet,
    831       &planchet_details[i].denom_pub_hash,
    832       &bch);
    833     GNUNET_CRYPTO_hash_context_read (
    834       coins_hctx,
    835       &bch,
    836       sizeof(bch));
    837   }
    838 
    839   GNUNET_CRYPTO_hash_context_finish (
    840     coins_hctx,
    841     &h_planchets->hash);
    842 }
    843 
    844 
    845 struct TALER_HashReservePublicKeyP
    846 TALER_wallet_hash_reserve_pub (
    847   const struct TALER_ReservePublicKeyP *reserve_pub)
    848 {
    849   struct TALER_HashReservePublicKeyP hr;
    850 
    851   GNUNET_CRYPTO_hash (reserve_pub,
    852                       sizeof(*reserve_pub),
    853                       &hr.hash);
    854   return hr;
    855 }
    856 
    857 
    858 void
    859 TALER_wallet_withdraw_sign (
    860   const struct TALER_Amount *amount,
    861   const struct TALER_Amount *fee,
    862   const struct TALER_HashBlindedPlanchetsP *h_planchets,
    863   const struct TALER_BlindingMasterSeedP *blinding_seed,
    864   const struct TALER_AgeMask *mask,
    865   uint8_t max_age,
    866   const struct TALER_ReservePrivateKeyP *reserve_priv,
    867   struct TALER_ReserveSignatureP *reserve_sig)
    868 {
    869   struct TALER_WithdrawRequestPS req = {
    870     .purpose.size = htonl (sizeof(req)),
    871     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW),
    872   };
    873 
    874   GNUNET_assert (NULL != h_planchets);
    875   req.h_planchets = *h_planchets;
    876   if (NULL != mask)
    877   {
    878     req.mask = *mask;
    879     req.max_age_group =
    880       TALER_get_age_group (mask,
    881                            max_age);
    882   }
    883   TALER_amount_hton (&req.amount,
    884                      amount);
    885   TALER_amount_hton (&req.fee,
    886                      fee);
    887   if (NULL != blinding_seed)
    888     req.blinding_seed = *blinding_seed;
    889 
    890   GNUNET_CRYPTO_eddsa_sign (
    891     &reserve_priv->eddsa_priv,
    892     &req,
    893     &reserve_sig->eddsa_signature);
    894 
    895 }
    896 
    897 
    898 enum GNUNET_GenericReturnValue
    899 TALER_wallet_withdraw_verify (
    900   const struct TALER_Amount *amount,
    901   const struct TALER_Amount *fee,
    902   const struct TALER_HashBlindedPlanchetsP *h_planchets,
    903   const struct TALER_BlindingMasterSeedP *blinding_seed,
    904   const struct TALER_AgeMask *mask,
    905   uint8_t max_age,
    906   const struct TALER_ReservePublicKeyP *reserve_pub,
    907   const struct TALER_ReserveSignatureP *reserve_sig)
    908 {
    909   struct TALER_WithdrawRequestPS req = {
    910     .purpose.size = htonl (sizeof(req)),
    911     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW),
    912   };
    913 
    914   GNUNET_assert (NULL != h_planchets);
    915   req.h_planchets = *h_planchets;
    916   if (NULL != mask)
    917   {
    918     req.mask = *mask;
    919     req.max_age_group =
    920       TALER_get_age_group (mask,
    921                            max_age);
    922   }
    923   TALER_amount_hton (&req.amount,
    924                      amount);
    925   TALER_amount_hton (&req.fee,
    926                      fee);
    927   if (NULL != blinding_seed)
    928     req.blinding_seed = *blinding_seed;
    929 
    930   return GNUNET_CRYPTO_eddsa_verify (
    931     TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW,
    932     &req,
    933     &reserve_sig->eddsa_signature,
    934     &reserve_pub->eddsa_pub);
    935 }
    936 
    937 
    938 GNUNET_NETWORK_STRUCT_BEGIN
    939 
    940 
    941 /**
    942  * @brief Format used for to generate the signature on a request to withdraw
    943  * coins from a reserve.
    944  */
    945 struct TALER_AccountSetupRequestSignaturePS
    946 {
    947 
    948   /**
    949    * Purpose must be #TALER_SIGNATURE_WALLET_ACCOUNT_SETUP.
    950    * Used with an EdDSA signature of a `struct TALER_ReservePublicKeyP`.
    951    */
    952   struct GNUNET_CRYPTO_SignaturePurpose purpose;
    953 
    954   /**
    955    * Balance threshold the wallet is about to cross.
    956    */
    957   struct TALER_AmountNBO threshold;
    958 
    959 };
    960 
    961 
    962 GNUNET_NETWORK_STRUCT_END
    963 
    964 
    965 void
    966 TALER_wallet_account_setup_sign (
    967   const struct TALER_ReservePrivateKeyP *reserve_priv,
    968   const struct TALER_Amount *balance_threshold,
    969   struct TALER_ReserveSignatureP *reserve_sig)
    970 {
    971   struct TALER_AccountSetupRequestSignaturePS asap = {
    972     .purpose.size = htonl (sizeof (asap)),
    973     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_ACCOUNT_SETUP)
    974   };
    975 
    976   TALER_amount_hton (&asap.threshold,
    977                      balance_threshold);
    978   GNUNET_CRYPTO_eddsa_sign (&reserve_priv->eddsa_priv,
    979                             &asap,
    980                             &reserve_sig->eddsa_signature);
    981 }
    982 
    983 
    984 enum GNUNET_GenericReturnValue
    985 TALER_wallet_account_setup_verify (
    986   const struct TALER_ReservePublicKeyP *reserve_pub,
    987   const struct TALER_Amount *balance_threshold,
    988   const struct TALER_ReserveSignatureP *reserve_sig)
    989 {
    990   struct TALER_AccountSetupRequestSignaturePS asap = {
    991     .purpose.size = htonl (sizeof (asap)),
    992     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_ACCOUNT_SETUP)
    993   };
    994 
    995   TALER_amount_hton (&asap.threshold,
    996                      balance_threshold);
    997   return GNUNET_CRYPTO_eddsa_verify (
    998     TALER_SIGNATURE_WALLET_ACCOUNT_SETUP,
    999     &asap,
   1000     &reserve_sig->eddsa_signature,
   1001     &reserve_pub->eddsa_pub);
   1002 }
   1003 
   1004 
   1005 GNUNET_NETWORK_STRUCT_BEGIN
   1006 
   1007 
   1008 /**
   1009  * Response by which a wallet requests a reserve history.
   1010  */
   1011 struct TALER_ReserveHistoryRequestPS
   1012 {
   1013 
   1014   /**
   1015    * Purpose is #TALER_SIGNATURE_WALLET_RESERVE_HISTORY
   1016    */
   1017   struct GNUNET_CRYPTO_SignaturePurpose purpose;
   1018 
   1019   /**
   1020    * Which entries to exclude. Only return above this offset.
   1021    */
   1022   uint64_t start_off;
   1023 
   1024 };
   1025 
   1026 GNUNET_NETWORK_STRUCT_END
   1027 
   1028 
   1029 enum GNUNET_GenericReturnValue
   1030 TALER_wallet_reserve_history_verify (
   1031   uint64_t start_off,
   1032   const struct TALER_ReservePublicKeyP *reserve_pub,
   1033   const struct TALER_ReserveSignatureP *reserve_sig)
   1034 {
   1035   struct TALER_ReserveHistoryRequestPS rhr = {
   1036     .purpose.size = htonl (sizeof (rhr)),
   1037     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_HISTORY),
   1038     .start_off = GNUNET_htonll (start_off)
   1039   };
   1040 
   1041   return GNUNET_CRYPTO_eddsa_verify (
   1042     TALER_SIGNATURE_WALLET_RESERVE_HISTORY,
   1043     &rhr,
   1044     &reserve_sig->eddsa_signature,
   1045     &reserve_pub->eddsa_pub);
   1046 }
   1047 
   1048 
   1049 void
   1050 TALER_wallet_reserve_history_sign (
   1051   uint64_t start_off,
   1052   const struct TALER_ReservePrivateKeyP *reserve_priv,
   1053   struct TALER_ReserveSignatureP *reserve_sig)
   1054 {
   1055   struct TALER_ReserveHistoryRequestPS rhr = {
   1056     .purpose.size = htonl (sizeof (rhr)),
   1057     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_HISTORY),
   1058     .start_off = GNUNET_htonll (start_off)
   1059   };
   1060 
   1061   GNUNET_CRYPTO_eddsa_sign (&reserve_priv->eddsa_priv,
   1062                             &rhr,
   1063                             &reserve_sig->eddsa_signature);
   1064 }
   1065 
   1066 
   1067 GNUNET_NETWORK_STRUCT_BEGIN
   1068 
   1069 /**
   1070  * Response by which a wallet requests a coin history.
   1071  */
   1072 struct TALER_CoinHistoryRequestPS
   1073 {
   1074 
   1075   /**
   1076    * Purpose is #TALER_SIGNATURE_WALLET_COIN_HISTORY
   1077    */
   1078   struct GNUNET_CRYPTO_SignaturePurpose purpose;
   1079 
   1080   /**
   1081    * Which entries to exclude. Only return above this offset.
   1082    */
   1083   uint64_t start_off;
   1084 
   1085 };
   1086 
   1087 GNUNET_NETWORK_STRUCT_END
   1088 
   1089 enum GNUNET_GenericReturnValue
   1090 TALER_wallet_coin_history_verify (
   1091   uint64_t start_off,
   1092   const struct TALER_CoinSpendPublicKeyP *coin_pub,
   1093   const struct TALER_CoinSpendSignatureP *coin_sig)
   1094 {
   1095   struct TALER_CoinHistoryRequestPS rsr = {
   1096     .purpose.size = htonl (sizeof (rsr)),
   1097     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_HISTORY),
   1098     .start_off = GNUNET_htonll (start_off)
   1099   };
   1100 
   1101   return GNUNET_CRYPTO_eddsa_verify (
   1102     TALER_SIGNATURE_WALLET_COIN_HISTORY,
   1103     &rsr,
   1104     &coin_sig->eddsa_signature,
   1105     &coin_pub->eddsa_pub);
   1106 }
   1107 
   1108 
   1109 void
   1110 TALER_wallet_coin_history_sign (
   1111   uint64_t start_off,
   1112   const struct TALER_CoinSpendPrivateKeyP *coin_priv,
   1113   struct TALER_CoinSpendSignatureP *coin_sig)
   1114 {
   1115   struct TALER_CoinHistoryRequestPS rsr = {
   1116     .purpose.size = htonl (sizeof (rsr)),
   1117     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_HISTORY),
   1118     .start_off = GNUNET_htonll (start_off)
   1119   };
   1120 
   1121   GNUNET_CRYPTO_eddsa_sign (&coin_priv->eddsa_priv,
   1122                             &rsr,
   1123                             &coin_sig->eddsa_signature);
   1124 }
   1125 
   1126 
   1127 GNUNET_NETWORK_STRUCT_BEGIN
   1128 
   1129 /**
   1130  * Message signed to create a purse (without reserve).
   1131  */
   1132 struct TALER_PurseCreatePS
   1133 {
   1134 
   1135   /**
   1136    * Purpose is #TALER_SIGNATURE_WALLET_PURSE_CREATE
   1137    */
   1138   struct GNUNET_CRYPTO_SignaturePurpose purpose;
   1139 
   1140   /**
   1141    * Time when the purse will expire if still unmerged or unpaid.
   1142    */
   1143   struct GNUNET_TIME_TimestampNBO purse_expiration;
   1144 
   1145   /**
   1146    * Total amount (with fees) to be put into the purse.
   1147    */
   1148   struct TALER_AmountNBO purse_amount;
   1149 
   1150   /**
   1151    * Contract this purse pays for.
   1152    */
   1153   struct TALER_PrivateContractHashP h_contract_terms;
   1154 
   1155   /**
   1156    * Public key identifying the merge capability.
   1157    */
   1158   struct TALER_PurseMergePublicKeyP merge_pub;
   1159 
   1160   /**
   1161    * Minimum age required for payments into this purse.
   1162    */
   1163   uint32_t min_age GNUNET_PACKED;
   1164 
   1165 };
   1166 
   1167 
   1168 GNUNET_NETWORK_STRUCT_END
   1169 
   1170 
   1171 void
   1172 TALER_wallet_purse_create_sign (
   1173   struct GNUNET_TIME_Timestamp purse_expiration,
   1174   const struct TALER_PrivateContractHashP *h_contract_terms,
   1175   const struct TALER_PurseMergePublicKeyP *merge_pub,
   1176   uint32_t min_age,
   1177   const struct TALER_Amount *amount,
   1178   const struct TALER_PurseContractPrivateKeyP *purse_priv,
   1179   struct TALER_PurseContractSignatureP *purse_sig)
   1180 {
   1181   struct TALER_PurseCreatePS pm = {
   1182     .purpose.size = htonl (sizeof (pm)),
   1183     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_PURSE_CREATE),
   1184     .purse_expiration = GNUNET_TIME_timestamp_hton (purse_expiration),
   1185     .h_contract_terms = *h_contract_terms,
   1186     .merge_pub = *merge_pub,
   1187     .min_age = htonl (min_age)
   1188   };
   1189 
   1190   TALER_amount_hton (&pm.purse_amount,
   1191                      amount);
   1192   GNUNET_CRYPTO_eddsa_sign (&purse_priv->eddsa_priv,
   1193                             &pm,
   1194                             &purse_sig->eddsa_signature);
   1195 }
   1196 
   1197 
   1198 enum GNUNET_GenericReturnValue
   1199 TALER_wallet_purse_create_verify (
   1200   struct GNUNET_TIME_Timestamp purse_expiration,
   1201   const struct TALER_PrivateContractHashP *h_contract_terms,
   1202   const struct TALER_PurseMergePublicKeyP *merge_pub,
   1203   uint32_t min_age,
   1204   const struct TALER_Amount *amount,
   1205   const struct TALER_PurseContractPublicKeyP *purse_pub,
   1206   const struct TALER_PurseContractSignatureP *purse_sig)
   1207 {
   1208   struct TALER_PurseCreatePS pm = {
   1209     .purpose.size = htonl (sizeof (pm)),
   1210     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_PURSE_CREATE),
   1211     .purse_expiration = GNUNET_TIME_timestamp_hton (purse_expiration),
   1212     .h_contract_terms = *h_contract_terms,
   1213     .merge_pub = *merge_pub,
   1214     .min_age = htonl (min_age)
   1215   };
   1216 
   1217   TALER_amount_hton (&pm.purse_amount,
   1218                      amount);
   1219   return GNUNET_CRYPTO_eddsa_verify (
   1220     TALER_SIGNATURE_WALLET_PURSE_CREATE,
   1221     &pm,
   1222     &purse_sig->eddsa_signature,
   1223     &purse_pub->eddsa_pub);
   1224 }
   1225 
   1226 
   1227 GNUNET_NETWORK_STRUCT_BEGIN
   1228 
   1229 /**
   1230  * Message signed to delete a purse.
   1231  */
   1232 struct TALER_PurseDeletePS
   1233 {
   1234 
   1235   /**
   1236    * Purpose is #TALER_SIGNATURE_WALLET_PURSE_DELETE
   1237    */
   1238   struct GNUNET_CRYPTO_SignaturePurpose purpose;
   1239 
   1240 };
   1241 
   1242 
   1243 GNUNET_NETWORK_STRUCT_END
   1244 
   1245 
   1246 void
   1247 TALER_wallet_purse_delete_sign (
   1248   const struct TALER_PurseContractPrivateKeyP *purse_priv,
   1249   struct TALER_PurseContractSignatureP *purse_sig)
   1250 {
   1251   struct TALER_PurseDeletePS pm = {
   1252     .purpose.size = htonl (sizeof (pm)),
   1253     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_PURSE_DELETE)
   1254   };
   1255 
   1256   GNUNET_CRYPTO_eddsa_sign (&purse_priv->eddsa_priv,
   1257                             &pm,
   1258                             &purse_sig->eddsa_signature);
   1259 }
   1260 
   1261 
   1262 enum GNUNET_GenericReturnValue
   1263 TALER_wallet_purse_delete_verify (
   1264   const struct TALER_PurseContractPublicKeyP *purse_pub,
   1265   const struct TALER_PurseContractSignatureP *purse_sig)
   1266 {
   1267   struct TALER_PurseDeletePS pm = {
   1268     .purpose.size = htonl (sizeof (pm)),
   1269     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_PURSE_DELETE)
   1270   };
   1271 
   1272   return GNUNET_CRYPTO_eddsa_verify (
   1273     TALER_SIGNATURE_WALLET_PURSE_DELETE,
   1274     &pm,
   1275     &purse_sig->eddsa_signature,
   1276     &purse_pub->eddsa_pub);
   1277 }
   1278 
   1279 
   1280 void
   1281 TALER_wallet_purse_status_sign (
   1282   const struct TALER_PurseContractPrivateKeyP *purse_priv,
   1283   struct TALER_PurseContractSignatureP *purse_sig)
   1284 {
   1285   struct GNUNET_CRYPTO_SignaturePurpose purpose = {
   1286     .size = htonl (sizeof (purpose)),
   1287     .purpose = htonl (TALER_SIGNATURE_WALLET_PURSE_STATUS)
   1288   };
   1289 
   1290   GNUNET_assert (GNUNET_OK ==
   1291                  GNUNET_CRYPTO_eddsa_sign_ (&purse_priv->eddsa_priv,
   1292                                             &purpose,
   1293                                             &purse_sig->eddsa_signature));
   1294 }
   1295 
   1296 
   1297 enum GNUNET_GenericReturnValue
   1298 TALER_wallet_purse_status_verify (
   1299   const struct TALER_PurseContractPublicKeyP *purse_pub,
   1300   const struct TALER_PurseContractSignatureP *purse_sig)
   1301 {
   1302   struct GNUNET_CRYPTO_SignaturePurpose purpose = {
   1303     .size = htonl (sizeof (purpose)),
   1304     .purpose = htonl (TALER_SIGNATURE_WALLET_PURSE_STATUS)
   1305   };
   1306 
   1307   return GNUNET_CRYPTO_eddsa_verify_ (TALER_SIGNATURE_WALLET_PURSE_STATUS,
   1308                                       &purpose,
   1309                                       &purse_sig->eddsa_signature,
   1310                                       &purse_pub->eddsa_pub);
   1311 }
   1312 
   1313 
   1314 GNUNET_NETWORK_STRUCT_BEGIN
   1315 
   1316 /**
   1317  * Message signed to deposit a coin into a purse.
   1318  */
   1319 struct TALER_PurseDepositPS
   1320 {
   1321 
   1322   /**
   1323    * Purpose is #TALER_SIGNATURE_WALLET_PURSE_DEPOSIT
   1324    */
   1325   struct GNUNET_CRYPTO_SignaturePurpose purpose;
   1326 
   1327   /**
   1328    * Amount (with deposit fee) to be deposited into the purse.
   1329    */
   1330   struct TALER_AmountNBO coin_amount;
   1331 
   1332   /**
   1333    * Hash over the denomination public key used to sign the coin.
   1334    */
   1335   struct TALER_DenominationHashP h_denom_pub GNUNET_PACKED;
   1336 
   1337   /**
   1338    * Hash over the age commitment that went into the coin. Maybe all zero, if
   1339    * age commitment isn't applicable to the denomination.
   1340    */
   1341   struct TALER_AgeCommitmentHashP h_age_commitment GNUNET_PACKED;
   1342 
   1343   /**
   1344    * Purse to deposit funds into.
   1345    */
   1346   struct TALER_PurseContractPublicKeyP purse_pub;
   1347 
   1348   /**
   1349    * Hash of the base URL of the exchange hosting the
   1350    * @e purse_pub.
   1351    */
   1352   struct GNUNET_HashCode h_exchange_base_url GNUNET_PACKED;
   1353 };
   1354 
   1355 GNUNET_NETWORK_STRUCT_END
   1356 
   1357 void
   1358 TALER_wallet_purse_deposit_sign (
   1359   const char *exchange_base_url,
   1360   const struct TALER_PurseContractPublicKeyP *purse_pub,
   1361   const struct TALER_Amount *amount,
   1362   const struct TALER_DenominationHashP *h_denom_pub,
   1363   const struct TALER_AgeCommitmentHashP *h_age_commitment,
   1364   const struct TALER_CoinSpendPrivateKeyP *coin_priv,
   1365   struct TALER_CoinSpendSignatureP *coin_sig)
   1366 {
   1367   struct TALER_PurseDepositPS pm = {
   1368     .purpose.size = htonl (sizeof (pm)),
   1369     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_PURSE_DEPOSIT),
   1370     .purse_pub = *purse_pub,
   1371     .h_denom_pub = *h_denom_pub,
   1372     .h_age_commitment = *h_age_commitment
   1373   };
   1374 
   1375   GNUNET_CRYPTO_hash (exchange_base_url,
   1376                       strlen (exchange_base_url) + 1,
   1377                       &pm.h_exchange_base_url);
   1378   TALER_amount_hton (&pm.coin_amount,
   1379                      amount);
   1380   GNUNET_CRYPTO_eddsa_sign (&coin_priv->eddsa_priv,
   1381                             &pm,
   1382                             &coin_sig->eddsa_signature);
   1383 }
   1384 
   1385 
   1386 enum GNUNET_GenericReturnValue
   1387 TALER_wallet_purse_deposit_verify (
   1388   const char *exchange_base_url,
   1389   const struct TALER_PurseContractPublicKeyP *purse_pub,
   1390   const struct TALER_Amount *amount,
   1391   const struct TALER_DenominationHashP *h_denom_pub,
   1392   const struct TALER_AgeCommitmentHashP *h_age_commitment,
   1393   const struct TALER_CoinSpendPublicKeyP *coin_pub,
   1394   const struct TALER_CoinSpendSignatureP *coin_sig)
   1395 {
   1396   struct TALER_PurseDepositPS pm = {
   1397     .purpose.size = htonl (sizeof (pm)),
   1398     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_PURSE_DEPOSIT),
   1399     .purse_pub = *purse_pub,
   1400     .h_denom_pub = *h_denom_pub,
   1401     .h_age_commitment = *h_age_commitment
   1402   };
   1403 
   1404   GNUNET_CRYPTO_hash (exchange_base_url,
   1405                       strlen (exchange_base_url) + 1,
   1406                       &pm.h_exchange_base_url);
   1407   TALER_amount_hton (&pm.coin_amount,
   1408                      amount);
   1409   return GNUNET_CRYPTO_eddsa_verify (
   1410     TALER_SIGNATURE_WALLET_PURSE_DEPOSIT,
   1411     &pm,
   1412     &coin_sig->eddsa_signature,
   1413     &coin_pub->eddsa_pub);
   1414 }
   1415 
   1416 
   1417 GNUNET_NETWORK_STRUCT_BEGIN
   1418 
   1419 /**
   1420  * Message signed to merge a purse into a reserve.
   1421  */
   1422 struct TALER_PurseMergePS
   1423 {
   1424 
   1425   /**
   1426    * Purpose is #TALER_SIGNATURE_WALLET_PURSE_MERGE
   1427    */
   1428   struct GNUNET_CRYPTO_SignaturePurpose purpose;
   1429 
   1430   /**
   1431    * Time when the purse is merged into the reserve.
   1432    */
   1433   struct GNUNET_TIME_TimestampNBO merge_timestamp;
   1434 
   1435   /**
   1436    * Which purse is being merged?
   1437    */
   1438   struct TALER_PurseContractPublicKeyP purse_pub;
   1439 
   1440   /**
   1441    * Which reserve should the purse be merged with.
   1442    * Hash of the reserve's payto:// URI.
   1443    */
   1444   struct TALER_NormalizedPaytoHashP h_payto;
   1445 
   1446 };
   1447 
   1448 GNUNET_NETWORK_STRUCT_END
   1449 
   1450 void
   1451 TALER_wallet_purse_merge_sign (
   1452   const struct TALER_NormalizedPayto reserve_uri,
   1453   struct GNUNET_TIME_Timestamp merge_timestamp,
   1454   const struct TALER_PurseContractPublicKeyP *purse_pub,
   1455   const struct TALER_PurseMergePrivateKeyP *merge_priv,
   1456   struct TALER_PurseMergeSignatureP *merge_sig)
   1457 {
   1458   struct TALER_PurseMergePS pm = {
   1459     .purpose.size = htonl (sizeof (pm)),
   1460     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_PURSE_MERGE),
   1461     .merge_timestamp = GNUNET_TIME_timestamp_hton (merge_timestamp),
   1462     .purse_pub = *purse_pub
   1463   };
   1464 
   1465   GNUNET_assert (0 ==
   1466                  strncasecmp (reserve_uri.normalized_payto,
   1467                               "payto://taler-reserve",
   1468                               strlen ("payto://taler-reserve")));
   1469   TALER_normalized_payto_hash (reserve_uri,
   1470                                &pm.h_payto);
   1471   GNUNET_CRYPTO_eddsa_sign (&merge_priv->eddsa_priv,
   1472                             &pm,
   1473                             &merge_sig->eddsa_signature);
   1474 }
   1475 
   1476 
   1477 enum GNUNET_GenericReturnValue
   1478 TALER_wallet_purse_merge_verify (
   1479   const struct TALER_NormalizedPayto reserve_uri,
   1480   struct GNUNET_TIME_Timestamp merge_timestamp,
   1481   const struct TALER_PurseContractPublicKeyP *purse_pub,
   1482   const struct TALER_PurseMergePublicKeyP *merge_pub,
   1483   const struct TALER_PurseMergeSignatureP *merge_sig)
   1484 {
   1485   struct TALER_PurseMergePS pm = {
   1486     .purpose.size = htonl (sizeof (pm)),
   1487     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_PURSE_MERGE),
   1488     .merge_timestamp = GNUNET_TIME_timestamp_hton (merge_timestamp),
   1489     .purse_pub = *purse_pub
   1490   };
   1491 
   1492   if (0 !=
   1493       strncasecmp (reserve_uri.normalized_payto,
   1494                    "payto://taler-reserve",
   1495                    strlen ("payto://taler-reserve")))
   1496   {
   1497     GNUNET_break (0);
   1498     return GNUNET_NO;
   1499   }
   1500   TALER_normalized_payto_hash (reserve_uri,
   1501                                &pm.h_payto);
   1502   return GNUNET_CRYPTO_eddsa_verify (
   1503     TALER_SIGNATURE_WALLET_PURSE_MERGE,
   1504     &pm,
   1505     &merge_sig->eddsa_signature,
   1506     &merge_pub->eddsa_pub);
   1507 }
   1508 
   1509 
   1510 GNUNET_NETWORK_STRUCT_BEGIN
   1511 
   1512 /**
   1513  * Message signed by account to merge a purse into a reserve.
   1514  */
   1515 struct TALER_AccountMergePS
   1516 {
   1517 
   1518   /**
   1519    * Purpose is #TALER_SIGNATURE_WALLET_ACCOUNT_MERGE
   1520    */
   1521   struct GNUNET_CRYPTO_SignaturePurpose purpose;
   1522 
   1523   /**
   1524    * Time when the purse will expire if still unmerged or unpaid.
   1525    */
   1526   struct GNUNET_TIME_TimestampNBO purse_expiration;
   1527 
   1528   /**
   1529    * Total amount (with fees) to be put into the purse.
   1530    */
   1531   struct TALER_AmountNBO purse_amount;
   1532 
   1533   /**
   1534    * Purse creation fee to be paid by the reserve for
   1535    * this operation.
   1536    */
   1537   struct TALER_AmountNBO purse_fee;
   1538 
   1539   /**
   1540    * Contract this purse pays for.
   1541    */
   1542   struct TALER_PrivateContractHashP h_contract_terms;
   1543 
   1544   /**
   1545    * Purse to merge.
   1546    */
   1547   struct TALER_PurseContractPublicKeyP purse_pub;
   1548 
   1549   /**
   1550    * Time when the purse is merged into the reserve.
   1551    */
   1552   struct GNUNET_TIME_TimestampNBO merge_timestamp;
   1553 
   1554   /**
   1555    * Minimum age required for payments into this purse,
   1556    * in NBO.
   1557    */
   1558   uint32_t min_age GNUNET_PACKED;
   1559 
   1560   /**
   1561    * Flags for the operation, in NBO. See
   1562    * `enum TALER_WalletAccountMergeFlags`.
   1563    */
   1564   uint32_t flags GNUNET_PACKED;
   1565 };
   1566 
   1567 GNUNET_NETWORK_STRUCT_END
   1568 
   1569 
   1570 void
   1571 TALER_wallet_account_merge_sign (
   1572   struct GNUNET_TIME_Timestamp merge_timestamp,
   1573   const struct TALER_PurseContractPublicKeyP *purse_pub,
   1574   struct GNUNET_TIME_Timestamp purse_expiration,
   1575   const struct TALER_PrivateContractHashP *h_contract_terms,
   1576   const struct TALER_Amount *amount,
   1577   const struct TALER_Amount *purse_fee,
   1578   uint32_t min_age,
   1579   enum TALER_WalletAccountMergeFlags flags,
   1580   const struct TALER_ReservePrivateKeyP *reserve_priv,
   1581   struct TALER_ReserveSignatureP *reserve_sig)
   1582 {
   1583   struct TALER_AccountMergePS pm = {
   1584     .purpose.size = htonl (sizeof (pm)),
   1585     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_ACCOUNT_MERGE),
   1586     .merge_timestamp = GNUNET_TIME_timestamp_hton (merge_timestamp),
   1587     .purse_pub = *purse_pub,
   1588     .purse_expiration = GNUNET_TIME_timestamp_hton (purse_expiration),
   1589     .h_contract_terms = *h_contract_terms,
   1590     .min_age = htonl (min_age),
   1591     .flags = htonl ((uint32_t) flags)
   1592   };
   1593 
   1594   TALER_amount_hton (&pm.purse_amount,
   1595                      amount);
   1596   TALER_amount_hton (&pm.purse_fee,
   1597                      purse_fee);
   1598   GNUNET_CRYPTO_eddsa_sign (&reserve_priv->eddsa_priv,
   1599                             &pm,
   1600                             &reserve_sig->eddsa_signature);
   1601 }
   1602 
   1603 
   1604 enum GNUNET_GenericReturnValue
   1605 TALER_wallet_account_merge_verify (
   1606   struct GNUNET_TIME_Timestamp merge_timestamp,
   1607   const struct TALER_PurseContractPublicKeyP *purse_pub,
   1608   struct GNUNET_TIME_Timestamp purse_expiration,
   1609   const struct TALER_PrivateContractHashP *h_contract_terms,
   1610   const struct TALER_Amount *amount,
   1611   const struct TALER_Amount *purse_fee,
   1612   uint32_t min_age,
   1613   enum TALER_WalletAccountMergeFlags flags,
   1614   const struct TALER_ReservePublicKeyP *reserve_pub,
   1615   const struct TALER_ReserveSignatureP *reserve_sig)
   1616 {
   1617   struct TALER_AccountMergePS pm = {
   1618     .purpose.size = htonl (sizeof (pm)),
   1619     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_ACCOUNT_MERGE),
   1620     .merge_timestamp = GNUNET_TIME_timestamp_hton (merge_timestamp),
   1621     .purse_pub = *purse_pub,
   1622     .purse_expiration = GNUNET_TIME_timestamp_hton (purse_expiration),
   1623     .h_contract_terms = *h_contract_terms,
   1624     .min_age = htonl (min_age),
   1625     .flags = htonl ((uint32_t) flags)
   1626   };
   1627 
   1628   TALER_amount_hton (&pm.purse_amount,
   1629                      amount);
   1630   TALER_amount_hton (&pm.purse_fee,
   1631                      purse_fee);
   1632   return GNUNET_CRYPTO_eddsa_verify (
   1633     TALER_SIGNATURE_WALLET_ACCOUNT_MERGE,
   1634     &pm,
   1635     &reserve_sig->eddsa_signature,
   1636     &reserve_pub->eddsa_pub);
   1637 }
   1638 
   1639 
   1640 GNUNET_NETWORK_STRUCT_BEGIN
   1641 
   1642 /**
   1643  * Message signed by reserve key.
   1644  */
   1645 struct TALER_ReserveOpenPS
   1646 {
   1647 
   1648   /**
   1649    * Purpose is #TALER_SIGNATURE_WALLET_RESERVE_OPEN
   1650    */
   1651   struct GNUNET_CRYPTO_SignaturePurpose purpose;
   1652 
   1653   /**
   1654    * Amount to be paid from the reserve balance to open
   1655    * the reserve.
   1656    */
   1657   struct TALER_AmountNBO reserve_payment;
   1658 
   1659   /**
   1660    * When was the request created.
   1661    */
   1662   struct GNUNET_TIME_TimestampNBO request_timestamp;
   1663 
   1664   /**
   1665    * For how long should the reserve be kept open.
   1666    * (Determines amount to be paid.)
   1667    */
   1668   struct GNUNET_TIME_TimestampNBO reserve_expiration;
   1669 
   1670   /**
   1671    * How many open purses should be included with the
   1672    * open reserve?
   1673    * (Determines amount to be paid.)
   1674    */
   1675   uint32_t purse_limit GNUNET_PACKED;
   1676 
   1677 };
   1678 
   1679 GNUNET_NETWORK_STRUCT_END
   1680 
   1681 
   1682 void
   1683 TALER_wallet_reserve_open_sign (
   1684   const struct TALER_Amount *reserve_payment,
   1685   struct GNUNET_TIME_Timestamp request_timestamp,
   1686   struct GNUNET_TIME_Timestamp reserve_expiration,
   1687   uint32_t purse_limit,
   1688   const struct TALER_ReservePrivateKeyP *reserve_priv,
   1689   struct TALER_ReserveSignatureP *reserve_sig)
   1690 {
   1691   struct TALER_ReserveOpenPS rop = {
   1692     .purpose.size = htonl (sizeof (rop)),
   1693     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_OPEN),
   1694     .request_timestamp = GNUNET_TIME_timestamp_hton (request_timestamp),
   1695     .reserve_expiration = GNUNET_TIME_timestamp_hton (reserve_expiration),
   1696     .purse_limit = htonl (purse_limit)
   1697   };
   1698 
   1699   TALER_amount_hton (&rop.reserve_payment,
   1700                      reserve_payment);
   1701   GNUNET_assert (GNUNET_OK ==
   1702                  GNUNET_CRYPTO_eddsa_sign_ (&reserve_priv->eddsa_priv,
   1703                                             &rop.purpose,
   1704                                             &reserve_sig->eddsa_signature));
   1705 }
   1706 
   1707 
   1708 enum GNUNET_GenericReturnValue
   1709 TALER_wallet_reserve_open_verify (
   1710   const struct TALER_Amount *reserve_payment,
   1711   struct GNUNET_TIME_Timestamp request_timestamp,
   1712   struct GNUNET_TIME_Timestamp reserve_expiration,
   1713   uint32_t purse_limit,
   1714   const struct TALER_ReservePublicKeyP *reserve_pub,
   1715   const struct TALER_ReserveSignatureP *reserve_sig)
   1716 {
   1717   struct TALER_ReserveOpenPS rop = {
   1718     .purpose.size = htonl (sizeof (rop)),
   1719     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_OPEN),
   1720     .request_timestamp = GNUNET_TIME_timestamp_hton (request_timestamp),
   1721     .reserve_expiration = GNUNET_TIME_timestamp_hton (reserve_expiration),
   1722     .purse_limit = htonl (purse_limit)
   1723   };
   1724 
   1725   TALER_amount_hton (&rop.reserve_payment,
   1726                      reserve_payment);
   1727   return GNUNET_CRYPTO_eddsa_verify_ (TALER_SIGNATURE_WALLET_RESERVE_OPEN,
   1728                                       &rop.purpose,
   1729                                       &reserve_sig->eddsa_signature,
   1730                                       &reserve_pub->eddsa_pub);
   1731 }
   1732 
   1733 
   1734 GNUNET_NETWORK_STRUCT_BEGIN
   1735 
   1736 /**
   1737  * Message signed by
   1738  */
   1739 struct TALER_ReserveOpenDepositPS
   1740 {
   1741 
   1742   /**
   1743    * Purpose is #TALER_SIGNATURE_WALLET_RESERVE_OPEN_DEPOSIT
   1744    */
   1745   struct GNUNET_CRYPTO_SignaturePurpose purpose;
   1746 
   1747   /**
   1748    * Which reserve's opening signature should be paid for?
   1749    */
   1750   struct TALER_ReserveSignatureP reserve_sig;
   1751 
   1752   /**
   1753    * Specifies how much of the coin's value should be spent on opening this
   1754    * reserve.
   1755    */
   1756   struct TALER_AmountNBO coin_contribution;
   1757 };
   1758 
   1759 GNUNET_NETWORK_STRUCT_END
   1760 
   1761 
   1762 // FIXME-#7267: add h_age_commitment, h_denom_pub to have proof!
   1763 void
   1764 TALER_wallet_reserve_open_deposit_sign (
   1765   const struct TALER_Amount *coin_contribution,
   1766   const struct TALER_ReserveSignatureP *reserve_sig,
   1767   const struct TALER_CoinSpendPrivateKeyP *coin_priv,
   1768   struct TALER_CoinSpendSignatureP *coin_sig)
   1769 {
   1770   struct TALER_ReserveOpenDepositPS rod = {
   1771     .purpose.size = htonl (sizeof (rod)),
   1772     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_OPEN_DEPOSIT),
   1773     .reserve_sig = *reserve_sig
   1774   };
   1775 
   1776   TALER_amount_hton (&rod.coin_contribution,
   1777                      coin_contribution);
   1778   GNUNET_assert (GNUNET_OK ==
   1779                  GNUNET_CRYPTO_eddsa_sign_ (&coin_priv->eddsa_priv,
   1780                                             &rod.purpose,
   1781                                             &coin_sig->eddsa_signature));
   1782 }
   1783 
   1784 
   1785 enum GNUNET_GenericReturnValue
   1786 TALER_wallet_reserve_open_deposit_verify (
   1787   const struct TALER_Amount *coin_contribution,
   1788   const struct TALER_ReserveSignatureP *reserve_sig,
   1789   const struct TALER_CoinSpendPublicKeyP *coin_pub,
   1790   const struct TALER_CoinSpendSignatureP *coin_sig)
   1791 {
   1792   struct TALER_ReserveOpenDepositPS rod = {
   1793     .purpose.size = htonl (sizeof (rod)),
   1794     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_OPEN_DEPOSIT),
   1795     .reserve_sig = *reserve_sig
   1796   };
   1797 
   1798   TALER_amount_hton (&rod.coin_contribution,
   1799                      coin_contribution);
   1800   return GNUNET_CRYPTO_eddsa_verify_ (
   1801     TALER_SIGNATURE_WALLET_RESERVE_OPEN_DEPOSIT,
   1802     &rod.purpose,
   1803     &coin_sig->eddsa_signature,
   1804     &coin_pub->eddsa_pub);
   1805 }
   1806 
   1807 
   1808 GNUNET_NETWORK_STRUCT_BEGIN
   1809 
   1810 /**
   1811  * Message signed by reserve key.
   1812  */
   1813 struct TALER_ReserveClosePS
   1814 {
   1815 
   1816   /**
   1817    * Purpose is #TALER_SIGNATURE_WALLET_RESERVE_CLOSE
   1818    */
   1819   struct GNUNET_CRYPTO_SignaturePurpose purpose;
   1820 
   1821   /**
   1822    * When was the request created.
   1823    */
   1824   struct GNUNET_TIME_TimestampNBO request_timestamp;
   1825 
   1826   /**
   1827    * Hash of the payto://-URI of the target account
   1828    * for the closure, or all zeros for the reserve
   1829    * origin account.
   1830    */
   1831   struct TALER_FullPaytoHashP target_account_h_payto;
   1832 
   1833 };
   1834 
   1835 GNUNET_NETWORK_STRUCT_END
   1836 
   1837 
   1838 void
   1839 TALER_wallet_reserve_close_sign (
   1840   struct GNUNET_TIME_Timestamp request_timestamp,
   1841   const struct TALER_FullPaytoHashP *h_payto,
   1842   const struct TALER_ReservePrivateKeyP *reserve_priv,
   1843   struct TALER_ReserveSignatureP *reserve_sig)
   1844 {
   1845   struct TALER_ReserveClosePS rcp = {
   1846     .purpose.size = htonl (sizeof (rcp)),
   1847     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_CLOSE),
   1848     .request_timestamp = GNUNET_TIME_timestamp_hton (request_timestamp)
   1849   };
   1850 
   1851   if (NULL != h_payto)
   1852     rcp.target_account_h_payto = *h_payto;
   1853   GNUNET_assert (GNUNET_OK ==
   1854                  GNUNET_CRYPTO_eddsa_sign_ (&reserve_priv->eddsa_priv,
   1855                                             &rcp.purpose,
   1856                                             &reserve_sig->eddsa_signature));
   1857 }
   1858 
   1859 
   1860 enum GNUNET_GenericReturnValue
   1861 TALER_wallet_reserve_close_verify (
   1862   struct GNUNET_TIME_Timestamp request_timestamp,
   1863   const struct TALER_FullPaytoHashP *h_payto,
   1864   const struct TALER_ReservePublicKeyP *reserve_pub,
   1865   const struct TALER_ReserveSignatureP *reserve_sig)
   1866 {
   1867   struct TALER_ReserveClosePS rcp = {
   1868     .purpose.size = htonl (sizeof (rcp)),
   1869     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_CLOSE),
   1870     .request_timestamp = GNUNET_TIME_timestamp_hton (request_timestamp)
   1871   };
   1872 
   1873   if (NULL != h_payto)
   1874     rcp.target_account_h_payto = *h_payto;
   1875   return GNUNET_CRYPTO_eddsa_verify_ (TALER_SIGNATURE_WALLET_RESERVE_CLOSE,
   1876                                       &rcp.purpose,
   1877                                       &reserve_sig->eddsa_signature,
   1878                                       &reserve_pub->eddsa_pub);
   1879 }
   1880 
   1881 
   1882 GNUNET_NETWORK_STRUCT_BEGIN
   1883 
   1884 /**
   1885  * Message signed by reserve private key.
   1886  */
   1887 struct TALER_ReserveAttestRequestPS
   1888 {
   1889 
   1890   /**
   1891    * Purpose is #TALER_SIGNATURE_WALLET_ATTEST_REQUEST
   1892    */
   1893   struct GNUNET_CRYPTO_SignaturePurpose purpose;
   1894 
   1895   /**
   1896    * When was the request created.
   1897    */
   1898   struct GNUNET_TIME_TimestampNBO request_timestamp;
   1899 
   1900   /**
   1901    * Hash over the JSON array of requested attributes.
   1902    */
   1903   struct GNUNET_HashCode h_details;
   1904 
   1905 };
   1906 
   1907 GNUNET_NETWORK_STRUCT_END
   1908 
   1909 
   1910 void
   1911 TALER_wallet_reserve_attest_request_sign (
   1912   struct GNUNET_TIME_Timestamp request_timestamp,
   1913   const json_t *details,
   1914   const struct TALER_ReservePrivateKeyP *reserve_priv,
   1915   struct TALER_ReserveSignatureP *reserve_sig)
   1916 {
   1917   struct TALER_ReserveAttestRequestPS rcp = {
   1918     .purpose.size = htonl (sizeof (rcp)),
   1919     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_ATTEST_DETAILS),
   1920     .request_timestamp = GNUNET_TIME_timestamp_hton (request_timestamp)
   1921   };
   1922 
   1923   TALER_json_hash (details,
   1924                    &rcp.h_details);
   1925   GNUNET_assert (GNUNET_OK ==
   1926                  GNUNET_CRYPTO_eddsa_sign_ (&reserve_priv->eddsa_priv,
   1927                                             &rcp.purpose,
   1928                                             &reserve_sig->eddsa_signature));
   1929 }
   1930 
   1931 
   1932 enum GNUNET_GenericReturnValue
   1933 TALER_wallet_reserve_attest_request_verify (
   1934   struct GNUNET_TIME_Timestamp request_timestamp,
   1935   const json_t *details,
   1936   const struct TALER_ReservePublicKeyP *reserve_pub,
   1937   const struct TALER_ReserveSignatureP *reserve_sig)
   1938 {
   1939   struct TALER_ReserveAttestRequestPS rcp = {
   1940     .purpose.size = htonl (sizeof (rcp)),
   1941     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_ATTEST_DETAILS),
   1942     .request_timestamp = GNUNET_TIME_timestamp_hton (request_timestamp)
   1943   };
   1944 
   1945   TALER_json_hash (details,
   1946                    &rcp.h_details);
   1947   return GNUNET_CRYPTO_eddsa_verify_ (
   1948     TALER_SIGNATURE_WALLET_RESERVE_ATTEST_DETAILS,
   1949     &rcp.purpose,
   1950     &reserve_sig->eddsa_signature,
   1951     &reserve_pub->eddsa_pub);
   1952 }
   1953 
   1954 
   1955 GNUNET_NETWORK_STRUCT_BEGIN
   1956 
   1957 /**
   1958  * Message signed by purse to associate an encrypted contract.
   1959  */
   1960 struct TALER_PurseContractPS
   1961 {
   1962 
   1963   /**
   1964    * Purpose is #TALER_SIGNATURE_WALLET_PURSE_ECONTRACT
   1965    */
   1966   struct GNUNET_CRYPTO_SignaturePurpose purpose;
   1967 
   1968   /**
   1969    * Hash over the encrypted contract.
   1970    */
   1971   struct GNUNET_HashCode h_econtract;
   1972 
   1973   /**
   1974    * Public key to decrypt the contract.
   1975    */
   1976   struct TALER_ContractDiffiePublicP contract_pub;
   1977 };
   1978 
   1979 GNUNET_NETWORK_STRUCT_END
   1980 
   1981 void
   1982 TALER_wallet_econtract_upload_sign (
   1983   const void *econtract,
   1984   size_t econtract_size,
   1985   const struct TALER_ContractDiffiePublicP *contract_pub,
   1986   const struct TALER_PurseContractPrivateKeyP *purse_priv,
   1987   struct TALER_PurseContractSignatureP *purse_sig)
   1988 {
   1989   struct TALER_PurseContractPS pc = {
   1990     .purpose.size = htonl (sizeof (pc)),
   1991     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_PURSE_ECONTRACT),
   1992     .contract_pub = *contract_pub
   1993   };
   1994 
   1995   GNUNET_CRYPTO_hash (econtract,
   1996                       econtract_size,
   1997                       &pc.h_econtract);
   1998   GNUNET_assert (GNUNET_OK ==
   1999                  GNUNET_CRYPTO_eddsa_sign_ (&purse_priv->eddsa_priv,
   2000                                             &pc.purpose,
   2001                                             &purse_sig->eddsa_signature));
   2002 }
   2003 
   2004 
   2005 enum GNUNET_GenericReturnValue
   2006 TALER_wallet_econtract_upload_verify2 (
   2007   const struct GNUNET_HashCode *h_econtract,
   2008   const struct TALER_ContractDiffiePublicP *contract_pub,
   2009   const struct TALER_PurseContractPublicKeyP *purse_pub,
   2010   const struct TALER_PurseContractSignatureP *purse_sig)
   2011 {
   2012   struct TALER_PurseContractPS pc = {
   2013     .purpose.size = htonl (sizeof (pc)),
   2014     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_PURSE_ECONTRACT),
   2015     .contract_pub = *contract_pub,
   2016     .h_econtract = *h_econtract
   2017   };
   2018 
   2019   return GNUNET_CRYPTO_eddsa_verify_ (TALER_SIGNATURE_WALLET_PURSE_ECONTRACT,
   2020                                       &pc.purpose,
   2021                                       &purse_sig->eddsa_signature,
   2022                                       &purse_pub->eddsa_pub);
   2023 }
   2024 
   2025 
   2026 enum GNUNET_GenericReturnValue
   2027 TALER_wallet_econtract_upload_verify (
   2028   const void *econtract,
   2029   size_t econtract_size,
   2030   const struct TALER_ContractDiffiePublicP *contract_pub,
   2031   const struct TALER_PurseContractPublicKeyP *purse_pub,
   2032   const struct TALER_PurseContractSignatureP *purse_sig)
   2033 {
   2034   struct GNUNET_HashCode h_econtract;
   2035 
   2036   GNUNET_CRYPTO_hash (econtract,
   2037                       econtract_size,
   2038                       &h_econtract);
   2039   return TALER_wallet_econtract_upload_verify2 (&h_econtract,
   2040                                                 contract_pub,
   2041                                                 purse_pub,
   2042                                                 purse_sig);
   2043 }
   2044 
   2045 
   2046 GNUNET_NETWORK_STRUCT_BEGIN
   2047 
   2048 /**
   2049  * Message signed by wallet to confirm usage of a token for a transaction.
   2050  */
   2051 struct TALER_TokenUseRequestPS
   2052 {
   2053 
   2054   /**
   2055    * Purpose is #TALER_SIGNATURE_WALLET_TOKEN_USE
   2056    */
   2057   struct GNUNET_CRYPTO_SignaturePurpose purpose;
   2058 
   2059   /**
   2060    * Hash over the contract for which this token is used.
   2061    */
   2062   struct TALER_PrivateContractHashP h_contract_terms GNUNET_PACKED;
   2063 
   2064   /**
   2065    * Hash over a JSON containing data provided by the
   2066    * wallet to complete the contract upon payment.
   2067    */
   2068   struct GNUNET_HashCode wallet_data_hash;
   2069 
   2070 };
   2071 
   2072 GNUNET_NETWORK_STRUCT_END
   2073 
   2074 
   2075 void
   2076 TALER_wallet_token_use_sign (
   2077   const struct TALER_PrivateContractHashP *h_contract_terms,
   2078   const struct GNUNET_HashCode *wallet_data_hash,
   2079   const struct TALER_TokenUsePrivateKeyP *token_use_priv,
   2080   struct TALER_TokenUseSignatureP *token_sig)
   2081 {
   2082   struct TALER_TokenUseRequestPS tur = {
   2083     .purpose.size = htonl (sizeof (tur)),
   2084     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_TOKEN_USE),
   2085     .h_contract_terms = *h_contract_terms,
   2086     .wallet_data_hash = *wallet_data_hash
   2087   };
   2088 
   2089   GNUNET_CRYPTO_eddsa_sign (&token_use_priv->private_key,
   2090                             &tur,
   2091                             &token_sig->signature);
   2092 }
   2093 
   2094 
   2095 enum GNUNET_GenericReturnValue
   2096 TALER_wallet_token_use_verify (
   2097   const struct TALER_PrivateContractHashP *h_contract_terms,
   2098   const struct GNUNET_HashCode *wallet_data_hash,
   2099   const struct TALER_TokenUsePublicKeyP *token_use_pub,
   2100   const struct TALER_TokenUseSignatureP *token_sig)
   2101 {
   2102   struct TALER_TokenUseRequestPS tur = {
   2103     .purpose.size = htonl (sizeof (tur)),
   2104     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_TOKEN_USE),
   2105     .h_contract_terms = *h_contract_terms,
   2106     .wallet_data_hash = *wallet_data_hash
   2107   };
   2108 
   2109   return GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_TOKEN_USE,
   2110                                      &tur,
   2111                                      &token_sig->signature,
   2112                                      &token_use_pub->public_key);
   2113 }
   2114 
   2115 
   2116 /* end of wallet_signatures.c */