exchange

Base system with REST service to issue digital coins, run by the payment service provider
Log | Files | Refs | Submodules | README | LICENSE

crypto.c (24024B)


      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/taler_util.h"
     27 #include <gcrypt.h>
     28 
     29 /**
     30  * Function called by libgcrypt on serious errors.
     31  * Prints an error message and aborts the process.
     32  *
     33  * @param cls NULL
     34  * @param wtf unknown
     35  * @param msg error message
     36  */
     37 static void
     38 fatal_error_handler (void *cls,
     39                      int wtf,
     40                      const char *msg)
     41 {
     42   (void) cls;
     43   (void) wtf;
     44   fprintf (stderr,
     45            "Fatal error in libgcrypt: %s\n",
     46            msg);
     47   abort ();
     48 }
     49 
     50 
     51 /**
     52  * Initialize libgcrypt.
     53  */
     54 void __attribute__ ((constructor))
     55 TALER_gcrypt_init ()
     56 {
     57   gcry_set_fatalerror_handler (&fatal_error_handler,
     58                                NULL);
     59   if (! gcry_check_version (NEED_LIBGCRYPT_VERSION))
     60   {
     61     fprintf (stderr,
     62              "libgcrypt version mismatch\n");
     63     abort ();
     64   }
     65   /* Disable secure memory (we should never run on a system that
     66      even uses swap space for memory). */
     67   gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
     68   gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
     69 }
     70 
     71 
     72 enum GNUNET_GenericReturnValue
     73 TALER_test_coin_valid (const struct TALER_CoinPublicInfo *coin_public_info,
     74                        const struct TALER_DenominationPublicKey *denom_pub)
     75 {
     76   struct TALER_CoinPubHashP c_hash;
     77 #if ENABLE_SANITY_CHECKS
     78   struct TALER_DenominationHashP d_hash;
     79 
     80   TALER_denom_pub_hash (denom_pub,
     81                         &d_hash);
     82   GNUNET_assert (0 ==
     83                  GNUNET_memcmp (&d_hash,
     84                                 &coin_public_info->denom_pub_hash));
     85 #endif
     86 
     87   TALER_coin_pub_hash (&coin_public_info->coin_pub,
     88                        coin_public_info->no_age_commitment
     89                        ? NULL
     90                        : &coin_public_info->h_age_commitment,
     91                        &c_hash);
     92 
     93   if (GNUNET_OK !=
     94       TALER_denom_pub_verify (denom_pub,
     95                               &coin_public_info->denom_sig,
     96                               &c_hash))
     97   {
     98     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
     99                 "coin signature is invalid\n");
    100     return GNUNET_NO;
    101   }
    102   return GNUNET_YES;
    103 }
    104 
    105 
    106 void
    107 TALER_link_derive_transfer_secret (
    108   const struct TALER_CoinSpendPrivateKeyP *coin_priv,
    109   const struct TALER_TransferPrivateKeyP *trans_priv,
    110   struct TALER_TransferSecretP *ts)
    111 {
    112   struct TALER_CoinSpendPublicKeyP coin_pub;
    113 
    114   GNUNET_CRYPTO_eddsa_key_get_public (&coin_priv->eddsa_priv,
    115                                       &coin_pub.eddsa_pub);
    116   GNUNET_assert (GNUNET_OK ==
    117                  GNUNET_CRYPTO_ecdh_eddsa (&trans_priv->ecdhe_priv,
    118                                            &coin_pub.eddsa_pub,
    119                                            &ts->key));
    120 }
    121 
    122 
    123 void
    124 TALER_link_reveal_transfer_secret (
    125   const struct TALER_TransferPrivateKeyP *trans_priv,
    126   const struct TALER_CoinSpendPublicKeyP *coin_pub,
    127   struct TALER_TransferSecretP *transfer_secret)
    128 {
    129   GNUNET_assert (GNUNET_OK ==
    130                  GNUNET_CRYPTO_ecdh_eddsa (&trans_priv->ecdhe_priv,
    131                                            &coin_pub->eddsa_pub,
    132                                            &transfer_secret->key));
    133 }
    134 
    135 
    136 void
    137 TALER_link_recover_transfer_secret (
    138   const struct TALER_TransferPublicKeyP *trans_pub,
    139   const struct TALER_CoinSpendPrivateKeyP *coin_priv,
    140   struct TALER_TransferSecretP *transfer_secret)
    141 {
    142   GNUNET_assert (GNUNET_OK ==
    143                  GNUNET_CRYPTO_eddsa_ecdh (&coin_priv->eddsa_priv,
    144                                            &trans_pub->ecdhe_pub,
    145                                            &transfer_secret->key));
    146 }
    147 
    148 
    149 void
    150 TALER_withdraw_expand_secrets (
    151   size_t num_coins,
    152   const struct TALER_WithdrawMasterSeedP *seed,
    153   struct TALER_PlanchetMasterSecretP secrets[static num_coins])
    154 {
    155   _Static_assert (sizeof(seed->seed_data) == sizeof(secrets->key_data));
    156   GNUNET_assert (0 < num_coins);
    157 
    158   if (1 == num_coins)
    159   {
    160     GNUNET_memcpy (&secrets[0].key_data,
    161                    &seed->seed_data,
    162                    sizeof(secrets[0].key_data));
    163   }
    164   else
    165   {
    166     uint32_t be_salt = htonl (num_coins);
    167 
    168     GNUNET_assert (GNUNET_OK ==
    169                    GNUNET_CRYPTO_hkdf_gnunet (
    170                      secrets,
    171                      sizeof (*secrets) * num_coins,
    172                      &be_salt,
    173                      sizeof (be_salt),
    174                      seed,
    175                      sizeof (*seed),
    176                      GNUNET_CRYPTO_kdf_arg_string ("taler-withdraw-secrets")));
    177   }
    178 }
    179 
    180 
    181 void
    182 TALER_withdraw_expand_kappa_seed (
    183   const struct TALER_WithdrawMasterSeedP *seed,
    184   struct TALER_KappaWithdrawMasterSeedP *seeds)
    185 {
    186   uint32_t be_salt = htonl (TALER_CNC_KAPPA);
    187 
    188   GNUNET_assert (GNUNET_OK ==
    189                  GNUNET_CRYPTO_hkdf_gnunet (
    190                    seeds,
    191                    sizeof (*seeds),
    192                    &be_salt,
    193                    sizeof (be_salt),
    194                    seed,
    195                    sizeof (*seed),
    196                    GNUNET_CRYPTO_kdf_arg_string ("taler-kappa-seeds")));
    197 }
    198 
    199 
    200 void
    201 TALER_planchet_master_setup_random (
    202   struct TALER_PlanchetMasterSecretP *ps)
    203 {
    204   GNUNET_CRYPTO_random_block (ps,
    205                               sizeof (*ps));
    206 }
    207 
    208 
    209 void
    210 TALER_withdraw_master_seed_setup_random (
    211   struct TALER_WithdrawMasterSeedP *seed)
    212 {
    213   GNUNET_CRYPTO_random_block (seed,
    214                               sizeof (*seed));
    215 }
    216 
    217 
    218 void
    219 TALER_refresh_master_setup_random (
    220   struct TALER_PublicRefreshMasterSeedP *rms)
    221 {
    222   GNUNET_CRYPTO_random_block (rms,
    223                               sizeof (*rms));
    224 }
    225 
    226 
    227 void
    228 TALER_transfer_secret_to_planchet_secret (
    229   const struct TALER_TransferSecretP *secret_seed,
    230   uint32_t coin_num_salt,
    231   struct TALER_PlanchetMasterSecretP *ps)
    232 {
    233   uint32_t be_salt = htonl (coin_num_salt);
    234 
    235   GNUNET_assert (GNUNET_OK ==
    236                  GNUNET_CRYPTO_hkdf_gnunet (
    237                    ps,
    238                    sizeof (*ps),
    239                    &be_salt,
    240                    sizeof (be_salt),
    241                    secret_seed,
    242                    sizeof (*secret_seed),
    243                    GNUNET_CRYPTO_kdf_arg_string ("taler-coin-derivation")));
    244 }
    245 
    246 
    247 void
    248 TALER_cs_withdraw_nonce_derive (
    249   const struct TALER_PlanchetMasterSecretP *ps,
    250   struct GNUNET_CRYPTO_CsSessionNonce *nonce)
    251 {
    252   GNUNET_assert (GNUNET_YES ==
    253                  GNUNET_CRYPTO_hkdf_gnunet (
    254                    nonce,
    255                    sizeof (*nonce),
    256                    "n",
    257                    strlen ("n"),
    258                    ps,
    259                    sizeof(*ps)));
    260 }
    261 
    262 
    263 void
    264 TALER_cs_withdraw_seed_to_blinding_seed (
    265   const struct TALER_WithdrawMasterSeedP *seed,
    266   struct TALER_BlindingMasterSeedP *blinding_seed)
    267 {
    268   GNUNET_assert (GNUNET_YES ==
    269                  GNUNET_CRYPTO_hkdf_gnunet (
    270                    blinding_seed,
    271                    sizeof (*blinding_seed),
    272                    "withdraw-blinding",
    273                    strlen ("withdraw-blinding"),
    274                    seed,
    275                    sizeof(*seed)));
    276 }
    277 
    278 
    279 void
    280 TALER_cs_refresh_seed_to_blinding_seed (
    281   const struct TALER_PublicRefreshMasterSeedP *seed,
    282   const struct TALER_CoinSpendPrivateKeyP *coin_priv,
    283   struct TALER_BlindingMasterSeedP *blinding_seed)
    284 {
    285   GNUNET_assert (GNUNET_YES ==
    286                  GNUNET_CRYPTO_hkdf_gnunet (
    287                    blinding_seed,
    288                    sizeof (*blinding_seed),
    289                    "refresh-blinding",
    290                    strlen ("refresh-blinding"),
    291                    coin_priv,
    292                    sizeof (*coin_priv),
    293                    GNUNET_CRYPTO_kdf_arg_auto (seed)));
    294 }
    295 
    296 
    297 void
    298 TALER_cs_nonce_derive_indexed (
    299   const struct TALER_BlindingMasterSeedP *seed,
    300   bool for_melt,
    301   uint32_t index,
    302   struct GNUNET_CRYPTO_CsSessionNonce *nonce)
    303 {
    304   uint32_t be_salt = htonl (index);
    305   const char *operation = for_melt ? "refresh-n" : "withdraw-n";
    306 
    307   GNUNET_assert (GNUNET_YES ==
    308                  GNUNET_CRYPTO_hkdf_gnunet (
    309                    nonce,
    310                    sizeof (*nonce),
    311                    &be_salt,
    312                    sizeof (be_salt),
    313                    operation,
    314                    strlen (operation),
    315                    GNUNET_CRYPTO_kdf_arg_auto (seed)));
    316 }
    317 
    318 
    319 void
    320 TALER_cs_derive_nonces_from_seed (
    321   const struct TALER_BlindingMasterSeedP *seed,
    322   bool for_melt,
    323   size_t num,
    324   const uint32_t indices[static num],
    325   struct GNUNET_CRYPTO_CsSessionNonce nonces[static num])
    326 {
    327   GNUNET_assert (TALER_MAX_COINS > num);
    328 
    329   for (size_t i = 0; i < num; i++)
    330     TALER_cs_nonce_derive_indexed (
    331       seed,
    332       for_melt,
    333       indices[i],
    334       &nonces[i]);
    335 }
    336 
    337 
    338 void
    339 TALER_cs_derive_only_cs_blind_nonces_from_seed (
    340   const struct TALER_BlindingMasterSeedP *seed,
    341   bool for_melt,
    342   size_t num,
    343   const uint32_t indices[static num],
    344   union GNUNET_CRYPTO_BlindSessionNonce nonces[static num])
    345 {
    346   GNUNET_assert (TALER_MAX_COINS > num);
    347 
    348   for (size_t i = 0; i < num; i++)
    349     TALER_cs_nonce_derive_indexed (
    350       seed,
    351       for_melt,
    352       indices[i],
    353       &nonces[i].cs_nonce);
    354 }
    355 
    356 
    357 void
    358 TALER_cs_derive_blind_nonces_from_seed (
    359   const struct TALER_BlindingMasterSeedP *seed,
    360   bool for_melt,
    361   size_t num,
    362   const bool is_cs[static num],
    363   union GNUNET_CRYPTO_BlindSessionNonce nonces[static num])
    364 {
    365   for (size_t i = 0; i < num; i++)
    366   {
    367     if (is_cs[i])
    368       TALER_cs_nonce_derive_indexed (
    369         seed,
    370         for_melt,
    371         i,
    372         &nonces[i].cs_nonce);
    373   }
    374 }
    375 
    376 
    377 void
    378 TALER_rsa_pub_hash (const struct GNUNET_CRYPTO_RsaPublicKey *rsa,
    379                     struct TALER_RsaPubHashP *h_rsa)
    380 {
    381   GNUNET_CRYPTO_rsa_public_key_hash (rsa,
    382                                      &h_rsa->hash);
    383 
    384 }
    385 
    386 
    387 void
    388 TALER_cs_pub_hash (const struct GNUNET_CRYPTO_CsPublicKey *cs,
    389                    struct TALER_CsPubHashP *h_cs)
    390 {
    391   GNUNET_CRYPTO_hash (cs,
    392                       sizeof(*cs),
    393                       &h_cs->hash);
    394 }
    395 
    396 
    397 enum GNUNET_GenericReturnValue
    398 TALER_planchet_prepare (
    399   const struct TALER_DenominationPublicKey *dk,
    400   const struct TALER_ExchangeBlindingValues *blinding_values,
    401   const union GNUNET_CRYPTO_BlindingSecretP *bks,
    402   const union GNUNET_CRYPTO_BlindSessionNonce *nonce,
    403   const struct TALER_CoinSpendPrivateKeyP *coin_priv,
    404   const struct TALER_AgeCommitmentHashP *ach,
    405   struct TALER_CoinPubHashP *c_hash,
    406   struct TALER_PlanchetDetail *pd)
    407 {
    408   struct TALER_CoinSpendPublicKeyP coin_pub;
    409 
    410   GNUNET_assert (blinding_values->blinding_inputs->cipher ==
    411                  dk->bsign_pub_key->cipher);
    412   GNUNET_CRYPTO_eddsa_key_get_public (&coin_priv->eddsa_priv,
    413                                       &coin_pub.eddsa_pub);
    414   if (GNUNET_OK !=
    415       TALER_denom_blind (dk,
    416                          bks,
    417                          nonce,
    418                          ach,
    419                          &coin_pub,
    420                          blinding_values,
    421                          c_hash,
    422                          &pd->blinded_planchet))
    423   {
    424     GNUNET_break (0);
    425     return GNUNET_SYSERR;
    426   }
    427   TALER_denom_pub_hash (dk,
    428                         &pd->denom_pub_hash);
    429   return GNUNET_OK;
    430 }
    431 
    432 
    433 void
    434 TALER_planchet_detail_free (struct TALER_PlanchetDetail *pd)
    435 {
    436   TALER_blinded_planchet_free (&pd->blinded_planchet);
    437 }
    438 
    439 
    440 enum GNUNET_GenericReturnValue
    441 TALER_planchet_to_coin (
    442   const struct TALER_DenominationPublicKey *dk,
    443   const struct TALER_BlindedDenominationSignature *blind_sig,
    444   const union GNUNET_CRYPTO_BlindingSecretP *bks,
    445   const struct TALER_CoinSpendPrivateKeyP *coin_priv,
    446   const struct TALER_AgeCommitmentHashP *ach,
    447   const struct TALER_CoinPubHashP *c_hash,
    448   const struct TALER_ExchangeBlindingValues *alg_values,
    449   struct TALER_FreshCoin *coin)
    450 {
    451   if (dk->bsign_pub_key->cipher !=
    452       blind_sig->blinded_sig->cipher)
    453   {
    454     GNUNET_break_op (0);
    455     return GNUNET_SYSERR;
    456   }
    457   if (dk->bsign_pub_key->cipher !=
    458       alg_values->blinding_inputs->cipher)
    459   {
    460     GNUNET_break_op (0);
    461     return GNUNET_SYSERR;
    462   }
    463   if (GNUNET_OK !=
    464       TALER_denom_sig_unblind (&coin->sig,
    465                                blind_sig,
    466                                bks,
    467                                c_hash,
    468                                alg_values,
    469                                dk))
    470   {
    471     GNUNET_break_op (0);
    472     return GNUNET_SYSERR;
    473   }
    474   if (GNUNET_OK !=
    475       TALER_denom_pub_verify (dk,
    476                               &coin->sig,
    477                               c_hash))
    478   {
    479     GNUNET_break_op (0);
    480     TALER_denom_sig_free (&coin->sig);
    481     return GNUNET_SYSERR;
    482   }
    483 
    484   coin->coin_priv = *coin_priv;
    485   coin->h_age_commitment = ach;
    486   return GNUNET_OK;
    487 }
    488 
    489 
    490 // FIXME-Oec: k_tpbs is dead in the code below!
    491 void
    492 TALER_refresh_get_commitment (
    493   struct TALER_RefreshCommitmentP *rc,
    494   const struct TALER_PublicRefreshMasterSeedP *refresh_seed,
    495   const struct TALER_BlindingMasterSeedP *blinding_seed,
    496   const struct TALER_KappaTransferPublicKeys *k_tpbs,
    497   const struct TALER_KappaHashBlindedPlanchetsP *k_bps_h,
    498   const struct TALER_CoinSpendPublicKeyP *coin_pub,
    499   const struct TALER_Amount *amount_with_fee)
    500 {
    501   struct GNUNET_HashContext *hash_context;
    502 
    503   hash_context = GNUNET_CRYPTO_hash_context_start ();
    504 
    505   /* First, the refresh master seed (from which the nonces, then signatures
    506      and finally private keys of the fresh coins are derived from) */
    507   GNUNET_assert (NULL != refresh_seed);
    508   GNUNET_CRYPTO_hash_context_read (hash_context,
    509                                    refresh_seed,
    510                                    sizeof (*refresh_seed));
    511 
    512   /* Then, in case of CS denominations, the blinding_seed from which all
    513      nonces are derived from, and therefore public R-values */
    514   {
    515     struct TALER_BlindingMasterSeedP blanko = {0};
    516     const struct TALER_BlindingMasterSeedP *pbms = &blanko;
    517 
    518     if (NULL != blinding_seed)
    519       pbms = blinding_seed;
    520     GNUNET_CRYPTO_hash_context_read (hash_context,
    521                                      pbms,
    522                                      sizeof(*pbms));
    523   }
    524 
    525   /* Next, add public key of coin and amount being refreshed */
    526   {
    527     struct TALER_AmountNBO melt_amountn;
    528 
    529     GNUNET_CRYPTO_hash_context_read (hash_context,
    530                                      coin_pub,
    531                                      sizeof (struct TALER_CoinSpendPublicKeyP));
    532     TALER_amount_hton (&melt_amountn,
    533                        amount_with_fee);
    534     GNUNET_CRYPTO_hash_context_read (hash_context,
    535                                      &melt_amountn,
    536                                      sizeof (struct TALER_AmountNBO));
    537   }
    538 
    539   /* Finally, add all the hashes of the blinded coins
    540    * (containing information about denominations), depths first */
    541   for (unsigned int k = 0; k<TALER_CNC_KAPPA; k++)
    542     GNUNET_CRYPTO_hash_context_read (hash_context,
    543                                      &k_bps_h->tuple[k],
    544                                      sizeof(k_bps_h->tuple[k]));
    545 
    546   /* Conclude */
    547   GNUNET_CRYPTO_hash_context_finish (hash_context,
    548                                      &rc->session_hash);
    549 }
    550 
    551 
    552 void
    553 TALER_refresh_expand_seed_to_kappa_batch_seeds (
    554   const struct TALER_PublicRefreshMasterSeedP *refresh_master_seed,
    555   const struct TALER_CoinSpendPrivateKeyP *coin_priv,
    556   struct TALER_KappaPrivateRefreshBatchSeedsP *kappa_batch_seeds)
    557 {
    558   GNUNET_assert (GNUNET_OK ==
    559                  GNUNET_CRYPTO_hkdf_gnunet (
    560                    kappa_batch_seeds,
    561                    sizeof (*kappa_batch_seeds),
    562                    "refresh-batch-seeds",
    563                    strlen ("refresh-batch-seeds"),
    564                    refresh_master_seed,
    565                    sizeof (*refresh_master_seed),
    566                    GNUNET_CRYPTO_kdf_arg_auto (coin_priv)));
    567 }
    568 
    569 
    570 void
    571 TALER_refresh_expand_batch_seed_to_transfer_private_keys (
    572   const struct TALER_PrivateRefreshBatchSeedP *batch_seed,
    573   size_t num_transfer_pks,
    574   struct TALER_TransferPrivateKeyP transfer_pks[num_transfer_pks])
    575 {
    576   GNUNET_assert (GNUNET_OK ==
    577                  GNUNET_CRYPTO_hkdf_gnunet (
    578                    transfer_pks,
    579                    sizeof (*transfer_pks) * num_transfer_pks,
    580                    "refresh-transfer-private-keys",
    581                    strlen ("refresh-transfer-private-keys"),
    582                    batch_seed,
    583                    sizeof (*batch_seed)));
    584 }
    585 
    586 
    587 void
    588 TALER_refresh_expand_batch_seed_to_transfer_secrets (
    589   const struct TALER_PrivateRefreshBatchSeedP *batch_seed,
    590   const struct TALER_CoinSpendPublicKeyP *coin_pub,
    591   size_t num_transfer_secrets,
    592   struct TALER_TransferSecretP transfer_secrets[num_transfer_secrets])
    593 {
    594   struct TALER_TransferPrivateKeyP transfer_pks[num_transfer_secrets];
    595 
    596   TALER_refresh_expand_batch_seed_to_transfer_private_keys (
    597     batch_seed,
    598     num_transfer_secrets,
    599     transfer_pks);
    600 
    601   for (size_t i = 0; i < num_transfer_secrets; i++)
    602   {
    603     TALER_link_reveal_transfer_secret (
    604       &transfer_pks[i],
    605       coin_pub,
    606       &transfer_secrets[i]);
    607   }
    608 }
    609 
    610 
    611 void
    612 TALER_refresh_expand_batch_seed_to_planchet_master_secrets (
    613   const struct TALER_PrivateRefreshBatchSeedP *batch_seed,
    614   const struct TALER_CoinSpendPublicKeyP *coin_pub,
    615   size_t num_planchet_secrets,
    616   struct TALER_PlanchetMasterSecretP planchet_secrets[num_planchet_secrets])
    617 {
    618   struct TALER_TransferPrivateKeyP transfer_pks[num_planchet_secrets];
    619   struct TALER_TransferSecretP transfer_secrets[num_planchet_secrets];
    620 
    621   TALER_refresh_expand_batch_seed_to_transfer_private_keys (
    622     batch_seed,
    623     num_planchet_secrets,
    624     transfer_pks);
    625 
    626   for (size_t i = 0; i < num_planchet_secrets; i++)
    627   {
    628     TALER_link_reveal_transfer_secret (
    629       &transfer_pks[i],
    630       coin_pub,
    631       &transfer_secrets[i]);
    632 
    633     TALER_transfer_secret_to_planchet_secret (
    634       &transfer_secrets[i],
    635       i,
    636       &planchet_secrets[i]);
    637   }
    638 }
    639 
    640 
    641 void
    642 TALER_refresh_expand_batch_seed_to_transfer_data (
    643   const struct TALER_PrivateRefreshBatchSeedP *batch_seed,
    644   const struct TALER_CoinSpendPublicKeyP *coin_pub,
    645   size_t num,
    646   struct TALER_PlanchetMasterSecretP planchet_secrets[num],
    647   struct TALER_TransferPublicKeyP transfer_pubs[num])
    648 {
    649   struct TALER_TransferPrivateKeyP transfer_pks[num];
    650   struct TALER_TransferSecretP transfer_secrets[num];
    651 
    652   TALER_refresh_expand_batch_seed_to_transfer_private_keys (
    653     batch_seed,
    654     num,
    655     transfer_pks);
    656 
    657   for (size_t i = 0; i < num; i++)
    658   {
    659     TALER_link_reveal_transfer_secret (
    660       &transfer_pks[i],
    661       coin_pub,
    662       &transfer_secrets[i]);
    663 
    664     TALER_transfer_secret_to_planchet_secret (
    665       &transfer_secrets[i],
    666       i,
    667       &planchet_secrets[i]);
    668 
    669     GNUNET_CRYPTO_ecdhe_key_get_public (
    670       &transfer_pks[i].ecdhe_priv,
    671       &transfer_pubs[i].ecdhe_pub);
    672   }
    673 }
    674 
    675 
    676 void
    677 TALER_refresh_expand_kappa_nonces_v27 (
    678   const struct TALER_PublicRefreshMasterSeedP *refresh_seed,
    679   struct TALER_KappaPublicRefreshNoncesP *kappa_nonces)
    680 {
    681   GNUNET_assert (GNUNET_OK ==
    682                  GNUNET_CRYPTO_hkdf_gnunet (
    683                    kappa_nonces,
    684                    sizeof (*kappa_nonces),
    685                    "refresh-kappa-nonces",
    686                    strlen ("refresh-kappa-nonces"),
    687                    refresh_seed,
    688                    sizeof (*refresh_seed)));
    689 }
    690 
    691 
    692 void
    693 TALER_refresh_signature_to_secrets_v27 (
    694   const struct TALER_PrivateRefreshNonceSignatureP *sig,
    695   size_t num_secrets,
    696   struct TALER_PlanchetMasterSecretP secrets[static num_secrets])
    697 {
    698   GNUNET_assert (GNUNET_YES ==
    699                  GNUNET_CRYPTO_hkdf_gnunet (
    700                    secrets,
    701                    sizeof (*secrets) * num_secrets,
    702                    "refresh-planchet-secret",
    703                    strlen ("refresh-planchet-secret"),
    704                    sig,
    705                    sizeof(*sig)));
    706 }
    707 
    708 
    709 void
    710 TALER_coin_pub_hash (const struct TALER_CoinSpendPublicKeyP *coin_pub,
    711                      const struct TALER_AgeCommitmentHashP *ach,
    712                      struct TALER_CoinPubHashP *coin_h)
    713 {
    714   if (TALER_AgeCommitmentHashP_isNullOrZero (ach))
    715   {
    716     /* No age commitment was set */
    717     GNUNET_CRYPTO_hash (&coin_pub->eddsa_pub,
    718                         sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey),
    719                         &coin_h->hash);
    720   }
    721   else
    722   {
    723     /* Coin comes with age commitment.  Take the hash of the age commitment
    724      * into account */
    725     struct GNUNET_HashContext *hash_context;
    726 
    727     hash_context = GNUNET_CRYPTO_hash_context_start ();
    728 
    729     GNUNET_CRYPTO_hash_context_read (
    730       hash_context,
    731       &coin_pub->eddsa_pub,
    732       sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey));
    733 
    734     GNUNET_CRYPTO_hash_context_read (
    735       hash_context,
    736       ach,
    737       sizeof(struct TALER_AgeCommitmentHashP));
    738 
    739     GNUNET_CRYPTO_hash_context_finish (
    740       hash_context,
    741       &coin_h->hash);
    742   }
    743 }
    744 
    745 
    746 void
    747 TALER_coin_ev_hash (const struct TALER_BlindedPlanchet *blinded_planchet,
    748                     const struct TALER_DenominationHashP *denom_hash,
    749                     struct TALER_BlindedCoinHashP *bch)
    750 {
    751   struct GNUNET_HashContext *hash_context;
    752 
    753   hash_context = GNUNET_CRYPTO_hash_context_start ();
    754   GNUNET_CRYPTO_hash_context_read (hash_context,
    755                                    denom_hash,
    756                                    sizeof(*denom_hash));
    757   TALER_blinded_planchet_hash_ (blinded_planchet,
    758                                 hash_context);
    759   GNUNET_CRYPTO_hash_context_finish (hash_context,
    760                                      &bch->hash);
    761 }
    762 
    763 
    764 GNUNET_NETWORK_STRUCT_BEGIN
    765 /**
    766  * Structure we hash to compute the group key for
    767  * a denomination group.
    768  */
    769 struct DenominationGroupP
    770 {
    771   /**
    772    * Value of coins in this denomination group.
    773    */
    774   struct TALER_AmountNBO value;
    775 
    776   /**
    777    * Fee structure for all coins in the group.
    778    */
    779   struct TALER_DenomFeeSetNBOP fees;
    780 
    781   /**
    782    * Age mask for the denomiation, in NBO.
    783    */
    784   uint32_t age_mask GNUNET_PACKED;
    785 
    786   /**
    787    * Cipher used for the denomination, in NBO.
    788    */
    789   uint32_t cipher GNUNET_PACKED;
    790 };
    791 GNUNET_NETWORK_STRUCT_END
    792 
    793 
    794 void
    795 TALER_denomination_group_get_key (
    796   const struct TALER_DenominationGroup *dg,
    797   struct GNUNET_HashCode *key)
    798 {
    799   struct DenominationGroupP dgp = {
    800     .age_mask = htonl (dg->age_mask.bits),
    801     .cipher = htonl (dg->cipher)
    802   };
    803 
    804   TALER_amount_hton (&dgp.value,
    805                      &dg->value);
    806   TALER_denom_fee_set_hton (&dgp.fees,
    807                             &dg->fees);
    808   GNUNET_CRYPTO_hash (&dgp,
    809                       sizeof (dgp),
    810                       key);
    811 }
    812 
    813 
    814 void
    815 TALER_kyc_measure_authorization_hash (
    816   const struct TALER_AccountAccessTokenP *access_token,
    817   uint64_t row,
    818   uint32_t offset,
    819   struct TALER_KycMeasureAuthorizationHashP *mah)
    820 {
    821   uint64_t be64 = GNUNET_htonll (row);
    822   uint32_t be32 = htonl ((uint32_t) offset);
    823 
    824   GNUNET_assert (
    825     GNUNET_YES ==
    826     GNUNET_CRYPTO_hkdf_gnunet (
    827       mah,
    828       sizeof (*mah),
    829       &be64,
    830       sizeof (be64),
    831       access_token,
    832       sizeof (*access_token),
    833       GNUNET_CRYPTO_kdf_arg_auto (&be32)));
    834 }
    835 
    836 
    837 void
    838 TALER_merchant_instance_auth_hash_with_salt (
    839   struct TALER_MerchantAuthenticationHashP *auth_hash,
    840   struct TALER_MerchantAuthenticationSaltP *salt,
    841   const char *passphrase)
    842 {
    843   GNUNET_assert (GNUNET_YES ==
    844                  GNUNET_CRYPTO_hkdf_gnunet (
    845                    auth_hash,
    846                    sizeof (*auth_hash),
    847                    salt,
    848                    sizeof (*salt),
    849                    passphrase,
    850                    strlen (passphrase),
    851                    GNUNET_CRYPTO_kdf_arg_string ("merchant-instance-auth")));
    852 }
    853 
    854 
    855 /* end of crypto.c */