/*
This file is part of TALER
Copyright (C) 2021-2023 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation; either version 3, or (at your option) any later version.
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
TALER; see the file COPYING. If not, see
*/
/**
* @file exchange_signatures.c
* @brief Utility functions for Taler security module signatures
* @author Christian Grothoff
*/
#include "platform.h"
#include "taler_util.h"
#include "taler_signatures.h"
GNUNET_NETWORK_STRUCT_BEGIN
/**
* @brief Format used to generate the signature on a confirmation
* from the exchange that a deposit request succeeded.
*/
struct TALER_DepositConfirmationPS
{
/**
* Purpose must be #TALER_SIGNATURE_EXCHANGE_CONFIRM_DEPOSIT. Signed
* by a `struct TALER_ExchangePublicKeyP` using EdDSA.
*/
struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
/**
* Hash over the contract for which this deposit is made.
*/
struct TALER_PrivateContractHashP h_contract_terms GNUNET_PACKED;
/**
* Hash over the wiring information of the merchant.
*/
struct TALER_MerchantWireHashP h_wire GNUNET_PACKED;
/**
* Hash over the optional policy extension of the deposit, 0 if there
* was no policy.
*/
struct TALER_ExtensionPolicyHashP h_policy GNUNET_PACKED;
/**
* Time when this confirmation was generated / when the exchange received
* the deposit request.
*/
struct GNUNET_TIME_TimestampNBO exchange_timestamp;
/**
* By when does the exchange expect to pay the merchant
* (as per the merchant's request).
*/
struct GNUNET_TIME_TimestampNBO wire_deadline;
/**
* How much time does the @e merchant have to issue a refund
* request? Zero if refunds are not allowed. After this time, the
* coin cannot be refunded. Note that the wire transfer will not be
* performed by the exchange until the refund deadline. This value
* is taken from the original deposit request.
*/
struct GNUNET_TIME_TimestampNBO refund_deadline;
/**
* Amount to be deposited, excluding fee. Calculated from the
* amount with fee and the fee from the deposit request.
*/
struct TALER_AmountNBO total_without_fee;
/**
* Hash over all of the coin signatures.
*/
struct GNUNET_HashCode h_coin_sigs;
/**
* The Merchant's public key. Allows the merchant to later refund
* the transaction or to inquire about the wire transfer identifier.
*/
struct TALER_MerchantPublicKeyP merchant_pub;
};
GNUNET_NETWORK_STRUCT_END
enum TALER_ErrorCode
TALER_exchange_online_deposit_confirmation_sign (
TALER_ExchangeSignCallback scb,
const struct TALER_PrivateContractHashP *h_contract_terms,
const struct TALER_MerchantWireHashP *h_wire,
const struct TALER_ExtensionPolicyHashP *h_policy,
struct GNUNET_TIME_Timestamp exchange_timestamp,
struct GNUNET_TIME_Timestamp wire_deadline,
struct GNUNET_TIME_Timestamp refund_deadline,
const struct TALER_Amount *total_without_fee,
unsigned int num_coins,
const struct TALER_CoinSpendSignatureP *coin_sigs[static num_coins],
const struct TALER_MerchantPublicKeyP *merchant_pub,
struct TALER_ExchangePublicKeyP *pub,
struct TALER_ExchangeSignatureP *sig)
{
struct TALER_DepositConfirmationPS dcs = {
.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_DEPOSIT),
.purpose.size = htonl (sizeof (struct TALER_DepositConfirmationPS)),
.h_contract_terms = *h_contract_terms,
.h_wire = *h_wire,
.exchange_timestamp = GNUNET_TIME_timestamp_hton (exchange_timestamp),
.wire_deadline = GNUNET_TIME_timestamp_hton (wire_deadline),
.refund_deadline = GNUNET_TIME_timestamp_hton (refund_deadline),
.merchant_pub = *merchant_pub
};
struct GNUNET_HashContext *hc;
hc = GNUNET_CRYPTO_hash_context_start ();
for (unsigned int i = 0; ieddsa_signature,
&exchange_pub->eddsa_pub))
{
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
return GNUNET_OK;
}
GNUNET_NETWORK_STRUCT_BEGIN
/**
* @brief Format used to generate the signature on a request to refund
* a coin into the account of the customer.
*/
struct TALER_RefundConfirmationPS
{
/**
* Purpose must be #TALER_SIGNATURE_EXCHANGE_CONFIRM_REFUND.
*/
struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
/**
* Hash over the proposal data to identify the contract
* which is being refunded.
*/
struct TALER_PrivateContractHashP h_contract_terms GNUNET_PACKED;
/**
* The coin's public key. This is the value that must have been
* signed (blindly) by the Exchange.
*/
struct TALER_CoinSpendPublicKeyP coin_pub;
/**
* The Merchant's public key. Allows the merchant to later refund
* the transaction or to inquire about the wire transfer identifier.
*/
struct TALER_MerchantPublicKeyP merchant;
/**
* Merchant-generated transaction ID for the refund.
*/
uint64_t rtransaction_id GNUNET_PACKED;
/**
* Amount to be refunded, including refund fee charged by the
* exchange to the customer.
*/
struct TALER_AmountNBO refund_amount;
};
GNUNET_NETWORK_STRUCT_END
enum TALER_ErrorCode
TALER_exchange_online_refund_confirmation_sign (
TALER_ExchangeSignCallback scb,
const struct TALER_PrivateContractHashP *h_contract_terms,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
const struct TALER_MerchantPublicKeyP *merchant,
uint64_t rtransaction_id,
const struct TALER_Amount *refund_amount,
struct TALER_ExchangePublicKeyP *pub,
struct TALER_ExchangeSignatureP *sig)
{
struct TALER_RefundConfirmationPS rc = {
.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_REFUND),
.purpose.size = htonl (sizeof (rc)),
.h_contract_terms = *h_contract_terms,
.coin_pub = *coin_pub,
.merchant = *merchant,
.rtransaction_id = GNUNET_htonll (rtransaction_id)
};
TALER_amount_hton (&rc.refund_amount,
refund_amount);
return scb (&rc.purpose,
pub,
sig);
}
enum GNUNET_GenericReturnValue
TALER_exchange_online_refund_confirmation_verify (
const struct TALER_PrivateContractHashP *h_contract_terms,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
const struct TALER_MerchantPublicKeyP *merchant,
uint64_t rtransaction_id,
const struct TALER_Amount *refund_amount,
const struct TALER_ExchangePublicKeyP *pub,
const struct TALER_ExchangeSignatureP *sig)
{
struct TALER_RefundConfirmationPS rc = {
.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_REFUND),
.purpose.size = htonl (sizeof (rc)),
.h_contract_terms = *h_contract_terms,
.coin_pub = *coin_pub,
.merchant = *merchant,
.rtransaction_id = GNUNET_htonll (rtransaction_id)
};
TALER_amount_hton (&rc.refund_amount,
refund_amount);
if (GNUNET_OK !=
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_CONFIRM_REFUND,
&rc,
&sig->eddsa_signature,
&pub->eddsa_pub))
{
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
return GNUNET_OK;
}
GNUNET_NETWORK_STRUCT_BEGIN
/**
* @brief Format of the block signed by the Exchange in response to a successful
* "/refresh/melt" request. Hereby the exchange affirms that all of the
* coins were successfully melted. This also commits the exchange to a
* particular index to not be revealed during the refresh.
*/
struct TALER_RefreshMeltConfirmationPS
{
/**
* Purpose is #TALER_SIGNATURE_EXCHANGE_CONFIRM_MELT. Signed
* by a `struct TALER_ExchangePublicKeyP` using EdDSA.
*/
struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
/**
* Commitment made in the /refresh/melt.
*/
struct TALER_RefreshCommitmentP rc GNUNET_PACKED;
/**
* Index that the client will not have to reveal, in NBO.
* Must be smaller than #TALER_CNC_KAPPA.
*/
uint32_t noreveal_index GNUNET_PACKED;
};
GNUNET_NETWORK_STRUCT_END
enum TALER_ErrorCode
TALER_exchange_online_melt_confirmation_sign (
TALER_ExchangeSignCallback scb,
const struct TALER_RefreshCommitmentP *rc,
uint32_t noreveal_index,
struct TALER_ExchangePublicKeyP *pub,
struct TALER_ExchangeSignatureP *sig)
{
struct TALER_RefreshMeltConfirmationPS confirm = {
.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_MELT),
.purpose.size = htonl (sizeof (confirm)),
.rc = *rc,
.noreveal_index = htonl (noreveal_index)
};
return scb (&confirm.purpose,
pub,
sig);
}
enum GNUNET_GenericReturnValue
TALER_exchange_online_melt_confirmation_verify (
const struct TALER_RefreshCommitmentP *rc,
uint32_t noreveal_index,
const struct TALER_ExchangePublicKeyP *exchange_pub,
const struct TALER_ExchangeSignatureP *exchange_sig)
{
struct TALER_RefreshMeltConfirmationPS confirm = {
.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_MELT),
.purpose.size = htonl (sizeof (confirm)),
.rc = *rc,
.noreveal_index = htonl (noreveal_index)
};
return
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_CONFIRM_MELT,
&confirm,
&exchange_sig->eddsa_signature,
&exchange_pub->eddsa_pub);
}
GNUNET_NETWORK_STRUCT_BEGIN
/**
* @brief Format of the block signed by the Exchange in response to a
* successful "/reserves/$RESERVE_PUB/age-withdraw" request. Hereby the
* exchange affirms that the commitment along with the maximum age group and
* the amount were accepted. This also commits the exchange to a particular
* index to not be revealed during the reveal.
*/
struct TALER_AgeWithdrawConfirmationPS
{
/**
* Purpose is #TALER_SIGNATURE_EXCHANGE_CONFIRM_AGE_WITHDRAW. Signed by a
* `struct TALER_ExchangePublicKeyP` using EdDSA.
*/
struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
/**
* Commitment made in the /reserves/$RESERVE_PUB/age-withdraw.
*/
struct TALER_AgeWithdrawCommitmentHashP h_commitment GNUNET_PACKED;
/**
* Index that the client will not have to reveal, in NBO.
* Must be smaller than #TALER_CNC_KAPPA.
*/
uint32_t noreveal_index GNUNET_PACKED;
};
GNUNET_NETWORK_STRUCT_END
enum TALER_ErrorCode
TALER_exchange_online_age_withdraw_confirmation_sign (
TALER_ExchangeSignCallback scb,
const struct TALER_AgeWithdrawCommitmentHashP *h_commitment,
uint32_t noreveal_index,
struct TALER_ExchangePublicKeyP *pub,
struct TALER_ExchangeSignatureP *sig)
{
struct TALER_AgeWithdrawConfirmationPS confirm = {
.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_AGE_WITHDRAW),
.purpose.size = htonl (sizeof (confirm)),
.h_commitment = *h_commitment,
.noreveal_index = htonl (noreveal_index)
};
return scb (&confirm.purpose,
pub,
sig);
}
enum GNUNET_GenericReturnValue
TALER_exchange_online_age_withdraw_confirmation_verify (
const struct TALER_AgeWithdrawCommitmentHashP *h_commitment,
uint32_t noreveal_index,
const struct TALER_ExchangePublicKeyP *exchange_pub,
const struct TALER_ExchangeSignatureP *exchange_sig)
{
struct TALER_AgeWithdrawConfirmationPS confirm = {
.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_AGE_WITHDRAW),
.purpose.size = htonl (sizeof (confirm)),
.h_commitment = *h_commitment,
.noreveal_index = htonl (noreveal_index)
};
if (GNUNET_OK !=
GNUNET_CRYPTO_eddsa_verify (
TALER_SIGNATURE_EXCHANGE_CONFIRM_AGE_WITHDRAW,
&confirm,
&exchange_sig->eddsa_signature,
&exchange_pub->eddsa_pub))
{
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
return GNUNET_OK;
}
/* TODO:oec: add signature for age-withdraw, age-reveal */
GNUNET_NETWORK_STRUCT_BEGIN
/**
* @brief Signature made by the exchange over the full set of keys, used
* to detect cheating exchanges that give out different sets to
* different users.
*/
struct TALER_ExchangeKeySetPS
{
/**
* Purpose is #TALER_SIGNATURE_EXCHANGE_KEY_SET. Signed
* by a `struct TALER_ExchangePublicKeyP` using EdDSA.
*/
struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
/**
* Time of the key set issue.
*/
struct GNUNET_TIME_TimestampNBO list_issue_date;
/**
* Hash over the various denomination signing keys returned.
*/
struct GNUNET_HashCode hc GNUNET_PACKED;
};
GNUNET_NETWORK_STRUCT_END
enum TALER_ErrorCode
TALER_exchange_online_key_set_sign (
TALER_ExchangeSignCallback2 scb,
void *cls,
struct GNUNET_TIME_Timestamp timestamp,
const struct GNUNET_HashCode *hc,
struct TALER_ExchangePublicKeyP *pub,
struct TALER_ExchangeSignatureP *sig)
{
struct TALER_ExchangeKeySetPS ks = {
.purpose.size = htonl (sizeof (ks)),
.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_KEY_SET),
.list_issue_date = GNUNET_TIME_timestamp_hton (timestamp),
.hc = *hc
};
return scb (cls,
&ks.purpose,
pub,
sig);
}
enum GNUNET_GenericReturnValue
TALER_exchange_online_key_set_verify (
struct GNUNET_TIME_Timestamp timestamp,
const struct GNUNET_HashCode *hc,
const struct TALER_ExchangePublicKeyP *pub,
const struct TALER_ExchangeSignatureP *sig)
{
struct TALER_ExchangeKeySetPS ks = {
.purpose.size = htonl (sizeof (ks)),
.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_KEY_SET),
.list_issue_date = GNUNET_TIME_timestamp_hton (timestamp),
.hc = *hc
};
return
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_KEY_SET,
&ks,
&sig->eddsa_signature,
&pub->eddsa_pub);
}
GNUNET_NETWORK_STRUCT_BEGIN
/**
* @brief Signature by which an exchange affirms that an account
* successfully passed the KYC checks.
*/
struct TALER_ExchangeAccountSetupSuccessPS
{
/**
* Purpose is #TALER_SIGNATURE_EXCHANGE_ACCOUNT_SETUP_SUCCESS. Signed by a
* `struct TALER_ExchangePublicKeyP` using EdDSA.
*/
struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
/**
* Hash over the payto for which the signature was made.
*/
struct TALER_PaytoHashP h_payto;
/**
* Hash over details on *which* KYC obligations were discharged!
*/
struct GNUNET_HashCode h_kyc;
/**
* When was the signature made.
*/
struct GNUNET_TIME_TimestampNBO timestamp;
};
GNUNET_NETWORK_STRUCT_END
enum TALER_ErrorCode
TALER_exchange_online_account_setup_success_sign (
TALER_ExchangeSignCallback scb,
const struct TALER_PaytoHashP *h_payto,
const json_t *kyc,
struct GNUNET_TIME_Timestamp timestamp,
struct TALER_ExchangePublicKeyP *pub,
struct TALER_ExchangeSignatureP *sig)
{
struct TALER_ExchangeAccountSetupSuccessPS kyc_purpose = {
.purpose.size = htonl (sizeof (kyc_purpose)),
.purpose.purpose = htonl (
TALER_SIGNATURE_EXCHANGE_ACCOUNT_SETUP_SUCCESS),
.h_payto = *h_payto,
.timestamp = GNUNET_TIME_timestamp_hton (timestamp)
};
TALER_json_hash (kyc,
&kyc_purpose.h_kyc);
return scb (&kyc_purpose.purpose,
pub,
sig);
}
enum GNUNET_GenericReturnValue
TALER_exchange_online_account_setup_success_verify (
const struct TALER_PaytoHashP *h_payto,
const json_t *kyc,
struct GNUNET_TIME_Timestamp timestamp,
const struct TALER_ExchangePublicKeyP *pub,
const struct TALER_ExchangeSignatureP *sig)
{
struct TALER_ExchangeAccountSetupSuccessPS kyc_purpose = {
.purpose.size = htonl (sizeof (kyc_purpose)),
.purpose.purpose = htonl (
TALER_SIGNATURE_EXCHANGE_ACCOUNT_SETUP_SUCCESS),
.h_payto = *h_payto,
.timestamp = GNUNET_TIME_timestamp_hton (timestamp)
};
TALER_json_hash (kyc,
&kyc_purpose.h_kyc);
return
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_ACCOUNT_SETUP_SUCCESS,
&kyc_purpose,
&sig->eddsa_signature,
&pub->eddsa_pub);
}
GNUNET_NETWORK_STRUCT_BEGIN
/**
* @brief Format internally used for packing the detailed information
* to generate the signature for /track/transfer signatures.
*/
struct TALER_WireDepositDetailP
{
/**
* Hash of the contract
*/
struct TALER_PrivateContractHashP h_contract_terms;
/**
* Time when the wire transfer was performed by the exchange.
*/
struct GNUNET_TIME_TimestampNBO execution_time;
/**
* Coin's public key.
*/
struct TALER_CoinSpendPublicKeyP coin_pub;
/**
* Total value of the coin.
*/
struct TALER_AmountNBO deposit_value;
/**
* Fees charged by the exchange for the deposit.
*/
struct TALER_AmountNBO deposit_fee;
};
GNUNET_NETWORK_STRUCT_END
void
TALER_exchange_online_wire_deposit_append (
struct GNUNET_HashContext *hash_context,
const struct TALER_PrivateContractHashP *h_contract_terms,
struct GNUNET_TIME_Timestamp execution_time,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
const struct TALER_Amount *deposit_value,
const struct TALER_Amount *deposit_fee)
{
struct TALER_WireDepositDetailP dd = {
.h_contract_terms = *h_contract_terms,
.execution_time = GNUNET_TIME_timestamp_hton (execution_time),
.coin_pub = *coin_pub
};
TALER_amount_hton (&dd.deposit_value,
deposit_value);
TALER_amount_hton (&dd.deposit_fee,
deposit_fee);
GNUNET_CRYPTO_hash_context_read (hash_context,
&dd,
sizeof (dd));
}
GNUNET_NETWORK_STRUCT_BEGIN
/**
* @brief Format used to generate the signature for /wire/deposit
* replies.
*/
struct TALER_WireDepositDataPS
{
/**
* Purpose header for the signature over the contract with
* purpose #TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE_DEPOSIT.
*/
struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
/**
* Total amount that was transferred.
*/
struct TALER_AmountNBO total;
/**
* Wire fee that was charged.
*/
struct TALER_AmountNBO wire_fee;
/**
* Public key of the merchant (for all aggregated transactions).
*/
struct TALER_MerchantPublicKeyP merchant_pub;
/**
* Hash of bank account of the merchant.
*/
struct TALER_PaytoHashP h_payto;
/**
* Hash of the individual deposits that were aggregated,
* each in the format of a `struct TALER_WireDepositDetailP`.
*/
struct GNUNET_HashCode h_details;
};
GNUNET_NETWORK_STRUCT_END
enum TALER_ErrorCode
TALER_exchange_online_wire_deposit_sign (
TALER_ExchangeSignCallback scb,
const struct TALER_Amount *total,
const struct TALER_Amount *wire_fee,
const struct TALER_MerchantPublicKeyP *merchant_pub,
const char *payto,
const struct GNUNET_HashCode *h_details,
struct TALER_ExchangePublicKeyP *pub,
struct TALER_ExchangeSignatureP *sig)
{
struct TALER_WireDepositDataPS wdp = {
.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE_DEPOSIT),
.purpose.size = htonl (sizeof (wdp)),
.merchant_pub = *merchant_pub,
.h_details = *h_details
};
TALER_amount_hton (&wdp.total,
total);
TALER_amount_hton (&wdp.wire_fee,
wire_fee);
TALER_payto_hash (payto,
&wdp.h_payto);
return scb (&wdp.purpose,
pub,
sig);
}
enum GNUNET_GenericReturnValue
TALER_exchange_online_wire_deposit_verify (
const struct TALER_Amount *total,
const struct TALER_Amount *wire_fee,
const struct TALER_MerchantPublicKeyP *merchant_pub,
const struct TALER_PaytoHashP *h_payto,
const struct GNUNET_HashCode *h_details,
const struct TALER_ExchangePublicKeyP *pub,
const struct TALER_ExchangeSignatureP *sig)
{
struct TALER_WireDepositDataPS wdp = {
.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE_DEPOSIT),
.purpose.size = htonl (sizeof (wdp)),
.merchant_pub = *merchant_pub,
.h_details = *h_details,
.h_payto = *h_payto
};
TALER_amount_hton (&wdp.total,
total);
TALER_amount_hton (&wdp.wire_fee,
wire_fee);
return
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE_DEPOSIT,
&wdp,
&sig->eddsa_signature,
&pub->eddsa_pub);
}
GNUNET_NETWORK_STRUCT_BEGIN
/**
* Details affirmed by the exchange about a wire transfer the exchange
* claims to have done with respect to a deposit operation.
*/
struct TALER_ConfirmWirePS
{
/**
* Purpose header for the signature over the contract with
* purpose #TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE.
*/
struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
/**
* Hash over the wiring information of the merchant.
*/
struct TALER_MerchantWireHashP h_wire GNUNET_PACKED;
/**
* Hash over the contract for which this deposit is made.
*/
struct TALER_PrivateContractHashP h_contract_terms GNUNET_PACKED;
/**
* Raw value (binary encoding) of the wire transfer subject.
*/
struct TALER_WireTransferIdentifierRawP wtid;
/**
* The coin's public key. This is the value that must have been
* signed (blindly) by the Exchange.
*/
struct TALER_CoinSpendPublicKeyP coin_pub;
/**
* When did the exchange execute this transfer? Note that the
* timestamp may not be exactly the same on the wire, i.e.
* because the wire has a different timezone or resolution.
*/
struct GNUNET_TIME_TimestampNBO execution_time;
/**
* The contribution of @e coin_pub to the total transfer volume.
* This is the value of the deposit minus the fee.
*/
struct TALER_AmountNBO coin_contribution;
};
GNUNET_NETWORK_STRUCT_END
enum TALER_ErrorCode
TALER_exchange_online_confirm_wire_sign (
TALER_ExchangeSignCallback scb,
const struct TALER_MerchantWireHashP *h_wire,
const struct TALER_PrivateContractHashP *h_contract_terms,
const struct TALER_WireTransferIdentifierRawP *wtid,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
struct GNUNET_TIME_Timestamp execution_time,
const struct TALER_Amount *coin_contribution,
struct TALER_ExchangePublicKeyP *pub,
struct TALER_ExchangeSignatureP *sig)
{
struct TALER_ConfirmWirePS cw = {
.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE),
.purpose.size = htonl (sizeof (cw)),
.h_wire = *h_wire,
.h_contract_terms = *h_contract_terms,
.wtid = *wtid,
.coin_pub = *coin_pub,
.execution_time = GNUNET_TIME_timestamp_hton (execution_time)
};
TALER_amount_hton (&cw.coin_contribution,
coin_contribution);
return scb (&cw.purpose,
pub,
sig);
}
enum GNUNET_GenericReturnValue
TALER_exchange_online_confirm_wire_verify (
const struct TALER_MerchantWireHashP *h_wire,
const struct TALER_PrivateContractHashP *h_contract_terms,
const struct TALER_WireTransferIdentifierRawP *wtid,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
struct GNUNET_TIME_Timestamp execution_time,
const struct TALER_Amount *coin_contribution,
const struct TALER_ExchangePublicKeyP *pub,
const struct TALER_ExchangeSignatureP *sig)
{
struct TALER_ConfirmWirePS cw = {
.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE),
.purpose.size = htonl (sizeof (cw)),
.h_wire = *h_wire,
.h_contract_terms = *h_contract_terms,
.wtid = *wtid,
.coin_pub = *coin_pub,
.execution_time = GNUNET_TIME_timestamp_hton (execution_time)
};
TALER_amount_hton (&cw.coin_contribution,
coin_contribution);
return
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE,
&cw,
&sig->eddsa_signature,
&pub->eddsa_pub);
}
GNUNET_NETWORK_STRUCT_BEGIN
/**
* Response by which the exchange affirms that it will
* refund a coin as part of the emergency /recoup
* protocol. The recoup will go back to the bank
* account that created the reserve.
*/
struct TALER_RecoupConfirmationPS
{
/**
* Purpose is #TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP
*/
struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
/**
* When did the exchange receive the recoup request?
* Indirectly determines when the wire transfer is (likely)
* to happen.
*/
struct GNUNET_TIME_TimestampNBO timestamp;
/**
* How much of the coin's value will the exchange transfer?
* (Needed in case the coin was partially spent.)
*/
struct TALER_AmountNBO recoup_amount;
/**
* Public key of the coin.
*/
struct TALER_CoinSpendPublicKeyP coin_pub;
/**
* Public key of the reserve that will receive the recoup.
*/
struct TALER_ReservePublicKeyP reserve_pub;
};
GNUNET_NETWORK_STRUCT_END
enum TALER_ErrorCode
TALER_exchange_online_confirm_recoup_sign (
TALER_ExchangeSignCallback scb,
struct GNUNET_TIME_Timestamp timestamp,
const struct TALER_Amount *recoup_amount,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
const struct TALER_ReservePublicKeyP *reserve_pub,
struct TALER_ExchangePublicKeyP *pub,
struct TALER_ExchangeSignatureP *sig)
{
struct TALER_RecoupConfirmationPS pc = {
.purpose.size = htonl (sizeof (pc)),
.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP),
.timestamp = GNUNET_TIME_timestamp_hton (timestamp),
.coin_pub = *coin_pub,
.reserve_pub = *reserve_pub
};
TALER_amount_hton (&pc.recoup_amount,
recoup_amount);
return scb (&pc.purpose,
pub,
sig);
}
enum GNUNET_GenericReturnValue
TALER_exchange_online_confirm_recoup_verify (
struct GNUNET_TIME_Timestamp timestamp,
const struct TALER_Amount *recoup_amount,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
const struct TALER_ReservePublicKeyP *reserve_pub,
const struct TALER_ExchangePublicKeyP *pub,
const struct TALER_ExchangeSignatureP *sig)
{
struct TALER_RecoupConfirmationPS pc = {
.purpose.size = htonl (sizeof (pc)),
.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP),
.timestamp = GNUNET_TIME_timestamp_hton (timestamp),
.coin_pub = *coin_pub,
.reserve_pub = *reserve_pub
};
TALER_amount_hton (&pc.recoup_amount,
recoup_amount);
return
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP,
&pc,
&sig->eddsa_signature,
&pub->eddsa_pub);
}
GNUNET_NETWORK_STRUCT_BEGIN
/**
* Response by which the exchange affirms that it will refund a refreshed coin
* as part of the emergency /recoup protocol. The recoup will go back to the
* old coin's balance.
*/
struct TALER_RecoupRefreshConfirmationPS
{
/**
* Purpose is #TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP_REFRESH
*/
struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
/**
* When did the exchange receive the recoup request?
* Indirectly determines when the wire transfer is (likely)
* to happen.
*/
struct GNUNET_TIME_TimestampNBO timestamp;
/**
* How much of the coin's value will the exchange transfer?
* (Needed in case the coin was partially spent.)
*/
struct TALER_AmountNBO recoup_amount;
/**
* Public key of the refreshed coin.
*/
struct TALER_CoinSpendPublicKeyP coin_pub;
/**
* Public key of the old coin that will receive the recoup.
*/
struct TALER_CoinSpendPublicKeyP old_coin_pub;
};
GNUNET_NETWORK_STRUCT_END
enum TALER_ErrorCode
TALER_exchange_online_confirm_recoup_refresh_sign (
TALER_ExchangeSignCallback scb,
struct GNUNET_TIME_Timestamp timestamp,
const struct TALER_Amount *recoup_amount,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
const struct TALER_CoinSpendPublicKeyP *old_coin_pub,
struct TALER_ExchangePublicKeyP *pub,
struct TALER_ExchangeSignatureP *sig)
{
struct TALER_RecoupRefreshConfirmationPS pc = {
.purpose.purpose = htonl (
TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP_REFRESH),
.purpose.size = htonl (sizeof (pc)),
.timestamp = GNUNET_TIME_timestamp_hton (timestamp),
.coin_pub = *coin_pub,
.old_coin_pub = *old_coin_pub
};
TALER_amount_hton (&pc.recoup_amount,
recoup_amount);
return scb (&pc.purpose,
pub,
sig);
}
enum GNUNET_GenericReturnValue
TALER_exchange_online_confirm_recoup_refresh_verify (
struct GNUNET_TIME_Timestamp timestamp,
const struct TALER_Amount *recoup_amount,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
const struct TALER_CoinSpendPublicKeyP *old_coin_pub,
const struct TALER_ExchangePublicKeyP *pub,
const struct TALER_ExchangeSignatureP *sig)
{
struct TALER_RecoupRefreshConfirmationPS pc = {
.purpose.purpose = htonl (
TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP_REFRESH),
.purpose.size = htonl (sizeof (pc)),
.timestamp = GNUNET_TIME_timestamp_hton (timestamp),
.coin_pub = *coin_pub,
.old_coin_pub = *old_coin_pub
};
TALER_amount_hton (&pc.recoup_amount,
recoup_amount);
return
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP_REFRESH,
&pc,
&sig->eddsa_signature,
&pub->eddsa_pub);
}
GNUNET_NETWORK_STRUCT_BEGIN
/**
* Response by which the exchange affirms that it does not
* currently know a denomination by the given hash.
*/
struct TALER_DenominationUnknownAffirmationPS
{
/**
* Purpose is #TALER_SIGNATURE_EXCHANGE_AFFIRM_DENOM_UNKNOWN
*/
struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
/**
* When did the exchange sign this message.
*/
struct GNUNET_TIME_TimestampNBO timestamp;
/**
* Hash of the public denomination key we do not know.
*/
struct TALER_DenominationHashP h_denom_pub;
};
GNUNET_NETWORK_STRUCT_END
enum TALER_ErrorCode
TALER_exchange_online_denomination_unknown_sign (
TALER_ExchangeSignCallback scb,
struct GNUNET_TIME_Timestamp timestamp,
const struct TALER_DenominationHashP *h_denom_pub,
struct TALER_ExchangePublicKeyP *pub,
struct TALER_ExchangeSignatureP *sig)
{
struct TALER_DenominationUnknownAffirmationPS dua = {
.purpose.size = htonl (sizeof (dua)),
.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_AFFIRM_DENOM_UNKNOWN),
.timestamp = GNUNET_TIME_timestamp_hton (timestamp),
.h_denom_pub = *h_denom_pub,
};
return scb (&dua.purpose,
pub,
sig);
}
enum GNUNET_GenericReturnValue
TALER_exchange_online_denomination_unknown_verify (
struct GNUNET_TIME_Timestamp timestamp,
const struct TALER_DenominationHashP *h_denom_pub,
const struct TALER_ExchangePublicKeyP *pub,
const struct TALER_ExchangeSignatureP *sig)
{
struct TALER_DenominationUnknownAffirmationPS dua = {
.purpose.size = htonl (sizeof (dua)),
.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_AFFIRM_DENOM_UNKNOWN),
.timestamp = GNUNET_TIME_timestamp_hton (timestamp),
.h_denom_pub = *h_denom_pub,
};
return
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_AFFIRM_DENOM_UNKNOWN,
&dua,
&sig->eddsa_signature,
&pub->eddsa_pub);
}
GNUNET_NETWORK_STRUCT_BEGIN
/**
* Response by which the exchange affirms that it does not
* currently consider the given denomination to be valid
* for the requested operation.
*/
struct TALER_DenominationExpiredAffirmationPS
{
/**
* Purpose is #TALER_SIGNATURE_EXCHANGE_AFFIRM_DENOM_EXPIRED
*/
struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
/**
* When did the exchange sign this message.
*/
struct GNUNET_TIME_TimestampNBO timestamp;
/**
* Name of the operation that is not allowed at this time. Might NOT be 0-terminated, but is padded with 0s.
*/
char operation[8];
/**
* Hash of the public denomination key we do not know.
*/
struct TALER_DenominationHashP h_denom_pub;
};
GNUNET_NETWORK_STRUCT_END
enum TALER_ErrorCode
TALER_exchange_online_denomination_expired_sign (
TALER_ExchangeSignCallback scb,
struct GNUNET_TIME_Timestamp timestamp,
const struct TALER_DenominationHashP *h_denom_pub,
const char *op,
struct TALER_ExchangePublicKeyP *pub,
struct TALER_ExchangeSignatureP *sig)
{
struct TALER_DenominationExpiredAffirmationPS dua = {
.purpose.size = htonl (sizeof (dua)),
.purpose.purpose = htonl (
TALER_SIGNATURE_EXCHANGE_AFFIRM_DENOM_EXPIRED),
.timestamp = GNUNET_TIME_timestamp_hton (timestamp),
.h_denom_pub = *h_denom_pub,
};
/* strncpy would create a compiler warning */
GNUNET_memcpy (dua.operation,
op,
GNUNET_MIN (sizeof (dua.operation),
strlen (op)));
return scb (&dua.purpose,
pub,
sig);
}
enum GNUNET_GenericReturnValue
TALER_exchange_online_denomination_expired_verify (
struct GNUNET_TIME_Timestamp timestamp,
const struct TALER_DenominationHashP *h_denom_pub,
const char *op,
const struct TALER_ExchangePublicKeyP *pub,
const struct TALER_ExchangeSignatureP *sig)
{
struct TALER_DenominationExpiredAffirmationPS dua = {
.purpose.size = htonl (sizeof (dua)),
.purpose.purpose = htonl (
TALER_SIGNATURE_EXCHANGE_AFFIRM_DENOM_EXPIRED),
.timestamp = GNUNET_TIME_timestamp_hton (timestamp),
.h_denom_pub = *h_denom_pub,
};
/* strncpy would create a compiler warning */
GNUNET_memcpy (dua.operation,
op,
GNUNET_MIN (sizeof (dua.operation),
strlen (op)));
return
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_AFFIRM_DENOM_EXPIRED,
&dua,
&sig->eddsa_signature,
&pub->eddsa_pub);
}
GNUNET_NETWORK_STRUCT_BEGIN
/**
* Response by which the exchange affirms that it has
* closed a reserve and send back the funds.
*/
struct TALER_ReserveCloseConfirmationPS
{
/**
* Purpose is #TALER_SIGNATURE_EXCHANGE_RESERVE_CLOSED
*/
struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
/**
* When did the exchange initiate the wire transfer.
*/
struct GNUNET_TIME_TimestampNBO timestamp;
/**
* How much did the exchange send?
*/
struct TALER_AmountNBO closing_amount;
/**
* How much did the exchange charge for closing the reserve?
*/
struct TALER_AmountNBO closing_fee;
/**
* Public key of the reserve that was closed.
*/
struct TALER_ReservePublicKeyP reserve_pub;
/**
* Hash of the receiver's bank account.
*/
struct TALER_PaytoHashP h_payto;
/**
* Wire transfer subject.
*/
struct TALER_WireTransferIdentifierRawP wtid;
};
GNUNET_NETWORK_STRUCT_END
enum TALER_ErrorCode
TALER_exchange_online_reserve_closed_sign (
TALER_ExchangeSignCallback scb,
struct GNUNET_TIME_Timestamp timestamp,
const struct TALER_Amount *closing_amount,
const struct TALER_Amount *closing_fee,
const char *payto,
const struct TALER_WireTransferIdentifierRawP *wtid,
const struct TALER_ReservePublicKeyP *reserve_pub,
struct TALER_ExchangePublicKeyP *pub,
struct TALER_ExchangeSignatureP *sig)
{
struct TALER_ReserveCloseConfirmationPS rcc = {
.purpose.size = htonl (sizeof (rcc)),
.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_RESERVE_CLOSED),
.wtid = *wtid,
.reserve_pub = *reserve_pub,
.timestamp = GNUNET_TIME_timestamp_hton (timestamp)
};
TALER_amount_hton (&rcc.closing_amount,
closing_amount);
TALER_amount_hton (&rcc.closing_fee,
closing_fee);
TALER_payto_hash (payto,
&rcc.h_payto);
return scb (&rcc.purpose,
pub,
sig);
}
enum GNUNET_GenericReturnValue
TALER_exchange_online_reserve_closed_verify (
struct GNUNET_TIME_Timestamp timestamp,
const struct TALER_Amount *closing_amount,
const struct TALER_Amount *closing_fee,
const char *payto,
const struct TALER_WireTransferIdentifierRawP *wtid,
const struct TALER_ReservePublicKeyP *reserve_pub,
const struct TALER_ExchangePublicKeyP *pub,
const struct TALER_ExchangeSignatureP *sig)
{
struct TALER_ReserveCloseConfirmationPS rcc = {
.purpose.size = htonl (sizeof (rcc)),
.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_RESERVE_CLOSED),
.wtid = *wtid,
.reserve_pub = *reserve_pub,
.timestamp = GNUNET_TIME_timestamp_hton (timestamp)
};
TALER_amount_hton (&rcc.closing_amount,
closing_amount);
TALER_amount_hton (&rcc.closing_fee,
closing_fee);
TALER_payto_hash (payto,
&rcc.h_payto);
return
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_RESERVE_CLOSED,
&rcc,
&sig->eddsa_signature,
&pub->eddsa_pub);
}
GNUNET_NETWORK_STRUCT_BEGIN
/**
* Response by which the exchange affirms that it has
* received funds deposited into a purse.
*/
struct TALER_PurseCreateDepositConfirmationPS
{
/**
* Purpose is #TALER_SIGNATURE_EXCHANGE_CONFIRM_PURSE_CREATION
*/
struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
/**
* When did the exchange receive the deposits.
*/
struct GNUNET_TIME_TimestampNBO exchange_time;
/**
* When will the purse expire?
*/
struct GNUNET_TIME_TimestampNBO purse_expiration;
/**
* How much should the purse ultimately contain.
*/
struct TALER_AmountNBO amount_without_fee;
/**
* How much was deposited so far.
*/
struct TALER_AmountNBO total_deposited;
/**
* Public key of the purse.
*/
struct TALER_PurseContractPublicKeyP purse_pub;
/**
* Hash of the contract of the purse.
*/
struct TALER_PrivateContractHashP h_contract_terms;
};
GNUNET_NETWORK_STRUCT_END
enum TALER_ErrorCode
TALER_exchange_online_purse_created_sign (
TALER_ExchangeSignCallback scb,
struct GNUNET_TIME_Timestamp exchange_time,
struct GNUNET_TIME_Timestamp purse_expiration,
const struct TALER_Amount *amount_without_fee,
const struct TALER_Amount *total_deposited,
const struct TALER_PurseContractPublicKeyP *purse_pub,
const struct TALER_PrivateContractHashP *h_contract_terms,
struct TALER_ExchangePublicKeyP *pub,
struct TALER_ExchangeSignatureP *sig)
{
struct TALER_PurseCreateDepositConfirmationPS dc = {
.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_PURSE_CREATION),
.purpose.size = htonl (sizeof (dc)),
.h_contract_terms = *h_contract_terms,
.purse_pub = *purse_pub,
.purse_expiration = GNUNET_TIME_timestamp_hton (purse_expiration),
.exchange_time = GNUNET_TIME_timestamp_hton (exchange_time)
};
TALER_amount_hton (&dc.amount_without_fee,
amount_without_fee);
TALER_amount_hton (&dc.total_deposited,
total_deposited);
return scb (&dc.purpose,
pub,
sig);
}
enum GNUNET_GenericReturnValue
TALER_exchange_online_purse_created_verify (
struct GNUNET_TIME_Timestamp exchange_time,
struct GNUNET_TIME_Timestamp purse_expiration,
const struct TALER_Amount *amount_without_fee,
const struct TALER_Amount *total_deposited,
const struct TALER_PurseContractPublicKeyP *purse_pub,
const struct TALER_PrivateContractHashP *h_contract_terms,
const struct TALER_ExchangePublicKeyP *pub,
const struct TALER_ExchangeSignatureP *sig)
{
struct TALER_PurseCreateDepositConfirmationPS dc = {
.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_PURSE_CREATION),
.purpose.size = htonl (sizeof (dc)),
.h_contract_terms = *h_contract_terms,
.purse_pub = *purse_pub,
.purse_expiration = GNUNET_TIME_timestamp_hton (purse_expiration),
.exchange_time = GNUNET_TIME_timestamp_hton (exchange_time)
};
TALER_amount_hton (&dc.amount_without_fee,
amount_without_fee);
TALER_amount_hton (&dc.total_deposited,
total_deposited);
return
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_CONFIRM_PURSE_CREATION,
&dc,
&sig->eddsa_signature,
&pub->eddsa_pub);
}
GNUNET_NETWORK_STRUCT_BEGIN
/**
* Response by which the exchange affirms that it has
* received funds deposited into a purse.
*/
struct TALER_CoinPurseRefundConfirmationPS
{
/**
* Purpose is #TALER_SIGNATURE_EXCHANGE_CONFIRM_PURSE_REFUND
*/
struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
/**
* Public key of the purse.
*/
struct TALER_PurseContractPublicKeyP purse_pub;
/**
* Public key of the coin.
*/
struct TALER_CoinSpendPublicKeyP coin_pub;
/**
* How much will be refunded to the purse.
*/
struct TALER_AmountNBO refunded_amount;
/**
* How much was the refund fee.
*/
struct TALER_AmountNBO refund_fee;
};
GNUNET_NETWORK_STRUCT_END
enum TALER_ErrorCode
TALER_exchange_online_purse_refund_sign (
TALER_ExchangeSignCallback scb,
const struct TALER_Amount *amount_without_fee,
const struct TALER_Amount *refund_fee,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
const struct TALER_PurseContractPublicKeyP *purse_pub,
struct TALER_ExchangePublicKeyP *pub,
struct TALER_ExchangeSignatureP *sig)
{
struct TALER_CoinPurseRefundConfirmationPS dc = {
.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_PURSE_REFUND),
.purpose.size = htonl (sizeof (dc)),
.coin_pub = *coin_pub,
.purse_pub = *purse_pub,
};
TALER_amount_hton (&dc.refunded_amount,
amount_without_fee);
TALER_amount_hton (&dc.refund_fee,
refund_fee);
return scb (&dc.purpose,
pub,
sig);
}
enum GNUNET_GenericReturnValue
TALER_exchange_online_purse_refund_verify (
const struct TALER_Amount *amount_without_fee,
const struct TALER_Amount *refund_fee,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
const struct TALER_PurseContractPublicKeyP *purse_pub,
const struct TALER_ExchangePublicKeyP *pub,
const struct TALER_ExchangeSignatureP *sig)
{
struct TALER_CoinPurseRefundConfirmationPS dc = {
.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_PURSE_REFUND),
.purpose.size = htonl (sizeof (dc)),
.coin_pub = *coin_pub,
.purse_pub = *purse_pub,
};
TALER_amount_hton (&dc.refunded_amount,
amount_without_fee);
TALER_amount_hton (&dc.refund_fee,
refund_fee);
return
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_CONFIRM_PURSE_REFUND,
&dc,
&sig->eddsa_signature,
&pub->eddsa_pub);
}
GNUNET_NETWORK_STRUCT_BEGIN
/**
* Response by which the exchange affirms that it has
* merged a purse into a reserve.
*/
struct TALER_PurseMergedConfirmationPS
{
/**
* Purpose is #TALER_SIGNATURE_EXCHANGE_CONFIRM_PURSE_MERGED
*/
struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
/**
* When did the exchange receive the deposits.
*/
struct GNUNET_TIME_TimestampNBO exchange_time;
/**
* When will the purse expire?
*/
struct GNUNET_TIME_TimestampNBO purse_expiration;
/**
* How much should the purse ultimately contain.
*/
struct TALER_AmountNBO amount_without_fee;
/**
* Public key of the purse.
*/
struct TALER_PurseContractPublicKeyP purse_pub;
/**
* Public key of the reserve.
*/
struct TALER_ReservePublicKeyP reserve_pub;
/**
* Hash of the contract of the purse.
*/
struct TALER_PrivateContractHashP h_contract_terms;
/**
* Hash of the provider URL hosting the reserve.
*/
struct GNUNET_HashCode h_provider_url;
};
GNUNET_NETWORK_STRUCT_END
enum TALER_ErrorCode
TALER_exchange_online_purse_merged_sign (
TALER_ExchangeSignCallback scb,
struct GNUNET_TIME_Timestamp exchange_time,
struct GNUNET_TIME_Timestamp purse_expiration,
const struct TALER_Amount *amount_without_fee,
const struct TALER_PurseContractPublicKeyP *purse_pub,
const struct TALER_PrivateContractHashP *h_contract_terms,
const struct TALER_ReservePublicKeyP *reserve_pub,
const char *exchange_url,
struct TALER_ExchangePublicKeyP *pub,
struct TALER_ExchangeSignatureP *sig)
{
struct TALER_PurseMergedConfirmationPS dc = {
.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_PURSE_MERGED),
.purpose.size = htonl (sizeof (dc)),
.h_contract_terms = *h_contract_terms,
.purse_pub = *purse_pub,
.reserve_pub = *reserve_pub,
.purse_expiration = GNUNET_TIME_timestamp_hton (purse_expiration),
.exchange_time = GNUNET_TIME_timestamp_hton (exchange_time)
};
TALER_amount_hton (&dc.amount_without_fee,
amount_without_fee);
GNUNET_CRYPTO_hash (exchange_url,
strlen (exchange_url) + 1,
&dc.h_provider_url);
return scb (&dc.purpose,
pub,
sig);
}
enum GNUNET_GenericReturnValue
TALER_exchange_online_purse_merged_verify (
struct GNUNET_TIME_Timestamp exchange_time,
struct GNUNET_TIME_Timestamp purse_expiration,
const struct TALER_Amount *amount_without_fee,
const struct TALER_PurseContractPublicKeyP *purse_pub,
const struct TALER_PrivateContractHashP *h_contract_terms,
const struct TALER_ReservePublicKeyP *reserve_pub,
const char *exchange_url,
const struct TALER_ExchangePublicKeyP *pub,
const struct TALER_ExchangeSignatureP *sig)
{
struct TALER_PurseMergedConfirmationPS dc = {
.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_PURSE_MERGED),
.purpose.size = htonl (sizeof (dc)),
.h_contract_terms = *h_contract_terms,
.purse_pub = *purse_pub,
.reserve_pub = *reserve_pub,
.purse_expiration = GNUNET_TIME_timestamp_hton (purse_expiration),
.exchange_time = GNUNET_TIME_timestamp_hton (exchange_time)
};
TALER_amount_hton (&dc.amount_without_fee,
amount_without_fee);
GNUNET_CRYPTO_hash (exchange_url,
strlen (exchange_url) + 1,
&dc.h_provider_url);
return
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_CONFIRM_PURSE_MERGED,
&dc,
&sig->eddsa_signature,
&pub->eddsa_pub);
}
GNUNET_NETWORK_STRUCT_BEGIN
/**
* @brief Format used to generate the signature on a purse status
* from the exchange.
*/
struct TALER_PurseStatusPS
{
/**
* Purpose must be #TALER_SIGNATURE_EXCHANGE_PURSE_STATUS. Signed
* by a `struct TALER_ExchangePublicKeyP` using EdDSA.
*/
struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
/**
* Time when the purse was merged, possibly 'never'.
*/
struct GNUNET_TIME_TimestampNBO merge_timestamp;
/**
* Time when the purse was deposited last, possibly 'never'.
*/
struct GNUNET_TIME_TimestampNBO deposit_timestamp;
/**
* Amount deposited in total in the purse without fees.
* May be possibly less than the target amount.
*/
struct TALER_AmountNBO balance;
};
GNUNET_NETWORK_STRUCT_END
enum TALER_ErrorCode
TALER_exchange_online_purse_status_sign (
TALER_ExchangeSignCallback scb,
struct GNUNET_TIME_Timestamp merge_timestamp,
struct GNUNET_TIME_Timestamp deposit_timestamp,
const struct TALER_Amount *balance,
struct TALER_ExchangePublicKeyP *pub,
struct TALER_ExchangeSignatureP *sig)
{
struct TALER_PurseStatusPS dcs = {
.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_PURSE_STATUS),
.purpose.size = htonl (sizeof (dcs)),
.merge_timestamp = GNUNET_TIME_timestamp_hton (merge_timestamp),
.deposit_timestamp = GNUNET_TIME_timestamp_hton (deposit_timestamp)
};
TALER_amount_hton (&dcs.balance,
balance);
return scb (&dcs.purpose,
pub,
sig);
}
enum GNUNET_GenericReturnValue
TALER_exchange_online_purse_status_verify (
struct GNUNET_TIME_Timestamp merge_timestamp,
struct GNUNET_TIME_Timestamp deposit_timestamp,
const struct TALER_Amount *balance,
const struct TALER_ExchangePublicKeyP *exchange_pub,
const struct TALER_ExchangeSignatureP *exchange_sig)
{
struct TALER_PurseStatusPS dcs = {
.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_PURSE_STATUS),
.purpose.size = htonl (sizeof (dcs)),
.merge_timestamp = GNUNET_TIME_timestamp_hton (merge_timestamp),
.deposit_timestamp = GNUNET_TIME_timestamp_hton (deposit_timestamp)
};
TALER_amount_hton (&dcs.balance,
balance);
if (GNUNET_OK !=
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_PURSE_STATUS,
&dcs,
&exchange_sig->eddsa_signature,
&exchange_pub->eddsa_pub))
{
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
return GNUNET_OK;
}
GNUNET_NETWORK_STRUCT_BEGIN
/**
* Message signed by the exchange to affirm that the
* owner of a reserve has certain attributes.
*/
struct TALER_ExchangeAttestPS
{
/**
* Purpose is #TALER_SIGNATURE_EXCHANGE_RESERVE_ATTEST_DETAILS
*/
struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
/**
* Time when the attestation was made.
*/
struct GNUNET_TIME_TimestampNBO attest_timestamp;
/**
* Time when the attestation expires.
*/
struct GNUNET_TIME_TimestampNBO expiration_time;
/**
* Public key of the reserve for which the attributes
* are attested.
*/
struct TALER_ReservePublicKeyP reserve_pub;
/**
* Hash over the attributes.
*/
struct GNUNET_HashCode h_attributes;
};
GNUNET_NETWORK_STRUCT_END
enum TALER_ErrorCode
TALER_exchange_online_reserve_attest_details_sign (
TALER_ExchangeSignCallback scb,
struct GNUNET_TIME_Timestamp attest_timestamp,
struct GNUNET_TIME_Timestamp expiration_time,
const struct TALER_ReservePublicKeyP *reserve_pub,
const json_t *attributes,
struct TALER_ExchangePublicKeyP *pub,
struct TALER_ExchangeSignatureP *sig)
{
struct TALER_ExchangeAttestPS rap = {
.purpose.size = htonl (sizeof (rap)),
.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_RESERVE_ATTEST_DETAILS),
.attest_timestamp = GNUNET_TIME_timestamp_hton (attest_timestamp),
.expiration_time = GNUNET_TIME_timestamp_hton (expiration_time),
.reserve_pub = *reserve_pub
};
TALER_json_hash (attributes,
&rap.h_attributes);
return scb (&rap.purpose,
pub,
sig);
}
enum GNUNET_GenericReturnValue
TALER_exchange_online_reserve_attest_details_verify (
struct GNUNET_TIME_Timestamp attest_timestamp,
struct GNUNET_TIME_Timestamp expiration_time,
const struct TALER_ReservePublicKeyP *reserve_pub,
const json_t *attributes,
struct TALER_ExchangePublicKeyP *pub,
struct TALER_ExchangeSignatureP *sig)
{
struct TALER_ExchangeAttestPS rap = {
.purpose.size = htonl (sizeof (rap)),
.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_RESERVE_ATTEST_DETAILS),
.attest_timestamp = GNUNET_TIME_timestamp_hton (attest_timestamp),
.expiration_time = GNUNET_TIME_timestamp_hton (expiration_time),
.reserve_pub = *reserve_pub
};
TALER_json_hash (attributes,
&rap.h_attributes);
if (GNUNET_OK !=
GNUNET_CRYPTO_eddsa_verify (
TALER_SIGNATURE_EXCHANGE_RESERVE_ATTEST_DETAILS,
&rap,
&sig->eddsa_signature,
&pub->eddsa_pub))
{
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
return GNUNET_OK;
}
/* end of exchange_signatures.c */