clean up refresh logic and use of signatures
This commit is contained in:
parent
e3b8f5117e
commit
7e26ae3858
@ -65,7 +65,7 @@
|
|||||||
* Signature where the refresh session confirms
|
* Signature where the refresh session confirms
|
||||||
* the commits.
|
* the commits.
|
||||||
*/
|
*/
|
||||||
#define TALER_SIGNATURE_REFRESH_MELT 6
|
#define TALER_SIGNATURE_REFRESH_MELT_SESSION 6
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Signature where the mint (current signing key)
|
* Signature where the mint (current signing key)
|
||||||
@ -221,7 +221,7 @@ struct TALER_DepositConfirmation
|
|||||||
struct GNUNET_CRYPTO_EcdsaPublicKey coin_pub;
|
struct GNUNET_CRYPTO_EcdsaPublicKey coin_pub;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Merachant's public key.
|
* The Merchant's public key.
|
||||||
*/
|
*/
|
||||||
struct GNUNET_CRYPTO_EddsaPublicKey merchant;
|
struct GNUNET_CRYPTO_EddsaPublicKey merchant;
|
||||||
|
|
||||||
@ -232,7 +232,7 @@ struct TALER_DepositConfirmation
|
|||||||
* Message signed by a coin to indicate that the coin should
|
* Message signed by a coin to indicate that the coin should
|
||||||
* be melted.
|
* be melted.
|
||||||
*/
|
*/
|
||||||
struct RefreshMeltSignatureBody
|
struct RefreshMeltCoinSignature
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Purpose is #TALER_SIGNATURE_REFRESH_MELT_COIN.
|
* Purpose is #TALER_SIGNATURE_REFRESH_MELT_COIN.
|
||||||
@ -245,11 +245,34 @@ struct RefreshMeltSignatureBody
|
|||||||
struct GNUNET_HashCode melt_hash;
|
struct GNUNET_HashCode melt_hash;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Signature of the client over the melt request (thereby
|
* How much of the value of the coin should be melted?
|
||||||
* indirectly including all of the information the client
|
* This amount includes the fees, so the final amount contributed
|
||||||
* sent).
|
* to the melt is this value minus the fee for melting the coin.
|
||||||
*/
|
*/
|
||||||
struct GNUNET_CRYPTO_EddsaSignature melt_client_signature;
|
struct TALER_AmountNBO amount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The coin's public key.
|
||||||
|
*/
|
||||||
|
struct GNUNET_CRYPTO_EcdsaPublicKey coin_pub;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Message signed by a coin to indicate that the coin should
|
||||||
|
* be melted.
|
||||||
|
*/
|
||||||
|
struct RefreshMeltSessionSignature
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Purpose is #TALER_SIGNATURE_REFRESH_MELT_SESSION
|
||||||
|
*/
|
||||||
|
struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Which melting operation should the coin become a part of.
|
||||||
|
*/
|
||||||
|
struct GNUNET_HashCode melt_hash;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Public key of the refresh session for which
|
* Public key of the refresh session for which
|
||||||
@ -258,32 +281,13 @@ struct RefreshMeltSignatureBody
|
|||||||
struct GNUNET_CRYPTO_EddsaPublicKey session_key;
|
struct GNUNET_CRYPTO_EddsaPublicKey session_key;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* How much of the value of the coin should be melted?
|
* What is the total value of the coins created during the
|
||||||
* This amount includes the fees, so the final amount contributed
|
* refresh, excluding fees?
|
||||||
* to the melt is this value minus the fee for melting the coin.
|
|
||||||
*/
|
*/
|
||||||
struct TALER_AmountNBO amount;
|
struct TALER_AmountNBO amount;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Message signed during melting committing the client to the
|
|
||||||
* hashed inputs.
|
|
||||||
*/
|
|
||||||
struct RefreshCommitSignatureBody
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Purpose is #TALER_SIGNATURE_REFRESH_MELT.
|
|
||||||
*/
|
|
||||||
struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Session state the client commits itself to.
|
|
||||||
*/
|
|
||||||
struct GNUNET_HashCode commit_hash;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Format of the block signed by the Mint in response to a successful
|
* Format of the block signed by the Mint in response to a successful
|
||||||
* "/refresh/melt" request. Hereby the mint affirms that all of the
|
* "/refresh/melt" request. Hereby the mint affirms that all of the
|
||||||
|
@ -35,109 +35,6 @@
|
|||||||
#include "taler-mint-httpd_keystate.h"
|
#include "taler-mint-httpd_keystate.h"
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Verify a signature that is encoded in a JSON object. Extracts
|
|
||||||
* the signature and its associated purpose and checks that it
|
|
||||||
* matches the specified @a purpose and @a pub public key. Any
|
|
||||||
* errors are reported via appropriate response messages.
|
|
||||||
*
|
|
||||||
* @param connection the connection to send errors to
|
|
||||||
* @param json_sig the JSON object with the signature
|
|
||||||
* @param the public key that the signature was created with
|
|
||||||
* @param purpose the signed message
|
|
||||||
* @return #GNUNET_YES if the signature was valid
|
|
||||||
* #GNUNET_NO if the signature was invalid
|
|
||||||
* #GNUNET_SYSERR on internal error
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
request_json_check_signature (struct MHD_Connection *connection,
|
|
||||||
const json_t *json_sig,
|
|
||||||
const struct GNUNET_CRYPTO_EddsaPublicKey *pub,
|
|
||||||
const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose)
|
|
||||||
{
|
|
||||||
struct GNUNET_CRYPTO_EddsaSignature signature;
|
|
||||||
int size;
|
|
||||||
uint32_t purpose_num;
|
|
||||||
int res;
|
|
||||||
json_t *el;
|
|
||||||
|
|
||||||
/* TODO: use specification array to simplify the parsing! */
|
|
||||||
res = GNUNET_MINT_parse_navigate_json (connection,
|
|
||||||
json_sig,
|
|
||||||
JNAV_FIELD,
|
|
||||||
"sig",
|
|
||||||
JNAV_RET_DATA,
|
|
||||||
&signature,
|
|
||||||
sizeof (struct GNUNET_CRYPTO_EddsaSignature));
|
|
||||||
|
|
||||||
if (GNUNET_OK != res)
|
|
||||||
return res;
|
|
||||||
|
|
||||||
res = GNUNET_MINT_parse_navigate_json (connection,
|
|
||||||
json_sig,
|
|
||||||
JNAV_FIELD,
|
|
||||||
"purpose",
|
|
||||||
JNAV_RET_TYPED_JSON,
|
|
||||||
JSON_INTEGER,
|
|
||||||
&el);
|
|
||||||
|
|
||||||
if (GNUNET_OK != res)
|
|
||||||
return res;
|
|
||||||
|
|
||||||
purpose_num = json_integer_value (el);
|
|
||||||
|
|
||||||
if (purpose_num != ntohl (purpose->purpose))
|
|
||||||
{
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
|
||||||
"signature invalid (purpose wrong)\n");
|
|
||||||
return TALER_MINT_reply_json_pack (connection,
|
|
||||||
MHD_HTTP_BAD_REQUEST,
|
|
||||||
"{s:s}",
|
|
||||||
"error", "signature invalid (purpose)");
|
|
||||||
}
|
|
||||||
|
|
||||||
res = GNUNET_MINT_parse_navigate_json (connection,
|
|
||||||
json_sig,
|
|
||||||
JNAV_FIELD, "size",
|
|
||||||
JNAV_RET_TYPED_JSON,
|
|
||||||
JSON_INTEGER,
|
|
||||||
&el);
|
|
||||||
|
|
||||||
if (GNUNET_OK != res)
|
|
||||||
return res;
|
|
||||||
|
|
||||||
size = json_integer_value (el);
|
|
||||||
|
|
||||||
if (size != ntohl (purpose->size))
|
|
||||||
{
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
|
||||||
"signature invalid (size wrong)\n");
|
|
||||||
return TALER_MINT_reply_json_pack (connection,
|
|
||||||
MHD_HTTP_BAD_REQUEST,
|
|
||||||
GNUNET_NO, GNUNET_SYSERR,
|
|
||||||
"{s:s}",
|
|
||||||
"error",
|
|
||||||
"signature invalid (size)");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (GNUNET_OK != GNUNET_CRYPTO_eddsa_verify (purpose_num,
|
|
||||||
purpose,
|
|
||||||
&signature,
|
|
||||||
pub))
|
|
||||||
{
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
|
||||||
"signature invalid (did not verify)\n");
|
|
||||||
return TALER_MINT_reply_json_pack (connection,
|
|
||||||
MHD_HTTP_UNAUTHORIZED,
|
|
||||||
"{s:s}",
|
|
||||||
"error",
|
|
||||||
"invalid signature (verification)");
|
|
||||||
}
|
|
||||||
|
|
||||||
return GNUNET_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle a "/refresh/melt" request after the main JSON parsing has happened.
|
* Handle a "/refresh/melt" request after the main JSON parsing has happened.
|
||||||
* We now need to validate the coins being melted and the session signature
|
* We now need to validate the coins being melted and the session signature
|
||||||
@ -150,7 +47,7 @@ request_json_check_signature (struct MHD_Connection *connection,
|
|||||||
* @param coin_count number of coins to be melted, size of y-dimension of @commit_coin array
|
* @param coin_count number of coins to be melted, size of y-dimension of @commit_coin array
|
||||||
* @param coin_public_infos array with @a coin_count entries about the coins
|
* @param coin_public_infos array with @a coin_count entries about the coins
|
||||||
* @param coin_melt_details array with @a coin_count entries with melting details
|
* @param coin_melt_details array with @a coin_count entries with melting details
|
||||||
* @param melt_sig_json signature affirming the overall melt operation
|
* @param commit_hash hash over the data that the client commits to
|
||||||
* @param commit_client_sig signature of the client over this commitment
|
* @param commit_client_sig signature of the client over this commitment
|
||||||
* @param kappa size of x-dimension of @commit_coin and @commit_link arrays
|
* @param kappa size of x-dimension of @commit_coin and @commit_link arrays
|
||||||
* @param commit_coin 2d array of coin commitments (what the mint is to sign
|
* @param commit_coin 2d array of coin commitments (what the mint is to sign
|
||||||
@ -168,18 +65,17 @@ handle_refresh_melt_binary (struct MHD_Connection *connection,
|
|||||||
unsigned int coin_count,
|
unsigned int coin_count,
|
||||||
struct TALER_CoinPublicInfo *coin_public_infos,
|
struct TALER_CoinPublicInfo *coin_public_infos,
|
||||||
const struct MeltDetails *coin_melt_details,
|
const struct MeltDetails *coin_melt_details,
|
||||||
const json_t *melt_sig_json,
|
const struct GNUNET_HashCode *commit_hash,
|
||||||
const struct GNUNET_CRYPTO_EddsaSignature *commit_client_sig,
|
const struct GNUNET_CRYPTO_EddsaSignature *commit_client_sig,
|
||||||
unsigned int kappa,
|
unsigned int kappa,
|
||||||
struct RefreshCommitCoin *const* commit_coin,
|
struct RefreshCommitCoin *const* commit_coin,
|
||||||
struct RefreshCommitLink *const* commit_link)
|
struct RefreshCommitLink *const* commit_link)
|
||||||
|
|
||||||
{
|
{
|
||||||
int res;
|
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
struct GNUNET_HashContext *hash_context;
|
struct GNUNET_HashContext *hash_context;
|
||||||
struct GNUNET_HashCode melt_hash;
|
struct GNUNET_HashCode melt_hash;
|
||||||
struct RefreshMeltSignatureBody body;
|
struct RefreshMeltSessionSignature body;
|
||||||
char *buf;
|
char *buf;
|
||||||
size_t buf_size;
|
size_t buf_size;
|
||||||
struct MintKeyState *key_state;
|
struct MintKeyState *key_state;
|
||||||
@ -207,18 +103,26 @@ handle_refresh_melt_binary (struct MHD_Connection *connection,
|
|||||||
sizeof (struct GNUNET_CRYPTO_EddsaPublicKey));
|
sizeof (struct GNUNET_CRYPTO_EddsaPublicKey));
|
||||||
GNUNET_CRYPTO_hash_context_finish (hash_context,
|
GNUNET_CRYPTO_hash_context_finish (hash_context,
|
||||||
&melt_hash);
|
&melt_hash);
|
||||||
|
// FIXME: what about the `commit_hash`?
|
||||||
|
|
||||||
body.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_MELT);
|
body.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_MELT_SESSION);
|
||||||
body.purpose.size = htonl (sizeof (struct RefreshMeltSignatureBody));
|
body.purpose.size = htonl (sizeof (struct RefreshMeltSessionSignature));
|
||||||
body.melt_hash = melt_hash;
|
body.melt_hash = melt_hash;
|
||||||
body.amount = TALER_amount_hton (coin_melt_details->melt_amount);
|
body.amount = TALER_amount_hton (coin_melt_details->melt_amount);
|
||||||
|
|
||||||
if (GNUNET_OK !=
|
if (GNUNET_OK != GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_REFRESH_MELT_SESSION,
|
||||||
(res = request_json_check_signature (connection,
|
&body.purpose,
|
||||||
melt_sig_json,
|
commit_client_sig,
|
||||||
refresh_session_pub,
|
refresh_session_pub))
|
||||||
&body.purpose)))
|
{
|
||||||
return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
|
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
||||||
|
"signature invalid (did not verify)\n");
|
||||||
|
return TALER_MINT_reply_json_pack (connection,
|
||||||
|
MHD_HTTP_UNAUTHORIZED,
|
||||||
|
"{s:s}",
|
||||||
|
"error",
|
||||||
|
"invalid signature (verification)");
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME: badness, use proper way to set to zero...
|
// FIXME: badness, use proper way to set to zero...
|
||||||
key_state = TALER_MINT_key_state_acquire ();
|
key_state = TALER_MINT_key_state_acquire ();
|
||||||
@ -276,15 +180,9 @@ handle_refresh_melt_binary (struct MHD_Connection *connection,
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract public coin information from a JSON object and verify
|
* Extract public coin information from a JSON object.
|
||||||
* that the signature shows that this coin is to be melted into
|
|
||||||
* the given @a session_pub melting session, and that this is
|
|
||||||
* a valid coin (we know the denomination key and the signature
|
|
||||||
* on it is valid). Essentially, this does all of the per-coin
|
|
||||||
* checks that can be done before the transaction starts.
|
|
||||||
*
|
*
|
||||||
* @param connection the connection to send error responses to
|
* @param connection the connection to send error responses to
|
||||||
* @param session_pub public key of the session the coin is melted into
|
|
||||||
* @param coin_info the JSON object to extract the coin info from
|
* @param coin_info the JSON object to extract the coin info from
|
||||||
* @param r_public_info[OUT] set to the coin's public information
|
* @param r_public_info[OUT] set to the coin's public information
|
||||||
* @param r_melt_detail[OUT] set to details about the coin's melting permission (if valid)
|
* @param r_melt_detail[OUT] set to details about the coin's melting permission (if valid)
|
||||||
@ -293,19 +191,15 @@ handle_refresh_melt_binary (struct MHD_Connection *connection,
|
|||||||
* #GNUNET_SYSERR on internal error
|
* #GNUNET_SYSERR on internal error
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
get_and_verify_coin_public_info (struct MHD_Connection *connection,
|
get_coin_public_info (struct MHD_Connection *connection,
|
||||||
const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub,
|
json_t *coin_info,
|
||||||
json_t *coin_info,
|
struct TALER_CoinPublicInfo *r_public_info,
|
||||||
struct TALER_CoinPublicInfo *r_public_info,
|
struct MeltDetails *r_melt_detail)
|
||||||
struct MeltDetails *r_melt_detail)
|
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
struct GNUNET_CRYPTO_EcdsaSignature melt_sig;
|
struct GNUNET_CRYPTO_EcdsaSignature melt_sig;
|
||||||
struct GNUNET_CRYPTO_rsa_Signature *sig;
|
struct GNUNET_CRYPTO_rsa_Signature *sig;
|
||||||
struct GNUNET_CRYPTO_rsa_PublicKey *pk;
|
struct GNUNET_CRYPTO_rsa_PublicKey *pk;
|
||||||
struct RefreshMeltConfirmSignRequestBody body;
|
|
||||||
struct MintKeyState *key_state;
|
|
||||||
struct TALER_MINT_DenomKeyIssuePriv *dki;
|
|
||||||
struct TALER_Amount amount;
|
struct TALER_Amount amount;
|
||||||
struct GNUNET_MINT_ParseFieldSpec spec[] = {
|
struct GNUNET_MINT_ParseFieldSpec spec[] = {
|
||||||
TALER_MINT_PARSE_FIXED ("coin_pub", &r_public_info->coin_pub),
|
TALER_MINT_PARSE_FIXED ("coin_pub", &r_public_info->coin_pub),
|
||||||
@ -316,6 +210,7 @@ get_and_verify_coin_public_info (struct MHD_Connection *connection,
|
|||||||
TALER_MINT_PARSE_END
|
TALER_MINT_PARSE_END
|
||||||
};
|
};
|
||||||
|
|
||||||
|
memset (&amount, 0, sizeof (amount)); // FIXME: #3636!
|
||||||
ret = TALER_MINT_parse_json_data (connection,
|
ret = TALER_MINT_parse_json_data (connection,
|
||||||
coin_info,
|
coin_info,
|
||||||
spec);
|
spec);
|
||||||
@ -323,38 +218,6 @@ get_and_verify_coin_public_info (struct MHD_Connection *connection,
|
|||||||
return ret;
|
return ret;
|
||||||
/* FIXME: include amount of coin value to be melted here (#3636!) and
|
/* FIXME: include amount of coin value to be melted here (#3636!) and
|
||||||
in what we return!? */
|
in what we return!? */
|
||||||
memset (&amount, 0, sizeof (amount)); // FIXME: #3636!
|
|
||||||
body.purpose.size = htonl (sizeof (struct RefreshMeltConfirmSignRequestBody));
|
|
||||||
body.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_MELT_CONFIRM);
|
|
||||||
body.session_pub = *session_pub;
|
|
||||||
if (GNUNET_OK !=
|
|
||||||
GNUNET_CRYPTO_ecdsa_verify (TALER_SIGNATURE_REFRESH_MELT_CONFIRM,
|
|
||||||
&body.purpose,
|
|
||||||
&melt_sig,
|
|
||||||
&r_public_info->coin_pub))
|
|
||||||
{
|
|
||||||
TALER_MINT_release_parsed_data (spec);
|
|
||||||
if (MHD_YES !=
|
|
||||||
TALER_MINT_reply_json_pack (connection,
|
|
||||||
MHD_HTTP_UNAUTHORIZED,
|
|
||||||
"{s:s}",
|
|
||||||
"error", "signature invalid"))
|
|
||||||
return GNUNET_SYSERR;
|
|
||||||
return GNUNET_NO;
|
|
||||||
}
|
|
||||||
key_state = TALER_MINT_key_state_acquire ();
|
|
||||||
dki = TALER_MINT_get_denom_key (key_state,
|
|
||||||
pk);
|
|
||||||
/* FIXME: need to check if denomination key is still
|
|
||||||
valid for issuing! (#3634) */
|
|
||||||
if (NULL == dki)
|
|
||||||
{
|
|
||||||
TALER_MINT_key_state_release (key_state);
|
|
||||||
LOG_WARNING ("Unknown denomination key in /refresh/melt request\n");
|
|
||||||
return TALER_MINT_reply_arg_invalid (connection,
|
|
||||||
"denom_pub");
|
|
||||||
}
|
|
||||||
TALER_MINT_key_state_release (key_state);
|
|
||||||
|
|
||||||
/* check mint signature on the coin */
|
/* check mint signature on the coin */
|
||||||
r_public_info->denom_sig = sig;
|
r_public_info->denom_sig = sig;
|
||||||
@ -374,6 +237,70 @@ get_and_verify_coin_public_info (struct MHD_Connection *connection,
|
|||||||
}
|
}
|
||||||
r_melt_detail->melt_sig = melt_sig;
|
r_melt_detail->melt_sig = melt_sig;
|
||||||
r_melt_detail->melt_amount = amount;
|
r_melt_detail->melt_amount = amount;
|
||||||
|
TALER_MINT_release_parsed_data (spec);
|
||||||
|
return GNUNET_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify that the signature shows that this coin is to be melted into
|
||||||
|
* the given @a session_pub melting session, and that this is a valid
|
||||||
|
* coin (we know the denomination key and the signature on it is
|
||||||
|
* valid). Essentially, this does all of the per-coin checks that can
|
||||||
|
* be done before the transaction starts.
|
||||||
|
*
|
||||||
|
* @param connection the connection to send error responses to
|
||||||
|
* @param melt_hash hash over refresh session the coin is melted into
|
||||||
|
* @param r_public_info the coin's public information
|
||||||
|
* @param r_melt_detail details about the coin's melting permission (if valid)
|
||||||
|
* @return #GNUNET_YES if coin public info in JSON was valid
|
||||||
|
* #GNUNET_NO JSON was invalid, response was generated
|
||||||
|
* #GNUNET_SYSERR on internal error
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
verify_coin_public_info (struct MHD_Connection *connection,
|
||||||
|
const struct GNUNET_HashCode *melt_hash,
|
||||||
|
const struct TALER_CoinPublicInfo *r_public_info,
|
||||||
|
const struct MeltDetails *r_melt_detail)
|
||||||
|
{
|
||||||
|
struct RefreshMeltCoinSignature body;
|
||||||
|
struct MintKeyState *key_state;
|
||||||
|
struct TALER_MINT_DenomKeyIssuePriv *dki;
|
||||||
|
|
||||||
|
/* FIXME: include amount of coin value to be melted here (#3636!) and
|
||||||
|
in what we return!? */
|
||||||
|
body.purpose.size = htonl (sizeof (struct RefreshMeltCoinSignature));
|
||||||
|
body.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_MELT_COIN);
|
||||||
|
body.melt_hash = *melt_hash;
|
||||||
|
body.amount = TALER_amount_hton (r_melt_detail->melt_amount);
|
||||||
|
body.coin_pub = r_public_info->coin_pub;
|
||||||
|
if (GNUNET_OK !=
|
||||||
|
GNUNET_CRYPTO_ecdsa_verify (TALER_SIGNATURE_REFRESH_MELT_COIN,
|
||||||
|
&body.purpose,
|
||||||
|
&r_melt_detail->melt_sig,
|
||||||
|
&r_public_info->coin_pub))
|
||||||
|
{
|
||||||
|
if (MHD_YES !=
|
||||||
|
TALER_MINT_reply_json_pack (connection,
|
||||||
|
MHD_HTTP_UNAUTHORIZED,
|
||||||
|
"{s:s}",
|
||||||
|
"error", "signature invalid"))
|
||||||
|
return GNUNET_SYSERR;
|
||||||
|
return GNUNET_NO;
|
||||||
|
}
|
||||||
|
key_state = TALER_MINT_key_state_acquire ();
|
||||||
|
dki = TALER_MINT_get_denom_key (key_state,
|
||||||
|
r_public_info->denom_pub);
|
||||||
|
/* FIXME: need to check if denomination key is still
|
||||||
|
valid for issuing! (#3634) */
|
||||||
|
if (NULL == dki)
|
||||||
|
{
|
||||||
|
TALER_MINT_key_state_release (key_state);
|
||||||
|
LOG_WARNING ("Unknown denomination key in /refresh/melt request\n");
|
||||||
|
return TALER_MINT_reply_arg_invalid (connection,
|
||||||
|
"denom_pub");
|
||||||
|
}
|
||||||
|
TALER_MINT_key_state_release (key_state);
|
||||||
return GNUNET_OK;
|
return GNUNET_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -478,9 +405,9 @@ handle_refresh_melt_json (struct MHD_Connection *connection,
|
|||||||
unsigned int coin_count;
|
unsigned int coin_count;
|
||||||
struct GNUNET_HashCode commit_hash;
|
struct GNUNET_HashCode commit_hash;
|
||||||
struct GNUNET_HashContext *hash_context;
|
struct GNUNET_HashContext *hash_context;
|
||||||
struct RefreshCommitSignatureBody body;
|
|
||||||
struct RefreshCommitCoin *commit_coin[kappa];
|
struct RefreshCommitCoin *commit_coin[kappa];
|
||||||
struct RefreshCommitLink *commit_link[kappa];
|
struct RefreshCommitLink *commit_link[kappa];
|
||||||
|
const struct GNUNET_CRYPTO_EddsaSignature commit_client_sig;
|
||||||
|
|
||||||
num_new_denoms = json_array_size (new_denoms);
|
num_new_denoms = json_array_size (new_denoms);
|
||||||
denom_pubs = GNUNET_malloc (num_new_denoms *
|
denom_pubs = GNUNET_malloc (num_new_denoms *
|
||||||
@ -509,11 +436,10 @@ handle_refresh_melt_json (struct MHD_Connection *connection,
|
|||||||
for (i=0;i<coin_count;i++)
|
for (i=0;i<coin_count;i++)
|
||||||
{
|
{
|
||||||
/* decode JSON data on coin to melt */
|
/* decode JSON data on coin to melt */
|
||||||
res = get_and_verify_coin_public_info (connection,
|
res = get_coin_public_info (connection,
|
||||||
refresh_session_pub,
|
json_array_get (melt_coins, i),
|
||||||
json_array_get (melt_coins, i),
|
&coin_public_infos[i],
|
||||||
&coin_public_infos[i],
|
&coin_melt_details[i]);
|
||||||
&coin_melt_details[i]);
|
|
||||||
if (GNUNET_OK != res)
|
if (GNUNET_OK != res)
|
||||||
{
|
{
|
||||||
for (j=0;j<i;j++)
|
for (j=0;j<i;j++)
|
||||||
@ -635,24 +561,34 @@ handle_refresh_melt_json (struct MHD_Connection *connection,
|
|||||||
}
|
}
|
||||||
GNUNET_CRYPTO_hash_context_finish (hash_context, &commit_hash);
|
GNUNET_CRYPTO_hash_context_finish (hash_context, &commit_hash);
|
||||||
|
|
||||||
/* verify commit signature */
|
|
||||||
body.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_MELT);
|
|
||||||
body.purpose.size = htonl (sizeof (struct RefreshCommitSignatureBody));
|
|
||||||
body.commit_hash = commit_hash;
|
|
||||||
|
|
||||||
if (GNUNET_OK !=
|
res = GNUNET_MINT_parse_navigate_json (connection,
|
||||||
(res = request_json_check_signature (connection,
|
commit_signature,
|
||||||
commit_signature,
|
JNAV_FIELD,
|
||||||
refresh_session_pub,
|
"sig",
|
||||||
&body.purpose)))
|
JNAV_RET_DATA,
|
||||||
|
&commit_client_sig,
|
||||||
|
sizeof (struct GNUNET_CRYPTO_EddsaSignature));
|
||||||
|
|
||||||
|
if (GNUNET_OK != res)
|
||||||
|
return (GNUNET_NO == res) ? MHD_YES : MHD_NO;
|
||||||
|
|
||||||
|
|
||||||
|
for (i=0;i<coin_count;i++)
|
||||||
{
|
{
|
||||||
free_commit_coins (commit_coin, kappa, num_newcoins);
|
/* verify signatures ons coin to melt */
|
||||||
free_commit_links (commit_link, kappa, num_oldcoins);
|
res = verify_coin_public_info (connection,
|
||||||
return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
|
&commit_hash,
|
||||||
|
&coin_public_infos[i],
|
||||||
|
&coin_melt_details[i]);
|
||||||
|
if (GNUNET_OK != res)
|
||||||
|
{
|
||||||
|
res = (GNUNET_NO == res) ? MHD_YES : MHD_NO;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* execute commit */
|
/* execute commit */
|
||||||
/* FIXME: we must also store the signature! (#3635) */
|
|
||||||
res = handle_refresh_melt_binary (connection,
|
res = handle_refresh_melt_binary (connection,
|
||||||
refresh_session_pub,
|
refresh_session_pub,
|
||||||
num_new_denoms,
|
num_new_denoms,
|
||||||
@ -660,11 +596,12 @@ handle_refresh_melt_json (struct MHD_Connection *connection,
|
|||||||
coin_count,
|
coin_count,
|
||||||
coin_public_infos,
|
coin_public_infos,
|
||||||
coin_melt_details,
|
coin_melt_details,
|
||||||
melt_sig_json,
|
&commit_hash,
|
||||||
NULL /* FIXME: 3635! */,
|
&commit_client_sig,
|
||||||
kappa,
|
kappa,
|
||||||
commit_coin,
|
commit_coin,
|
||||||
commit_link);
|
commit_link);
|
||||||
|
cleanup:
|
||||||
free_commit_coins (commit_coin, kappa, num_newcoins);
|
free_commit_coins (commit_coin, kappa, num_newcoins);
|
||||||
free_commit_links (commit_link, kappa, num_oldcoins);
|
free_commit_links (commit_link, kappa, num_oldcoins);
|
||||||
for (j=0;j<coin_count;j++)
|
for (j=0;j<coin_count;j++)
|
||||||
|
@ -355,15 +355,16 @@ compile_transaction_history (const struct TALER_MINT_DB_TransactionList *tl)
|
|||||||
}
|
}
|
||||||
case TALER_MINT_DB_TT_REFRESH_MELT:
|
case TALER_MINT_DB_TT_REFRESH_MELT:
|
||||||
{
|
{
|
||||||
struct RefreshMeltSignatureBody ms;
|
struct RefreshMeltCoinSignature ms;
|
||||||
const struct RefreshMelt *melt = pos->details.melt;
|
const struct RefreshMelt *melt = pos->details.melt;
|
||||||
|
|
||||||
type = "melt";
|
type = "melt";
|
||||||
value = melt->amount;
|
value = melt->amount;
|
||||||
ms.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_MELT);
|
ms.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_MELT_COIN);
|
||||||
ms.purpose.size = htonl (sizeof (struct RefreshMeltSignatureBody));
|
ms.purpose.size = htonl (sizeof (struct RefreshMeltCoinSignature));
|
||||||
ms.melt_hash = melt->melt_hash;
|
ms.melt_hash = melt->melt_hash;
|
||||||
ms.amount = TALER_amount_hton (melt->amount);
|
ms.amount = TALER_amount_hton (melt->amount);
|
||||||
|
ms.coin_pub = melt->coin.coin_pub;
|
||||||
transaction = TALER_JSON_from_ecdsa_sig (&ms.purpose,
|
transaction = TALER_JSON_from_ecdsa_sig (&ms.purpose,
|
||||||
&melt->coin_sig);
|
&melt->coin_sig);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user