diff options
author | Christian Grothoff <christian@grothoff.org> | 2015-03-10 17:00:12 +0100 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2015-03-10 17:00:12 +0100 |
commit | 7e26ae385896a974d8a90234a155c32b383e70f7 (patch) | |
tree | 1bbcf3e317744c9fa024bba5a6e46c84520dc9e5 | |
parent | e3b8f5117e8028f3183871ab0efb0c6f2ff959eb (diff) | |
download | exchange-7e26ae385896a974d8a90234a155c32b383e70f7.tar.gz exchange-7e26ae385896a974d8a90234a155c32b383e70f7.zip |
clean up refresh logic and use of signatures
-rw-r--r-- | src/include/taler_signatures.h | 48 | ||||
-rw-r--r-- | src/mint/taler-mint-httpd_refresh.c | 293 | ||||
-rw-r--r-- | src/mint/taler-mint-httpd_responses.c | 7 |
3 files changed, 145 insertions, 203 deletions
diff --git a/src/include/taler_signatures.h b/src/include/taler_signatures.h index 9e3068a78..b1b578236 100644 --- a/src/include/taler_signatures.h +++ b/src/include/taler_signatures.h | |||
@@ -65,7 +65,7 @@ | |||
65 | * Signature where the refresh session confirms | 65 | * Signature where the refresh session confirms |
66 | * the commits. | 66 | * the commits. |
67 | */ | 67 | */ |
68 | #define TALER_SIGNATURE_REFRESH_MELT 6 | 68 | #define TALER_SIGNATURE_REFRESH_MELT_SESSION 6 |
69 | 69 | ||
70 | /** | 70 | /** |
71 | * Signature where the mint (current signing key) | 71 | * Signature where the mint (current signing key) |
@@ -221,7 +221,7 @@ struct TALER_DepositConfirmation | |||
221 | struct GNUNET_CRYPTO_EcdsaPublicKey coin_pub; | 221 | struct GNUNET_CRYPTO_EcdsaPublicKey coin_pub; |
222 | 222 | ||
223 | /** | 223 | /** |
224 | * The Merachant's public key. | 224 | * The Merchant's public key. |
225 | */ | 225 | */ |
226 | struct GNUNET_CRYPTO_EddsaPublicKey merchant; | 226 | struct GNUNET_CRYPTO_EddsaPublicKey merchant; |
227 | 227 | ||
@@ -232,7 +232,7 @@ struct TALER_DepositConfirmation | |||
232 | * Message signed by a coin to indicate that the coin should | 232 | * Message signed by a coin to indicate that the coin should |
233 | * be melted. | 233 | * be melted. |
234 | */ | 234 | */ |
235 | struct RefreshMeltSignatureBody | 235 | struct RefreshMeltCoinSignature |
236 | { | 236 | { |
237 | /** | 237 | /** |
238 | * Purpose is #TALER_SIGNATURE_REFRESH_MELT_COIN. | 238 | * Purpose is #TALER_SIGNATURE_REFRESH_MELT_COIN. |
@@ -245,42 +245,46 @@ struct RefreshMeltSignatureBody | |||
245 | struct GNUNET_HashCode melt_hash; | 245 | struct GNUNET_HashCode melt_hash; |
246 | 246 | ||
247 | /** | 247 | /** |
248 | * Signature of the client over the melt request (thereby | ||
249 | * indirectly including all of the information the client | ||
250 | * sent). | ||
251 | */ | ||
252 | struct GNUNET_CRYPTO_EddsaSignature melt_client_signature; | ||
253 | |||
254 | /** | ||
255 | * Public key of the refresh session for which | ||
256 | * @e melt_client_signature must be a valid signature. | ||
257 | */ | ||
258 | struct GNUNET_CRYPTO_EddsaPublicKey session_key; | ||
259 | |||
260 | /** | ||
261 | * How much of the value of the coin should be melted? | 248 | * How much of the value of the coin should be melted? |
262 | * This amount includes the fees, so the final amount contributed | 249 | * This amount includes the fees, so the final amount contributed |
263 | * to the melt is this value minus the fee for melting the coin. | 250 | * to the melt is this value minus the fee for melting the coin. |
264 | */ | 251 | */ |
265 | struct TALER_AmountNBO amount; | 252 | struct TALER_AmountNBO amount; |
253 | |||
254 | /** | ||
255 | * The coin's public key. | ||
256 | */ | ||
257 | struct GNUNET_CRYPTO_EcdsaPublicKey coin_pub; | ||
266 | }; | 258 | }; |
267 | 259 | ||
268 | 260 | ||
269 | /** | 261 | /** |
270 | * Message signed during melting committing the client to the | 262 | * Message signed by a coin to indicate that the coin should |
271 | * hashed inputs. | 263 | * be melted. |
272 | */ | 264 | */ |
273 | struct RefreshCommitSignatureBody | 265 | struct RefreshMeltSessionSignature |
274 | { | 266 | { |
275 | /** | 267 | /** |
276 | * Purpose is #TALER_SIGNATURE_REFRESH_MELT. | 268 | * Purpose is #TALER_SIGNATURE_REFRESH_MELT_SESSION |
277 | */ | 269 | */ |
278 | struct GNUNET_CRYPTO_EccSignaturePurpose purpose; | 270 | struct GNUNET_CRYPTO_EccSignaturePurpose purpose; |
279 | 271 | ||
280 | /** | 272 | /** |
281 | * Session state the client commits itself to. | 273 | * Which melting operation should the coin become a part of. |
274 | */ | ||
275 | struct GNUNET_HashCode melt_hash; | ||
276 | |||
277 | /** | ||
278 | * Public key of the refresh session for which | ||
279 | * @e melt_client_signature must be a valid signature. | ||
282 | */ | 280 | */ |
283 | struct GNUNET_HashCode commit_hash; | 281 | struct GNUNET_CRYPTO_EddsaPublicKey session_key; |
282 | |||
283 | /** | ||
284 | * What is the total value of the coins created during the | ||
285 | * refresh, excluding fees? | ||
286 | */ | ||
287 | struct TALER_AmountNBO amount; | ||
284 | }; | 288 | }; |
285 | 289 | ||
286 | 290 | ||
diff --git a/src/mint/taler-mint-httpd_refresh.c b/src/mint/taler-mint-httpd_refresh.c index 6c3cbbc71..d36e42085 100644 --- a/src/mint/taler-mint-httpd_refresh.c +++ b/src/mint/taler-mint-httpd_refresh.c | |||
@@ -36,109 +36,6 @@ | |||
36 | 36 | ||
37 | 37 | ||
38 | /** | 38 | /** |
39 | * Verify a signature that is encoded in a JSON object. Extracts | ||
40 | * the signature and its associated purpose and checks that it | ||
41 | * matches the specified @a purpose and @a pub public key. Any | ||
42 | * errors are reported via appropriate response messages. | ||
43 | * | ||
44 | * @param connection the connection to send errors to | ||
45 | * @param json_sig the JSON object with the signature | ||
46 | * @param the public key that the signature was created with | ||
47 | * @param purpose the signed message | ||
48 | * @return #GNUNET_YES if the signature was valid | ||
49 | * #GNUNET_NO if the signature was invalid | ||
50 | * #GNUNET_SYSERR on internal error | ||
51 | */ | ||
52 | static int | ||
53 | request_json_check_signature (struct MHD_Connection *connection, | ||
54 | const json_t *json_sig, | ||
55 | const struct GNUNET_CRYPTO_EddsaPublicKey *pub, | ||
56 | const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose) | ||
57 | { | ||
58 | struct GNUNET_CRYPTO_EddsaSignature signature; | ||
59 | int size; | ||
60 | uint32_t purpose_num; | ||
61 | int res; | ||
62 | json_t *el; | ||
63 | |||
64 | /* TODO: use specification array to simplify the parsing! */ | ||
65 | res = GNUNET_MINT_parse_navigate_json (connection, | ||
66 | json_sig, | ||
67 | JNAV_FIELD, | ||
68 | "sig", | ||
69 | JNAV_RET_DATA, | ||
70 | &signature, | ||
71 | sizeof (struct GNUNET_CRYPTO_EddsaSignature)); | ||
72 | |||
73 | if (GNUNET_OK != res) | ||
74 | return res; | ||
75 | |||
76 | res = GNUNET_MINT_parse_navigate_json (connection, | ||
77 | json_sig, | ||
78 | JNAV_FIELD, | ||
79 | "purpose", | ||
80 | JNAV_RET_TYPED_JSON, | ||
81 | JSON_INTEGER, | ||
82 | &el); | ||
83 | |||
84 | if (GNUNET_OK != res) | ||
85 | return res; | ||
86 | |||
87 | purpose_num = json_integer_value (el); | ||
88 | |||
89 | if (purpose_num != ntohl (purpose->purpose)) | ||
90 | { | ||
91 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
92 | "signature invalid (purpose wrong)\n"); | ||
93 | return TALER_MINT_reply_json_pack (connection, | ||
94 | MHD_HTTP_BAD_REQUEST, | ||
95 | "{s:s}", | ||
96 | "error", "signature invalid (purpose)"); | ||
97 | } | ||
98 | |||
99 | res = GNUNET_MINT_parse_navigate_json (connection, | ||
100 | json_sig, | ||
101 | JNAV_FIELD, "size", | ||
102 | JNAV_RET_TYPED_JSON, | ||
103 | JSON_INTEGER, | ||
104 | &el); | ||
105 | |||
106 | if (GNUNET_OK != res) | ||
107 | return res; | ||
108 | |||
109 | size = json_integer_value (el); | ||
110 | |||
111 | if (size != ntohl (purpose->size)) | ||
112 | { | ||
113 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
114 | "signature invalid (size wrong)\n"); | ||
115 | return TALER_MINT_reply_json_pack (connection, | ||
116 | MHD_HTTP_BAD_REQUEST, | ||
117 | GNUNET_NO, GNUNET_SYSERR, | ||
118 | "{s:s}", | ||
119 | "error", | ||
120 | "signature invalid (size)"); | ||
121 | } | ||
122 | |||
123 | if (GNUNET_OK != GNUNET_CRYPTO_eddsa_verify (purpose_num, | ||
124 | purpose, | ||
125 | &signature, | ||
126 | pub)) | ||
127 | { | ||
128 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
129 | "signature invalid (did not verify)\n"); | ||
130 | return TALER_MINT_reply_json_pack (connection, | ||
131 | MHD_HTTP_UNAUTHORIZED, | ||
132 | "{s:s}", | ||
133 | "error", | ||
134 | "invalid signature (verification)"); | ||
135 | } | ||
136 | |||
137 | return GNUNET_OK; | ||
138 | } | ||
139 | |||
140 | |||
141 | /** | ||
142 | * Handle a "/refresh/melt" request after the main JSON parsing has happened. | 39 | * Handle a "/refresh/melt" request after the main JSON parsing has happened. |
143 | * We now need to validate the coins being melted and the session signature | 40 | * We now need to validate the coins being melted and the session signature |
144 | * and then hand things of to execute the melt operation. | 41 | * and then hand things of to execute the melt operation. |
@@ -150,7 +47,7 @@ request_json_check_signature (struct MHD_Connection *connection, | |||
150 | * @param coin_count number of coins to be melted, size of y-dimension of @commit_coin array | 47 | * @param coin_count number of coins to be melted, size of y-dimension of @commit_coin array |
151 | * @param coin_public_infos array with @a coin_count entries about the coins | 48 | * @param coin_public_infos array with @a coin_count entries about the coins |
152 | * @param coin_melt_details array with @a coin_count entries with melting details | 49 | * @param coin_melt_details array with @a coin_count entries with melting details |
153 | * @param melt_sig_json signature affirming the overall melt operation | 50 | * @param commit_hash hash over the data that the client commits to |
154 | * @param commit_client_sig signature of the client over this commitment | 51 | * @param commit_client_sig signature of the client over this commitment |
155 | * @param kappa size of x-dimension of @commit_coin and @commit_link arrays | 52 | * @param kappa size of x-dimension of @commit_coin and @commit_link arrays |
156 | * @param commit_coin 2d array of coin commitments (what the mint is to sign | 53 | * @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, | |||
168 | unsigned int coin_count, | 65 | unsigned int coin_count, |
169 | struct TALER_CoinPublicInfo *coin_public_infos, | 66 | struct TALER_CoinPublicInfo *coin_public_infos, |
170 | const struct MeltDetails *coin_melt_details, | 67 | const struct MeltDetails *coin_melt_details, |
171 | const json_t *melt_sig_json, | 68 | const struct GNUNET_HashCode *commit_hash, |
172 | const struct GNUNET_CRYPTO_EddsaSignature *commit_client_sig, | 69 | const struct GNUNET_CRYPTO_EddsaSignature *commit_client_sig, |
173 | unsigned int kappa, | 70 | unsigned int kappa, |
174 | struct RefreshCommitCoin *const* commit_coin, | 71 | struct RefreshCommitCoin *const* commit_coin, |
175 | struct RefreshCommitLink *const* commit_link) | 72 | struct RefreshCommitLink *const* commit_link) |
176 | 73 | ||
177 | { | 74 | { |
178 | int res; | ||
179 | unsigned int i; | 75 | unsigned int i; |
180 | struct GNUNET_HashContext *hash_context; | 76 | struct GNUNET_HashContext *hash_context; |
181 | struct GNUNET_HashCode melt_hash; | 77 | struct GNUNET_HashCode melt_hash; |
182 | struct RefreshMeltSignatureBody body; | 78 | struct RefreshMeltSessionSignature body; |
183 | char *buf; | 79 | char *buf; |
184 | size_t buf_size; | 80 | size_t buf_size; |
185 | struct MintKeyState *key_state; | 81 | struct MintKeyState *key_state; |
@@ -207,18 +103,26 @@ handle_refresh_melt_binary (struct MHD_Connection *connection, | |||
207 | sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)); | 103 | sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)); |
208 | GNUNET_CRYPTO_hash_context_finish (hash_context, | 104 | GNUNET_CRYPTO_hash_context_finish (hash_context, |
209 | &melt_hash); | 105 | &melt_hash); |
106 | // FIXME: what about the `commit_hash`? | ||
210 | 107 | ||
211 | body.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_MELT); | 108 | body.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_MELT_SESSION); |
212 | body.purpose.size = htonl (sizeof (struct RefreshMeltSignatureBody)); | 109 | body.purpose.size = htonl (sizeof (struct RefreshMeltSessionSignature)); |
213 | body.melt_hash = melt_hash; | 110 | body.melt_hash = melt_hash; |
214 | body.amount = TALER_amount_hton (coin_melt_details->melt_amount); | 111 | body.amount = TALER_amount_hton (coin_melt_details->melt_amount); |
215 | 112 | ||
216 | if (GNUNET_OK != | 113 | if (GNUNET_OK != GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_REFRESH_MELT_SESSION, |
217 | (res = request_json_check_signature (connection, | 114 | &body.purpose, |
218 | melt_sig_json, | 115 | commit_client_sig, |
219 | refresh_session_pub, | 116 | refresh_session_pub)) |
220 | &body.purpose))) | 117 | { |
221 | return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; | 118 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, |
119 | "signature invalid (did not verify)\n"); | ||
120 | return TALER_MINT_reply_json_pack (connection, | ||
121 | MHD_HTTP_UNAUTHORIZED, | ||
122 | "{s:s}", | ||
123 | "error", | ||
124 | "invalid signature (verification)"); | ||
125 | } | ||
222 | 126 | ||
223 | // FIXME: badness, use proper way to set to zero... | 127 | // FIXME: badness, use proper way to set to zero... |
224 | key_state = TALER_MINT_key_state_acquire (); | 128 | key_state = TALER_MINT_key_state_acquire (); |
@@ -276,15 +180,9 @@ handle_refresh_melt_binary (struct MHD_Connection *connection, | |||
276 | 180 | ||
277 | 181 | ||
278 | /** | 182 | /** |
279 | * Extract public coin information from a JSON object and verify | 183 | * Extract public coin information from a JSON object. |
280 | * that the signature shows that this coin is to be melted into | ||
281 | * the given @a session_pub melting session, and that this is | ||
282 | * a valid coin (we know the denomination key and the signature | ||
283 | * on it is valid). Essentially, this does all of the per-coin | ||
284 | * checks that can be done before the transaction starts. | ||
285 | * | 184 | * |
286 | * @param connection the connection to send error responses to | 185 | * @param connection the connection to send error responses to |
287 | * @param session_pub public key of the session the coin is melted into | ||
288 | * @param coin_info the JSON object to extract the coin info from | 186 | * @param coin_info the JSON object to extract the coin info from |
289 | * @param r_public_info[OUT] set to the coin's public information | 187 | * @param r_public_info[OUT] set to the coin's public information |
290 | * @param r_melt_detail[OUT] set to details about the coin's melting permission (if valid) | 188 | * @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, | |||
293 | * #GNUNET_SYSERR on internal error | 191 | * #GNUNET_SYSERR on internal error |
294 | */ | 192 | */ |
295 | static int | 193 | static int |
296 | get_and_verify_coin_public_info (struct MHD_Connection *connection, | 194 | get_coin_public_info (struct MHD_Connection *connection, |
297 | const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, | 195 | json_t *coin_info, |
298 | json_t *coin_info, | 196 | struct TALER_CoinPublicInfo *r_public_info, |
299 | struct TALER_CoinPublicInfo *r_public_info, | 197 | struct MeltDetails *r_melt_detail) |
300 | struct MeltDetails *r_melt_detail) | ||
301 | { | 198 | { |
302 | int ret; | 199 | int ret; |
303 | struct GNUNET_CRYPTO_EcdsaSignature melt_sig; | 200 | struct GNUNET_CRYPTO_EcdsaSignature melt_sig; |
304 | struct GNUNET_CRYPTO_rsa_Signature *sig; | 201 | struct GNUNET_CRYPTO_rsa_Signature *sig; |
305 | struct GNUNET_CRYPTO_rsa_PublicKey *pk; | 202 | struct GNUNET_CRYPTO_rsa_PublicKey *pk; |
306 | struct RefreshMeltConfirmSignRequestBody body; | ||
307 | struct MintKeyState *key_state; | ||
308 | struct TALER_MINT_DenomKeyIssuePriv *dki; | ||
309 | struct TALER_Amount amount; | 203 | struct TALER_Amount amount; |
310 | struct GNUNET_MINT_ParseFieldSpec spec[] = { | 204 | struct GNUNET_MINT_ParseFieldSpec spec[] = { |
311 | TALER_MINT_PARSE_FIXED ("coin_pub", &r_public_info->coin_pub), | 205 | 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, | |||
316 | TALER_MINT_PARSE_END | 210 | TALER_MINT_PARSE_END |
317 | }; | 211 | }; |
318 | 212 | ||
213 | memset (&amount, 0, sizeof (amount)); // FIXME: #3636! | ||
319 | ret = TALER_MINT_parse_json_data (connection, | 214 | ret = TALER_MINT_parse_json_data (connection, |
320 | coin_info, | 215 | coin_info, |
321 | spec); | 216 | spec); |
@@ -323,17 +218,68 @@ get_and_verify_coin_public_info (struct MHD_Connection *connection, | |||
323 | return ret; | 218 | return ret; |
324 | /* FIXME: include amount of coin value to be melted here (#3636!) and | 219 | /* FIXME: include amount of coin value to be melted here (#3636!) and |
325 | in what we return!? */ | 220 | in what we return!? */ |
326 | memset (&amount, 0, sizeof (amount)); // FIXME: #3636! | 221 | |
327 | body.purpose.size = htonl (sizeof (struct RefreshMeltConfirmSignRequestBody)); | 222 | /* check mint signature on the coin */ |
328 | body.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_MELT_CONFIRM); | 223 | r_public_info->denom_sig = sig; |
329 | body.session_pub = *session_pub; | 224 | r_public_info->denom_pub = pk; |
330 | if (GNUNET_OK != | 225 | if (GNUNET_OK != |
331 | GNUNET_CRYPTO_ecdsa_verify (TALER_SIGNATURE_REFRESH_MELT_CONFIRM, | 226 | TALER_test_coin_valid (r_public_info)) |
227 | { | ||
228 | TALER_MINT_release_parsed_data (spec); | ||
229 | r_public_info->denom_sig = NULL; | ||
230 | r_public_info->denom_pub = NULL; | ||
231 | return (MHD_YES == | ||
232 | TALER_MINT_reply_json_pack (connection, | ||
233 | MHD_HTTP_NOT_FOUND, | ||
234 | "{s:s}", | ||
235 | "error", "coin invalid")) | ||
236 | ? GNUNET_NO : GNUNET_SYSERR; | ||
237 | } | ||
238 | r_melt_detail->melt_sig = melt_sig; | ||
239 | r_melt_detail->melt_amount = amount; | ||
240 | TALER_MINT_release_parsed_data (spec); | ||
241 | return GNUNET_OK; | ||
242 | } | ||
243 | |||
244 | |||
245 | /** | ||
246 | * Verify that the signature shows that this coin is to be melted into | ||
247 | * the given @a session_pub melting session, and that this is a valid | ||
248 | * coin (we know the denomination key and the signature on it is | ||
249 | * valid). Essentially, this does all of the per-coin checks that can | ||
250 | * be done before the transaction starts. | ||
251 | * | ||
252 | * @param connection the connection to send error responses to | ||
253 | * @param melt_hash hash over refresh session the coin is melted into | ||
254 | * @param r_public_info the coin's public information | ||
255 | * @param r_melt_detail details about the coin's melting permission (if valid) | ||
256 | * @return #GNUNET_YES if coin public info in JSON was valid | ||
257 | * #GNUNET_NO JSON was invalid, response was generated | ||
258 | * #GNUNET_SYSERR on internal error | ||
259 | */ | ||
260 | static int | ||
261 | verify_coin_public_info (struct MHD_Connection *connection, | ||
262 | const struct GNUNET_HashCode *melt_hash, | ||
263 | const struct TALER_CoinPublicInfo *r_public_info, | ||
264 | const struct MeltDetails *r_melt_detail) | ||
265 | { | ||
266 | struct RefreshMeltCoinSignature body; | ||
267 | struct MintKeyState *key_state; | ||
268 | struct TALER_MINT_DenomKeyIssuePriv *dki; | ||
269 | |||
270 | /* FIXME: include amount of coin value to be melted here (#3636!) and | ||
271 | in what we return!? */ | ||
272 | body.purpose.size = htonl (sizeof (struct RefreshMeltCoinSignature)); | ||
273 | body.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_MELT_COIN); | ||
274 | body.melt_hash = *melt_hash; | ||
275 | body.amount = TALER_amount_hton (r_melt_detail->melt_amount); | ||
276 | body.coin_pub = r_public_info->coin_pub; | ||
277 | if (GNUNET_OK != | ||
278 | GNUNET_CRYPTO_ecdsa_verify (TALER_SIGNATURE_REFRESH_MELT_COIN, | ||
332 | &body.purpose, | 279 | &body.purpose, |
333 | &melt_sig, | 280 | &r_melt_detail->melt_sig, |
334 | &r_public_info->coin_pub)) | 281 | &r_public_info->coin_pub)) |
335 | { | 282 | { |
336 | TALER_MINT_release_parsed_data (spec); | ||
337 | if (MHD_YES != | 283 | if (MHD_YES != |
338 | TALER_MINT_reply_json_pack (connection, | 284 | TALER_MINT_reply_json_pack (connection, |
339 | MHD_HTTP_UNAUTHORIZED, | 285 | MHD_HTTP_UNAUTHORIZED, |
@@ -344,7 +290,7 @@ get_and_verify_coin_public_info (struct MHD_Connection *connection, | |||
344 | } | 290 | } |
345 | key_state = TALER_MINT_key_state_acquire (); | 291 | key_state = TALER_MINT_key_state_acquire (); |
346 | dki = TALER_MINT_get_denom_key (key_state, | 292 | dki = TALER_MINT_get_denom_key (key_state, |
347 | pk); | 293 | r_public_info->denom_pub); |
348 | /* FIXME: need to check if denomination key is still | 294 | /* FIXME: need to check if denomination key is still |
349 | valid for issuing! (#3634) */ | 295 | valid for issuing! (#3634) */ |
350 | if (NULL == dki) | 296 | if (NULL == dki) |
@@ -355,25 +301,6 @@ get_and_verify_coin_public_info (struct MHD_Connection *connection, | |||
355 | "denom_pub"); | 301 | "denom_pub"); |
356 | } | 302 | } |
357 | TALER_MINT_key_state_release (key_state); | 303 | TALER_MINT_key_state_release (key_state); |
358 | |||
359 | /* check mint signature on the coin */ | ||
360 | r_public_info->denom_sig = sig; | ||
361 | r_public_info->denom_pub = pk; | ||
362 | if (GNUNET_OK != | ||
363 | TALER_test_coin_valid (r_public_info)) | ||
364 | { | ||
365 | TALER_MINT_release_parsed_data (spec); | ||
366 | r_public_info->denom_sig = NULL; | ||
367 | r_public_info->denom_pub = NULL; | ||
368 | return (MHD_YES == | ||
369 | TALER_MINT_reply_json_pack (connection, | ||
370 | MHD_HTTP_NOT_FOUND, | ||
371 | "{s:s}", | ||
372 | "error", "coin invalid")) | ||
373 | ? GNUNET_NO : GNUNET_SYSERR; | ||
374 | } | ||
375 | r_melt_detail->melt_sig = melt_sig; | ||
376 | r_melt_detail->melt_amount = amount; | ||
377 | return GNUNET_OK; | 304 | return GNUNET_OK; |
378 | } | 305 | } |
379 | 306 | ||
@@ -478,9 +405,9 @@ handle_refresh_melt_json (struct MHD_Connection *connection, | |||
478 | unsigned int coin_count; | 405 | unsigned int coin_count; |
479 | struct GNUNET_HashCode commit_hash; | 406 | struct GNUNET_HashCode commit_hash; |
480 | struct GNUNET_HashContext *hash_context; | 407 | struct GNUNET_HashContext *hash_context; |
481 | struct RefreshCommitSignatureBody body; | ||
482 | struct RefreshCommitCoin *commit_coin[kappa]; | 408 | struct RefreshCommitCoin *commit_coin[kappa]; |
483 | struct RefreshCommitLink *commit_link[kappa]; | 409 | struct RefreshCommitLink *commit_link[kappa]; |
410 | const struct GNUNET_CRYPTO_EddsaSignature commit_client_sig; | ||
484 | 411 | ||
485 | num_new_denoms = json_array_size (new_denoms); | 412 | num_new_denoms = json_array_size (new_denoms); |
486 | denom_pubs = GNUNET_malloc (num_new_denoms * | 413 | denom_pubs = GNUNET_malloc (num_new_denoms * |
@@ -509,11 +436,10 @@ handle_refresh_melt_json (struct MHD_Connection *connection, | |||
509 | for (i=0;i<coin_count;i++) | 436 | for (i=0;i<coin_count;i++) |
510 | { | 437 | { |
511 | /* decode JSON data on coin to melt */ | 438 | /* decode JSON data on coin to melt */ |
512 | res = get_and_verify_coin_public_info (connection, | 439 | res = get_coin_public_info (connection, |
513 | refresh_session_pub, | 440 | json_array_get (melt_coins, i), |
514 | json_array_get (melt_coins, i), | 441 | &coin_public_infos[i], |
515 | &coin_public_infos[i], | 442 | &coin_melt_details[i]); |
516 | &coin_melt_details[i]); | ||
517 | if (GNUNET_OK != res) | 443 | if (GNUNET_OK != res) |
518 | { | 444 | { |
519 | for (j=0;j<i;j++) | 445 | for (j=0;j<i;j++) |
@@ -635,24 +561,34 @@ handle_refresh_melt_json (struct MHD_Connection *connection, | |||
635 | } | 561 | } |
636 | GNUNET_CRYPTO_hash_context_finish (hash_context, &commit_hash); | 562 | GNUNET_CRYPTO_hash_context_finish (hash_context, &commit_hash); |
637 | 563 | ||
638 | /* verify commit signature */ | ||
639 | body.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_MELT); | ||
640 | body.purpose.size = htonl (sizeof (struct RefreshCommitSignatureBody)); | ||
641 | body.commit_hash = commit_hash; | ||
642 | 564 | ||
643 | if (GNUNET_OK != | 565 | res = GNUNET_MINT_parse_navigate_json (connection, |
644 | (res = request_json_check_signature (connection, | 566 | commit_signature, |
645 | commit_signature, | 567 | JNAV_FIELD, |
646 | refresh_session_pub, | 568 | "sig", |
647 | &body.purpose))) | 569 | JNAV_RET_DATA, |
570 | &commit_client_sig, | ||
571 | sizeof (struct GNUNET_CRYPTO_EddsaSignature)); | ||
572 | |||
573 | if (GNUNET_OK != res) | ||
574 | return (GNUNET_NO == res) ? MHD_YES : MHD_NO; | ||
575 | |||
576 | |||
577 | for (i=0;i<coin_count;i++) | ||
648 | { | 578 | { |
649 | free_commit_coins (commit_coin, kappa, num_newcoins); | 579 | /* verify signatures ons coin to melt */ |
650 | free_commit_links (commit_link, kappa, num_oldcoins); | 580 | res = verify_coin_public_info (connection, |
651 | return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; | 581 | &commit_hash, |
582 | &coin_public_infos[i], | ||
583 | &coin_melt_details[i]); | ||
584 | if (GNUNET_OK != res) | ||
585 | { | ||
586 | res = (GNUNET_NO == res) ? MHD_YES : MHD_NO; | ||
587 | goto cleanup; | ||
588 | } | ||
652 | } | 589 | } |
653 | 590 | ||
654 | /* execute commit */ | 591 | /* execute commit */ |
655 | /* FIXME: we must also store the signature! (#3635) */ | ||
656 | res = handle_refresh_melt_binary (connection, | 592 | res = handle_refresh_melt_binary (connection, |
657 | refresh_session_pub, | 593 | refresh_session_pub, |
658 | num_new_denoms, | 594 | num_new_denoms, |
@@ -660,11 +596,12 @@ handle_refresh_melt_json (struct MHD_Connection *connection, | |||
660 | coin_count, | 596 | coin_count, |
661 | coin_public_infos, | 597 | coin_public_infos, |
662 | coin_melt_details, | 598 | coin_melt_details, |
663 | melt_sig_json, | 599 | &commit_hash, |
664 | NULL /* FIXME: 3635! */, | 600 | &commit_client_sig, |
665 | kappa, | 601 | kappa, |
666 | commit_coin, | 602 | commit_coin, |
667 | commit_link); | 603 | commit_link); |
604 | cleanup: | ||
668 | free_commit_coins (commit_coin, kappa, num_newcoins); | 605 | free_commit_coins (commit_coin, kappa, num_newcoins); |
669 | free_commit_links (commit_link, kappa, num_oldcoins); | 606 | free_commit_links (commit_link, kappa, num_oldcoins); |
670 | for (j=0;j<coin_count;j++) | 607 | for (j=0;j<coin_count;j++) |
diff --git a/src/mint/taler-mint-httpd_responses.c b/src/mint/taler-mint-httpd_responses.c index 83c81e800..2faeb5ca8 100644 --- a/src/mint/taler-mint-httpd_responses.c +++ b/src/mint/taler-mint-httpd_responses.c | |||
@@ -355,15 +355,16 @@ compile_transaction_history (const struct TALER_MINT_DB_TransactionList *tl) | |||
355 | } | 355 | } |
356 | case TALER_MINT_DB_TT_REFRESH_MELT: | 356 | case TALER_MINT_DB_TT_REFRESH_MELT: |
357 | { | 357 | { |
358 | struct RefreshMeltSignatureBody ms; | 358 | struct RefreshMeltCoinSignature ms; |
359 | const struct RefreshMelt *melt = pos->details.melt; | 359 | const struct RefreshMelt *melt = pos->details.melt; |
360 | 360 | ||
361 | type = "melt"; | 361 | type = "melt"; |
362 | value = melt->amount; | 362 | value = melt->amount; |
363 | ms.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_MELT); | 363 | ms.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_MELT_COIN); |
364 | ms.purpose.size = htonl (sizeof (struct RefreshMeltSignatureBody)); | 364 | ms.purpose.size = htonl (sizeof (struct RefreshMeltCoinSignature)); |
365 | ms.melt_hash = melt->melt_hash; | 365 | ms.melt_hash = melt->melt_hash; |
366 | ms.amount = TALER_amount_hton (melt->amount); | 366 | ms.amount = TALER_amount_hton (melt->amount); |
367 | ms.coin_pub = melt->coin.coin_pub; | ||
367 | transaction = TALER_JSON_from_ecdsa_sig (&ms.purpose, | 368 | transaction = TALER_JSON_from_ecdsa_sig (&ms.purpose, |
368 | &melt->coin_sig); | 369 | &melt->coin_sig); |
369 | } | 370 | } |