diff options
author | Christian Grothoff <christian@grothoff.org> | 2015-08-08 22:11:58 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2015-08-08 22:11:58 +0200 |
commit | 6b048a0dc60f3c50f3fd3d6bed09dcf0d1f5a547 (patch) | |
tree | 221ff1aea4bff062e85105a1acf1d9fb02d54271 /src/mint-lib | |
parent | 1e8529a19ed41d4ea8c92ab855d6b24a9f7b9899 (diff) |
implement handle_refresh_reveal_finished (200 OK handler)
Diffstat (limited to 'src/mint-lib')
-rw-r--r-- | src/mint-lib/mint_api_refresh.c | 131 |
1 files changed, 129 insertions, 2 deletions
diff --git a/src/mint-lib/mint_api_refresh.c b/src/mint-lib/mint_api_refresh.c index 51571009f..00f2a825a 100644 --- a/src/mint-lib/mint_api_refresh.c +++ b/src/mint-lib/mint_api_refresh.c @@ -869,6 +869,7 @@ TALER_MINT_refresh_prepare (unsigned int num_melts, unsigned int j; struct GNUNET_HashContext *hash_context; + /* build up melt data structure */ for (i=0;i<TALER_CNC_KAPPA;i++) GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG, &md.link_secrets[i], @@ -1660,10 +1661,108 @@ struct TALER_MINT_RefreshRevealHandle */ struct MeltData *md; + /** + * The index selected by the mint in cut-and-choose to not be revealed. + */ + uint16_t noreveal_index; + }; /** + * We got a 200 OK response for the /refresh/reveal operation. + * Extract the coin signatures and return them to the caller. + * The signatures we get from the mint is for the blinded value. + * Thus, we first must unblind them and then should verify their + * validity. + * + * If everything checks out, we return the unblinded signatures + * to the application via the callback. + * + * @param rrh operation handle + * @param jsona reply from the mint + * @param[out] coin_privs array of length `num_fresh_coins`, initialized to contain private keys + * @param[out] sigs array of length `num_fresh_coins`, initialized to cointain RSA signatures + * @return #GNUNET_OK on success, #GNUNET_SYSERR on errors + */ +static int +refresh_reveal_ok (struct TALER_MINT_RefreshRevealHandle *rrh, + json_t *jsona, + struct TALER_CoinSpendPrivateKeyP *coin_privs, + struct TALER_DenominationSignature *sigs) +{ + unsigned int i; + + if (! json_is_array (jsona)) + { + /* We expected an array of coins */ + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + if (rrh->md->num_fresh_coins != json_array_size (jsona)) + { + /* Number of coins generated does not match our expectation */ + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + for (i=0;i<rrh->md->num_fresh_coins;i++) + { + const struct FreshCoin *fc; + struct TALER_DenominationPublicKey *pk; + json_t *json; + struct GNUNET_CRYPTO_rsa_Signature *blind_sig; + struct GNUNET_CRYPTO_rsa_Signature *sig; + struct TALER_CoinSpendPublicKeyP coin_pub; + struct GNUNET_HashCode coin_hash; + + struct MAJ_Specification spec[] = { + MAJ_spec_rsa_signature ("ev_sig", &blind_sig), + MAJ_spec_end + }; + + fc = &rrh->md->fresh_coins[rrh->noreveal_index][i]; + pk = &rrh->md->fresh_pks[i]; + json = json_array_get (jsona, i); + GNUNET_assert (NULL != json); + + if (GNUNET_OK != + MAJ_parse_json (json, + spec)) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + + /* unblind the signature */ + sig = GNUNET_CRYPTO_rsa_unblind (blind_sig, + fc->blinding_key.rsa_blinding_key, + pk->rsa_public_key); + GNUNET_CRYPTO_rsa_signature_free (blind_sig); + + /* verify the signature */ + GNUNET_CRYPTO_eddsa_key_get_public (&fc->coin_priv.eddsa_priv, + &coin_pub.eddsa_pub); + GNUNET_CRYPTO_hash (&coin_pub.eddsa_pub, + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey), + &coin_hash); + + if (GNUNET_OK != + GNUNET_CRYPTO_rsa_verify (&coin_hash, + sig, + pk->rsa_public_key)) + { + GNUNET_break_op (0); + GNUNET_CRYPTO_rsa_signature_free (sig); + return GNUNET_SYSERR; + } + coin_privs[i] = fc->coin_priv; + sigs[i].rsa_signature = sig; + } + return GNUNET_OK; +} + + +/** * Function called when we're done processing the * HTTP /refresh/reveal request. * @@ -1687,8 +1786,35 @@ handle_refresh_reveal_finished (void *cls, case 0: break; case MHD_HTTP_OK: - GNUNET_break (0); // FIXME: NOT implemented! - // rrh->reveal_cb = NULL; (call with real result, do not call again below) + { + struct TALER_CoinSpendPrivateKeyP coin_privs[rrh->md->num_fresh_coins]; + struct TALER_DenominationSignature sigs[rrh->md->num_fresh_coins]; + unsigned int i; + int ret; + + memset (sigs, 0, sizeof (sigs)); + ret = refresh_reveal_ok (rrh, + json, + coin_privs, + sigs); + if (GNUNET_OK != ret) + { + response_code = 0; + } + else + { + rrh->reveal_cb (rrh->reveal_cb_cls, + MHD_HTTP_OK, + rrh->md->num_fresh_coins, + coin_privs, + sigs, + json); + rrh->reveal_cb = NULL; + } + for (i=0;i<rrh->md->num_fresh_coins;i++) + if (NULL != sigs[i].rsa_signature) + GNUNET_CRYPTO_rsa_signature_free (sigs[i].rsa_signature); + } break; case MHD_HTTP_BAD_REQUEST: /* This should never happen, either us or the mint is buggy @@ -1820,6 +1946,7 @@ TALER_MINT_refresh_reveal (struct TALER_MINT_Handle *mint, /* finally, we can actually issue the request */ rrh = GNUNET_new (struct TALER_MINT_RefreshRevealHandle); rrh->mint = mint; + rrh->noreveal_index = noreveal_index; rrh->reveal_cb = reveal_cb; rrh->reveal_cb_cls = reveal_cb_cls; rrh->md = md; |