summaryrefslogtreecommitdiff
path: root/src/util/exchange_signatures.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/exchange_signatures.c')
-rw-r--r--src/util/exchange_signatures.c396
1 files changed, 349 insertions, 47 deletions
diff --git a/src/util/exchange_signatures.c b/src/util/exchange_signatures.c
index 3f590325c..aaefb5cec 100644
--- a/src/util/exchange_signatures.c
+++ b/src/util/exchange_signatures.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2021, 2022 Taler Systems SA
+ 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
@@ -48,10 +48,10 @@ struct TALER_DepositConfirmationPS
struct TALER_MerchantWireHashP h_wire GNUNET_PACKED;
/**
- * Hash over the extension options of the deposit, 0 if there
- * were not extension options.
+ * Hash over the optional policy extension of the deposit, 0 if there
+ * was no policy.
*/
- struct TALER_ExtensionContractHashP h_extensions GNUNET_PACKED;
+ struct TALER_ExtensionPolicyHashP h_policy GNUNET_PACKED;
/**
* Time when this confirmation was generated / when the exchange received
@@ -78,12 +78,12 @@ struct TALER_DepositConfirmationPS
* Amount to be deposited, excluding fee. Calculated from the
* amount with fee and the fee from the deposit request.
*/
- struct TALER_AmountNBO amount_without_fee;
+ struct TALER_AmountNBO total_without_fee;
/**
- * The public key of the coin that was deposited.
+ * Hash over all of the coin signatures.
*/
- struct TALER_CoinSpendPublicKeyP coin_pub;
+ struct GNUNET_HashCode h_coin_sigs;
/**
* The Merchant's public key. Allows the merchant to later refund
@@ -101,12 +101,13 @@ 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_ExtensionContractHashP *h_extensions,
+ 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 *amount_without_fee,
- const struct TALER_CoinSpendPublicKeyP *coin_pub,
+ 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)
@@ -119,14 +120,22 @@ TALER_exchange_online_deposit_confirmation_sign (
.exchange_timestamp = GNUNET_TIME_timestamp_hton (exchange_timestamp),
.wire_deadline = GNUNET_TIME_timestamp_hton (wire_deadline),
.refund_deadline = GNUNET_TIME_timestamp_hton (refund_deadline),
- .coin_pub = *coin_pub,
- .merchant_pub = *merchant_pub
+ .merchant_pub = *merchant_pub,
+ .h_policy = {{{0}}}
};
-
- if (NULL != h_extensions)
- dcs.h_extensions = *h_extensions;
- TALER_amount_hton (&dcs.amount_without_fee,
- amount_without_fee);
+ struct GNUNET_HashContext *hc;
+
+ hc = GNUNET_CRYPTO_hash_context_start ();
+ for (unsigned int i = 0; i<num_coins; i++)
+ GNUNET_CRYPTO_hash_context_read (hc,
+ coin_sigs[i],
+ sizeof (*coin_sigs[i]));
+ GNUNET_CRYPTO_hash_context_finish (hc,
+ &dcs.h_coin_sigs);
+ if (NULL != h_policy)
+ dcs.h_policy = *h_policy;
+ TALER_amount_hton (&dcs.total_without_fee,
+ total_without_fee);
return scb (&dcs.purpose,
pub,
sig);
@@ -137,12 +146,13 @@ enum GNUNET_GenericReturnValue
TALER_exchange_online_deposit_confirmation_verify (
const struct TALER_PrivateContractHashP *h_contract_terms,
const struct TALER_MerchantWireHashP *h_wire,
- const struct TALER_ExtensionContractHashP *h_extensions,
+ 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 *amount_without_fee,
- const struct TALER_CoinSpendPublicKeyP *coin_pub,
+ 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,
const struct TALER_ExchangePublicKeyP *exchange_pub,
const struct TALER_ExchangeSignatureP *exchange_sig)
@@ -155,14 +165,21 @@ TALER_exchange_online_deposit_confirmation_verify (
.exchange_timestamp = GNUNET_TIME_timestamp_hton (exchange_timestamp),
.wire_deadline = GNUNET_TIME_timestamp_hton (wire_deadline),
.refund_deadline = GNUNET_TIME_timestamp_hton (refund_deadline),
- .coin_pub = *coin_pub,
.merchant_pub = *merchant_pub
};
-
- if (NULL != h_extensions)
- dcs.h_extensions = *h_extensions;
- TALER_amount_hton (&dcs.amount_without_fee,
- amount_without_fee);
+ struct GNUNET_HashContext *hc;
+
+ hc = GNUNET_CRYPTO_hash_context_start ();
+ for (unsigned int i = 0; i<num_coins; i++)
+ GNUNET_CRYPTO_hash_context_read (hc,
+ coin_sigs[i],
+ sizeof (*coin_sigs[i]));
+ GNUNET_CRYPTO_hash_context_finish (hc,
+ &dcs.h_coin_sigs);
+ if (NULL != h_policy)
+ dcs.h_policy = *h_policy;
+ TALER_amount_hton (&dcs.total_without_fee,
+ total_without_fee);
if (GNUNET_OK !=
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_CONFIRM_DEPOSIT,
&dcs,
@@ -362,6 +379,91 @@ TALER_exchange_online_melt_confirmation_verify (
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.
@@ -449,19 +551,20 @@ struct TALER_ExchangeAccountSetupSuccessPS
struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
/**
- * Hash over the payto for which the signature was
- * made.
+ * Hash over the payto for which the signature was made.
*/
struct TALER_PaytoHashP h_payto;
- // FIXME: include details on *which* KYC process
- // was satisfied!
+ /**
+ * Hash over details on *which* KYC obligations were discharged!
+ */
+ struct GNUNET_HashCode h_kyc;
/**
* When was the signature made.
- * FIXME: replace by *expiration* time!
*/
struct GNUNET_TIME_TimestampNBO timestamp;
+
};
GNUNET_NETWORK_STRUCT_END
@@ -471,6 +574,7 @@ 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)
@@ -480,10 +584,11 @@ TALER_exchange_online_account_setup_success_sign (
.purpose.purpose = htonl (
TALER_SIGNATURE_EXCHANGE_ACCOUNT_SETUP_SUCCESS),
.h_payto = *h_payto,
- .timestamp = GNUNET_TIME_timestamp_hton (
- timestamp)
+ .timestamp = GNUNET_TIME_timestamp_hton (timestamp)
};
+ TALER_json_hash (kyc,
+ &kyc_purpose.h_kyc);
return scb (&kyc_purpose.purpose,
pub,
sig);
@@ -493,6 +598,7 @@ TALER_exchange_online_account_setup_success_sign (
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)
@@ -502,10 +608,11 @@ TALER_exchange_online_account_setup_success_verify (
.purpose.purpose = htonl (
TALER_SIGNATURE_EXCHANGE_ACCOUNT_SETUP_SUCCESS),
.h_payto = *h_payto,
- .timestamp = GNUNET_TIME_timestamp_hton (
- timestamp)
+ .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,
@@ -853,8 +960,9 @@ TALER_exchange_online_confirm_recoup_sign (
struct TALER_RecoupConfirmationPS pc = {
.purpose.size = htonl (sizeof (pc)),
.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP),
- .reserve_pub = *reserve_pub,
- .coin_pub = *coin_pub
+ .timestamp = GNUNET_TIME_timestamp_hton (timestamp),
+ .coin_pub = *coin_pub,
+ .reserve_pub = *reserve_pub
};
TALER_amount_hton (&pc.recoup_amount,
@@ -877,8 +985,9 @@ TALER_exchange_online_confirm_recoup_verify (
struct TALER_RecoupConfirmationPS pc = {
.purpose.size = htonl (sizeof (pc)),
.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP),
- .reserve_pub = *reserve_pub,
- .coin_pub = *coin_pub
+ .timestamp = GNUNET_TIME_timestamp_hton (timestamp),
+ .coin_pub = *coin_pub,
+ .reserve_pub = *reserve_pub
};
TALER_amount_hton (&pc.recoup_amount,
@@ -1113,10 +1222,10 @@ TALER_exchange_online_denomination_expired_sign (
};
/* strncpy would create a compiler warning */
- memcpy (dua.operation,
- op,
- GNUNET_MIN (sizeof (dua.operation),
- strlen (op)));
+ GNUNET_memcpy (dua.operation,
+ op,
+ GNUNET_MIN (sizeof (dua.operation),
+ strlen (op)));
return scb (&dua.purpose,
pub,
sig);
@@ -1140,10 +1249,10 @@ TALER_exchange_online_denomination_expired_verify (
};
/* strncpy would create a compiler warning */
- memcpy (dua.operation,
- op,
- GNUNET_MIN (sizeof (dua.operation),
- strlen (op)));
+ GNUNET_memcpy (dua.operation,
+ op,
+ GNUNET_MIN (sizeof (dua.operation),
+ strlen (op)));
return
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_AFFIRM_DENOM_EXPIRED,
&dua,
@@ -1381,6 +1490,100 @@ 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
@@ -1589,4 +1792,103 @@ TALER_exchange_online_purse_status_verify (
}
+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 */