Line data Source code
1 : /*
2 : This file is part of TALER
3 : Copyright (C) 2020 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 merchant_signatures.c
18 : * @brief Utility functions for Taler merchant signatures
19 : * @author Christian Grothoff
20 : */
21 : #include "platform.h"
22 : #include "taler_util.h"
23 : #include "taler_signatures.h"
24 :
25 :
26 : GNUNET_NETWORK_STRUCT_BEGIN
27 :
28 : /**
29 : * @brief Format used to generate the signature on a request to obtain
30 : * the wire transfer identifier associated with a deposit.
31 : */
32 : struct TALER_DepositTrackPS
33 : {
34 : /**
35 : * Purpose must be #TALER_SIGNATURE_MERCHANT_TRACK_TRANSACTION.
36 : */
37 : struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
38 :
39 : /**
40 : * Hash over the proposal data of the contract for which this deposit is made.
41 : */
42 : struct TALER_PrivateContractHashP h_contract_terms GNUNET_PACKED;
43 :
44 : /**
45 : * Hash over the wiring information of the merchant.
46 : */
47 : struct TALER_MerchantWireHashP h_wire GNUNET_PACKED;
48 :
49 : /**
50 : * The coin's public key. This is the value that must have been
51 : * signed (blindly) by the Exchange.
52 : */
53 : struct TALER_CoinSpendPublicKeyP coin_pub;
54 :
55 : };
56 :
57 : GNUNET_NETWORK_STRUCT_END
58 :
59 :
60 : void
61 0 : TALER_merchant_deposit_sign (
62 : const struct TALER_PrivateContractHashP *h_contract_terms,
63 : const struct TALER_MerchantWireHashP *h_wire,
64 : const struct TALER_CoinSpendPublicKeyP *coin_pub,
65 : const struct TALER_MerchantPrivateKeyP *merchant_priv,
66 : struct TALER_MerchantSignatureP *merchant_sig)
67 : {
68 0 : struct TALER_DepositTrackPS dtp = {
69 0 : .purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_TRACK_TRANSACTION),
70 0 : .purpose.size = htonl (sizeof (dtp)),
71 : .h_contract_terms = *h_contract_terms,
72 : .h_wire = *h_wire,
73 : .coin_pub = *coin_pub
74 : };
75 :
76 0 : GNUNET_CRYPTO_eddsa_sign (&merchant_priv->eddsa_priv,
77 : &dtp,
78 : &merchant_sig->eddsa_sig);
79 0 : }
80 :
81 :
82 : enum GNUNET_GenericReturnValue
83 0 : TALER_merchant_deposit_verify (
84 : const struct TALER_MerchantPublicKeyP *merchant,
85 : const struct TALER_CoinSpendPublicKeyP *coin_pub,
86 : const struct TALER_PrivateContractHashP *h_contract_terms,
87 : const struct TALER_MerchantWireHashP *h_wire,
88 : const struct TALER_MerchantSignatureP *merchant_sig)
89 : {
90 0 : struct TALER_DepositTrackPS tps = {
91 0 : .purpose.size = htonl (sizeof (tps)),
92 0 : .purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_TRACK_TRANSACTION),
93 : .coin_pub = *coin_pub,
94 : .h_contract_terms = *h_contract_terms,
95 : .h_wire = *h_wire
96 : };
97 :
98 : return
99 0 : GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MERCHANT_TRACK_TRANSACTION,
100 : &tps,
101 : &merchant_sig->eddsa_sig,
102 : &merchant->eddsa_pub);
103 : }
104 :
105 :
106 : /**
107 : * @brief Format used to generate the signature on a request to refund
108 : * a coin into the account of the customer.
109 : */
110 : struct TALER_RefundRequestPS
111 : {
112 : /**
113 : * Purpose must be #TALER_SIGNATURE_MERCHANT_REFUND.
114 : */
115 : struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
116 :
117 : /**
118 : * Hash over the proposal data to identify the contract
119 : * which is being refunded.
120 : */
121 : struct TALER_PrivateContractHashP h_contract_terms GNUNET_PACKED;
122 :
123 : /**
124 : * The coin's public key. This is the value that must have been
125 : * signed (blindly) by the Exchange.
126 : */
127 : struct TALER_CoinSpendPublicKeyP coin_pub;
128 :
129 : /**
130 : * Merchant-generated transaction ID for the refund.
131 : */
132 : uint64_t rtransaction_id GNUNET_PACKED;
133 :
134 : /**
135 : * Amount to be refunded, including refund fee charged by the
136 : * exchange to the customer.
137 : */
138 : struct TALER_AmountNBO refund_amount;
139 : };
140 :
141 :
142 : void
143 0 : TALER_merchant_refund_sign (
144 : const struct TALER_CoinSpendPublicKeyP *coin_pub,
145 : const struct TALER_PrivateContractHashP *h_contract_terms,
146 : uint64_t rtransaction_id,
147 : const struct TALER_Amount *amount,
148 : const struct TALER_MerchantPrivateKeyP *merchant_priv,
149 : struct TALER_MerchantSignatureP *merchant_sig)
150 : {
151 0 : struct TALER_RefundRequestPS rr = {
152 0 : .purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_REFUND),
153 0 : .purpose.size = htonl (sizeof (rr)),
154 : .h_contract_terms = *h_contract_terms,
155 : .coin_pub = *coin_pub,
156 0 : .rtransaction_id = GNUNET_htonll (rtransaction_id)
157 : };
158 :
159 0 : TALER_amount_hton (&rr.refund_amount,
160 : amount);
161 0 : GNUNET_CRYPTO_eddsa_sign (&merchant_priv->eddsa_priv,
162 : &rr,
163 : &merchant_sig->eddsa_sig);
164 0 : }
165 :
166 :
167 : enum GNUNET_GenericReturnValue
168 0 : TALER_merchant_refund_verify (
169 : const struct TALER_CoinSpendPublicKeyP *coin_pub,
170 : const struct TALER_PrivateContractHashP *h_contract_terms,
171 : uint64_t rtransaction_id,
172 : const struct TALER_Amount *amount,
173 : const struct TALER_MerchantPublicKeyP *merchant_pub,
174 : const struct TALER_MerchantSignatureP *merchant_sig)
175 : {
176 0 : struct TALER_RefundRequestPS rr = {
177 0 : .purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_REFUND),
178 0 : .purpose.size = htonl (sizeof (rr)),
179 : .h_contract_terms = *h_contract_terms,
180 : .coin_pub = *coin_pub,
181 0 : .rtransaction_id = GNUNET_htonll (rtransaction_id)
182 : };
183 :
184 0 : TALER_amount_hton (&rr.refund_amount,
185 : amount);
186 : return
187 0 : GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MERCHANT_REFUND,
188 : &rr,
189 : &merchant_sig->eddsa_sig,
190 : &merchant_pub->eddsa_pub);
191 : }
192 :
193 :
194 : /**
195 : * @brief Information signed by the exchange's master
196 : * key affirming the IBAN details for the exchange.
197 : */
198 : struct TALER_MerchantWireDetailsPS
199 : {
200 :
201 : /**
202 : * Purpose is #TALER_SIGNATURE_MERCHANT_WIRE_DETAILS.
203 : */
204 : struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
205 :
206 : /**
207 : * Salted hash over the account holder's payto:// URL and
208 : * the salt, as done by #TALER_merchant_wire_signature_hash().
209 : */
210 : struct TALER_MerchantWireHashP h_wire_details GNUNET_PACKED;
211 :
212 : };
213 :
214 :
215 : enum GNUNET_GenericReturnValue
216 3 : TALER_merchant_wire_signature_check (
217 : const char *payto_uri,
218 : const struct TALER_WireSaltP *salt,
219 : const struct TALER_MerchantPublicKeyP *merch_pub,
220 : const struct TALER_MerchantSignatureP *merch_sig)
221 : {
222 3 : struct TALER_MerchantWireDetailsPS wd = {
223 3 : .purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_WIRE_DETAILS),
224 3 : .purpose.size = htonl (sizeof (wd))
225 : };
226 :
227 3 : TALER_merchant_wire_signature_hash (payto_uri,
228 : salt,
229 : &wd.h_wire_details);
230 3 : return GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MERCHANT_WIRE_DETAILS,
231 : &wd,
232 : &merch_sig->eddsa_sig,
233 : &merch_pub->eddsa_pub);
234 : }
235 :
236 :
237 : void
238 1 : TALER_merchant_wire_signature_make (
239 : const char *payto_uri,
240 : const struct TALER_WireSaltP *salt,
241 : const struct TALER_MerchantPrivateKeyP *merch_priv,
242 : struct TALER_MerchantSignatureP *merch_sig)
243 : {
244 1 : struct TALER_MerchantWireDetailsPS wd = {
245 1 : .purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_WIRE_DETAILS),
246 1 : .purpose.size = htonl (sizeof (wd))
247 : };
248 :
249 1 : TALER_merchant_wire_signature_hash (payto_uri,
250 : salt,
251 : &wd.h_wire_details);
252 1 : GNUNET_CRYPTO_eddsa_sign (&merch_priv->eddsa_priv,
253 : &wd,
254 : &merch_sig->eddsa_sig);
255 1 : }
256 :
257 :
258 : /**
259 : * Used by merchants to return signed responses to /pay requests.
260 : * Currently only used to return 200 OK signed responses.
261 : */
262 : struct TALER_PaymentResponsePS
263 : {
264 : /**
265 : * Set to #TALER_SIGNATURE_MERCHANT_PAYMENT_OK. Note that
266 : * unsuccessful payments are usually proven by some exchange's signature.
267 : */
268 : struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
269 :
270 : /**
271 : * Hash of the proposal data associated with this confirmation
272 : */
273 : struct TALER_PrivateContractHashP h_contract_terms;
274 : };
275 :
276 : void
277 0 : TALER_merchant_pay_sign (
278 : const struct TALER_PrivateContractHashP *h_contract_terms,
279 : const struct TALER_MerchantPrivateKeyP *merch_priv,
280 : struct GNUNET_CRYPTO_EddsaSignature *merch_sig)
281 : {
282 0 : struct TALER_PaymentResponsePS mr = {
283 0 : .purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_PAYMENT_OK),
284 0 : .purpose.size = htonl (sizeof (mr)),
285 : .h_contract_terms = *h_contract_terms
286 : };
287 :
288 0 : GNUNET_CRYPTO_eddsa_sign (&merch_priv->eddsa_priv,
289 : &mr,
290 : merch_sig);
291 0 : }
292 :
293 :
294 : enum GNUNET_GenericReturnValue
295 0 : TALER_merchant_pay_verify (
296 : const struct TALER_PrivateContractHashP *h_contract_terms,
297 : const struct TALER_MerchantPublicKeyP *merchant_pub,
298 : const struct TALER_MerchantSignatureP *merchant_sig)
299 : {
300 0 : struct TALER_PaymentResponsePS pr = {
301 0 : .purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_PAYMENT_OK),
302 0 : .purpose.size = htonl (sizeof (pr)),
303 : .h_contract_terms = *h_contract_terms
304 : };
305 :
306 : return
307 0 : GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MERCHANT_PAYMENT_OK,
308 : &pr,
309 : &merchant_sig->eddsa_sig,
310 : &merchant_pub->eddsa_pub);
311 : }
312 :
313 :
314 : /**
315 : * The contract sent by the merchant to the wallet.
316 : */
317 : struct TALER_ProposalDataPS
318 : {
319 : /**
320 : * Purpose header for the signature over the proposal data
321 : * with purpose #TALER_SIGNATURE_MERCHANT_CONTRACT.
322 : */
323 : struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
324 :
325 : /**
326 : * Hash of the JSON contract in UTF-8 including 0-termination,
327 : * using JSON_COMPACT | JSON_SORT_KEYS
328 : */
329 : struct TALER_PrivateContractHashP hash;
330 : };
331 :
332 : void
333 0 : TALER_merchant_contract_sign (
334 : const struct TALER_PrivateContractHashP *h_contract_terms,
335 : const struct TALER_MerchantPrivateKeyP *merch_priv,
336 : struct GNUNET_CRYPTO_EddsaSignature *merch_sig)
337 : {
338 0 : struct TALER_ProposalDataPS pdps = {
339 0 : .purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_CONTRACT),
340 0 : .purpose.size = htonl (sizeof (pdps)),
341 : .hash = *h_contract_terms
342 : };
343 :
344 0 : GNUNET_CRYPTO_eddsa_sign (&merch_priv->eddsa_priv,
345 : &pdps,
346 : merch_sig);
347 0 : }
348 :
349 :
350 : // NB: "TALER_merchant_contract_verify" not (yet?) needed / not defined.
351 :
352 : /* end of merchant_signatures.c */
|