exchange

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

crypto.c (24162B)


      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 "taler/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 (GNUNET_CRYPTO_QUALITY_STRONG,
    205                               ps,
    206                               sizeof (*ps));
    207 }
    208 
    209 
    210 void
    211 TALER_withdraw_master_seed_setup_random (
    212   struct TALER_WithdrawMasterSeedP *seed)
    213 {
    214   GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG,
    215                               seed,
    216                               sizeof (*seed));
    217 }
    218 
    219 
    220 void
    221 TALER_refresh_master_setup_random (
    222   struct TALER_PublicRefreshMasterSeedP *rms)
    223 {
    224   GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG,
    225                               rms,
    226                               sizeof (*rms));
    227 }
    228 
    229 
    230 void
    231 TALER_transfer_secret_to_planchet_secret (
    232   const struct TALER_TransferSecretP *secret_seed,
    233   uint32_t coin_num_salt,
    234   struct TALER_PlanchetMasterSecretP *ps)
    235 {
    236   uint32_t be_salt = htonl (coin_num_salt);
    237 
    238   GNUNET_assert (GNUNET_OK ==
    239                  GNUNET_CRYPTO_hkdf_gnunet (
    240                    ps,
    241                    sizeof (*ps),
    242                    &be_salt,
    243                    sizeof (be_salt),
    244                    secret_seed,
    245                    sizeof (*secret_seed),
    246                    GNUNET_CRYPTO_kdf_arg_string ("taler-coin-derivation")));
    247 }
    248 
    249 
    250 void
    251 TALER_cs_withdraw_nonce_derive (
    252   const struct TALER_PlanchetMasterSecretP *ps,
    253   struct GNUNET_CRYPTO_CsSessionNonce *nonce)
    254 {
    255   GNUNET_assert (GNUNET_YES ==
    256                  GNUNET_CRYPTO_hkdf_gnunet (
    257                    nonce,
    258                    sizeof (*nonce),
    259                    "n",
    260                    strlen ("n"),
    261                    ps,
    262                    sizeof(*ps)));
    263 }
    264 
    265 
    266 void
    267 TALER_cs_withdraw_seed_to_blinding_seed (
    268   const struct TALER_WithdrawMasterSeedP *seed,
    269   struct TALER_BlindingMasterSeedP *blinding_seed)
    270 {
    271   GNUNET_assert (GNUNET_YES ==
    272                  GNUNET_CRYPTO_hkdf_gnunet (
    273                    blinding_seed,
    274                    sizeof (*blinding_seed),
    275                    "withdraw-blinding",
    276                    strlen ("withdraw-blinding"),
    277                    seed,
    278                    sizeof(*seed)));
    279 }
    280 
    281 
    282 void
    283 TALER_cs_refresh_seed_to_blinding_seed (
    284   const struct TALER_PublicRefreshMasterSeedP *seed,
    285   const struct TALER_CoinSpendPrivateKeyP *coin_priv,
    286   struct TALER_BlindingMasterSeedP *blinding_seed)
    287 {
    288   GNUNET_assert (GNUNET_YES ==
    289                  GNUNET_CRYPTO_hkdf_gnunet (
    290                    blinding_seed,
    291                    sizeof (*blinding_seed),
    292                    "refresh-blinding",
    293                    strlen ("refresh-blinding"),
    294                    coin_priv,
    295                    sizeof (*coin_priv),
    296                    GNUNET_CRYPTO_kdf_arg_auto (seed)));
    297 }
    298 
    299 
    300 void
    301 TALER_cs_nonce_derive_indexed (
    302   const struct TALER_BlindingMasterSeedP *seed,
    303   bool for_melt,
    304   uint32_t index,
    305   struct GNUNET_CRYPTO_CsSessionNonce *nonce)
    306 {
    307   uint32_t be_salt = htonl (index);
    308   const char *operation = for_melt ? "refresh-n" : "withdraw-n";
    309 
    310   GNUNET_assert (GNUNET_YES ==
    311                  GNUNET_CRYPTO_hkdf_gnunet (
    312                    nonce,
    313                    sizeof (*nonce),
    314                    &be_salt,
    315                    sizeof (be_salt),
    316                    operation,
    317                    strlen (operation),
    318                    GNUNET_CRYPTO_kdf_arg_auto (seed)));
    319 }
    320 
    321 
    322 void
    323 TALER_cs_derive_nonces_from_seed (
    324   const struct TALER_BlindingMasterSeedP *seed,
    325   bool for_melt,
    326   size_t num,
    327   const uint32_t indices[static num],
    328   struct GNUNET_CRYPTO_CsSessionNonce nonces[static num])
    329 {
    330   GNUNET_assert (TALER_MAX_COINS > num);
    331 
    332   for (size_t i = 0; i < num; i++)
    333     TALER_cs_nonce_derive_indexed (
    334       seed,
    335       for_melt,
    336       indices[i],
    337       &nonces[i]);
    338 }
    339 
    340 
    341 void
    342 TALER_cs_derive_only_cs_blind_nonces_from_seed (
    343   const struct TALER_BlindingMasterSeedP *seed,
    344   bool for_melt,
    345   size_t num,
    346   const uint32_t indices[static num],
    347   union GNUNET_CRYPTO_BlindSessionNonce nonces[static num])
    348 {
    349   GNUNET_assert (TALER_MAX_COINS > num);
    350 
    351   for (size_t i = 0; i < num; i++)
    352     TALER_cs_nonce_derive_indexed (
    353       seed,
    354       for_melt,
    355       indices[i],
    356       &nonces[i].cs_nonce);
    357 }
    358 
    359 
    360 void
    361 TALER_cs_derive_blind_nonces_from_seed (
    362   const struct TALER_BlindingMasterSeedP *seed,
    363   bool for_melt,
    364   size_t num,
    365   const bool is_cs[static num],
    366   union GNUNET_CRYPTO_BlindSessionNonce nonces[static num])
    367 {
    368   for (size_t i = 0; i < num; i++)
    369   {
    370     if (is_cs[i])
    371       TALER_cs_nonce_derive_indexed (
    372         seed,
    373         for_melt,
    374         i,
    375         &nonces[i].cs_nonce);
    376   }
    377 }
    378 
    379 
    380 void
    381 TALER_rsa_pub_hash (const struct GNUNET_CRYPTO_RsaPublicKey *rsa,
    382                     struct TALER_RsaPubHashP *h_rsa)
    383 {
    384   GNUNET_CRYPTO_rsa_public_key_hash (rsa,
    385                                      &h_rsa->hash);
    386 
    387 }
    388 
    389 
    390 void
    391 TALER_cs_pub_hash (const struct GNUNET_CRYPTO_CsPublicKey *cs,
    392                    struct TALER_CsPubHashP *h_cs)
    393 {
    394   GNUNET_CRYPTO_hash (cs,
    395                       sizeof(*cs),
    396                       &h_cs->hash);
    397 }
    398 
    399 
    400 enum GNUNET_GenericReturnValue
    401 TALER_planchet_prepare (
    402   const struct TALER_DenominationPublicKey *dk,
    403   const struct TALER_ExchangeBlindingValues *blinding_values,
    404   const union GNUNET_CRYPTO_BlindingSecretP *bks,
    405   const union GNUNET_CRYPTO_BlindSessionNonce *nonce,
    406   const struct TALER_CoinSpendPrivateKeyP *coin_priv,
    407   const struct TALER_AgeCommitmentHashP *ach,
    408   struct TALER_CoinPubHashP *c_hash,
    409   struct TALER_PlanchetDetail *pd)
    410 {
    411   struct TALER_CoinSpendPublicKeyP coin_pub;
    412 
    413   GNUNET_assert (blinding_values->blinding_inputs->cipher ==
    414                  dk->bsign_pub_key->cipher);
    415   GNUNET_CRYPTO_eddsa_key_get_public (&coin_priv->eddsa_priv,
    416                                       &coin_pub.eddsa_pub);
    417   if (GNUNET_OK !=
    418       TALER_denom_blind (dk,
    419                          bks,
    420                          nonce,
    421                          ach,
    422                          &coin_pub,
    423                          blinding_values,
    424                          c_hash,
    425                          &pd->blinded_planchet))
    426   {
    427     GNUNET_break (0);
    428     return GNUNET_SYSERR;
    429   }
    430   TALER_denom_pub_hash (dk,
    431                         &pd->denom_pub_hash);
    432   return GNUNET_OK;
    433 }
    434 
    435 
    436 void
    437 TALER_planchet_detail_free (struct TALER_PlanchetDetail *pd)
    438 {
    439   TALER_blinded_planchet_free (&pd->blinded_planchet);
    440 }
    441 
    442 
    443 enum GNUNET_GenericReturnValue
    444 TALER_planchet_to_coin (
    445   const struct TALER_DenominationPublicKey *dk,
    446   const struct TALER_BlindedDenominationSignature *blind_sig,
    447   const union GNUNET_CRYPTO_BlindingSecretP *bks,
    448   const struct TALER_CoinSpendPrivateKeyP *coin_priv,
    449   const struct TALER_AgeCommitmentHashP *ach,
    450   const struct TALER_CoinPubHashP *c_hash,
    451   const struct TALER_ExchangeBlindingValues *alg_values,
    452   struct TALER_FreshCoin *coin)
    453 {
    454   if (dk->bsign_pub_key->cipher !=
    455       blind_sig->blinded_sig->cipher)
    456   {
    457     GNUNET_break_op (0);
    458     return GNUNET_SYSERR;
    459   }
    460   if (dk->bsign_pub_key->cipher !=
    461       alg_values->blinding_inputs->cipher)
    462   {
    463     GNUNET_break_op (0);
    464     return GNUNET_SYSERR;
    465   }
    466   if (GNUNET_OK !=
    467       TALER_denom_sig_unblind (&coin->sig,
    468                                blind_sig,
    469                                bks,
    470                                c_hash,
    471                                alg_values,
    472                                dk))
    473   {
    474     GNUNET_break_op (0);
    475     return GNUNET_SYSERR;
    476   }
    477   if (GNUNET_OK !=
    478       TALER_denom_pub_verify (dk,
    479                               &coin->sig,
    480                               c_hash))
    481   {
    482     GNUNET_break_op (0);
    483     TALER_denom_sig_free (&coin->sig);
    484     return GNUNET_SYSERR;
    485   }
    486 
    487   coin->coin_priv = *coin_priv;
    488   coin->h_age_commitment = ach;
    489   return GNUNET_OK;
    490 }
    491 
    492 
    493 void
    494 TALER_refresh_get_commitment (
    495   struct TALER_RefreshCommitmentP *rc,
    496   const struct TALER_PublicRefreshMasterSeedP *refresh_seed,
    497   const struct TALER_BlindingMasterSeedP *blinding_seed,
    498   const struct TALER_KappaTransferPublicKeys *k_tpbs,
    499   const struct TALER_KappaHashBlindedPlanchetsP *k_bps_h,
    500   const struct TALER_CoinSpendPublicKeyP *coin_pub,
    501   const struct TALER_Amount *amount_with_fee)
    502 {
    503   struct GNUNET_HashContext *hash_context;
    504 
    505   hash_context = GNUNET_CRYPTO_hash_context_start ();
    506 
    507   /* First, the refresh master seed (from which the nonces, then signatures
    508      and finally private keys of the fresh coins are derived from) */
    509   GNUNET_assert (NULL != refresh_seed);
    510   GNUNET_CRYPTO_hash_context_read (hash_context,
    511                                    refresh_seed,
    512                                    sizeof (*refresh_seed));
    513 
    514   /* Then, in case of CS denominations, the blinding_seed from which all
    515      nonces are derived from, and therefore public R-values */
    516   {
    517     struct TALER_BlindingMasterSeedP blanko = {0};
    518     const struct TALER_BlindingMasterSeedP *pbms = &blanko;
    519 
    520     if (NULL != blinding_seed)
    521       pbms = blinding_seed;
    522     GNUNET_CRYPTO_hash_context_read (hash_context,
    523                                      pbms,
    524                                      sizeof(*pbms));
    525   }
    526 
    527   /* Next, add public key of coin and amount being refreshed */
    528   {
    529     struct TALER_AmountNBO melt_amountn;
    530 
    531     GNUNET_CRYPTO_hash_context_read (hash_context,
    532                                      coin_pub,
    533                                      sizeof (struct TALER_CoinSpendPublicKeyP));
    534     TALER_amount_hton (&melt_amountn,
    535                        amount_with_fee);
    536     GNUNET_CRYPTO_hash_context_read (hash_context,
    537                                      &melt_amountn,
    538                                      sizeof (struct TALER_AmountNBO));
    539   }
    540 
    541   /* Finally, add all the hashes of the blinded coins
    542    * (containing information about denominations), depths first */
    543   for (unsigned int k = 0; k<TALER_CNC_KAPPA; k++)
    544     GNUNET_CRYPTO_hash_context_read (hash_context,
    545                                      &k_bps_h->tuple[k],
    546                                      sizeof(k_bps_h->tuple[k]));
    547 
    548   /* Conclude */
    549   GNUNET_CRYPTO_hash_context_finish (hash_context,
    550                                      &rc->session_hash);
    551 }
    552 
    553 
    554 void
    555 TALER_refresh_expand_seed_to_kappa_batch_seeds (
    556   const struct TALER_PublicRefreshMasterSeedP *refresh_master_seed,
    557   const struct TALER_CoinSpendPrivateKeyP *coin_priv,
    558   struct TALER_KappaPrivateRefreshBatchSeedsP *kappa_batch_seeds)
    559 {
    560   GNUNET_assert (GNUNET_OK ==
    561                  GNUNET_CRYPTO_hkdf_gnunet (
    562                    kappa_batch_seeds,
    563                    sizeof (*kappa_batch_seeds),
    564                    "refresh-batch-seeds",
    565                    strlen ("refresh-batch-seeds"),
    566                    refresh_master_seed,
    567                    sizeof (*refresh_master_seed),
    568                    GNUNET_CRYPTO_kdf_arg_auto (coin_priv)));
    569 }
    570 
    571 
    572 void
    573 TALER_refresh_expand_batch_seed_to_transfer_private_keys (
    574   const struct TALER_PrivateRefreshBatchSeedP *batch_seed,
    575   size_t num_transfer_pks,
    576   struct TALER_TransferPrivateKeyP transfer_pks[num_transfer_pks])
    577 {
    578   GNUNET_assert (GNUNET_OK ==
    579                  GNUNET_CRYPTO_hkdf_gnunet (
    580                    transfer_pks,
    581                    sizeof (*transfer_pks) * num_transfer_pks,
    582                    "refresh-transfer-private-keys",
    583                    strlen ("refresh-transfer-private-keys"),
    584                    batch_seed,
    585                    sizeof (*batch_seed)));
    586 }
    587 
    588 
    589 void
    590 TALER_refresh_expand_batch_seed_to_transfer_secrets (
    591   const struct TALER_PrivateRefreshBatchSeedP *batch_seed,
    592   const struct TALER_CoinSpendPublicKeyP *coin_pub,
    593   size_t num_transfer_secrets,
    594   struct TALER_TransferSecretP transfer_secrets[num_transfer_secrets])
    595 {
    596   struct TALER_TransferPrivateKeyP transfer_pks[num_transfer_secrets];
    597 
    598   TALER_refresh_expand_batch_seed_to_transfer_private_keys (
    599     batch_seed,
    600     num_transfer_secrets,
    601     transfer_pks);
    602 
    603   for (size_t i = 0; i < num_transfer_secrets; i++)
    604   {
    605     TALER_link_reveal_transfer_secret (
    606       &transfer_pks[i],
    607       coin_pub,
    608       &transfer_secrets[i]);
    609   }
    610 }
    611 
    612 
    613 void
    614 TALER_refresh_expand_batch_seed_to_planchet_master_secrets (
    615   const struct TALER_PrivateRefreshBatchSeedP *batch_seed,
    616   const struct TALER_CoinSpendPublicKeyP *coin_pub,
    617   size_t num_planchet_secrets,
    618   struct TALER_PlanchetMasterSecretP planchet_secrets[num_planchet_secrets])
    619 {
    620   struct TALER_TransferPrivateKeyP transfer_pks[num_planchet_secrets];
    621   struct TALER_TransferSecretP transfer_secrets[num_planchet_secrets];
    622 
    623   TALER_refresh_expand_batch_seed_to_transfer_private_keys (
    624     batch_seed,
    625     num_planchet_secrets,
    626     transfer_pks);
    627 
    628   for (size_t i = 0; i < num_planchet_secrets; i++)
    629   {
    630     TALER_link_reveal_transfer_secret (
    631       &transfer_pks[i],
    632       coin_pub,
    633       &transfer_secrets[i]);
    634 
    635     TALER_transfer_secret_to_planchet_secret (
    636       &transfer_secrets[i],
    637       i,
    638       &planchet_secrets[i]);
    639   }
    640 }
    641 
    642 
    643 void
    644 TALER_refresh_expand_batch_seed_to_transfer_data (
    645   const struct TALER_PrivateRefreshBatchSeedP *batch_seed,
    646   const struct TALER_CoinSpendPublicKeyP *coin_pub,
    647   size_t num,
    648   struct TALER_PlanchetMasterSecretP planchet_secrets[num],
    649   struct TALER_TransferPublicKeyP transfer_pubs[num])
    650 {
    651   struct TALER_TransferPrivateKeyP transfer_pks[num];
    652   struct TALER_TransferSecretP transfer_secrets[num];
    653 
    654   TALER_refresh_expand_batch_seed_to_transfer_private_keys (
    655     batch_seed,
    656     num,
    657     transfer_pks);
    658 
    659   for (size_t i = 0; i < num; i++)
    660   {
    661     TALER_link_reveal_transfer_secret (
    662       &transfer_pks[i],
    663       coin_pub,
    664       &transfer_secrets[i]);
    665 
    666     TALER_transfer_secret_to_planchet_secret (
    667       &transfer_secrets[i],
    668       i,
    669       &planchet_secrets[i]);
    670 
    671     GNUNET_CRYPTO_ecdhe_key_get_public (
    672       &transfer_pks[i].ecdhe_priv,
    673       &transfer_pubs[i].ecdhe_pub);
    674   }
    675 }
    676 
    677 
    678 void
    679 TALER_refresh_expand_kappa_nonces_v27 (
    680   const struct TALER_PublicRefreshMasterSeedP *refresh_seed,
    681   struct TALER_KappaPublicRefreshNoncesP *kappa_nonces)
    682 {
    683   GNUNET_assert (GNUNET_OK ==
    684                  GNUNET_CRYPTO_hkdf_gnunet (
    685                    kappa_nonces,
    686                    sizeof (*kappa_nonces),
    687                    "refresh-kappa-nonces",
    688                    strlen ("refresh-kappa-nonces"),
    689                    refresh_seed,
    690                    sizeof (*refresh_seed)));
    691 }
    692 
    693 
    694 void
    695 TALER_refresh_signature_to_secrets_v27 (
    696   const struct TALER_PrivateRefreshNonceSignatureP *sig,
    697   size_t num_secrets,
    698   struct TALER_PlanchetMasterSecretP secrets[static num_secrets])
    699 {
    700   GNUNET_assert (GNUNET_YES ==
    701                  GNUNET_CRYPTO_hkdf_gnunet (
    702                    secrets,
    703                    sizeof (*secrets) * num_secrets,
    704                    "refresh-planchet-secret",
    705                    strlen ("refresh-planchet-secret"),
    706                    sig,
    707                    sizeof(*sig)));
    708 }
    709 
    710 
    711 void
    712 TALER_coin_pub_hash (const struct TALER_CoinSpendPublicKeyP *coin_pub,
    713                      const struct TALER_AgeCommitmentHashP *ach,
    714                      struct TALER_CoinPubHashP *coin_h)
    715 {
    716   if (TALER_AgeCommitmentHashP_isNullOrZero (ach))
    717   {
    718     /* No age commitment was set */
    719     GNUNET_CRYPTO_hash (&coin_pub->eddsa_pub,
    720                         sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey),
    721                         &coin_h->hash);
    722   }
    723   else
    724   {
    725     /* Coin comes with age commitment.  Take the hash of the age commitment
    726      * into account */
    727     struct GNUNET_HashContext *hash_context;
    728 
    729     hash_context = GNUNET_CRYPTO_hash_context_start ();
    730 
    731     GNUNET_CRYPTO_hash_context_read (
    732       hash_context,
    733       &coin_pub->eddsa_pub,
    734       sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey));
    735 
    736     GNUNET_CRYPTO_hash_context_read (
    737       hash_context,
    738       ach,
    739       sizeof(struct TALER_AgeCommitmentHashP));
    740 
    741     GNUNET_CRYPTO_hash_context_finish (
    742       hash_context,
    743       &coin_h->hash);
    744   }
    745 }
    746 
    747 
    748 void
    749 TALER_coin_ev_hash (const struct TALER_BlindedPlanchet *blinded_planchet,
    750                     const struct TALER_DenominationHashP *denom_hash,
    751                     struct TALER_BlindedCoinHashP *bch)
    752 {
    753   struct GNUNET_HashContext *hash_context;
    754 
    755   hash_context = GNUNET_CRYPTO_hash_context_start ();
    756   GNUNET_CRYPTO_hash_context_read (hash_context,
    757                                    denom_hash,
    758                                    sizeof(*denom_hash));
    759   TALER_blinded_planchet_hash_ (blinded_planchet,
    760                                 hash_context);
    761   GNUNET_CRYPTO_hash_context_finish (hash_context,
    762                                      &bch->hash);
    763 }
    764 
    765 
    766 GNUNET_NETWORK_STRUCT_BEGIN
    767 /**
    768  * Structure we hash to compute the group key for
    769  * a denomination group.
    770  */
    771 struct DenominationGroupP
    772 {
    773   /**
    774    * Value of coins in this denomination group.
    775    */
    776   struct TALER_AmountNBO value;
    777 
    778   /**
    779    * Fee structure for all coins in the group.
    780    */
    781   struct TALER_DenomFeeSetNBOP fees;
    782 
    783   /**
    784    * Age mask for the denomiation, in NBO.
    785    */
    786   uint32_t age_mask GNUNET_PACKED;
    787 
    788   /**
    789    * Cipher used for the denomination, in NBO.
    790    */
    791   uint32_t cipher GNUNET_PACKED;
    792 };
    793 GNUNET_NETWORK_STRUCT_END
    794 
    795 
    796 void
    797 TALER_denomination_group_get_key (
    798   const struct TALER_DenominationGroup *dg,
    799   struct GNUNET_HashCode *key)
    800 {
    801   struct DenominationGroupP dgp = {
    802     .age_mask = htonl (dg->age_mask.bits),
    803     .cipher = htonl (dg->cipher)
    804   };
    805 
    806   TALER_amount_hton (&dgp.value,
    807                      &dg->value);
    808   TALER_denom_fee_set_hton (&dgp.fees,
    809                             &dg->fees);
    810   GNUNET_CRYPTO_hash (&dgp,
    811                       sizeof (dgp),
    812                       key);
    813 }
    814 
    815 
    816 void
    817 TALER_kyc_measure_authorization_hash (
    818   const struct TALER_AccountAccessTokenP *access_token,
    819   uint64_t row,
    820   uint32_t offset,
    821   struct TALER_KycMeasureAuthorizationHashP *mah)
    822 {
    823   uint64_t be64 = GNUNET_htonll (row);
    824   uint32_t be32 = htonl ((uint32_t) offset);
    825 
    826   GNUNET_assert (
    827     GNUNET_YES ==
    828     GNUNET_CRYPTO_hkdf_gnunet (
    829       mah,
    830       sizeof (*mah),
    831       &be64,
    832       sizeof (be64),
    833       access_token,
    834       sizeof (*access_token),
    835       GNUNET_CRYPTO_kdf_arg_auto (&be32)));
    836 }
    837 
    838 
    839 void
    840 TALER_merchant_instance_auth_hash_with_salt (
    841   struct TALER_MerchantAuthenticationHashP *auth_hash,
    842   struct TALER_MerchantAuthenticationSaltP *salt,
    843   const char *passphrase)
    844 {
    845   GNUNET_assert (GNUNET_YES ==
    846                  GNUNET_CRYPTO_hkdf_gnunet (
    847                    auth_hash,
    848                    sizeof (*auth_hash),
    849                    salt,
    850                    sizeof (*salt),
    851                    passphrase,
    852                    strlen (passphrase),
    853                    GNUNET_CRYPTO_kdf_arg_string ("merchant-instance-auth")));
    854 }
    855 
    856 
    857 /* end of crypto.c */