diff options
Diffstat (limited to 'src/util/crypto.c')
-rw-r--r-- | src/util/crypto.c | 321 |
1 files changed, 255 insertions, 66 deletions
diff --git a/src/util/crypto.c b/src/util/crypto.c index 178db3aad..4735af3b0 100644 --- a/src/util/crypto.c +++ b/src/util/crypto.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014-2017 Taler Systems SA + Copyright (C) 2014-2022 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 @@ -20,12 +20,12 @@ * @author Florian Dold * @author Benedikt Mueller * @author Christian Grothoff + * @author Özgür Kesim */ #include "platform.h" #include "taler_util.h" #include <gcrypt.h> - /** * Function called by libgcrypt on serious errors. * Prints an error message and aborts the process. @@ -73,9 +73,9 @@ enum GNUNET_GenericReturnValue TALER_test_coin_valid (const struct TALER_CoinPublicInfo *coin_public_info, const struct TALER_DenominationPublicKey *denom_pub) { - struct TALER_CoinPubHash c_hash; + struct TALER_CoinPubHashP c_hash; #if ENABLE_SANITY_CHECKS - struct TALER_DenominationHash d_hash; + struct TALER_DenominationHashP d_hash; TALER_denom_pub_hash (denom_pub, &d_hash); @@ -83,12 +83,13 @@ TALER_test_coin_valid (const struct TALER_CoinPublicInfo *coin_public_info, GNUNET_memcmp (&d_hash, &coin_public_info->denom_pub_hash)); #endif - // FIXME-Oec: replace with function that - // also hashes the age vector if we have - // one! - GNUNET_CRYPTO_hash (&coin_public_info->coin_pub, - sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey), - &c_hash.hash); + + TALER_coin_pub_hash (&coin_public_info->coin_pub, + coin_public_info->no_age_commitment + ? NULL + : &coin_public_info->h_age_commitment, + &c_hash); + if (GNUNET_OK != TALER_denom_pub_verify (denom_pub, &coin_public_info->denom_sig, @@ -116,7 +117,6 @@ TALER_link_derive_transfer_secret ( GNUNET_CRYPTO_ecdh_eddsa (&trans_priv->ecdhe_priv, &coin_pub.eddsa_pub, &ts->key)); - } @@ -147,9 +147,30 @@ TALER_link_recover_transfer_secret ( void -TALER_planchet_setup_refresh (const struct TALER_TransferSecretP *secret_seed, - uint32_t coin_num_salt, - struct TALER_PlanchetSecretsP *ps) +TALER_planchet_master_setup_random ( + struct TALER_PlanchetMasterSecretP *ps) +{ + GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG, + ps, + sizeof (*ps)); +} + + +void +TALER_refresh_master_setup_random ( + struct TALER_RefreshMasterSecretP *rms) +{ + GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG, + rms, + sizeof (*rms)); +} + + +void +TALER_transfer_secret_to_planchet_secret ( + const struct TALER_TransferSecretP *secret_seed, + uint32_t coin_num_salt, + struct TALER_PlanchetMasterSecretP *ps) { uint32_t be_salt = htonl (coin_num_salt); @@ -167,32 +188,114 @@ TALER_planchet_setup_refresh (const struct TALER_TransferSecretP *secret_seed, void -TALER_planchet_setup_random (struct TALER_PlanchetSecretsP *ps) +TALER_planchet_secret_to_transfer_priv ( + const struct TALER_RefreshMasterSecretP *rms, + const struct TALER_CoinSpendPrivateKeyP *old_coin_priv, + uint32_t cnc_num, + struct TALER_TransferPrivateKeyP *tpriv) { - GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG, - ps, - sizeof (*ps)); + uint32_t be_salt = htonl (cnc_num); + + GNUNET_assert (GNUNET_OK == + GNUNET_CRYPTO_kdf (tpriv, + sizeof (*tpriv), + &be_salt, + sizeof (be_salt), + old_coin_priv, + sizeof (*old_coin_priv), + rms, + sizeof (*rms), + "taler-transfer-priv-derivation", + strlen ("taler-transfer-priv-derivation"), + NULL, 0)); +} + + +void +TALER_cs_withdraw_nonce_derive ( + const struct TALER_PlanchetMasterSecretP *ps, + struct GNUNET_CRYPTO_CsSessionNonce *nonce) +{ + GNUNET_assert (GNUNET_YES == + GNUNET_CRYPTO_kdf (nonce, + sizeof (*nonce), + "n", + strlen ("n"), + ps, + sizeof(*ps), + NULL, + 0)); +} + + +void +TALER_cs_refresh_nonce_derive ( + const struct TALER_RefreshMasterSecretP *rms, + uint32_t coin_num_salt, + struct GNUNET_CRYPTO_CsSessionNonce *nonce) +{ + uint32_t be_salt = htonl (coin_num_salt); + + GNUNET_assert (GNUNET_YES == + GNUNET_CRYPTO_kdf (nonce, + sizeof (*nonce), + &be_salt, + sizeof (be_salt), + "refresh-n", + strlen ("refresh-n"), + rms, + sizeof(*rms), + NULL, + 0)); +} + + +void +TALER_rsa_pub_hash (const struct GNUNET_CRYPTO_RsaPublicKey *rsa, + struct TALER_RsaPubHashP *h_rsa) +{ + GNUNET_CRYPTO_rsa_public_key_hash (rsa, + &h_rsa->hash); + +} + + +void +TALER_cs_pub_hash (const struct GNUNET_CRYPTO_CsPublicKey *cs, + struct TALER_CsPubHashP *h_cs) +{ + GNUNET_CRYPTO_hash (cs, + sizeof(*cs), + &h_cs->hash); } enum GNUNET_GenericReturnValue TALER_planchet_prepare (const struct TALER_DenominationPublicKey *dk, - const struct TALER_PlanchetSecretsP *ps, - struct TALER_CoinPubHash *c_hash, - struct TALER_PlanchetDetail *pd) + const struct TALER_ExchangeWithdrawValues *alg_values, + const union GNUNET_CRYPTO_BlindingSecretP *bks, + const union GNUNET_CRYPTO_BlindSessionNonce *nonce, + const struct TALER_CoinSpendPrivateKeyP *coin_priv, + const struct TALER_AgeCommitmentHash *ach, + struct TALER_CoinPubHashP *c_hash, + struct TALER_PlanchetDetail *pd + ) { struct TALER_CoinSpendPublicKeyP coin_pub; - GNUNET_CRYPTO_eddsa_key_get_public (&ps->coin_priv.eddsa_priv, + GNUNET_assert (alg_values->blinding_inputs->cipher == + dk->bsign_pub_key->cipher); + GNUNET_CRYPTO_eddsa_key_get_public (&coin_priv->eddsa_priv, &coin_pub.eddsa_pub); if (GNUNET_OK != TALER_denom_blind (dk, - &ps->blinding_key, - NULL, /* FIXME-Oec */ + bks, + nonce, + ach, &coin_pub, + alg_values, c_hash, - &pd->coin_ev, - &pd->coin_ev_size)) + &pd->blinded_planchet)) { GNUNET_break (0); return GNUNET_SYSERR; @@ -203,20 +306,42 @@ TALER_planchet_prepare (const struct TALER_DenominationPublicKey *dk, } +void +TALER_planchet_detail_free (struct TALER_PlanchetDetail *pd) +{ + TALER_blinded_planchet_free (&pd->blinded_planchet); +} + + enum GNUNET_GenericReturnValue TALER_planchet_to_coin ( const struct TALER_DenominationPublicKey *dk, const struct TALER_BlindedDenominationSignature *blind_sig, - const struct TALER_PlanchetSecretsP *ps, - const struct TALER_CoinPubHash *c_hash, + const union GNUNET_CRYPTO_BlindingSecretP *bks, + const struct TALER_CoinSpendPrivateKeyP *coin_priv, + const struct TALER_AgeCommitmentHash *ach, + const struct TALER_CoinPubHashP *c_hash, + const struct TALER_ExchangeWithdrawValues *alg_values, struct TALER_FreshCoin *coin) { - struct TALER_DenominationSignature sig; - + if (dk->bsign_pub_key->cipher != + blind_sig->blinded_sig->cipher) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + if (dk->bsign_pub_key->cipher != + alg_values->blinding_inputs->cipher) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } if (GNUNET_OK != - TALER_denom_sig_unblind (&sig, + TALER_denom_sig_unblind (&coin->sig, blind_sig, - &ps->blinding_key, + bks, + c_hash, + alg_values, dk)) { GNUNET_break_op (0); @@ -224,15 +349,16 @@ TALER_planchet_to_coin ( } if (GNUNET_OK != TALER_denom_pub_verify (dk, - &sig, + &coin->sig, c_hash)) { GNUNET_break_op (0); - TALER_denom_sig_free (&sig); + TALER_denom_sig_free (&coin->sig); return GNUNET_SYSERR; } - coin->sig = sig; - coin->coin_priv = ps->coin_priv; + + coin->coin_priv = *coin_priv; + coin->h_age_commitment = ach; return GNUNET_OK; } @@ -240,6 +366,7 @@ TALER_planchet_to_coin ( void TALER_refresh_get_commitment (struct TALER_RefreshCommitmentP *rc, uint32_t kappa, + const struct TALER_RefreshMasterSecretP *rms, uint32_t num_new_coins, const struct TALER_RefreshCommitmentEntry *rcs, const struct TALER_CoinSpendPublicKeyP *coin_pub, @@ -248,6 +375,10 @@ TALER_refresh_get_commitment (struct TALER_RefreshCommitmentP *rc, struct GNUNET_HashContext *hash_context; hash_context = GNUNET_CRYPTO_hash_context_start (); + if (NULL != rms) + GNUNET_CRYPTO_hash_context_read (hash_context, + rms, + sizeof (*rms)); /* first, iterate over transfer public keys for hash_context */ for (unsigned int i = 0; i<kappa; i++) { @@ -259,7 +390,7 @@ TALER_refresh_get_commitment (struct TALER_RefreshCommitmentP *rc, hash_context */ for (unsigned int i = 0; i<num_new_coins; i++) { - struct TALER_DenominationHash denom_hash; + struct TALER_DenominationHashP denom_hash; /* The denomination keys should / must all be identical regardless of what offset we use, so we use [0]. */ @@ -294,9 +425,8 @@ TALER_refresh_get_commitment (struct TALER_RefreshCommitmentP *rc, { const struct TALER_RefreshCoinData *rcd = &rce->new_coins[j]; - GNUNET_CRYPTO_hash_context_read (hash_context, - rcd->coin_ev, - rcd->coin_ev_size); + TALER_blinded_planchet_hash_ (&rcd->blinded_planchet, + hash_context); } } @@ -307,22 +437,11 @@ TALER_refresh_get_commitment (struct TALER_RefreshCommitmentP *rc, void -TALER_coin_ev_hash (const void *coin_ev, - size_t coin_ev_size, - struct TALER_BlindedCoinHash *bch) -{ - GNUNET_CRYPTO_hash (coin_ev, - coin_ev_size, - &bch->hash); -} - - -void TALER_coin_pub_hash (const struct TALER_CoinSpendPublicKeyP *coin_pub, - const struct TALER_AgeHash *age_commitment_hash, - struct TALER_CoinPubHash *coin_h) + const struct TALER_AgeCommitmentHash *ach, + struct TALER_CoinPubHashP *coin_h) { - if (NULL == age_commitment_hash) + if (TALER_AgeCommitmentHash_isNullOrZero (ach)) { /* No age commitment was set */ GNUNET_CRYPTO_hash (&coin_pub->eddsa_pub, @@ -333,23 +452,93 @@ TALER_coin_pub_hash (const struct TALER_CoinSpendPublicKeyP *coin_pub, { /* Coin comes with age commitment. Take the hash of the age commitment * into account */ - const size_t key_s = sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey); - const size_t age_s = sizeof(struct TALER_AgeHash); - char data[key_s + age_s]; + struct GNUNET_HashContext *hash_context; - GNUNET_memcpy (&data[0], - &coin_pub->eddsa_pub, - key_s); + hash_context = GNUNET_CRYPTO_hash_context_start (); - GNUNET_memcpy (&data[key_s], - age_commitment_hash, - age_s); + GNUNET_CRYPTO_hash_context_read ( + hash_context, + &coin_pub->eddsa_pub, + sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)); - GNUNET_CRYPTO_hash (&data, - key_s + age_s, - &coin_h->hash); + GNUNET_CRYPTO_hash_context_read ( + hash_context, + ach, + sizeof(struct TALER_AgeCommitmentHash)); + + GNUNET_CRYPTO_hash_context_finish ( + hash_context, + &coin_h->hash); } } +void +TALER_coin_ev_hash (const struct TALER_BlindedPlanchet *blinded_planchet, + const struct TALER_DenominationHashP *denom_hash, + struct TALER_BlindedCoinHashP *bch) +{ + struct GNUNET_HashContext *hash_context; + + hash_context = GNUNET_CRYPTO_hash_context_start (); + GNUNET_CRYPTO_hash_context_read (hash_context, + denom_hash, + sizeof(*denom_hash)); + TALER_blinded_planchet_hash_ (blinded_planchet, + hash_context); + GNUNET_CRYPTO_hash_context_finish (hash_context, + &bch->hash); +} + + +GNUNET_NETWORK_STRUCT_BEGIN +/** + * Structure we hash to compute the group key for + * a denomination group. + */ +struct DenominationGroupP +{ + /** + * Value of coins in this denomination group. + */ + struct TALER_AmountNBO value; + + /** + * Fee structure for all coins in the group. + */ + struct TALER_DenomFeeSetNBOP fees; + + /** + * Age mask for the denomiation, in NBO. + */ + uint32_t age_mask GNUNET_PACKED; + + /** + * Cipher used for the denomination, in NBO. + */ + uint32_t cipher GNUNET_PACKED; +}; +GNUNET_NETWORK_STRUCT_END + + +void +TALER_denomination_group_get_key ( + const struct TALER_DenominationGroup *dg, + struct GNUNET_HashCode *key) +{ + struct DenominationGroupP dgp = { + .age_mask = htonl (dg->age_mask.bits), + .cipher = htonl (dg->cipher) + }; + + TALER_amount_hton (&dgp.value, + &dg->value); + TALER_denom_fee_set_hton (&dgp.fees, + &dg->fees); + GNUNET_CRYPTO_hash (&dgp, + sizeof (dgp), + key); +} + + /* end of crypto.c */ |