diff options
Diffstat (limited to 'src/util/exchange_signatures.c')
-rw-r--r-- | src/util/exchange_signatures.c | 403 |
1 files changed, 350 insertions, 53 deletions
diff --git a/src/util/exchange_signatures.c b/src/util/exchange_signatures.c index 5c72289e1..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,15 +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; /** + * 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 @@ -467,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) @@ -476,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); @@ -489,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) @@ -498,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, @@ -849,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, @@ -873,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, @@ -1109,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); @@ -1136,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, @@ -1301,11 +1414,6 @@ struct TALER_PurseCreateDepositConfirmationPS struct TALER_PurseContractPublicKeyP purse_pub; /** - * Public key of the merge capability. - */ - struct TALER_PurseMergePublicKeyP merge_pub; - - /** * Hash of the contract of the purse. */ struct TALER_PrivateContractHashP h_contract_terms; @@ -1323,7 +1431,6 @@ TALER_exchange_online_purse_created_sign ( const struct TALER_Amount *amount_without_fee, const struct TALER_Amount *total_deposited, const struct TALER_PurseContractPublicKeyP *purse_pub, - const struct TALER_PurseMergePublicKeyP *merge_pub, const struct TALER_PrivateContractHashP *h_contract_terms, struct TALER_ExchangePublicKeyP *pub, struct TALER_ExchangeSignatureP *sig) @@ -1333,7 +1440,6 @@ TALER_exchange_online_purse_created_sign ( .purpose.size = htonl (sizeof (dc)), .h_contract_terms = *h_contract_terms, .purse_pub = *purse_pub, - .merge_pub = *merge_pub, .purse_expiration = GNUNET_TIME_timestamp_hton (purse_expiration), .exchange_time = GNUNET_TIME_timestamp_hton (exchange_time) }; @@ -1355,7 +1461,6 @@ TALER_exchange_online_purse_created_verify ( const struct TALER_Amount *amount_without_fee, const struct TALER_Amount *total_deposited, const struct TALER_PurseContractPublicKeyP *purse_pub, - const struct TALER_PurseMergePublicKeyP *merge_pub, const struct TALER_PrivateContractHashP *h_contract_terms, const struct TALER_ExchangePublicKeyP *pub, const struct TALER_ExchangeSignatureP *sig) @@ -1365,7 +1470,6 @@ TALER_exchange_online_purse_created_verify ( .purpose.size = htonl (sizeof (dc)), .h_contract_terms = *h_contract_terms, .purse_pub = *purse_pub, - .merge_pub = *merge_pub, .purse_expiration = GNUNET_TIME_timestamp_hton (purse_expiration), .exchange_time = GNUNET_TIME_timestamp_hton (exchange_time) }; @@ -1386,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 @@ -1594,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 */ |