From c42376cf400b59006fa9ed0a195c014d10c7eca1 Mon Sep 17 00:00:00 2001 From: Gian Demarmels Date: Sat, 5 Feb 2022 00:32:53 +0100 Subject: [PATCH] crypto implementation --- src/include/taler_crypto_lib.h | 101 ++++++++++++++------------- src/lib/exchange_api_withdraw.c | 6 ++ src/util/crypto.c | 119 ++++++++++++++++++-------------- 3 files changed, 126 insertions(+), 100 deletions(-) diff --git a/src/include/taler_crypto_lib.h b/src/include/taler_crypto_lib.h index 62c9191a5..0783b1e85 100644 --- a/src/include/taler_crypto_lib.h +++ b/src/include/taler_crypto_lib.h @@ -455,6 +455,25 @@ struct TALER_RsaPubHashP struct GNUNET_HashCode hash; }; +GNUNET_NETWORK_STRUCT_BEGIN + +/** + * Master key material for the deriviation of + * private coins and blinding factors. + */ +struct TALER_PlanchetSecretsP +{ + + /** + * Key material. + */ + uint32_t key_data[8]; + +}; + + +GNUNET_NETWORK_STRUCT_END + /** * Hash @a rsa. @@ -990,11 +1009,14 @@ TALER_denom_pub_free (struct TALER_DenominationPublicKey *denom_pub); /** * Create private key for a Taler coin. - * + * @param ps planchet secret to derive coin priv key + * @param alg_values includes algorithm specific values * @param[out] coin_priv private key to initialize */ void TALER_planchet_setup_coin_priv ( + const struct TALER_PlanchetSecretsP *ps, + const struct TALER_ExchangeWithdrawValues *alg_values, struct TALER_CoinSpendPrivateKeyP *coin_priv); @@ -1302,27 +1324,6 @@ void TALER_payto_hash (const char *payto, struct TALER_PaytoHash *h_payto); - -GNUNET_NETWORK_STRUCT_BEGIN - -/** - * Master key material for the deriviation of - * private coins and blinding factors. - */ -struct TALER_PlanchetSecretsP -{ - - /** - * Key material. - */ - uint32_t key_data[8]; - -}; - - -GNUNET_NETWORK_STRUCT_END - - /** * Details about a planchet that the customer wants to obtain * a withdrawal authorization. This is the information that @@ -1465,10 +1466,10 @@ GNUNET_NETWORK_STRUCT_END * @param[out] ps value to initialize */ void -XXXTALER_planchet_setup_refresh (const struct - TALER_TransferSecretP *secret_seed, - uint32_t coin_num_salt, - struct TALER_PlanchetSecretsP *ps); +TALER_planchet_setup_refresh (const struct TALER_TransferSecretP *secret_seed, + uint32_t coin_num_salt, + struct TALER_CoinSpendPrivateKeyP *coin_priv, + union TALER_DenominationBlindingKeyP *bks); /** @@ -1485,21 +1486,25 @@ TALER_planchet_setup_random ( /** * Create a blinding secret @a bs for @a cipher. * - * @param[out] ps planchet with blinding secret to initialize + * @param ps secret to derive blindings from * @param alg_values withdraw values containing cipher and additional CS values + * @param bks blinding secrets */ void -XXXTALER_planchet_blinding_secret_create (struct TALER_PlanchetSecretsP *ps, - const struct - TALER_ExchangeWithdrawValues * - alg_values); +TALER_planchet_blinding_secret_create (const struct TALER_PlanchetSecretsP *ps, + + const struct + TALER_ExchangeWithdrawValues *alg_values, + union TALER_DenominationBlindingKeyP *bks); /** * Prepare a planchet for tipping. Creates and blinds a coin. * * @param dk denomination key for the coin to be created - * @param ps secret planchet internals (for #TALER_planchet_to_coin) + * @param alg_values algorithm specific values + * @param bks blinding secrets + * @param coin_priv coin private key * @param[out] c_hash set to the hash of the public key of the coin (needed later) * @param[out] pd set to the planchet detail for TALER_MERCHANT_tip_pickup() and * other withdraw operations, pd->blinded_planchet.cipher will be set @@ -1507,12 +1512,13 @@ XXXTALER_planchet_blinding_secret_create (struct TALER_PlanchetSecretsP *ps, * @return #GNUNET_OK on success */ enum GNUNET_GenericReturnValue -XXXTALER_planchet_prepare (const struct TALER_DenominationPublicKey *dk, - const struct - TALER_ExchangeWithdrawValues *alg_values, - struct TALER_PlanchetSecretsP *ps, - struct TALER_CoinPubHash *c_hash, - struct TALER_PlanchetDetail *pd); +TALER_planchet_prepare (const struct TALER_DenominationPublicKey *dk, + const struct TALER_ExchangeWithdrawValues *alg_values, + const union TALER_DenominationBlindingKeyP *bks, + const struct TALER_CoinSpendPrivateKeyP *coin_priv, + struct TALER_CoinPubHash *c_hash, + struct TALER_PlanchetDetail *pd + ); /** @@ -1531,20 +1537,21 @@ TALER_blinded_planchet_free (struct TALER_BlindedPlanchet *blinded_planchet); * * @param dk denomination key, must match what was given to #TALER_planchet_prepare() * @param blind_sig blind signature from the exchange - * @param ps secrets from #TALER_planchet_prepare() + * @param bks blinding key secret + * @param coin_priv private key of the coin * @param c_hash hash of the coin's public key for verification of the signature * @param[out] coin set to the details of the fresh coin * @return #GNUNET_OK on success */ enum GNUNET_GenericReturnValue -XXXTALER_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 struct - TALER_ExchangeWithdrawValues *alg_values, - struct TALER_FreshCoin *coin); +TALER_planchet_to_coin (const struct TALER_DenominationPublicKey *dk, + const struct + TALER_BlindedDenominationSignature *blind_sig, + const union TALER_DenominationBlindingKeyP *bks, + const struct TALER_CoinSpendPrivateKeyP *coin_priv, + const struct TALER_CoinPubHash *c_hash, + const struct TALER_ExchangeWithdrawValues *alg_values, + struct TALER_FreshCoin *coin); /* ****************** Refresh crypto primitives ************* */ diff --git a/src/lib/exchange_api_withdraw.c b/src/lib/exchange_api_withdraw.c index 7b851b492..477af5446 100644 --- a/src/lib/exchange_api_withdraw.c +++ b/src/lib/exchange_api_withdraw.c @@ -242,9 +242,15 @@ TALER_EXCHANGE_withdraw ( TALER_denom_pub_deep_copy (&wh->pk.key, &pk->key); + switch (pk->key.cipher) { case TALER_DENOMINATION_RSA: + struct TALER_CoinSpendPrivateKeyP priv; + alg_values.cipher = TALER_DENOMINATION_RSA; + + TALER_planchet_setup_coin_priv (ps, &wh->alg_values, &priv); + if (GNUNET_OK != TALER_planchet_prepare (&pk->key, &wh->alg_values, diff --git a/src/util/crypto.c b/src/util/crypto.c index 18f809e34..4363c5616 100644 --- a/src/util/crypto.c +++ b/src/util/crypto.c @@ -149,13 +149,19 @@ 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) + struct TALER_CoinSpendPrivateKeyP *coin_priv, + union TALER_DenominationBlindingKeyP *bks) { uint32_t be_salt = htonl (coin_num_salt); + struct + { + struct TALER_CoinSpendPrivateKeyP coin_priv; + union TALER_DenominationBlindingKeyP bks; + } out; GNUNET_assert (GNUNET_OK == - GNUNET_CRYPTO_kdf (ps, - sizeof (*ps), + GNUNET_CRYPTO_kdf (&out, + sizeof (out), &be_salt, sizeof (be_salt), secret_seed, @@ -163,12 +169,14 @@ TALER_planchet_setup_refresh (const struct TALER_TransferSecretP *secret_seed, "taler-coin-derivation", strlen ("taler-coin-derivation"), NULL, 0)); + *coin_priv = out.coin_priv; + *bks = out.bks; } void cs_blinding_seed_derive (const struct - TALER_CoinSpendPrivateKeyP *coin_priv, + TALER_PlanchetSecretsP *ps, const struct GNUNET_CRYPTO_CsRPublic r_pub[2], struct GNUNET_CRYPTO_CsNonce *blind_seed) { @@ -179,8 +187,8 @@ cs_blinding_seed_derive (const struct GCRY_MD_SHA256, "bseed", strlen ("bseed"), - coin_priv, - sizeof(*coin_priv), + ps, + sizeof(*ps), r_pub, sizeof(struct GNUNET_CRYPTO_CsRPublic) * 2, NULL, @@ -217,9 +225,11 @@ TALER_cs_withdraw_nonce_generate (struct TALER_CsNonce *nonce) void -TALER_planchet_blinding_secret_create (struct TALER_PlanchetSecretsP *ps, +TALER_planchet_blinding_secret_create (const struct TALER_PlanchetSecretsP *ps, + const struct - TALER_ExchangeWithdrawValues *alg_values) + TALER_ExchangeWithdrawValues *alg_values, + union TALER_DenominationBlindingKeyP *bks) { switch (alg_values->cipher) { @@ -227,16 +237,26 @@ TALER_planchet_blinding_secret_create (struct TALER_PlanchetSecretsP *ps, GNUNET_break (0); return; case TALER_DENOMINATION_RSA: - GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG, - &ps->blinding_key.rsa_bks, - sizeof (struct - GNUNET_CRYPTO_RsaBlindingKeySecret)); + GNUNET_assert (GNUNET_YES == + GNUNET_CRYPTO_hkdf (&bks->rsa_bks, + sizeof (struct + GNUNET_CRYPTO_RsaBlindingKeySecret), + GCRY_MD_SHA512, + GCRY_MD_SHA256, + "bks", + strlen ("bks"), + ps, + sizeof(*ps), + &alg_values->details, /* Could be null on RSA case*/ + sizeof(alg_values->details), + NULL, + 0)); return; case TALER_DENOMINATION_CS: { - cs_blinding_seed_derive (&ps->coin_priv, + cs_blinding_seed_derive (ps, alg_values->details.cs_values.r_pub.r_pub, - &ps->blinding_key.nonce); + &bks->nonce); return; } default: @@ -247,51 +267,43 @@ TALER_planchet_blinding_secret_create (struct TALER_PlanchetSecretsP *ps, void TALER_planchet_setup_coin_priv ( + const struct TALER_PlanchetSecretsP *ps, + const struct TALER_ExchangeWithdrawValues *alg_values, struct TALER_CoinSpendPrivateKeyP *coin_priv) { - GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG, - coin_priv, - sizeof (*coin_priv)); - // FIXME-jeff/dold: Clamping? -} - - -void -TALER_planchet_setup_random ( - struct TALER_PlanchetSecretsP *ps, - const struct TALER_ExchangeWithdrawValues *alg_values) -{ - TALER_planchet_setup_coin_priv (&ps->coin_priv); - switch (alg_values->cipher) - { - case TALER_DENOMINATION_INVALID: - GNUNET_break (0); - return; - case TALER_DENOMINATION_RSA: - TALER_planchet_blinding_secret_create (ps, - alg_values); - return; - case TALER_DENOMINATION_CS: - // Will be set in a later stage for Clause Blind Schnorr Scheme - return; - default: - GNUNET_break (0); - } + GNUNET_assert (GNUNET_YES == + GNUNET_CRYPTO_hkdf (coin_priv, + sizeof (*coin_priv), + GCRY_MD_SHA512, + GCRY_MD_SHA256, + "coin", + strlen ("coin"), + ps, + sizeof(*ps), + &alg_values->details, /* Could be null on RSA case*/ + sizeof(alg_values->details), + NULL, + 0)); + coin_priv->eddsa_priv.d[0] &= 248; + coin_priv->eddsa_priv.d[31] &= 127; + coin_priv->eddsa_priv.d[31] |= 64; } enum GNUNET_GenericReturnValue TALER_planchet_prepare (const struct TALER_DenominationPublicKey *dk, const struct TALER_ExchangeWithdrawValues *alg_values, - struct TALER_PlanchetSecretsP *ps, + const union TALER_DenominationBlindingKeyP *bks, + const struct TALER_CoinSpendPrivateKeyP *coin_priv, struct TALER_CoinPubHash *c_hash, - struct TALER_PlanchetDetail *pd) + struct TALER_PlanchetDetail *pd + ) { struct TALER_CoinSpendPublicKeyP coin_pub; GNUNET_assert (alg_values->cipher == dk->cipher); - GNUNET_CRYPTO_eddsa_key_get_public (&ps->coin_priv.eddsa_priv, + GNUNET_CRYPTO_eddsa_key_get_public (&coin_priv->eddsa_priv, &coin_pub.eddsa_pub); switch (dk->cipher) @@ -299,7 +311,7 @@ TALER_planchet_prepare (const struct TALER_DenominationPublicKey *dk, case TALER_DENOMINATION_RSA: if (GNUNET_OK != TALER_denom_blind (dk, - &ps->blinding_key, + bks, NULL, /* FIXME-Oec */ &coin_pub, alg_values, @@ -313,8 +325,8 @@ TALER_planchet_prepare (const struct TALER_DenominationPublicKey *dk, case TALER_DENOMINATION_CS: if (GNUNET_OK != TALER_denom_blind (dk, - &ps->blinding_key, - NULL, /* FIXME-Oec */ + bks, + NULL, /* FIXME-Oec */ &coin_pub, alg_values, c_hash, @@ -357,7 +369,8 @@ enum GNUNET_GenericReturnValue TALER_planchet_to_coin (const struct TALER_DenominationPublicKey *dk, const struct TALER_BlindedDenominationSignature *blind_sig, - const struct TALER_PlanchetSecretsP *ps, + const union TALER_DenominationBlindingKeyP *bks, + const struct TALER_CoinSpendPrivateKeyP *coin_priv, const struct TALER_CoinPubHash *c_hash, const struct TALER_ExchangeWithdrawValues *alg_values, struct TALER_FreshCoin *coin) @@ -377,7 +390,7 @@ TALER_planchet_to_coin (const struct TALER_DenominationPublicKey *dk, if (GNUNET_OK != TALER_denom_sig_unblind (&sig, blind_sig, - &ps->blinding_key, + bks, dk)) { GNUNET_break_op (0); @@ -390,7 +403,7 @@ TALER_planchet_to_coin (const struct TALER_DenominationPublicKey *dk, struct GNUNET_CRYPTO_CsBlindingSecret bs[2]; struct TALER_DenominationCsPublicR r_pub_blind; - GNUNET_CRYPTO_cs_blinding_secrets_derive (&ps->blinding_key.nonce, bs); + GNUNET_CRYPTO_cs_blinding_secrets_derive (&bks->nonce, bs); GNUNET_CRYPTO_cs_calc_blinded_c (bs, alg_values->details.cs_values.r_pub.r_pub, @@ -406,7 +419,7 @@ TALER_planchet_to_coin (const struct TALER_DenominationPublicKey *dk, if (GNUNET_OK != TALER_denom_sig_unblind (&sig, blind_sig, - &ps->blinding_key, + bks, dk)) { GNUNET_break_op (0); @@ -430,7 +443,7 @@ TALER_planchet_to_coin (const struct TALER_DenominationPublicKey *dk, } coin->sig = sig; - coin->coin_priv = ps->coin_priv; + coin->coin_priv = *coin_priv; return GNUNET_OK; }