Line data Source code
1 : /*
2 : This file is part of TALER
3 : Copyright (C) 2014-2022 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 util/crypto.c
18 : * @brief Cryptographic utility functions
19 : * @author Sree Harsha Totakura <sreeharsha@totakura.in>
20 : * @author Florian Dold
21 : * @author Benedikt Mueller
22 : * @author Christian Grothoff
23 : * @author Özgür Kesim
24 : */
25 : #include "platform.h"
26 : #include "taler_util.h"
27 : #include <gcrypt.h>
28 :
29 : /**
30 : * Used in TALER_AgeCommitmentHash_isNullOrZero for comparison
31 : */
32 : const struct TALER_AgeCommitmentHash TALER_ZeroAgeCommitmentHash = {0};
33 :
34 : /**
35 : * Function called by libgcrypt on serious errors.
36 : * Prints an error message and aborts the process.
37 : *
38 : * @param cls NULL
39 : * @param wtf unknown
40 : * @param msg error message
41 : */
42 : static void
43 0 : fatal_error_handler (void *cls,
44 : int wtf,
45 : const char *msg)
46 : {
47 : (void) cls;
48 : (void) wtf;
49 0 : fprintf (stderr,
50 : "Fatal error in libgcrypt: %s\n",
51 : msg);
52 0 : abort ();
53 : }
54 :
55 :
56 : /**
57 : * Initialize libgcrypt.
58 : */
59 : void __attribute__ ((constructor))
60 72 : TALER_gcrypt_init ()
61 : {
62 72 : gcry_set_fatalerror_handler (&fatal_error_handler,
63 : NULL);
64 72 : if (! gcry_check_version (NEED_LIBGCRYPT_VERSION))
65 : {
66 0 : fprintf (stderr,
67 : "libgcrypt version mismatch\n");
68 0 : abort ();
69 : }
70 : /* Disable secure memory (we should never run on a system that
71 : even uses swap space for memory). */
72 72 : gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
73 72 : gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
74 72 : }
75 :
76 :
77 : enum GNUNET_GenericReturnValue
78 0 : TALER_test_coin_valid (const struct TALER_CoinPublicInfo *coin_public_info,
79 : const struct TALER_DenominationPublicKey *denom_pub)
80 : {
81 : struct TALER_CoinPubHashP c_hash;
82 : #if ENABLE_SANITY_CHECKS
83 : struct TALER_DenominationHashP d_hash;
84 :
85 0 : TALER_denom_pub_hash (denom_pub,
86 : &d_hash);
87 0 : GNUNET_assert (0 ==
88 : GNUNET_memcmp (&d_hash,
89 : &coin_public_info->denom_pub_hash));
90 : #endif
91 :
92 0 : TALER_coin_pub_hash (&coin_public_info->coin_pub,
93 : &coin_public_info->h_age_commitment,
94 : &c_hash);
95 :
96 0 : if (GNUNET_OK !=
97 0 : TALER_denom_pub_verify (denom_pub,
98 : &coin_public_info->denom_sig,
99 : &c_hash))
100 : {
101 0 : GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
102 : "coin signature is invalid\n");
103 0 : return GNUNET_NO;
104 : }
105 0 : return GNUNET_YES;
106 : }
107 :
108 :
109 : void
110 1 : TALER_link_derive_transfer_secret (
111 : const struct TALER_CoinSpendPrivateKeyP *coin_priv,
112 : const struct TALER_TransferPrivateKeyP *trans_priv,
113 : struct TALER_TransferSecretP *ts)
114 : {
115 : struct TALER_CoinSpendPublicKeyP coin_pub;
116 :
117 1 : GNUNET_CRYPTO_eddsa_key_get_public (&coin_priv->eddsa_priv,
118 : &coin_pub.eddsa_pub);
119 1 : GNUNET_assert (GNUNET_OK ==
120 : GNUNET_CRYPTO_ecdh_eddsa (&trans_priv->ecdhe_priv,
121 : &coin_pub.eddsa_pub,
122 : &ts->key));
123 1 : }
124 :
125 :
126 : void
127 1 : TALER_link_reveal_transfer_secret (
128 : const struct TALER_TransferPrivateKeyP *trans_priv,
129 : const struct TALER_CoinSpendPublicKeyP *coin_pub,
130 : struct TALER_TransferSecretP *transfer_secret)
131 : {
132 1 : GNUNET_assert (GNUNET_OK ==
133 : GNUNET_CRYPTO_ecdh_eddsa (&trans_priv->ecdhe_priv,
134 : &coin_pub->eddsa_pub,
135 : &transfer_secret->key));
136 1 : }
137 :
138 :
139 : void
140 1 : TALER_link_recover_transfer_secret (
141 : const struct TALER_TransferPublicKeyP *trans_pub,
142 : const struct TALER_CoinSpendPrivateKeyP *coin_priv,
143 : struct TALER_TransferSecretP *transfer_secret)
144 : {
145 1 : GNUNET_assert (GNUNET_OK ==
146 : GNUNET_CRYPTO_eddsa_ecdh (&coin_priv->eddsa_priv,
147 : &trans_pub->ecdhe_pub,
148 : &transfer_secret->key));
149 1 : }
150 :
151 :
152 : void
153 20 : TALER_planchet_master_setup_random (
154 : struct TALER_PlanchetMasterSecretP *ps)
155 : {
156 20 : GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG,
157 : ps,
158 : sizeof (*ps));
159 20 : }
160 :
161 :
162 : void
163 0 : TALER_refresh_master_setup_random (
164 : struct TALER_RefreshMasterSecretP *rms)
165 : {
166 0 : GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG,
167 : rms,
168 : sizeof (*rms));
169 0 : }
170 :
171 :
172 : void
173 2 : TALER_transfer_secret_to_planchet_secret (
174 : const struct TALER_TransferSecretP *secret_seed,
175 : uint32_t coin_num_salt,
176 : struct TALER_PlanchetMasterSecretP *ps)
177 : {
178 2 : uint32_t be_salt = htonl (coin_num_salt);
179 :
180 2 : GNUNET_assert (GNUNET_OK ==
181 : GNUNET_CRYPTO_kdf (ps,
182 : sizeof (*ps),
183 : &be_salt,
184 : sizeof (be_salt),
185 : secret_seed,
186 : sizeof (*secret_seed),
187 : "taler-coin-derivation",
188 : strlen ("taler-coin-derivation"),
189 : NULL, 0));
190 2 : }
191 :
192 :
193 : void
194 0 : TALER_planchet_secret_to_transfer_priv (
195 : const struct TALER_RefreshMasterSecretP *rms,
196 : const struct TALER_CoinSpendPrivateKeyP *old_coin_priv,
197 : uint32_t cnc_num,
198 : struct TALER_TransferPrivateKeyP *tpriv)
199 : {
200 0 : uint32_t be_salt = htonl (cnc_num);
201 :
202 0 : GNUNET_assert (GNUNET_OK ==
203 : GNUNET_CRYPTO_kdf (tpriv,
204 : sizeof (*tpriv),
205 : &be_salt,
206 : sizeof (be_salt),
207 : old_coin_priv,
208 : sizeof (*old_coin_priv),
209 : rms,
210 : sizeof (*rms),
211 : "taler-transfer-priv-derivation",
212 : strlen ("taler-transfer-priv-derivation"),
213 : NULL, 0));
214 0 : }
215 :
216 :
217 : void
218 23 : TALER_cs_withdraw_nonce_derive (
219 : const struct TALER_PlanchetMasterSecretP *ps,
220 : struct TALER_CsNonce *nonce)
221 : {
222 23 : GNUNET_assert (GNUNET_YES ==
223 : GNUNET_CRYPTO_kdf (nonce,
224 : sizeof (*nonce),
225 : "n",
226 : strlen ("n"),
227 : ps,
228 : sizeof(*ps),
229 : NULL,
230 : 0));
231 23 : }
232 :
233 :
234 : void
235 0 : TALER_cs_refresh_nonce_derive (
236 : const struct TALER_RefreshMasterSecretP *rms,
237 : uint32_t coin_num_salt,
238 : struct TALER_CsNonce *nonce)
239 : {
240 0 : uint32_t be_salt = htonl (coin_num_salt);
241 :
242 0 : GNUNET_assert (GNUNET_YES ==
243 : GNUNET_CRYPTO_kdf (nonce,
244 : sizeof (*nonce),
245 : &be_salt,
246 : sizeof (be_salt),
247 : "refresh-n",
248 : strlen ("refresh-n"),
249 : rms,
250 : sizeof(*rms),
251 : NULL,
252 : 0));
253 0 : }
254 :
255 :
256 : enum GNUNET_GenericReturnValue
257 31 : TALER_planchet_prepare (const struct TALER_DenominationPublicKey *dk,
258 : const struct TALER_ExchangeWithdrawValues *alg_values,
259 : const union TALER_DenominationBlindingKeyP *bks,
260 : const struct TALER_CoinSpendPrivateKeyP *coin_priv,
261 : const struct TALER_AgeCommitmentHash *ach,
262 : struct TALER_CoinPubHashP *c_hash,
263 : struct TALER_PlanchetDetail *pd
264 : )
265 : {
266 : struct TALER_CoinSpendPublicKeyP coin_pub;
267 :
268 31 : GNUNET_assert (alg_values->cipher == dk->cipher);
269 31 : GNUNET_CRYPTO_eddsa_key_get_public (&coin_priv->eddsa_priv,
270 : &coin_pub.eddsa_pub);
271 31 : if (GNUNET_OK !=
272 31 : TALER_denom_blind (dk,
273 : bks,
274 : ach,
275 : &coin_pub,
276 : alg_values,
277 : c_hash,
278 : &pd->blinded_planchet))
279 : {
280 0 : GNUNET_break (0);
281 0 : return GNUNET_SYSERR;
282 : }
283 31 : TALER_denom_pub_hash (dk,
284 : &pd->denom_pub_hash);
285 31 : return GNUNET_OK;
286 : }
287 :
288 :
289 : void
290 4 : TALER_planchet_detail_free (struct TALER_PlanchetDetail *pd)
291 : {
292 4 : TALER_blinded_planchet_free (&pd->blinded_planchet);
293 4 : }
294 :
295 :
296 : enum GNUNET_GenericReturnValue
297 5 : TALER_planchet_to_coin (
298 : const struct TALER_DenominationPublicKey *dk,
299 : const struct TALER_BlindedDenominationSignature *blind_sig,
300 : const union TALER_DenominationBlindingKeyP *bks,
301 : const struct TALER_CoinSpendPrivateKeyP *coin_priv,
302 : const struct TALER_AgeCommitmentHash *ach,
303 : const struct TALER_CoinPubHashP *c_hash,
304 : const struct TALER_ExchangeWithdrawValues *alg_values,
305 : struct TALER_FreshCoin *coin)
306 : {
307 5 : if ( (dk->cipher != blind_sig->cipher) ||
308 5 : (dk->cipher != alg_values->cipher) )
309 : {
310 0 : GNUNET_break_op (0);
311 0 : return GNUNET_SYSERR;
312 : }
313 5 : if (GNUNET_OK !=
314 5 : TALER_denom_sig_unblind (&coin->sig,
315 : blind_sig,
316 : bks,
317 : c_hash,
318 : alg_values,
319 : dk))
320 : {
321 0 : GNUNET_break_op (0);
322 0 : return GNUNET_SYSERR;
323 : }
324 5 : if (GNUNET_OK !=
325 5 : TALER_denom_pub_verify (dk,
326 5 : &coin->sig,
327 : c_hash))
328 : {
329 0 : GNUNET_break_op (0);
330 0 : TALER_denom_sig_free (&coin->sig);
331 0 : return GNUNET_SYSERR;
332 : }
333 :
334 5 : coin->coin_priv = *coin_priv;
335 5 : coin->h_age_commitment = ach;
336 5 : return GNUNET_OK;
337 : }
338 :
339 :
340 : void
341 0 : TALER_refresh_get_commitment (struct TALER_RefreshCommitmentP *rc,
342 : uint32_t kappa,
343 : const struct TALER_RefreshMasterSecretP *rms,
344 : uint32_t num_new_coins,
345 : const struct TALER_RefreshCommitmentEntry *rcs,
346 : const struct TALER_CoinSpendPublicKeyP *coin_pub,
347 : const struct TALER_Amount *amount_with_fee)
348 : {
349 : struct GNUNET_HashContext *hash_context;
350 :
351 0 : hash_context = GNUNET_CRYPTO_hash_context_start ();
352 0 : if (NULL != rms)
353 0 : GNUNET_CRYPTO_hash_context_read (hash_context,
354 : rms,
355 : sizeof (*rms));
356 : /* first, iterate over transfer public keys for hash_context */
357 0 : for (unsigned int i = 0; i<kappa; i++)
358 : {
359 0 : GNUNET_CRYPTO_hash_context_read (hash_context,
360 0 : &rcs[i].transfer_pub,
361 : sizeof (struct TALER_TransferPublicKeyP));
362 : }
363 : /* next, add all of the hashes from the denomination keys to the
364 : hash_context */
365 0 : for (unsigned int i = 0; i<num_new_coins; i++)
366 : {
367 : struct TALER_DenominationHashP denom_hash;
368 :
369 : /* The denomination keys should / must all be identical regardless
370 : of what offset we use, so we use [0]. */
371 0 : GNUNET_assert (kappa > 0); /* sanity check */
372 0 : TALER_denom_pub_hash (rcs[0].new_coins[i].dk,
373 : &denom_hash);
374 0 : GNUNET_CRYPTO_hash_context_read (hash_context,
375 : &denom_hash,
376 : sizeof (denom_hash));
377 : }
378 :
379 : /* next, add public key of coin and amount being refreshed */
380 : {
381 : struct TALER_AmountNBO melt_amountn;
382 :
383 0 : GNUNET_CRYPTO_hash_context_read (hash_context,
384 : coin_pub,
385 : sizeof (struct TALER_CoinSpendPublicKeyP));
386 0 : TALER_amount_hton (&melt_amountn,
387 : amount_with_fee);
388 0 : GNUNET_CRYPTO_hash_context_read (hash_context,
389 : &melt_amountn,
390 : sizeof (struct TALER_AmountNBO));
391 : }
392 :
393 : /* finally, add all the envelopes */
394 0 : for (unsigned int i = 0; i<kappa; i++)
395 : {
396 0 : const struct TALER_RefreshCommitmentEntry *rce = &rcs[i];
397 :
398 0 : for (unsigned int j = 0; j<num_new_coins; j++)
399 : {
400 0 : const struct TALER_RefreshCoinData *rcd = &rce->new_coins[j];
401 :
402 0 : TALER_blinded_planchet_hash_ (&rcd->blinded_planchet,
403 : hash_context);
404 : }
405 : }
406 :
407 : /* Conclude */
408 0 : GNUNET_CRYPTO_hash_context_finish (hash_context,
409 : &rc->session_hash);
410 0 : }
411 :
412 :
413 : void
414 31 : TALER_coin_pub_hash (const struct TALER_CoinSpendPublicKeyP *coin_pub,
415 : const struct TALER_AgeCommitmentHash *ach,
416 : struct TALER_CoinPubHashP *coin_h)
417 : {
418 31 : if (TALER_AgeCommitmentHash_isNullOrZero (ach))
419 : {
420 : /* No age commitment was set */
421 14 : GNUNET_CRYPTO_hash (&coin_pub->eddsa_pub,
422 : sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey),
423 : &coin_h->hash);
424 : }
425 : else
426 17 : {
427 : /* Coin comes with age commitment. Take the hash of the age commitment
428 : * into account */
429 17 : const size_t key_s = sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey);
430 17 : const size_t age_s = sizeof(struct TALER_AgeCommitmentHash);
431 17 : char data[key_s + age_s];
432 :
433 17 : GNUNET_memcpy (&data[0],
434 : &coin_pub->eddsa_pub,
435 : key_s);
436 17 : GNUNET_memcpy (&data[key_s],
437 : ach,
438 : age_s);
439 17 : GNUNET_CRYPTO_hash (&data,
440 : key_s + age_s,
441 : &coin_h->hash);
442 : }
443 31 : }
444 :
445 :
446 : enum GNUNET_GenericReturnValue
447 0 : TALER_coin_ev_hash (const struct TALER_BlindedPlanchet *blinded_planchet,
448 : const struct TALER_DenominationHashP *denom_hash,
449 : struct TALER_BlindedCoinHashP *bch)
450 : {
451 : struct GNUNET_HashContext *hash_context;
452 :
453 0 : hash_context = GNUNET_CRYPTO_hash_context_start ();
454 0 : GNUNET_CRYPTO_hash_context_read (hash_context,
455 : denom_hash,
456 : sizeof(*denom_hash));
457 0 : TALER_blinded_planchet_hash_ (blinded_planchet,
458 : hash_context);
459 0 : GNUNET_CRYPTO_hash_context_finish (hash_context,
460 : &bch->hash);
461 0 : return GNUNET_OK;
462 : }
463 :
464 :
465 : /* end of crypto.c */
|