diff options
Diffstat (limited to 'src/util/crypto.c')
-rw-r--r-- | src/util/crypto.c | 377 |
1 files changed, 296 insertions, 81 deletions
diff --git a/src/util/crypto.c b/src/util/crypto.c index a7ea4f4c5..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,23 +73,27 @@ enum GNUNET_GenericReturnValue TALER_test_coin_valid (const struct TALER_CoinPublicInfo *coin_public_info, const struct TALER_DenominationPublicKey *denom_pub) { - struct GNUNET_HashCode c_hash; + struct TALER_CoinPubHashP c_hash; #if ENABLE_SANITY_CHECKS - struct GNUNET_HashCode d_hash; + struct TALER_DenominationHashP d_hash; - GNUNET_CRYPTO_rsa_public_key_hash (denom_pub->rsa_public_key, - &d_hash); + TALER_denom_pub_hash (denom_pub, + &d_hash); GNUNET_assert (0 == GNUNET_memcmp (&d_hash, &coin_public_info->denom_pub_hash)); #endif - GNUNET_CRYPTO_hash (&coin_public_info->coin_pub, - sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey), - &c_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 != - GNUNET_CRYPTO_rsa_verify (&c_hash, - coin_public_info->denom_sig.rsa_signature, - denom_pub->rsa_public_key)) + TALER_denom_pub_verify (denom_pub, + &coin_public_info->denom_sig, + &c_hash)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "coin signature is invalid\n"); @@ -113,7 +117,6 @@ TALER_link_derive_transfer_secret ( GNUNET_CRYPTO_ecdh_eddsa (&trans_priv->ecdhe_priv, &coin_pub.eddsa_pub, &ts->key)); - } @@ -144,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); @@ -164,66 +188,177 @@ 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 GNUNET_HashCode *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); - GNUNET_CRYPTO_hash (&coin_pub.eddsa_pub, - sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey), - c_hash); - if (GNUNET_YES != - TALER_rsa_blind (c_hash, - &ps->blinding_key.bks, - dk->rsa_public_key, - &pd->coin_ev, - &pd->coin_ev_size)) + if (GNUNET_OK != + TALER_denom_blind (dk, + bks, + nonce, + ach, + &coin_pub, + alg_values, + c_hash, + &pd->blinded_planchet)) { - GNUNET_break_op (0); + GNUNET_break (0); return GNUNET_SYSERR; } - GNUNET_CRYPTO_rsa_public_key_hash (dk->rsa_public_key, - &pd->denom_pub_hash); + TALER_denom_pub_hash (dk, + &pd->denom_pub_hash); return GNUNET_OK; } -enum GNUNET_GenericReturnValue -TALER_planchet_to_coin (const struct TALER_DenominationPublicKey *dk, - const struct GNUNET_CRYPTO_RsaSignature *blind_sig, - const struct TALER_PlanchetSecretsP *ps, - const struct GNUNET_HashCode *c_hash, - struct TALER_FreshCoin *coin) +void +TALER_planchet_detail_free (struct TALER_PlanchetDetail *pd) { - struct GNUNET_CRYPTO_RsaSignature *sig; + TALER_blinded_planchet_free (&pd->blinded_planchet); +} + - sig = TALER_rsa_unblind (blind_sig, - &ps->blinding_key.bks, - dk->rsa_public_key); +enum GNUNET_GenericReturnValue +TALER_planchet_to_coin ( + const struct TALER_DenominationPublicKey *dk, + const struct TALER_BlindedDenominationSignature *blind_sig, + 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) +{ + 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 != - GNUNET_CRYPTO_rsa_verify (c_hash, - sig, - dk->rsa_public_key)) + TALER_denom_sig_unblind (&coin->sig, + blind_sig, + bks, + c_hash, + alg_values, + dk)) { GNUNET_break_op (0); - GNUNET_CRYPTO_rsa_signature_free (sig); return GNUNET_SYSERR; } - coin->sig.rsa_signature = sig; - coin->coin_priv = ps->coin_priv; + if (GNUNET_OK != + TALER_denom_pub_verify (dk, + &coin->sig, + c_hash)) + { + GNUNET_break_op (0); + TALER_denom_sig_free (&coin->sig); + return GNUNET_SYSERR; + } + + coin->coin_priv = *coin_priv; + coin->h_age_commitment = ach; return GNUNET_OK; } @@ -231,6 +366,7 @@ TALER_planchet_to_coin (const struct TALER_DenominationPublicKey *dk, 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, @@ -239,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++) { @@ -250,19 +390,16 @@ TALER_refresh_get_commitment (struct TALER_RefreshCommitmentP *rc, hash_context */ for (unsigned int i = 0; i<num_new_coins; i++) { - void *buf; - size_t buf_size; + struct TALER_DenominationHashP denom_hash; /* The denomination keys should / must all be identical regardless of what offset we use, so we use [0]. */ GNUNET_assert (kappa > 0); /* sanity check */ - buf_size = GNUNET_CRYPTO_rsa_public_key_encode ( - rcs[0].new_coins[i].dk->rsa_public_key, - &buf); + TALER_denom_pub_hash (rcs[0].new_coins[i].dk, + &denom_hash); GNUNET_CRYPTO_hash_context_read (hash_context, - buf, - buf_size); - GNUNET_free (buf); + &denom_hash, + sizeof (denom_hash)); } /* next, add public key of coin and amount being refreshed */ @@ -288,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); } } @@ -300,29 +436,108 @@ TALER_refresh_get_commitment (struct TALER_RefreshCommitmentP *rc, } -enum GNUNET_GenericReturnValue -TALER_rsa_blind (const struct GNUNET_HashCode *hash, - const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks, - struct GNUNET_CRYPTO_RsaPublicKey *pkey, - void **buf, - size_t *buf_size) +void +TALER_coin_pub_hash (const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_AgeCommitmentHash *ach, + struct TALER_CoinPubHashP *coin_h) { - return GNUNET_CRYPTO_rsa_blind (hash, - bks, - pkey, - buf, - buf_size); + if (TALER_AgeCommitmentHash_isNullOrZero (ach)) + { + /* No age commitment was set */ + GNUNET_CRYPTO_hash (&coin_pub->eddsa_pub, + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey), + &coin_h->hash); + } + else + { + /* Coin comes with age commitment. Take the hash of the age commitment + * into account */ + struct GNUNET_HashContext *hash_context; + + hash_context = GNUNET_CRYPTO_hash_context_start (); + + GNUNET_CRYPTO_hash_context_read ( + hash_context, + &coin_pub->eddsa_pub, + sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)); + + 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); } -struct GNUNET_CRYPTO_RsaSignature * -TALER_rsa_unblind (const struct GNUNET_CRYPTO_RsaSignature *sig, - const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks, - struct GNUNET_CRYPTO_RsaPublicKey *pkey) +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) { - return GNUNET_CRYPTO_rsa_unblind (sig, - bks, - pkey); + 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); } |