diff --git a/src/mint-lib/mint_api_deposit.c b/src/mint-lib/mint_api_deposit.c index c404676a5..c78680756 100644 --- a/src/mint-lib/mint_api_deposit.c +++ b/src/mint-lib/mint_api_deposit.c @@ -92,6 +92,16 @@ struct TALER_MINT_DepositHandle */ struct TALER_DepositConfirmationPS depconf; + /** + * Value of the /deposit transaction, including fee. + */ + struct TALER_Amount amount_with_fee; + + /** + * Total value of the coin being transacted with. + */ + struct TALER_Amount coin_value; + /** * The size of the download buffer */ @@ -160,19 +170,95 @@ static int verify_deposit_signature_forbidden (const struct TALER_MINT_DepositHandle *dh, json_t *json) { - struct MAJ_Specification spec[] = { - MAJ_spec_end - }; + json_t *history; + size_t len; + size_t off; + struct TALER_Amount total; - if (GNUNET_OK != - MAJ_parse_json (json, - spec)) + history = json_object_get (json, + "history"); + if (NULL == history) { GNUNET_break_op (0); return GNUNET_SYSERR; } + len = json_array_size (history); + if (0 == len) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + TALER_amount_get_zero (dh->coin_value.currency, + &total); + for (off=0;offdepconf.coin_pub.eddsa_pub), + MAJ_spec_end + }; - GNUNET_break (0); // not implemented + transaction = json_array_get (history, + off); + if (GNUNET_OK != + MAJ_parse_json (transaction, + spec)) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + switch (purpose->purpose) + { + case TALER_SIGNATURE_WALLET_COIN_DEPOSIT: + GNUNET_break (0); + /* FIXME: check amount! #3516 */ + break; + case TALER_SIGNATURE_WALLET_COIN_MELT: + GNUNET_break (0); + /* FIXME: check amount! #3516 */ + break; + default: + /* signature not supported, new version on server? */ + GNUNET_break (0); + MAJ_parse_free (spec); + return GNUNET_SYSERR; + } + if (GNUNET_OK != + TALER_amount_add (&total, + &total, + &amount)) + { + /* overflow in history already!? inconceivable! */ + GNUNET_break_op (0); + MAJ_parse_free (spec); + return GNUNET_SYSERR; + } + MAJ_parse_free (spec); + } + if (GNUNET_OK != + TALER_amount_add (&total, + &total, + &dh->amount_with_fee)) + { + /* clearly not OK if our transaction would have caused + the overflow... */ + return GNUNET_OK; + } + + if (0 >= TALER_amount_cmp (&total, + &dh->coin_value)) + { + /* transaction should have still fit */ + GNUNET_break (0); + return GNUNET_SYSERR; + } + /* everything OK, proof of double-spending was provided */ return GNUNET_OK; } @@ -530,7 +616,8 @@ TALER_MINT_deposit (struct TALER_MINT_Handle *mint, &amount_without_fee); dh->depconf.coin_pub = *coin_pub; dh->depconf.merchant = *merchant_pub; - + dh->amount_with_fee = *amount; + dh->coin_value = dki->value; eh = curl_easy_init (); GNUNET_assert (NULL != (dh->json_enc = diff --git a/src/mint-lib/mint_api_json.c b/src/mint-lib/mint_api_json.c index b702ba0d9..81511c1c0 100644 --- a/src/mint-lib/mint_api_json.c +++ b/src/mint-lib/mint_api_json.c @@ -200,6 +200,17 @@ parse_json (json_t *root, } break; + case MAJ_CMD_EDDSA_SIGNATURE: + { + /* FIXME: parse the JSON signature + and the purpose, then check that the + signature is valid and the size field + is also correct; if all checks out, + return the purpose */ + GNUNET_break (0); // FIXME: implement! #3516 + } + break; + default: GNUNET_break (0); return i; @@ -248,6 +259,9 @@ parse_free (struct MAJ_Specification *spec, GNUNET_CRYPTO_rsa_signature_free (*spec[i].details.rsa_signature); *spec[i].details.rsa_signature = NULL; break; + case MAJ_CMD_EDDSA_SIGNATURE: + GNUNET_free (*spec[i].details.eddsa_signature.purpose_p); + *spec[i].details.eddsa_signature.purpose_p = NULL; default: GNUNET_break (0); break; @@ -378,4 +392,28 @@ MAJ_spec_rsa_signature (const char *name, } +/** + * Specification for parsing an EdDSA object signature with purpose. + * Also validates the signature (!). + * + * @param name name of the JSON field + * @param purpose_p where to store the purpose + * @param pub_key public key to use for validation + */ +struct MAJ_Specification +MAJ_spec_eddsa_signed_purpose (const char *name, + struct GNUNET_CRYPTO_EccSignaturePurpose **purpose_p, + const struct GNUNET_CRYPTO_EddsaPublicKey *pub_key) +{ + struct MAJ_Specification ret = + { + .cmd = MAJ_CMD_EDDSA_SIGNATURE, + .field = name, + .details.eddsa_signature.purpose_p = purpose_p, + .details.eddsa_signature.pub_key = pub_key + }; + return ret; +} + + /* end of mint_api_json.c */ diff --git a/src/mint-lib/mint_api_json.h b/src/mint-lib/mint_api_json.h index 78107ed9e..91679831d 100644 --- a/src/mint-lib/mint_api_json.h +++ b/src/mint-lib/mint_api_json.h @@ -69,9 +69,9 @@ enum MAJ_Command MAJ_CMD_RSA_SIGNATURE, /** - * Parse at current position. + * Parse object with EdDSA signature and purpose at current position. */ - MAJ_CMD_A, + MAJ_CMD_EDDSA_SIGNATURE, /** * Parse at current position. @@ -159,6 +159,23 @@ struct MAJ_Specification */ struct GNUNET_CRYPTO_rsa_Signature **rsa_signature; + /** + * Details for #MAJ_CMD_EDDSA_SIGNATURE + */ + struct { + + /** + * Where to store the purpose. + */ + struct GNUNET_CRYPTO_EccSignaturePurpose **purpose_p; + + /** + * Key to verify the signature against. + */ + const struct GNUNET_CRYPTO_EddsaPublicKey *pub_key; + + } eddsa_signature; + } details; }; @@ -223,6 +240,20 @@ MAJ_spec_amount (const char *name, struct TALER_Amount *amount); +/** + * Specification for parsing an EdDSA object signature with purpose. + * Also validates the signature (!). + * + * @param name name of the JSON field + * @param purpose_p where to store the purpose + * @param pub_key public key to use for validation + */ +struct MAJ_Specification +MAJ_spec_eddsa_signed_purpose (const char *name, + struct GNUNET_CRYPTO_EccSignaturePurpose **purpose_p, + const struct GNUNET_CRYPTO_EddsaPublicKey *pub_key); + + /** * Specification for parsing an RSA public key. *