From 62d3d352502f5b1d109b18456a87c704a70fcca5 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Wed, 28 Jan 2015 20:23:19 +0100 Subject: [PATCH] move coin validity test to libtalerutil --- src/include/taler_util.h | 41 +++++++++++++++++++++++++++++ src/mint/mint.h | 28 -------------------- src/mint/taler-mint-httpd_deposit.c | 16 ++++++++--- src/mint/taler-mint-httpd_keys.c | 35 ------------------------ src/mint/taler-mint-httpd_refresh.c | 38 ++++++++++++++++++-------- src/util/crypto.c | 31 ++++++++++++++++++++++ 6 files changed, 112 insertions(+), 77 deletions(-) diff --git a/src/include/taler_util.h b/src/include/taler_util.h index ab5ee11df..5ee90a6cc 100644 --- a/src/include/taler_util.h +++ b/src/include/taler_util.h @@ -251,6 +251,47 @@ TALER_data_to_string_alloc (const void *buf, size_t size); +/* ****************** Coin crypto primitives ************* */ + +/** + * Public information about a coin (including the public key + * of the coin, the denomination key and the signature with + * the denomination key). + */ +struct TALER_CoinPublicInfo +{ + /** + * The coin's public key. + */ + struct GNUNET_CRYPTO_EcdsaPublicKey coin_pub; + + /** + * Public key representing the denomination of the coin + * that is being deposited. + */ + struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub; + + /** + * (Unblinded) signature over @e coin_pub with @e denom_pub, + * which demonstrates that the coin is valid. + */ + struct GNUNET_CRYPTO_rsa_Signature *denom_sig; +}; + + +/** + * Check if a coin is valid; that is, whether the denomination key exists, + * is not expired, and the signature is correct. + * + * @param coin_public_info the coin public info to check for validity + * @return #GNUNET_YES if the coin is valid, + * #GNUNET_NO if it is invalid + * #GNUNET_SYSERROR if an internal error occured + */ +int +TALER_test_coin_valid (const struct TALER_CoinPublicInfo *coin_public_info); + + /* ****************** Refresh crypto primitives ************* */ /** diff --git a/src/mint/mint.h b/src/mint/mint.h index 13719e625..b29162b20 100644 --- a/src/mint/mint.h +++ b/src/mint/mint.h @@ -34,31 +34,6 @@ #define MINT_CURRENCY "EUR" -/** - * Public information about a coin (including the public key - * of the coin, the denomination key and the signature with - * the denomination key). - */ -struct TALER_CoinPublicInfo -{ - /** - * The coin's public key. - */ - struct GNUNET_CRYPTO_EcdsaPublicKey coin_pub; - - /** - * Public key representing the denomination of the coin - * that is being deposited. - */ - struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub; - - /** - * (Unblinded) signature over @e coin_pub with @e denom_pub, - * which demonstrates that the coin is valid. - */ - struct GNUNET_CRYPTO_rsa_Signature *denom_sig; -}; - /** * Information we keep for a withdrawn coin to reproduce @@ -91,9 +66,6 @@ struct CollectableBlindcoin }; - - - /** * Global information for a refreshing session. */ diff --git a/src/mint/taler-mint-httpd_deposit.c b/src/mint/taler-mint-httpd_deposit.c index 0bd1134a6..63ce03579 100644 --- a/src/mint/taler-mint-httpd_deposit.c +++ b/src/mint/taler-mint-httpd_deposit.c @@ -59,6 +59,7 @@ verify_and_execute_deposit (struct MHD_Connection *connection, { struct MintKeyState *key_state; struct TALER_DepositRequest dr; + struct TALER_MINT_DenomKeyIssuePriv *dki; dr.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_DEPOSIT); dr.purpose.size = htonl (sizeof (struct TALER_DepositRequest)); @@ -77,11 +78,20 @@ verify_and_execute_deposit (struct MHD_Connection *connection, return TALER_MINT_reply_arg_invalid (connection, "csig"); } - + /* check denomination exists and is valid */ key_state = TALER_MINT_key_state_acquire (); + dki = TALER_MINT_get_denom_key (key_state, + deposit->coin.denom_pub); + if (NULL == dki) + { + TALER_MINT_key_state_release (key_state); + LOG_WARNING ("Unknown denomination key in /deposit request\n"); + return TALER_MINT_reply_arg_invalid (connection, + "denom_pub"); + } + /* check coin signature */ if (GNUNET_YES != - TALER_MINT_test_coin_valid (key_state, - &deposit->coin)) + TALER_test_coin_valid (&deposit->coin)) { LOG_WARNING ("Invalid coin passed for /deposit\n"); TALER_MINT_key_state_release (key_state); diff --git a/src/mint/taler-mint-httpd_keys.c b/src/mint/taler-mint-httpd_keys.c index fc425876f..71d7f077e 100644 --- a/src/mint/taler-mint-httpd_keys.c +++ b/src/mint/taler-mint-httpd_keys.c @@ -72,41 +72,6 @@ TALER_MINT_handler_keys (struct RequestHandler *rh, } -/** - * Check if a coin is valid; that is, whether the denomination key exists, - * is not expired, and the signature is correct. - * - * @param key_state the key state to use for checking the coin's validity - * @param coin_public_info the coin public info to check for validity - * @return #GNUNET_YES if the coin is valid, - * #GNUNET_NO if it is invalid - * #GNUNET_SYSERROR if an internal error occured - */ -int -TALER_MINT_test_coin_valid (const struct MintKeyState *key_state, - const struct TALER_CoinPublicInfo *coin_public_info) -{ - struct TALER_MINT_DenomKeyIssuePriv *dki; - struct GNUNET_HashCode c_hash; - - dki = TALER_MINT_get_denom_key (key_state, coin_public_info->denom_pub); - if (NULL == dki) - return GNUNET_NO; - /* FIXME: we had envisioned a more complex scheme... */ - GNUNET_CRYPTO_hash (&coin_public_info->coin_pub, - sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey), - &c_hash); - if (GNUNET_OK != - GNUNET_CRYPTO_rsa_verify (&c_hash, - coin_public_info->denom_sig, - dki->issue.denom_pub)) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "coin signature is invalid\n"); - return GNUNET_NO; - } - return GNUNET_YES; -} /** diff --git a/src/mint/taler-mint-httpd_refresh.c b/src/mint/taler-mint-httpd_refresh.c index 057414a8f..5983962f8 100644 --- a/src/mint/taler-mint-httpd_refresh.c +++ b/src/mint/taler-mint-httpd_refresh.c @@ -262,6 +262,7 @@ TALER_MINT_handler_refresh_melt (struct RequestHandler *rh, json_t *melt_sig_json; char *buf; size_t buf_size; + struct TALER_MINT_DenomKeyIssuePriv *dki; res = TALER_MINT_parse_post_json (connection, connection_cls, @@ -360,24 +361,39 @@ TALER_MINT_handler_refresh_melt (struct RequestHandler *rh, { GNUNET_break (GNUNET_SYSERR != res); // FIXME: leaks! + TALER_MINT_key_state_release (key_state); return res; } /* check that this coin's private key was used to sign that we should melt it */ - if (GNUNET_OK != (res = check_confirm_signature (connection, - json_array_get (melt_coins, i), - &coin_public_infos[i].coin_pub, - &refresh_session_pub))) - { - GNUNET_break (GNUNET_SYSERR != res); - // FIXME: leaks! - return res; - } + if (GNUNET_OK != + (res = check_confirm_signature (connection, + json_array_get (melt_coins, i), + &coin_public_infos[i].coin_pub, + &refresh_session_pub))) + { + GNUNET_break (GNUNET_SYSERR != res); + // FIXME: leaks! + TALER_MINT_key_state_release (key_state); + return res; + } + /* check coin denomination is valid */ + dki = TALER_MINT_get_denom_key (key_state, + coin_public_infos[i].denom_pub); + if (NULL == dki) + { + TALER_MINT_key_state_release (key_state); + LOG_WARNING ("Unknown denomination key in /refresh/melt request\n"); + TALER_MINT_key_state_release (key_state); + return TALER_MINT_reply_arg_invalid (connection, + "melt_coins"); + } /* check mint signature on the coin */ - if (GNUNET_OK != TALER_MINT_test_coin_valid (key_state, - &coin_public_infos[i])) + if (GNUNET_OK != + TALER_test_coin_valid (&coin_public_infos[i])) { // FIXME: leaks! + TALER_MINT_key_state_release (key_state); return (MHD_YES == TALER_MINT_reply_json_pack (connection, MHD_HTTP_NOT_FOUND, diff --git a/src/util/crypto.c b/src/util/crypto.c index 4e60d138a..8ce3ade2c 100644 --- a/src/util/crypto.c +++ b/src/util/crypto.c @@ -267,4 +267,35 @@ TALER_refresh_encrypt (const struct TALER_RefreshLinkDecrypted *input, } +/** + * Check if a coin is valid; that is, whether the denomination key exists, + * is not expired, and the signature is correct. + * + * @param coin_public_info the coin public info to check for validity + * @return #GNUNET_YES if the coin is valid, + * #GNUNET_NO if it is invalid + * #GNUNET_SYSERROR if an internal error occured + */ +int +TALER_test_coin_valid (const struct TALER_CoinPublicInfo *coin_public_info) +{ + struct GNUNET_HashCode c_hash; + + /* FIXME: we had envisioned a more complex scheme... */ + GNUNET_CRYPTO_hash (&coin_public_info->coin_pub, + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey), + &c_hash); + if (GNUNET_OK != + GNUNET_CRYPTO_rsa_verify (&c_hash, + coin_public_info->denom_sig, + coin_public_info->denom_pub)) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "coin signature is invalid\n"); + return GNUNET_NO; + } + return GNUNET_YES; +} + + /* end of crypto.c */