move coin validity test to libtalerutil

This commit is contained in:
Christian Grothoff 2015-01-28 20:23:19 +01:00
parent 2debf6c3f0
commit 62d3d35250
6 changed files with 112 additions and 77 deletions

View File

@ -251,6 +251,47 @@ TALER_data_to_string_alloc (const void *buf,
size_t size); 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 ************* */ /* ****************** Refresh crypto primitives ************* */
/** /**

View File

@ -34,31 +34,6 @@
#define MINT_CURRENCY "EUR" #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 * Information we keep for a withdrawn coin to reproduce
@ -91,9 +66,6 @@ struct CollectableBlindcoin
}; };
/** /**
* Global information for a refreshing session. * Global information for a refreshing session.
*/ */

View File

@ -59,6 +59,7 @@ verify_and_execute_deposit (struct MHD_Connection *connection,
{ {
struct MintKeyState *key_state; struct MintKeyState *key_state;
struct TALER_DepositRequest dr; struct TALER_DepositRequest dr;
struct TALER_MINT_DenomKeyIssuePriv *dki;
dr.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_DEPOSIT); dr.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_DEPOSIT);
dr.purpose.size = htonl (sizeof (struct TALER_DepositRequest)); 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, return TALER_MINT_reply_arg_invalid (connection,
"csig"); "csig");
} }
/* check denomination exists and is valid */
key_state = TALER_MINT_key_state_acquire (); 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 != if (GNUNET_YES !=
TALER_MINT_test_coin_valid (key_state, TALER_test_coin_valid (&deposit->coin))
&deposit->coin))
{ {
LOG_WARNING ("Invalid coin passed for /deposit\n"); LOG_WARNING ("Invalid coin passed for /deposit\n");
TALER_MINT_key_state_release (key_state); TALER_MINT_key_state_release (key_state);

View File

@ -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;
}
/** /**

View File

@ -262,6 +262,7 @@ TALER_MINT_handler_refresh_melt (struct RequestHandler *rh,
json_t *melt_sig_json; json_t *melt_sig_json;
char *buf; char *buf;
size_t buf_size; size_t buf_size;
struct TALER_MINT_DenomKeyIssuePriv *dki;
res = TALER_MINT_parse_post_json (connection, res = TALER_MINT_parse_post_json (connection,
connection_cls, connection_cls,
@ -360,24 +361,39 @@ TALER_MINT_handler_refresh_melt (struct RequestHandler *rh,
{ {
GNUNET_break (GNUNET_SYSERR != res); GNUNET_break (GNUNET_SYSERR != res);
// FIXME: leaks! // FIXME: leaks!
TALER_MINT_key_state_release (key_state);
return res; return res;
} }
/* check that this coin's private key was used to sign that /* check that this coin's private key was used to sign that
we should melt it */ we should melt it */
if (GNUNET_OK != (res = check_confirm_signature (connection, if (GNUNET_OK !=
json_array_get (melt_coins, i), (res = check_confirm_signature (connection,
&coin_public_infos[i].coin_pub, json_array_get (melt_coins, i),
&refresh_session_pub))) &coin_public_infos[i].coin_pub,
{ &refresh_session_pub)))
GNUNET_break (GNUNET_SYSERR != res); {
// FIXME: leaks! GNUNET_break (GNUNET_SYSERR != res);
return 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 */ /* check mint signature on the coin */
if (GNUNET_OK != TALER_MINT_test_coin_valid (key_state, if (GNUNET_OK !=
&coin_public_infos[i])) TALER_test_coin_valid (&coin_public_infos[i]))
{ {
// FIXME: leaks! // FIXME: leaks!
TALER_MINT_key_state_release (key_state);
return (MHD_YES == return (MHD_YES ==
TALER_MINT_reply_json_pack (connection, TALER_MINT_reply_json_pack (connection,
MHD_HTTP_NOT_FOUND, MHD_HTTP_NOT_FOUND,

View File

@ -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 */ /* end of crypto.c */