diff options
Diffstat (limited to 'src/util/denom.c')
-rw-r--r-- | src/util/denom.c | 473 |
1 files changed, 473 insertions, 0 deletions
diff --git a/src/util/denom.c b/src/util/denom.c new file mode 100644 index 000000000..cb232c4a3 --- /dev/null +++ b/src/util/denom.c @@ -0,0 +1,473 @@ +/* + This file is part of TALER + Copyright (C) 2021, 2022, 2023 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 + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> +*/ +/** + * @file denom.c + * @brief denomination utility functions + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_util.h" + + +enum GNUNET_GenericReturnValue +TALER_denom_priv_create (struct TALER_DenominationPrivateKey *denom_priv, + struct TALER_DenominationPublicKey *denom_pub, + enum GNUNET_CRYPTO_BlindSignatureAlgorithm cipher, + ...) +{ + enum GNUNET_GenericReturnValue ret; + va_list ap; + + memset (denom_pub, + 0, + sizeof (*denom_pub)); + memset (denom_priv, + 0, + sizeof (*denom_priv)); + va_start (ap, + cipher); + ret = GNUNET_CRYPTO_blind_sign_keys_create_va ( + &denom_priv->bsign_priv_key, + &denom_pub->bsign_pub_key, + cipher, + ap); + va_end (ap); + return ret; +} + + +enum GNUNET_GenericReturnValue +TALER_denom_sign_blinded (struct TALER_BlindedDenominationSignature *denom_sig, + const struct TALER_DenominationPrivateKey *denom_priv, + bool for_melt, + const struct TALER_BlindedPlanchet *blinded_planchet) +{ + denom_sig->blinded_sig + = GNUNET_CRYPTO_blind_sign (denom_priv->bsign_priv_key, + for_melt ? "rm" : "rw", + blinded_planchet->blinded_message); + if (NULL == denom_sig->blinded_sig) + return GNUNET_SYSERR; + return GNUNET_OK; +} + + +enum GNUNET_GenericReturnValue +TALER_denom_sig_unblind ( + struct TALER_DenominationSignature *denom_sig, + const struct TALER_BlindedDenominationSignature *bdenom_sig, + const union GNUNET_CRYPTO_BlindingSecretP *bks, + const struct TALER_CoinPubHashP *c_hash, + const struct TALER_ExchangeWithdrawValues *alg_values, + const struct TALER_DenominationPublicKey *denom_pub) +{ + denom_sig->unblinded_sig + = GNUNET_CRYPTO_blind_sig_unblind (bdenom_sig->blinded_sig, + bks, + c_hash, + sizeof (*c_hash), + alg_values->blinding_inputs, + denom_pub->bsign_pub_key); + if (NULL == denom_sig->unblinded_sig) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + return GNUNET_OK; +} + + +void +TALER_denom_pub_hash (const struct TALER_DenominationPublicKey *denom_pub, + struct TALER_DenominationHashP *denom_hash) +{ + struct GNUNET_CRYPTO_BlindSignPublicKey *bsp + = denom_pub->bsign_pub_key; + uint32_t opt[2] = { + htonl (denom_pub->age_mask.bits), + htonl ((uint32_t) bsp->cipher) + }; + struct GNUNET_HashContext *hc; + + hc = GNUNET_CRYPTO_hash_context_start (); + GNUNET_CRYPTO_hash_context_read (hc, + opt, + sizeof (opt)); + switch (bsp->cipher) + { + case GNUNET_CRYPTO_BSA_RSA: + { + void *buf; + size_t blen; + + blen = GNUNET_CRYPTO_rsa_public_key_encode ( + bsp->details.rsa_public_key, + &buf); + GNUNET_CRYPTO_hash_context_read (hc, + buf, + blen); + GNUNET_free (buf); + } + break; + case GNUNET_CRYPTO_BSA_CS: + GNUNET_CRYPTO_hash_context_read (hc, + &bsp->details.cs_public_key, + sizeof(bsp->details.cs_public_key)); + break; + default: + GNUNET_assert (0); + } + GNUNET_CRYPTO_hash_context_finish (hc, + &denom_hash->hash); +} + + +const struct TALER_ExchangeWithdrawValues * +TALER_denom_ewv_rsa_singleton () +{ + static struct GNUNET_CRYPTO_BlindingInputValues bi = { + .cipher = GNUNET_CRYPTO_BSA_RSA + }; + static struct TALER_ExchangeWithdrawValues alg_values = { + .blinding_inputs = &bi + }; + return &alg_values; +} + + +enum GNUNET_GenericReturnValue +TALER_denom_blind ( + const struct TALER_DenominationPublicKey *dk, + const union GNUNET_CRYPTO_BlindingSecretP *coin_bks, + const union GNUNET_CRYPTO_BlindSessionNonce *nonce, + const struct TALER_AgeCommitmentHash *ach, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_ExchangeWithdrawValues *alg_values, + struct TALER_CoinPubHashP *c_hash, + struct TALER_BlindedPlanchet *blinded_planchet) +{ + TALER_coin_pub_hash (coin_pub, + ach, + c_hash); + blinded_planchet->blinded_message + = GNUNET_CRYPTO_message_blind_to_sign (dk->bsign_pub_key, + coin_bks, + nonce, + c_hash, + sizeof (*c_hash), + alg_values->blinding_inputs); + if (NULL == blinded_planchet->blinded_message) + return GNUNET_SYSERR; + return GNUNET_OK; +} + + +enum GNUNET_GenericReturnValue +TALER_denom_pub_verify (const struct TALER_DenominationPublicKey *denom_pub, + const struct TALER_DenominationSignature *denom_sig, + const struct TALER_CoinPubHashP *c_hash) +{ + return GNUNET_CRYPTO_blind_sig_verify (denom_pub->bsign_pub_key, + denom_sig->unblinded_sig, + c_hash, + sizeof (*c_hash)); +} + + +void +TALER_denom_pub_free (struct TALER_DenominationPublicKey *denom_pub) +{ + if (NULL != denom_pub->bsign_pub_key) + { + GNUNET_CRYPTO_blind_sign_pub_decref (denom_pub->bsign_pub_key); + denom_pub->bsign_pub_key = NULL; + } +} + + +void +TALER_denom_priv_free (struct TALER_DenominationPrivateKey *denom_priv) +{ + if (NULL != denom_priv->bsign_priv_key) + { + GNUNET_CRYPTO_blind_sign_priv_decref (denom_priv->bsign_priv_key); + denom_priv->bsign_priv_key = NULL; + } +} + + +void +TALER_denom_sig_free (struct TALER_DenominationSignature *denom_sig) +{ + if (NULL != denom_sig->unblinded_sig) + { + GNUNET_CRYPTO_unblinded_sig_decref (denom_sig->unblinded_sig); + denom_sig->unblinded_sig = NULL; + } +} + + +void +TALER_blinded_denom_sig_free ( + struct TALER_BlindedDenominationSignature *denom_sig) +{ + if (NULL != denom_sig->blinded_sig) + { + GNUNET_CRYPTO_blinded_sig_decref (denom_sig->blinded_sig); + denom_sig->blinded_sig = NULL; + } +} + + +void +TALER_denom_ewv_free (struct TALER_ExchangeWithdrawValues *ewv) +{ + if (ewv == TALER_denom_ewv_rsa_singleton ()) + return; + if (ewv->blinding_inputs == + TALER_denom_ewv_rsa_singleton ()->blinding_inputs) + { + ewv->blinding_inputs = NULL; + return; + } + if (NULL != ewv->blinding_inputs) + { + GNUNET_CRYPTO_blinding_input_values_decref (ewv->blinding_inputs); + ewv->blinding_inputs = NULL; + } +} + + +void +TALER_denom_ewv_copy (struct TALER_ExchangeWithdrawValues *bi_dst, + const struct TALER_ExchangeWithdrawValues *bi_src) +{ + if (bi_src == TALER_denom_ewv_rsa_singleton ()) + { + *bi_dst = *bi_src; + return; + } + bi_dst->blinding_inputs + = GNUNET_CRYPTO_blinding_input_values_incref (bi_src->blinding_inputs); +} + + +void +TALER_denom_pub_copy (struct TALER_DenominationPublicKey *denom_dst, + const struct TALER_DenominationPublicKey *denom_src) +{ + denom_dst->age_mask = denom_src->age_mask; + denom_dst->bsign_pub_key + = GNUNET_CRYPTO_bsign_pub_incref (denom_src->bsign_pub_key); +} + + +void +TALER_denom_sig_copy (struct TALER_DenominationSignature *denom_dst, + const struct TALER_DenominationSignature *denom_src) +{ + denom_dst->unblinded_sig + = GNUNET_CRYPTO_ub_sig_incref (denom_src->unblinded_sig); +} + + +void +TALER_blinded_denom_sig_copy ( + struct TALER_BlindedDenominationSignature *denom_dst, + const struct TALER_BlindedDenominationSignature *denom_src) +{ + denom_dst->blinded_sig + = GNUNET_CRYPTO_blind_sig_incref (denom_src->blinded_sig); +} + + +int +TALER_denom_pub_cmp (const struct TALER_DenominationPublicKey *denom1, + const struct TALER_DenominationPublicKey *denom2) +{ + if (denom1->bsign_pub_key->cipher != + denom2->bsign_pub_key->cipher) + return (denom1->bsign_pub_key->cipher > + denom2->bsign_pub_key->cipher) ? 1 : -1; + if (denom1->age_mask.bits != denom2->age_mask.bits) + return (denom1->age_mask.bits > denom2->age_mask.bits) ? 1 : -1; + return GNUNET_CRYPTO_bsign_pub_cmp (denom1->bsign_pub_key, + denom2->bsign_pub_key); +} + + +int +TALER_denom_sig_cmp (const struct TALER_DenominationSignature *sig1, + const struct TALER_DenominationSignature *sig2) +{ + return GNUNET_CRYPTO_ub_sig_cmp (sig1->unblinded_sig, + sig1->unblinded_sig); +} + + +int +TALER_blinded_planchet_cmp ( + const struct TALER_BlindedPlanchet *bp1, + const struct TALER_BlindedPlanchet *bp2) +{ + return GNUNET_CRYPTO_blinded_message_cmp (bp1->blinded_message, + bp2->blinded_message); +} + + +int +TALER_blinded_denom_sig_cmp ( + const struct TALER_BlindedDenominationSignature *sig1, + const struct TALER_BlindedDenominationSignature *sig2) +{ + return GNUNET_CRYPTO_blind_sig_cmp (sig1->blinded_sig, + sig1->blinded_sig); +} + + +void +TALER_blinded_planchet_hash_ (const struct TALER_BlindedPlanchet *bp, + struct GNUNET_HashContext *hash_context) +{ + const struct GNUNET_CRYPTO_BlindedMessage *bm = bp->blinded_message; + uint32_t cipher = htonl (bm->cipher); + + GNUNET_CRYPTO_hash_context_read (hash_context, + &cipher, + sizeof (cipher)); + switch (bm->cipher) + { + case GNUNET_CRYPTO_BSA_INVALID: + GNUNET_break (0); + return; + case GNUNET_CRYPTO_BSA_RSA: + GNUNET_CRYPTO_hash_context_read ( + hash_context, + bm->details.rsa_blinded_message.blinded_msg, + bm->details.rsa_blinded_message.blinded_msg_size); + return; + case GNUNET_CRYPTO_BSA_CS: + GNUNET_CRYPTO_hash_context_read ( + hash_context, + &bm->details.cs_blinded_message, + sizeof (bm->details.cs_blinded_message)); + return; + } + GNUNET_assert (0); +} + + +void +TALER_planchet_blinding_secret_create ( + const struct TALER_PlanchetMasterSecretP *ps, + const struct TALER_ExchangeWithdrawValues *alg_values, + union GNUNET_CRYPTO_BlindingSecretP *bks) +{ + const struct GNUNET_CRYPTO_BlindingInputValues *bi = + alg_values->blinding_inputs; + + switch (bi->cipher) + { + case GNUNET_CRYPTO_BSA_INVALID: + GNUNET_break (0); + return; + case GNUNET_CRYPTO_BSA_RSA: + GNUNET_assert (GNUNET_YES == + GNUNET_CRYPTO_kdf (&bks->rsa_bks, + sizeof (bks->rsa_bks), + "bks", + strlen ("bks"), + ps, + sizeof(*ps), + NULL, + 0)); + return; + case GNUNET_CRYPTO_BSA_CS: + GNUNET_assert (GNUNET_YES == + GNUNET_CRYPTO_kdf (&bks->nonce, + sizeof (bks->nonce), + "bseed", + strlen ("bseed"), + ps, + sizeof(*ps), + &bi->details.cs_values, + sizeof(bi->details.cs_values), + NULL, + 0)); + return; + } + GNUNET_assert (0); +} + + +void +TALER_planchet_setup_coin_priv ( + const struct TALER_PlanchetMasterSecretP *ps, + const struct TALER_ExchangeWithdrawValues *alg_values, + struct TALER_CoinSpendPrivateKeyP *coin_priv) +{ + const struct GNUNET_CRYPTO_BlindingInputValues *bi + = alg_values->blinding_inputs; + + switch (bi->cipher) + { + case GNUNET_CRYPTO_BSA_INVALID: + GNUNET_break (0); + memset (coin_priv, + 0, + sizeof (*coin_priv)); + return; + case GNUNET_CRYPTO_BSA_RSA: + GNUNET_assert (GNUNET_YES == + GNUNET_CRYPTO_kdf (coin_priv, + sizeof (*coin_priv), + "coin", + strlen ("coin"), + ps, + sizeof(*ps), + NULL, + 0)); + return; + case GNUNET_CRYPTO_BSA_CS: + GNUNET_assert (GNUNET_YES == + GNUNET_CRYPTO_kdf (coin_priv, + sizeof (*coin_priv), + "coin", + strlen ("coin"), + ps, + sizeof(*ps), + &bi->details.cs_values, + sizeof(bi->details.cs_values), + NULL, + 0)); + return; + } + GNUNET_assert (0); +} + + +void +TALER_blinded_planchet_free (struct TALER_BlindedPlanchet *blinded_planchet) +{ + if (NULL != blinded_planchet->blinded_message) + { + GNUNET_CRYPTO_blinded_message_decref (blinded_planchet->blinded_message); + blinded_planchet->blinded_message = NULL; + } +} + + +/* end of denom.c */ |