diff --git a/Makefile.am b/Makefile.am
index 977a4d0..92674e6 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -7,6 +7,8 @@ lib_LTLIBRARIES = \
libbrandt_la_SOURCES = \
brandt.c \
crypto.c \
+ fp_priv.c \
+ fp_pub.c \
util.c
libbrandt_la_LIBADD = \
diff --git a/crypto.c b/crypto.c
index b9f55db..3b5205a 100644
--- a/crypto.c
+++ b/crypto.c
@@ -58,11 +58,11 @@ struct zkp_challenge_0og {
};
-static gcry_ctx_t ec_ctx;
-static gcry_mpi_point_t ec_gen;
-static gcry_mpi_point_t ec_zero;
-static gcry_mpi_t ec_n;
-static struct GNUNET_CRYPTO_EccDlogContext *ec_dlogctx;
+gcry_ctx_t ec_ctx = NULL;
+gcry_mpi_point_t ec_gen = NULL;
+gcry_mpi_point_t ec_zero = NULL;
+gcry_mpi_t ec_n = NULL;
+struct GNUNET_CRYPTO_EccDlogContext *ec_dlogctx = NULL;
/**
@@ -553,7 +553,7 @@ smc_init3 (uint16_t size1, uint16_t size2, uint16_t size3)
* @param[in] stepo The amount of items to advance in @a out each step. Can be
* used to store the sum in multi-dimensional arrays.
*/
-static void
+void
smc_sums_partial (gcry_mpi_point_t out[],
gcry_mpi_point_t in[],
uint16_t len,
@@ -577,7 +577,7 @@ smc_sums_partial (gcry_mpi_point_t out[],
* @param[in] step The amount of items to advance in @a in each step. Can be
* used to sum over multi-dimensional arrays.
*/
-static void
+void
smc_sum (gcry_mpi_point_t out,
gcry_mpi_point_t in[],
uint16_t len,
@@ -813,970 +813,6 @@ quit:
}
-void
-fp_pub_prep_outcome (struct BRANDT_Auction *ad)
-{
- gcry_mpi_t coeff = gcry_mpi_copy (GCRYMPI_CONST_ONE);
- gcry_mpi_point_t tmp = gcry_mpi_point_new (0);
- gcry_mpi_point_t *tlta1;
- gcry_mpi_point_t *tltb1;
- gcry_mpi_point_t **tlta2;
- gcry_mpi_point_t **tltb2;
-
- ad->gamma2 = smc_init2 (ad->n, ad->k);
- brandt_assert (ad->gamma2);
-
- ad->delta2 = smc_init2 (ad->n, ad->k);
- brandt_assert (ad->delta2);
-
- ad->tmpa1 = smc_init1 (ad->k);
- brandt_assert (ad->tmpa1);
-
- ad->tmpb1 = smc_init1 (ad->k);
- brandt_assert (ad->tmpb1);
-
- /* create temporary lookup tables with partial sums */
- tlta1 = smc_init1 (ad->k);
- tltb1 = smc_init1 (ad->k);
- tlta2 = smc_init2 (ad->n, ad->k);
- tltb2 = smc_init2 (ad->n, ad->k);
-
- /* temporary lookup table for sum of bid vectors */
- for (uint16_t i = 0; i < ad->n; i++)
- {
- smc_sums_partial (tlta2[i], ad->alpha[i], ad->k, 1, 1);
- smc_sums_partial (tltb2[i], ad->beta[i], ad->k, 1, 1);
- for (uint16_t j = 0; j < ad->k; j++)
- {
- gcry_mpi_ec_sub (tlta2[i][j],
- tlta2[i][ad->k - 1],
- tlta2[i][j],
- ec_ctx);
- gcry_mpi_ec_sub (tltb2[i][j],
- tltb2[i][ad->k - 1],
- tltb2[i][j],
- ec_ctx);
- }
- brandt_assert (!ec_point_cmp (ec_zero, tlta2[i][ad->k - 1]));
- brandt_assert (!ec_point_cmp (ec_zero, tltb2[i][ad->k - 1]));
- }
- for (uint16_t j = 0; j < ad->k; j++)
- {
- smc_sum (tlta1[j], &tlta2[0][j], ad->n, ad->k);
- smc_sum (tltb1[j], &tltb2[0][j], ad->n, ad->k);
- }
- smc_free2 (tlta2, ad->n, ad->k);
- smc_free2 (tltb2, ad->n, ad->k);
- brandt_assert (!ec_point_cmp (ec_zero, tlta1[ad->k - 1]));
- brandt_assert (!ec_point_cmp (ec_zero, tltb1[ad->k - 1]));
-
- /* initialize tmp array with zeroes, since we are calculating a sum */
- for (uint16_t j = 0; j < ad->k; j++)
- {
- ec_point_copy (ad->tmpa1[j], ec_zero);
- ec_point_copy (ad->tmpb1[j], ec_zero);
- }
- /* store the \sum_{i=1}^n2^{i-1}b_i in tmp1 until outcome determination,
- * since it is needed each time a gamma,delta pair is received from another
- * bidder */
- for (uint16_t i = 0; i < ad->n; i++)
- {
- for (uint16_t j = 0; j < ad->k; j++)
- {
- gcry_mpi_ec_mul (tmp, coeff, ad->alpha[i][j], ec_ctx);
- gcry_mpi_ec_add (ad->tmpa1[j], ad->tmpa1[j], tmp, ec_ctx);
- gcry_mpi_ec_mul (tmp, coeff, ad->beta[i][j], ec_ctx);
- gcry_mpi_ec_add (ad->tmpb1[j], ad->tmpb1[j], tmp, ec_ctx);
- }
- gcry_mpi_lshift (coeff, coeff, 1);
- }
-
- for (uint16_t j = 0; j < ad->k; j++)
- {
- /* copy unmasked outcome to all other bidder layers so they don't
- * have to be recomputed to check the ZK proof_2dle's from other
- * bidders when receiving their outcome messages */
- for (uint16_t a = 0; a < ad->n; a++)
- {
- ec_point_copy (ad->gamma2[a][j], tlta1[j]);
- ec_point_copy (ad->delta2[a][j], tltb1[j]);
- }
- }
-
- gcry_mpi_release (coeff);
- gcry_mpi_point_release (tmp);
- smc_free1 (tlta1, ad->k);
- smc_free1 (tltb1, ad->k);
-}
-
-
-/**
- * fp_pub_compute_outcome computes the outcome for first price auctions with a
- * public outcome and packs it into a message buffer together with proofs of
- * correctnes.
- *
- * @param[in] ad Pointer to the BRANDT_Auction struct to operate on
- * @param[out] buflen Size of the returned message buffer in bytes
- * @return A buffer containing the encrypted outcome vectors
- * which needs to be broadcast
- */
-unsigned char *
-fp_pub_compute_outcome (struct BRANDT_Auction *ad, size_t *buflen)
-{
- unsigned char *ret;
- unsigned char *cur;
- gcry_mpi_point_t tmpa = gcry_mpi_point_new (0);
- gcry_mpi_point_t tmpb = gcry_mpi_point_new (0);
- struct msg_head *head;
- struct ec_mpi *gamma;
- struct ec_mpi *delta;
- struct proof_2dle *proof2;
-
- brandt_assert (ad && buflen);
-
- *buflen = (sizeof (*head) +
- ad->k * (sizeof (*gamma) +
- sizeof (*delta) +
- sizeof (*proof2)));
- ret = GNUNET_new_array (*buflen, unsigned char);
-
- head = (struct msg_head *)ret;
- head->prot_version = htonl (0);
- head->msg_type = htonl (msg_outcome);
- cur = ret + sizeof (*head);
-
- for (uint16_t j = 0; j < ad->k; j++)
- {
- gamma = (struct ec_mpi *)cur;
- delta = &((struct ec_mpi *)cur)[1];
- proof2 = (struct proof_2dle *)(cur + 2 * sizeof (struct ec_mpi));
-
- ec_point_copy (tmpa, ad->gamma2[ad->i][j]);
- ec_point_copy (tmpb, ad->delta2[ad->i][j]);
-
- /* apply random masking for losing bidders */
- smc_zkp_2dle (ad->gamma2[ad->i][j],
- ad->delta2[ad->i][j],
- tmpa,
- tmpb,
- NULL,
- proof2);
-
- ec_point_serialize (gamma, ad->gamma2[ad->i][j]);
- ec_point_serialize (delta, ad->delta2[ad->i][j]);
-
- /* add winner determination for own gamma,delta */
- gcry_mpi_ec_add (ad->gamma2[ad->i][j],
- ad->gamma2[ad->i][j],
- ad->tmpa1[j],
- ec_ctx);
- gcry_mpi_ec_add (ad->delta2[ad->i][j],
- ad->delta2[ad->i][j],
- ad->tmpb1[j],
- ec_ctx);
-
- cur += sizeof (*gamma) + sizeof (*delta) + sizeof (*proof2);
- }
-
- gcry_mpi_point_release (tmpa);
- gcry_mpi_point_release (tmpb);
- return ret;
-}
-
-
-int
-fp_pub_recv_outcome (struct BRANDT_Auction *ad,
- const unsigned char *buf,
- size_t buflen,
- uint16_t sender)
-{
- int ret = 0;
- const unsigned char *cur = buf;
- struct proof_2dle *proof2;
- gcry_mpi_point_t gamma = gcry_mpi_point_new (0);
- gcry_mpi_point_t delta = gcry_mpi_point_new (0);
-
- brandt_assert (ad && buf);
-
- if (buflen != (ad->k * (2 * sizeof (struct ec_mpi) + sizeof (*proof2))))
- {
- weprintf ("wrong size of received outcome");
- goto quit;
- }
-
- for (uint16_t j = 0; j < ad->k; j++)
- {
- ec_point_parse (gamma, (struct ec_mpi *)cur);
- ec_point_parse (delta, &((struct ec_mpi *)cur)[1]);
- proof2 = (struct proof_2dle *)(cur + 2 * sizeof (struct ec_mpi));
- if (smc_zkp_2dle_check (gamma,
- delta,
- ad->gamma2[sender][j],
- ad->delta2[sender][j],
- proof2))
- {
- weprintf ("wrong zkp2 for gamma, delta received");
- goto quit;
- }
- ec_point_copy (ad->gamma2[sender][j], gamma);
- ec_point_copy (ad->delta2[sender][j], delta);
-
- /* add winner determination summand */
- gcry_mpi_ec_add (ad->gamma2[sender][j],
- ad->gamma2[sender][j],
- ad->tmpa1[j],
- ec_ctx);
- gcry_mpi_ec_add (ad->delta2[sender][j],
- ad->delta2[sender][j],
- ad->tmpb1[j],
- ec_ctx);
-
- cur += 2 * sizeof (struct ec_mpi) + sizeof (*proof2);
- }
-
- ret = 1;
-quit:
- gcry_mpi_point_release (gamma);
- gcry_mpi_point_release (delta);
- return ret;
-}
-
-
-void
-fp_pub_prep_decryption (struct BRANDT_Auction *ad)
-{
- gcry_mpi_point_t tmp = gcry_mpi_point_new (0);
-
- ad->phi2 = smc_init2 (ad->n, ad->k);
- brandt_assert (ad->phi2);
-
- for (uint16_t j = 0; j < ad->k; j++)
- {
- smc_sum (tmp, &ad->delta2[0][j], ad->n, ad->k);
-
- /* copy still encrypted outcome to all other bidder layers so they
- * don't have to be recomputed to check the ZK proof_2dle's from
- * other bidders when receiving their outcome decryption messages */
- for (uint16_t a = 0; a < ad->n; a++)
- ec_point_copy (ad->phi2[a][j], tmp);
- }
-
- gcry_mpi_point_release (tmp);
-}
-
-
-/**
- * fp_pub_decrypt_outcome decrypts part of the outcome and packs it into a
- * message buffer together with proofs of correctnes.
- *
- * @param[in] ad Pointer to the BRANDT_Auction struct to operate on
- * @param[out] buflen Size of the returned message buffer in bytes
- * @return A buffer containing the own share of the decrypted outcome
- * which needs to be broadcast
- */
-unsigned char *
-fp_pub_decrypt_outcome (struct BRANDT_Auction *ad, size_t *buflen)
-{
- unsigned char *ret;
- unsigned char *cur;
- gcry_mpi_point_t tmp = gcry_mpi_point_new (0);
- struct msg_head *head;
- struct ec_mpi *phi;
- struct proof_2dle *proof2;
-
- brandt_assert (ad && buflen);
-
- *buflen = (sizeof (*head) + ad->k * (sizeof (*phi) + sizeof (*proof2)));
- ret = GNUNET_new_array (*buflen, unsigned char);
-
- head = (struct msg_head *)ret;
- head->prot_version = htonl (0);
- head->msg_type = htonl (msg_decrypt);
- cur = ret + sizeof (*head);
-
- for (uint16_t j = 0; j < ad->k; j++)
- {
- phi = (struct ec_mpi *)cur;
- proof2 = (struct proof_2dle *)(cur + sizeof (*phi));
-
- ec_point_copy (tmp, ad->phi2[ad->i][j]);
-
- /* decrypt outcome component and prove the correct key was used */
- smc_zkp_2dle (ad->phi2[ad->i][j],
- NULL,
- tmp,
- ec_gen,
- ad->x,
- proof2);
-
- ec_point_serialize (phi, ad->phi2[ad->i][j]);
-
- cur += sizeof (*phi) + sizeof (*proof2);
- }
-
- gcry_mpi_point_release (tmp);
- return ret;
-}
-
-
-int
-fp_pub_recv_decryption (struct BRANDT_Auction *ad,
- const unsigned char *buf,
- size_t buflen,
- uint16_t sender)
-{
- int ret = 0;
- const unsigned char *cur = buf;
- struct proof_2dle *proof2;
- gcry_mpi_point_t phi = gcry_mpi_point_new (0);
-
- brandt_assert (ad && buf);
-
- if (buflen != (ad->k * (sizeof (struct ec_mpi) + sizeof (*proof2))))
- {
- weprintf ("wrong size of received outcome decryption");
- goto quit;
- }
-
- for (uint16_t j = 0; j < ad->k; j++)
- {
- ec_point_parse (phi, (struct ec_mpi *)cur);
- proof2 = (struct proof_2dle *)(cur + sizeof (struct ec_mpi));
- if (smc_zkp_2dle_check (phi,
- ad->y[sender],
- ad->phi2[sender][j],
- ec_gen,
- proof2))
- {
- weprintf ("wrong zkp2 for phi, y received");
- goto quit;
- }
- ec_point_copy (ad->phi2[sender][j], phi);
- cur += sizeof (struct ec_mpi) + sizeof (*proof2);
- }
-
- ret = 1;
-quit:
- gcry_mpi_point_release (phi);
- return ret;
-}
-
-
-struct BRANDT_Result *
-fp_pub_determine_outcome (struct BRANDT_Auction *ad,
- uint16_t *len)
-{
- struct BRANDT_Result *ret;
- int32_t price = -1;
- int32_t winner = -1;
- int dlogi = -1;
- gcry_mpi_point_t sum_gamma = gcry_mpi_point_new (0);
- gcry_mpi_point_t sum_phi = gcry_mpi_point_new (0);
-
- brandt_assert (ad);
-
- for (uint16_t j = ad->k - 1; j >= 0; j--)
- {
- smc_sum (sum_gamma, &ad->gamma2[0][j], ad->n, ad->k);
- smc_sum (sum_phi, &ad->phi2[0][j], ad->n, ad->k);
- gcry_mpi_ec_sub (sum_gamma, sum_gamma, sum_phi, ec_ctx);
- /* first non-zero component determines the price */
- if (ec_point_cmp (sum_gamma, ec_zero))
- {
- price = j;
- break;
- }
- }
-
- dlogi = GNUNET_CRYPTO_ecc_dlog (ec_dlogctx, sum_gamma);
- brandt_assert (dlogi > 0);
-
- /* all bidders participated with a multiplicative share */
- dlogi /= ad->n;
-
- /* can only support up to bits(dlogi) bidders */
- brandt_assert (sizeof (int) * 8 - 1 >= ad->n);
- for (uint16_t i = 0; i < ad->n; i++)
- {
- /* first set bit determines the winner */
- if (dlogi & (1 << i))
- {
- winner = i;
- break;
- }
- }
-
- gcry_mpi_point_release (sum_gamma);
- gcry_mpi_point_release (sum_phi);
-
- if (-1 == winner || -1 == price)
- return NULL;
-
- ret = GNUNET_new (struct BRANDT_Result);
- ret->bidder = winner;
- ret->price = price;
- ret->status = BRANDT_bidder_won;
- if (len)
- *len = 1;
- return ret;
-}
-
-
-void
-fp_priv_prep_outcome (struct BRANDT_Auction *ad)
-{
- gcry_mpi_point_t tmpa = gcry_mpi_point_new (0);
- gcry_mpi_point_t tmpb = gcry_mpi_point_new (0);
- gcry_mpi_point_t *tlta1;
- gcry_mpi_point_t *tltb1;
- gcry_mpi_point_t **tlta2;
- gcry_mpi_point_t **tltb2;
- gcry_mpi_point_t **tlta3;
- gcry_mpi_point_t **tltb3;
-
- ad->gamma3 = smc_init3 (ad->n, ad->n, ad->k);
- brandt_assert (ad->gamma3);
-
- ad->delta3 = smc_init3 (ad->n, ad->n, ad->k);
- brandt_assert (ad->delta3);
-
- /* create temporary lookup tables with partial sums */
- tlta1 = smc_init1 (ad->k);
- tltb1 = smc_init1 (ad->k);
- tlta2 = smc_init2 (ad->n, ad->k);
- tltb2 = smc_init2 (ad->n, ad->k);
- tlta3 = smc_init2 (ad->n, ad->k);
- tltb3 = smc_init2 (ad->n, ad->k);
-
- /* temporary lookup table for first summand (no one has a higher bid) */
- for (uint16_t i = 0; i < ad->n; i++)
- {
- smc_sums_partial (tlta2[i], ad->alpha[i], ad->k, 1, 1);
- smc_sums_partial (tltb2[i], ad->beta[i], ad->k, 1, 1);
- for (uint16_t j = 0; j < ad->k; j++)
- {
- gcry_mpi_ec_sub (tlta3[i][j],
- tlta2[i][ad->k - 1],
- tlta2[i][j],
- ec_ctx);
- gcry_mpi_ec_sub (tltb3[i][j],
- tltb2[i][ad->k - 1],
- tltb2[i][j],
- ec_ctx);
- }
- brandt_assert (!ec_point_cmp (ec_zero, tlta3[i][ad->k - 1]));
- brandt_assert (!ec_point_cmp (ec_zero, tltb3[i][ad->k - 1]));
- }
- for (uint16_t j = 0; j < ad->k; j++)
- {
- smc_sum (tlta1[j], &tlta3[0][j], ad->n, ad->k);
- smc_sum (tltb1[j], &tltb3[0][j], ad->n, ad->k);
- }
- brandt_assert (!ec_point_cmp (ec_zero, tlta1[ad->k - 1]));
- brandt_assert (!ec_point_cmp (ec_zero, tltb1[ad->k - 1]));
- /* \todo: merge into one nested i,j loop and one nested j,i loop? */
-
- /* temporary lookup table for second summand (my bid is not lower) */
- for (uint16_t i = 0; i < ad->n; i++)
- {
- for (uint16_t j = 0; j < ad->k; j++)
- {
- gcry_mpi_ec_sub (tlta2[i][j], tlta2[i][j], ad->alpha[i][j], ec_ctx);
- gcry_mpi_ec_sub (tltb2[i][j], tltb2[i][j], ad->beta[i][j], ec_ctx);
- }
- brandt_assert (!ec_point_cmp (ec_zero, tlta2[i][0]));
- brandt_assert (!ec_point_cmp (ec_zero, tltb2[i][0]));
- }
-
- /* temporary lookup table for third summand (no one with a lower index has
- * the same bid) */
- for (uint16_t j = 0; j < ad->k; j++)
- {
- smc_sums_partial (&tlta3[0][j], &ad->alpha[0][j], ad->n, ad->k, ad->k);
- smc_sums_partial (&tltb3[0][j], &ad->beta[0][j], ad->n, ad->k, ad->k);
- for (uint16_t i = 0; i < ad->n; i++)
- {
- gcry_mpi_ec_sub (tlta3[i][j], tlta3[i][j], ad->alpha[i][j], ec_ctx);
- gcry_mpi_ec_sub (tltb3[i][j], tltb3[i][j], ad->beta[i][j], ec_ctx);
- }
- brandt_assert (!ec_point_cmp (ec_zero, tlta3[0][j]));
- brandt_assert (!ec_point_cmp (ec_zero, tltb3[0][j]));
- }
-
- for (uint16_t i = 0; i < ad->n; i++)
- {
- for (uint16_t j = 0; j < ad->k; j++)
- {
- /* compute inner gamma */
- gcry_mpi_ec_add (tmpa, tlta1[j], tlta2[i][j], ec_ctx);
- gcry_mpi_ec_add (tmpa, tmpa, tlta3[i][j], ec_ctx);
-
- /* compute inner delta */
- gcry_mpi_ec_add (tmpb, tltb1[j], tltb2[i][j], ec_ctx);
- gcry_mpi_ec_add (tmpb, tmpb, tltb3[i][j], ec_ctx);
-
- /* copy unmasked outcome to all other bidder layers so they don't
- * have to be recomputed to check the ZK proof_2dle's from other
- * bidders when receiving their outcome messages */
- for (uint16_t a = 0; a < ad->n; a++)
- {
- ec_point_copy (ad->gamma3[a][i][j], tmpa);
- ec_point_copy (ad->delta3[a][i][j], tmpb);
- }
- }
- }
-
- gcry_mpi_point_release (tmpa);
- gcry_mpi_point_release (tmpb);
- smc_free1 (tlta1, ad->k);
- smc_free1 (tltb1, ad->k);
- smc_free2 (tlta2, ad->n, ad->k);
- smc_free2 (tltb2, ad->n, ad->k);
- smc_free2 (tlta3, ad->n, ad->k);
- smc_free2 (tltb3, ad->n, ad->k);
-}
-
-
-/**
- * fp_priv_compute_outcome computes encrypted outcome shares and packs them into
- * a message buffer together with proofs of correctnes.
- *
- * @param[in] ad Pointer to the BRANDT_Auction struct to operate on
- * @param[out] buflen Size of the returned message buffer in bytes
- * @return A buffer containing the encrypted outcome vectors
- * which needs to be broadcast
- */
-unsigned char *
-fp_priv_compute_outcome (struct BRANDT_Auction *ad, size_t *buflen)
-{
- unsigned char *ret;
- unsigned char *cur;
- struct msg_head *head;
- gcry_mpi_point_t tmpa = gcry_mpi_point_new (0);
- gcry_mpi_point_t tmpb = gcry_mpi_point_new (0);
- struct ec_mpi *gamma;
- struct ec_mpi *delta;
- struct proof_2dle *proof2;
-
- brandt_assert (ad && buflen);
-
- *buflen = (sizeof (*head) + /* msg header */
- ad->n * ad->k * /* nk * (gamma, delta, proof2) */
- (sizeof (*gamma) + sizeof (*delta) + sizeof (*proof2)));
- ret = GNUNET_new_array (*buflen, unsigned char);
-
- head = (struct msg_head *)ret;
- head->prot_version = htonl (0);
- head->msg_type = htonl (msg_outcome);
- cur = ret + sizeof (*head);
-
- for (uint16_t i = 0; i < ad->n; i++)
- {
- for (uint16_t j = 0; j < ad->k; j++)
- {
- gamma = (struct ec_mpi *)cur;
- delta = &((struct ec_mpi *)cur)[1];
- proof2 = (struct proof_2dle *)(cur + 2 * sizeof (struct ec_mpi));
-
- ec_point_copy (tmpa, ad->gamma3[ad->i][i][j]);
- ec_point_copy (tmpb, ad->delta3[ad->i][i][j]);
-
- /* apply random masking for losing bidders */
- smc_zkp_2dle (ad->gamma3[ad->i][i][j],
- ad->delta3[ad->i][i][j],
- tmpa,
- tmpb,
- NULL,
- proof2);
-
- ec_point_serialize (gamma, ad->gamma3[ad->i][i][j]);
- ec_point_serialize (delta, ad->delta3[ad->i][i][j]);
-
- cur += sizeof (*gamma) + sizeof (*delta) + sizeof (*proof2);
- }
- }
-
- gcry_mpi_point_release (tmpa);
- gcry_mpi_point_release (tmpb);
- return ret;
-}
-
-
-int
-fp_priv_recv_outcome (struct BRANDT_Auction *ad,
- const unsigned char *buf,
- size_t buflen,
- uint16_t sender)
-{
- int ret = 0;
- const unsigned char *cur = buf;
- struct proof_2dle *proof2;
- gcry_mpi_point_t gamma = gcry_mpi_point_new (0);
- gcry_mpi_point_t delta = gcry_mpi_point_new (0);
-
- brandt_assert (ad && buf);
-
- if (buflen != (ad->n * ad->k *
- (2 * sizeof (struct ec_mpi) + sizeof (*proof2))))
- {
- weprintf ("wrong size of received outcome");
- goto quit;
- }
-
- for (uint16_t i = 0; i < ad->n; i++)
- {
- for (uint16_t j = 0; j < ad->k; j++)
- {
- ec_point_parse (gamma, (struct ec_mpi *)cur);
- ec_point_parse (delta, &((struct ec_mpi *)cur)[1]);
- proof2 = (struct proof_2dle *)(cur + 2 * sizeof (struct ec_mpi));
- if (smc_zkp_2dle_check (gamma,
- delta,
- ad->gamma3[sender][i][j],
- ad->delta3[sender][i][j],
- proof2))
- {
- weprintf ("wrong zkp2 for gamma, delta received");
- goto quit;
- }
- ec_point_copy (ad->gamma3[sender][i][j], gamma);
- ec_point_copy (ad->delta3[sender][i][j], delta);
- cur += 2 * sizeof (struct ec_mpi) + sizeof (*proof2);
- }
- }
-
- ret = 1;
-quit:
- gcry_mpi_point_release (gamma);
- gcry_mpi_point_release (delta);
- return ret;
-}
-
-
-void
-fp_priv_prep_decryption (struct BRANDT_Auction *ad)
-{
- gcry_mpi_point_t tmp = gcry_mpi_point_new (0);
-
- ad->phi3 = smc_init3 (ad->n, ad->n, ad->k);
- brandt_assert (ad->phi3);
-
- ad->phiproofs3 = GNUNET_new_array_3d (ad->n,
- ad->n,
- ad->k,
- struct proof_2dle);
- brandt_assert (ad->phiproofs3);
-
- for (uint16_t i = 0; i < ad->n; i++)
- {
- for (uint16_t j = 0; j < ad->k; j++)
- {
- smc_sum (tmp, &ad->delta3[0][i][j], ad->n, ad->n * ad->k);
-
- /* copy still encrypted outcome to all other bidder layers so they
- * don't have to be recomputed to check the ZK proof_2dle's from
- * other bidders when receiving their outcome decryption messages */
- for (uint16_t a = 0; a < ad->n; a++)
- ec_point_copy (ad->phi3[a][i][j], tmp);
- }
- }
-
- gcry_mpi_point_release (tmp);
-}
-
-
-static unsigned char *
-fp_priv_decrypt_outcome_seller (struct BRANDT_Auction *ad, size_t *buflen)
-{
- unsigned char *ret;
- unsigned char *cur;
- struct msg_head *head;
- gcry_mpi_point_t tmp = gcry_mpi_point_new (0);
- struct ec_mpi *phi;
- struct proof_2dle *proof2;
-
- *buflen = (sizeof (*head) +
- (ad->n - 1) * ad->n * ad->k * (sizeof (*phi) +
- sizeof (*proof2)));
- ret = GNUNET_new_array (*buflen, unsigned char);
-
- head = (struct msg_head *)ret;
- head->prot_version = htonl (0);
- head->msg_type = htonl (msg_decrypt);
- cur = ret + sizeof (*head);
-
- for (uint16_t h = 0; h < ad->n; h++)
- {
- for (uint16_t i = 0; i < ad->n; i++)
- {
- /* don't reveal outcome to losing bidders */
- if (h == i)
- continue;
-
- for (uint16_t j = 0; j < ad->k; j++)
- {
- phi = (struct ec_mpi *)cur;
- proof2 = (struct proof_2dle *)(cur + sizeof (*phi));
-
- ec_point_serialize (phi, ad->phi3[h][i][j]);
- memcpy (proof2, &ad->phiproofs3[h][i][j], sizeof (*proof2));
-
- cur += sizeof (*phi) + sizeof (*proof2);
- }
- }
- }
-
- gcry_mpi_point_release (tmp);
- return ret;
-}
-
-
-static unsigned char *
-fp_priv_decrypt_outcome_bidder (struct BRANDT_Auction *ad, size_t *buflen)
-{
- unsigned char *ret;
- unsigned char *cur;
- struct msg_head *head;
- gcry_mpi_point_t tmp = gcry_mpi_point_new (0);
- struct ec_mpi *phi;
- struct proof_2dle *proof2;
-
- *buflen = (sizeof (*head) +
- ad->n * ad->k * (sizeof (*phi) + sizeof (*proof2)));
- ret = GNUNET_new_array (*buflen, unsigned char);
-
- head = (struct msg_head *)ret;
- head->prot_version = htonl (0);
- head->msg_type = htonl (msg_decrypt);
- cur = ret + sizeof (*head);
-
- for (uint16_t i = 0; i < ad->n; i++)
- {
- for (uint16_t j = 0; j < ad->k; j++)
- {
- phi = (struct ec_mpi *)cur;
- proof2 = (struct proof_2dle *)(cur + sizeof (*phi));
-
- ec_point_copy (tmp, ad->phi3[ad->i][i][j]);
-
- /* decrypt outcome component and prove the correct key was used */
- smc_zkp_2dle (ad->phi3[ad->i][i][j],
- NULL,
- tmp,
- ec_gen,
- ad->x,
- proof2);
-
- ec_point_serialize (phi, ad->phi3[ad->i][i][j]);
-
- cur += sizeof (*phi) + sizeof (*proof2);
- }
- }
-
- gcry_mpi_point_release (tmp);
- return ret;
-}
-
-
-/**
- * fp_priv_decrypt_outcome decrypts the own shares of the outcome and packs them
- * into a message buffer together with proofs of correctnes. When this is called
- * as the seller it will not decrypt anything, but just create the message
- * buffer from all received decryption shares to broadcast back to all bidders.
- *
- * @param[in] ad Pointer to the BRANDT_Auction struct to operate on
- * @param[out] buflen Size of the returned message buffer in bytes
- * @return A buffer containing the share of the decrypted outcome
- * which needs to be broadcast
- */
-unsigned char *
-fp_priv_decrypt_outcome (struct BRANDT_Auction *ad, size_t *buflen)
-{
- brandt_assert (ad && buflen);
- if (ad->seller_mode)
- return fp_priv_decrypt_outcome_seller (ad, buflen);
- else
- return fp_priv_decrypt_outcome_bidder (ad, buflen);
-}
-
-
-static int
-fp_priv_recv_decryption_seller (struct BRANDT_Auction *ad,
- const unsigned char *buf,
- size_t buflen,
- uint16_t sender)
-{
- int ret = 0;
- const unsigned char *cur = buf;
- struct proof_2dle *proof2;
- gcry_mpi_point_t phi = gcry_mpi_point_new (0);
-
- if (buflen != (ad->n * ad->k * (sizeof (struct ec_mpi) + sizeof (*proof2))))
- {
- weprintf ("wrong size of received outcome decryption from bidder");
- goto quit;
- }
-
- for (uint16_t i = 0; i < ad->n; i++)
- {
- for (uint16_t j = 0; j < ad->k; j++)
- {
- ec_point_parse (phi, (struct ec_mpi *)cur);
- proof2 = (struct proof_2dle *)(cur + sizeof (struct ec_mpi));
- if (smc_zkp_2dle_check (phi,
- ad->y[sender],
- ad->phi3[sender][i][j],
- ec_gen,
- proof2))
- {
- weprintf ("wrong zkp2 for phi, y received from bidder");
- goto quit;
- }
-
- /* store proof. we need to rebroadcast it to the other bidders */
- memcpy (&ad->phiproofs3[sender][i][j], proof2, sizeof (*proof2));
-
- ec_point_copy (ad->phi3[sender][i][j], phi);
- cur += sizeof (struct ec_mpi) + sizeof (*proof2);
- }
- }
-
- ret = 1;
-quit:
- gcry_mpi_point_release (phi);
- return ret;
-}
-
-
-static int
-fp_priv_recv_decryption_bidder (struct BRANDT_Auction *ad,
- const unsigned char *buf,
- size_t buflen,
- uint16_t sender)
-{
- int ret = 0;
- const unsigned char *cur = buf;
- struct proof_2dle *proof2;
- gcry_mpi_point_t phi = gcry_mpi_point_new (0);
-
- if (buflen != ((ad->n - 1) * ad->n * ad->k * (sizeof (struct ec_mpi) +
- sizeof (*proof2))))
- {
- weprintf ("wrong size of received outcome decryption from seller");
- goto quit;
- }
-
- for (uint16_t h = 0; h < ad->n; h++)
- {
- for (uint16_t i = 0; i < ad->n; i++)
- {
- /* those combinations are not sent by the seller */
- if (h == i)
- continue;
-
- /* we already have our own phi values */
- if (h == ad->i)
- {
- cur += ad->k * (sizeof (struct ec_mpi) + sizeof (*proof2));
- continue;
- }
-
- for (uint16_t j = 0; j < ad->k; j++)
- {
- ec_point_parse (phi, (struct ec_mpi *)cur);
- proof2 = (struct proof_2dle *)(cur + sizeof (struct ec_mpi));
- if (smc_zkp_2dle_check (phi,
- ad->y[h],
- ad->phi3[h][i][j],
- ec_gen,
- proof2))
- {
- weprintf ("wrong zkp2 for phi, y received from seller");
- goto quit;
- }
- ec_point_copy (ad->phi3[h][i][j], phi);
- cur += sizeof (struct ec_mpi) + sizeof (*proof2);
- }
- }
- }
-
- ret = 1;
-quit:
- gcry_mpi_point_release (phi);
- return ret;
-}
-
-
-int
-fp_priv_recv_decryption (struct BRANDT_Auction *ad,
- const unsigned char *buf,
- size_t buflen,
- uint16_t sender)
-{
- brandt_assert (ad && buf);
- if (ad->seller_mode)
- return fp_priv_recv_decryption_seller (ad, buf, buflen, sender);
- else
- return fp_priv_recv_decryption_bidder (ad, buf, buflen, sender);
-}
-
-
-struct BRANDT_Result *
-fp_priv_determine_outcome (struct BRANDT_Auction *ad,
- uint16_t *len)
-{
- struct BRANDT_Result *ret;
- int32_t price = -1;
- int32_t winner = -1;
- gcry_mpi_point_t sum_gamma = gcry_mpi_point_new (0);
- gcry_mpi_point_t sum_phi = gcry_mpi_point_new (0);
-
- brandt_assert (ad);
-
- for (uint16_t i = 0; i < ad->n; i++)
- {
- if (!ad->seller_mode && i != ad->i)
- continue;
-
- for (uint16_t j = 0; j < ad->k; j++)
- {
- smc_sum (sum_gamma, &ad->gamma3[0][i][j], ad->n, ad->n * ad->k);
- smc_sum (sum_phi, &ad->phi3[0][i][j], ad->n, ad->n * ad->k);
- gcry_mpi_ec_sub (sum_gamma, sum_gamma, sum_phi, ec_ctx);
- if (!ec_point_cmp (sum_gamma, ec_zero))
- {
- if (-1 != price)
- {
- weprintf ("multiple winning prices detected");
- return NULL;
- }
- if (-1 != winner)
- {
- weprintf ("multiple winners detected");
- return NULL;
- }
- price = j;
- winner = i;
- }
- }
- }
-
- gcry_mpi_point_release (sum_gamma);
- gcry_mpi_point_release (sum_phi);
-
- if (-1 == winner || -1 == price)
- return NULL;
-
- ret = GNUNET_new (struct BRANDT_Result);
- ret->bidder = winner;
- ret->price = price;
- ret->status = BRANDT_bidder_won;
- if (len)
- *len = 1;
- return ret;
-}
-
-
/**
* smc_zkp_dl creates a proof of knowledge of @a x with \f$v = xg\f$ where
* \f$g\f$ is the base point on Ed25519.
diff --git a/crypto.h b/crypto.h
index e9338f4..b4344da 100644
--- a/crypto.h
+++ b/crypto.h
@@ -41,6 +41,9 @@ struct ec_mpi {
unsigned char data[256 / 8];
};
+void ec_point_serialize (struct ec_mpi *dst, const gcry_mpi_point_t src);
+void ec_point_parse (gcry_mpi_point_t dst, const struct ec_mpi *src);
+
gcry_mpi_point_t *smc_init1 (uint16_t size1);
gcry_mpi_point_t **smc_init2 (uint16_t size1, uint16_t size2);
gcry_mpi_point_t ***smc_init3 (uint16_t size1, uint16_t size2, uint16_t size3);
@@ -51,6 +54,16 @@ void smc_free3 (gcry_mpi_point_t ***dst,
uint16_t size2,
uint16_t size3);
+void smc_sums_partial (gcry_mpi_point_t out[],
+ gcry_mpi_point_t in[],
+ uint16_t len,
+ uint16_t stepi,
+ uint16_t stepo);
+void smc_sum (gcry_mpi_point_t out,
+ gcry_mpi_point_t in[],
+ uint16_t len,
+ uint16_t step);
+
void ec_point_copy (gcry_mpi_point_t dst, const gcry_mpi_point_t src);
int ec_point_cmp (const gcry_mpi_point_t a, const gcry_mpi_point_t b);
void ec_skey_create (gcry_mpi_t skey);
diff --git a/fp_priv.c b/fp_priv.c
new file mode 100644
index 0000000..c96f969
--- /dev/null
+++ b/fp_priv.c
@@ -0,0 +1,584 @@
+/* This file is part of libbrandt.
+ * Copyright (C) 2016 GNUnet e.V.
+ *
+ * libbrandt is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version.
+ *
+ * libbrandt is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * libbrandt. If not, see .
+ */
+
+/**
+ * @file fp_pub.c
+ * @brief Implementation of the first price public outcome algorithm.
+ * @author Markus Teich
+ */
+
+#include "platform.h"
+
+#include
+
+#include "crypto.h"
+#include "internals.h"
+#include "util.h"
+
+
+void
+fp_priv_prep_outcome (struct BRANDT_Auction *ad)
+{
+ gcry_mpi_point_t tmpa = gcry_mpi_point_new (0);
+ gcry_mpi_point_t tmpb = gcry_mpi_point_new (0);
+ gcry_mpi_point_t *tlta1;
+ gcry_mpi_point_t *tltb1;
+ gcry_mpi_point_t **tlta2;
+ gcry_mpi_point_t **tltb2;
+ gcry_mpi_point_t **tlta3;
+ gcry_mpi_point_t **tltb3;
+
+ ad->gamma3 = smc_init3 (ad->n, ad->n, ad->k);
+ brandt_assert (ad->gamma3);
+
+ ad->delta3 = smc_init3 (ad->n, ad->n, ad->k);
+ brandt_assert (ad->delta3);
+
+ /* create temporary lookup tables with partial sums */
+ tlta1 = smc_init1 (ad->k);
+ tltb1 = smc_init1 (ad->k);
+ tlta2 = smc_init2 (ad->n, ad->k);
+ tltb2 = smc_init2 (ad->n, ad->k);
+ tlta3 = smc_init2 (ad->n, ad->k);
+ tltb3 = smc_init2 (ad->n, ad->k);
+
+ /* temporary lookup table for first summand (no one has a higher bid) */
+ for (uint16_t i = 0; i < ad->n; i++)
+ {
+ smc_sums_partial (tlta2[i], ad->alpha[i], ad->k, 1, 1);
+ smc_sums_partial (tltb2[i], ad->beta[i], ad->k, 1, 1);
+ for (uint16_t j = 0; j < ad->k; j++)
+ {
+ gcry_mpi_ec_sub (tlta3[i][j],
+ tlta2[i][ad->k - 1],
+ tlta2[i][j],
+ ec_ctx);
+ gcry_mpi_ec_sub (tltb3[i][j],
+ tltb2[i][ad->k - 1],
+ tltb2[i][j],
+ ec_ctx);
+ }
+ brandt_assert (!ec_point_cmp (ec_zero, tlta3[i][ad->k - 1]));
+ brandt_assert (!ec_point_cmp (ec_zero, tltb3[i][ad->k - 1]));
+ }
+ for (uint16_t j = 0; j < ad->k; j++)
+ {
+ smc_sum (tlta1[j], &tlta3[0][j], ad->n, ad->k);
+ smc_sum (tltb1[j], &tltb3[0][j], ad->n, ad->k);
+ }
+ brandt_assert (!ec_point_cmp (ec_zero, tlta1[ad->k - 1]));
+ brandt_assert (!ec_point_cmp (ec_zero, tltb1[ad->k - 1]));
+ /* \todo: merge into one nested i,j loop and one nested j,i loop? */
+
+ /* temporary lookup table for second summand (my bid is not lower) */
+ for (uint16_t i = 0; i < ad->n; i++)
+ {
+ for (uint16_t j = 0; j < ad->k; j++)
+ {
+ gcry_mpi_ec_sub (tlta2[i][j], tlta2[i][j], ad->alpha[i][j], ec_ctx);
+ gcry_mpi_ec_sub (tltb2[i][j], tltb2[i][j], ad->beta[i][j], ec_ctx);
+ }
+ brandt_assert (!ec_point_cmp (ec_zero, tlta2[i][0]));
+ brandt_assert (!ec_point_cmp (ec_zero, tltb2[i][0]));
+ }
+
+ /* temporary lookup table for third summand (no one with a lower index has
+ * the same bid) */
+ for (uint16_t j = 0; j < ad->k; j++)
+ {
+ smc_sums_partial (&tlta3[0][j], &ad->alpha[0][j], ad->n, ad->k, ad->k);
+ smc_sums_partial (&tltb3[0][j], &ad->beta[0][j], ad->n, ad->k, ad->k);
+ for (uint16_t i = 0; i < ad->n; i++)
+ {
+ gcry_mpi_ec_sub (tlta3[i][j], tlta3[i][j], ad->alpha[i][j], ec_ctx);
+ gcry_mpi_ec_sub (tltb3[i][j], tltb3[i][j], ad->beta[i][j], ec_ctx);
+ }
+ brandt_assert (!ec_point_cmp (ec_zero, tlta3[0][j]));
+ brandt_assert (!ec_point_cmp (ec_zero, tltb3[0][j]));
+ }
+
+ for (uint16_t i = 0; i < ad->n; i++)
+ {
+ for (uint16_t j = 0; j < ad->k; j++)
+ {
+ /* compute inner gamma */
+ gcry_mpi_ec_add (tmpa, tlta1[j], tlta2[i][j], ec_ctx);
+ gcry_mpi_ec_add (tmpa, tmpa, tlta3[i][j], ec_ctx);
+
+ /* compute inner delta */
+ gcry_mpi_ec_add (tmpb, tltb1[j], tltb2[i][j], ec_ctx);
+ gcry_mpi_ec_add (tmpb, tmpb, tltb3[i][j], ec_ctx);
+
+ /* copy unmasked outcome to all other bidder layers so they don't
+ * have to be recomputed to check the ZK proof_2dle's from other
+ * bidders when receiving their outcome messages */
+ for (uint16_t a = 0; a < ad->n; a++)
+ {
+ ec_point_copy (ad->gamma3[a][i][j], tmpa);
+ ec_point_copy (ad->delta3[a][i][j], tmpb);
+ }
+ }
+ }
+
+ gcry_mpi_point_release (tmpa);
+ gcry_mpi_point_release (tmpb);
+ smc_free1 (tlta1, ad->k);
+ smc_free1 (tltb1, ad->k);
+ smc_free2 (tlta2, ad->n, ad->k);
+ smc_free2 (tltb2, ad->n, ad->k);
+ smc_free2 (tlta3, ad->n, ad->k);
+ smc_free2 (tltb3, ad->n, ad->k);
+}
+
+
+/**
+ * fp_priv_compute_outcome computes encrypted outcome shares and packs them into
+ * a message buffer together with proofs of correctnes.
+ *
+ * @param[in] ad Pointer to the BRANDT_Auction struct to operate on
+ * @param[out] buflen Size of the returned message buffer in bytes
+ * @return A buffer containing the encrypted outcome vectors
+ * which needs to be broadcast
+ */
+unsigned char *
+fp_priv_compute_outcome (struct BRANDT_Auction *ad, size_t *buflen)
+{
+ unsigned char *ret;
+ unsigned char *cur;
+ struct msg_head *head;
+ gcry_mpi_point_t tmpa = gcry_mpi_point_new (0);
+ gcry_mpi_point_t tmpb = gcry_mpi_point_new (0);
+ struct ec_mpi *gamma;
+ struct ec_mpi *delta;
+ struct proof_2dle *proof2;
+
+ brandt_assert (ad && buflen);
+
+ *buflen = (sizeof (*head) + /* msg header */
+ ad->n * ad->k * /* nk * (gamma, delta, proof2) */
+ (sizeof (*gamma) + sizeof (*delta) + sizeof (*proof2)));
+ ret = GNUNET_new_array (*buflen, unsigned char);
+
+ head = (struct msg_head *)ret;
+ head->prot_version = htonl (0);
+ head->msg_type = htonl (msg_outcome);
+ cur = ret + sizeof (*head);
+
+ for (uint16_t i = 0; i < ad->n; i++)
+ {
+ for (uint16_t j = 0; j < ad->k; j++)
+ {
+ gamma = (struct ec_mpi *)cur;
+ delta = &((struct ec_mpi *)cur)[1];
+ proof2 = (struct proof_2dle *)(cur + 2 * sizeof (struct ec_mpi));
+
+ ec_point_copy (tmpa, ad->gamma3[ad->i][i][j]);
+ ec_point_copy (tmpb, ad->delta3[ad->i][i][j]);
+
+ /* apply random masking for losing bidders */
+ smc_zkp_2dle (ad->gamma3[ad->i][i][j],
+ ad->delta3[ad->i][i][j],
+ tmpa,
+ tmpb,
+ NULL,
+ proof2);
+
+ ec_point_serialize (gamma, ad->gamma3[ad->i][i][j]);
+ ec_point_serialize (delta, ad->delta3[ad->i][i][j]);
+
+ cur += sizeof (*gamma) + sizeof (*delta) + sizeof (*proof2);
+ }
+ }
+
+ gcry_mpi_point_release (tmpa);
+ gcry_mpi_point_release (tmpb);
+ return ret;
+}
+
+
+int
+fp_priv_recv_outcome (struct BRANDT_Auction *ad,
+ const unsigned char *buf,
+ size_t buflen,
+ uint16_t sender)
+{
+ int ret = 0;
+ const unsigned char *cur = buf;
+ struct proof_2dle *proof2;
+ gcry_mpi_point_t gamma = gcry_mpi_point_new (0);
+ gcry_mpi_point_t delta = gcry_mpi_point_new (0);
+
+ brandt_assert (ad && buf);
+
+ if (buflen != (ad->n * ad->k *
+ (2 * sizeof (struct ec_mpi) + sizeof (*proof2))))
+ {
+ weprintf ("wrong size of received outcome");
+ goto quit;
+ }
+
+ for (uint16_t i = 0; i < ad->n; i++)
+ {
+ for (uint16_t j = 0; j < ad->k; j++)
+ {
+ ec_point_parse (gamma, (struct ec_mpi *)cur);
+ ec_point_parse (delta, &((struct ec_mpi *)cur)[1]);
+ proof2 = (struct proof_2dle *)(cur + 2 * sizeof (struct ec_mpi));
+ if (smc_zkp_2dle_check (gamma,
+ delta,
+ ad->gamma3[sender][i][j],
+ ad->delta3[sender][i][j],
+ proof2))
+ {
+ weprintf ("wrong zkp2 for gamma, delta received");
+ goto quit;
+ }
+ ec_point_copy (ad->gamma3[sender][i][j], gamma);
+ ec_point_copy (ad->delta3[sender][i][j], delta);
+ cur += 2 * sizeof (struct ec_mpi) + sizeof (*proof2);
+ }
+ }
+
+ ret = 1;
+quit:
+ gcry_mpi_point_release (gamma);
+ gcry_mpi_point_release (delta);
+ return ret;
+}
+
+
+void
+fp_priv_prep_decryption (struct BRANDT_Auction *ad)
+{
+ gcry_mpi_point_t tmp = gcry_mpi_point_new (0);
+
+ ad->phi3 = smc_init3 (ad->n, ad->n, ad->k);
+ brandt_assert (ad->phi3);
+
+ ad->phiproofs3 = GNUNET_new_array_3d (ad->n,
+ ad->n,
+ ad->k,
+ struct proof_2dle);
+ brandt_assert (ad->phiproofs3);
+
+ for (uint16_t i = 0; i < ad->n; i++)
+ {
+ for (uint16_t j = 0; j < ad->k; j++)
+ {
+ smc_sum (tmp, &ad->delta3[0][i][j], ad->n, ad->n * ad->k);
+
+ /* copy still encrypted outcome to all other bidder layers so they
+ * don't have to be recomputed to check the ZK proof_2dle's from
+ * other bidders when receiving their outcome decryption messages */
+ for (uint16_t a = 0; a < ad->n; a++)
+ ec_point_copy (ad->phi3[a][i][j], tmp);
+ }
+ }
+
+ gcry_mpi_point_release (tmp);
+}
+
+
+static unsigned char *
+fp_priv_decrypt_outcome_seller (struct BRANDT_Auction *ad, size_t *buflen)
+{
+ unsigned char *ret;
+ unsigned char *cur;
+ struct msg_head *head;
+ gcry_mpi_point_t tmp = gcry_mpi_point_new (0);
+ struct ec_mpi *phi;
+ struct proof_2dle *proof2;
+
+ *buflen = (sizeof (*head) +
+ (ad->n - 1) * ad->n * ad->k * (sizeof (*phi) +
+ sizeof (*proof2)));
+ ret = GNUNET_new_array (*buflen, unsigned char);
+
+ head = (struct msg_head *)ret;
+ head->prot_version = htonl (0);
+ head->msg_type = htonl (msg_decrypt);
+ cur = ret + sizeof (*head);
+
+ for (uint16_t h = 0; h < ad->n; h++)
+ {
+ for (uint16_t i = 0; i < ad->n; i++)
+ {
+ /* don't reveal outcome to losing bidders */
+ if (h == i)
+ continue;
+
+ for (uint16_t j = 0; j < ad->k; j++)
+ {
+ phi = (struct ec_mpi *)cur;
+ proof2 = (struct proof_2dle *)(cur + sizeof (*phi));
+
+ ec_point_serialize (phi, ad->phi3[h][i][j]);
+ memcpy (proof2, &ad->phiproofs3[h][i][j], sizeof (*proof2));
+
+ cur += sizeof (*phi) + sizeof (*proof2);
+ }
+ }
+ }
+
+ gcry_mpi_point_release (tmp);
+ return ret;
+}
+
+
+static unsigned char *
+fp_priv_decrypt_outcome_bidder (struct BRANDT_Auction *ad, size_t *buflen)
+{
+ unsigned char *ret;
+ unsigned char *cur;
+ struct msg_head *head;
+ gcry_mpi_point_t tmp = gcry_mpi_point_new (0);
+ struct ec_mpi *phi;
+ struct proof_2dle *proof2;
+
+ *buflen = (sizeof (*head) +
+ ad->n * ad->k * (sizeof (*phi) + sizeof (*proof2)));
+ ret = GNUNET_new_array (*buflen, unsigned char);
+
+ head = (struct msg_head *)ret;
+ head->prot_version = htonl (0);
+ head->msg_type = htonl (msg_decrypt);
+ cur = ret + sizeof (*head);
+
+ for (uint16_t i = 0; i < ad->n; i++)
+ {
+ for (uint16_t j = 0; j < ad->k; j++)
+ {
+ phi = (struct ec_mpi *)cur;
+ proof2 = (struct proof_2dle *)(cur + sizeof (*phi));
+
+ ec_point_copy (tmp, ad->phi3[ad->i][i][j]);
+
+ /* decrypt outcome component and prove the correct key was used */
+ smc_zkp_2dle (ad->phi3[ad->i][i][j],
+ NULL,
+ tmp,
+ ec_gen,
+ ad->x,
+ proof2);
+
+ ec_point_serialize (phi, ad->phi3[ad->i][i][j]);
+
+ cur += sizeof (*phi) + sizeof (*proof2);
+ }
+ }
+
+ gcry_mpi_point_release (tmp);
+ return ret;
+}
+
+
+/**
+ * fp_priv_decrypt_outcome decrypts the own shares of the outcome and packs them
+ * into a message buffer together with proofs of correctnes. When this is called
+ * as the seller it will not decrypt anything, but just create the message
+ * buffer from all received decryption shares to broadcast back to all bidders.
+ *
+ * @param[in] ad Pointer to the BRANDT_Auction struct to operate on
+ * @param[out] buflen Size of the returned message buffer in bytes
+ * @return A buffer containing the share of the decrypted outcome
+ * which needs to be broadcast
+ */
+unsigned char *
+fp_priv_decrypt_outcome (struct BRANDT_Auction *ad, size_t *buflen)
+{
+ brandt_assert (ad && buflen);
+ if (ad->seller_mode)
+ return fp_priv_decrypt_outcome_seller (ad, buflen);
+ else
+ return fp_priv_decrypt_outcome_bidder (ad, buflen);
+}
+
+
+static int
+fp_priv_recv_decryption_seller (struct BRANDT_Auction *ad,
+ const unsigned char *buf,
+ size_t buflen,
+ uint16_t sender)
+{
+ int ret = 0;
+ const unsigned char *cur = buf;
+ struct proof_2dle *proof2;
+ gcry_mpi_point_t phi = gcry_mpi_point_new (0);
+
+ if (buflen != (ad->n * ad->k * (sizeof (struct ec_mpi) + sizeof (*proof2))))
+ {
+ weprintf ("wrong size of received outcome decryption from bidder");
+ goto quit;
+ }
+
+ for (uint16_t i = 0; i < ad->n; i++)
+ {
+ for (uint16_t j = 0; j < ad->k; j++)
+ {
+ ec_point_parse (phi, (struct ec_mpi *)cur);
+ proof2 = (struct proof_2dle *)(cur + sizeof (struct ec_mpi));
+ if (smc_zkp_2dle_check (phi,
+ ad->y[sender],
+ ad->phi3[sender][i][j],
+ ec_gen,
+ proof2))
+ {
+ weprintf ("wrong zkp2 for phi, y received from bidder");
+ goto quit;
+ }
+
+ /* store proof. we need to rebroadcast it to the other bidders */
+ memcpy (&ad->phiproofs3[sender][i][j], proof2, sizeof (*proof2));
+
+ ec_point_copy (ad->phi3[sender][i][j], phi);
+ cur += sizeof (struct ec_mpi) + sizeof (*proof2);
+ }
+ }
+
+ ret = 1;
+quit:
+ gcry_mpi_point_release (phi);
+ return ret;
+}
+
+
+static int
+fp_priv_recv_decryption_bidder (struct BRANDT_Auction *ad,
+ const unsigned char *buf,
+ size_t buflen,
+ uint16_t sender)
+{
+ int ret = 0;
+ const unsigned char *cur = buf;
+ struct proof_2dle *proof2;
+ gcry_mpi_point_t phi = gcry_mpi_point_new (0);
+
+ if (buflen != ((ad->n - 1) * ad->n * ad->k * (sizeof (struct ec_mpi) +
+ sizeof (*proof2))))
+ {
+ weprintf ("wrong size of received outcome decryption from seller");
+ goto quit;
+ }
+
+ for (uint16_t h = 0; h < ad->n; h++)
+ {
+ for (uint16_t i = 0; i < ad->n; i++)
+ {
+ /* those combinations are not sent by the seller */
+ if (h == i)
+ continue;
+
+ /* we already have our own phi values */
+ if (h == ad->i)
+ {
+ cur += ad->k * (sizeof (struct ec_mpi) + sizeof (*proof2));
+ continue;
+ }
+
+ for (uint16_t j = 0; j < ad->k; j++)
+ {
+ ec_point_parse (phi, (struct ec_mpi *)cur);
+ proof2 = (struct proof_2dle *)(cur + sizeof (struct ec_mpi));
+ if (smc_zkp_2dle_check (phi,
+ ad->y[h],
+ ad->phi3[h][i][j],
+ ec_gen,
+ proof2))
+ {
+ weprintf ("wrong zkp2 for phi, y received from seller");
+ goto quit;
+ }
+ ec_point_copy (ad->phi3[h][i][j], phi);
+ cur += sizeof (struct ec_mpi) + sizeof (*proof2);
+ }
+ }
+ }
+
+ ret = 1;
+quit:
+ gcry_mpi_point_release (phi);
+ return ret;
+}
+
+
+int
+fp_priv_recv_decryption (struct BRANDT_Auction *ad,
+ const unsigned char *buf,
+ size_t buflen,
+ uint16_t sender)
+{
+ brandt_assert (ad && buf);
+ if (ad->seller_mode)
+ return fp_priv_recv_decryption_seller (ad, buf, buflen, sender);
+ else
+ return fp_priv_recv_decryption_bidder (ad, buf, buflen, sender);
+}
+
+
+struct BRANDT_Result *
+fp_priv_determine_outcome (struct BRANDT_Auction *ad,
+ uint16_t *len)
+{
+ struct BRANDT_Result *ret;
+ int32_t price = -1;
+ int32_t winner = -1;
+ gcry_mpi_point_t sum_gamma = gcry_mpi_point_new (0);
+ gcry_mpi_point_t sum_phi = gcry_mpi_point_new (0);
+
+ brandt_assert (ad);
+
+ for (uint16_t i = 0; i < ad->n; i++)
+ {
+ if (!ad->seller_mode && i != ad->i)
+ continue;
+
+ for (uint16_t j = 0; j < ad->k; j++)
+ {
+ smc_sum (sum_gamma, &ad->gamma3[0][i][j], ad->n, ad->n * ad->k);
+ smc_sum (sum_phi, &ad->phi3[0][i][j], ad->n, ad->n * ad->k);
+ gcry_mpi_ec_sub (sum_gamma, sum_gamma, sum_phi, ec_ctx);
+ if (!ec_point_cmp (sum_gamma, ec_zero))
+ {
+ if (-1 != price)
+ {
+ weprintf ("multiple winning prices detected");
+ return NULL;
+ }
+ if (-1 != winner)
+ {
+ weprintf ("multiple winners detected");
+ return NULL;
+ }
+ price = j;
+ winner = i;
+ }
+ }
+ }
+
+ gcry_mpi_point_release (sum_gamma);
+ gcry_mpi_point_release (sum_phi);
+
+ if (-1 == winner || -1 == price)
+ return NULL;
+
+ ret = GNUNET_new (struct BRANDT_Result);
+ ret->bidder = winner;
+ ret->price = price;
+ ret->status = BRANDT_bidder_won;
+ if (len)
+ *len = 1;
+ return ret;
+}
diff --git a/fp_pub.c b/fp_pub.c
new file mode 100644
index 0000000..eb0cfe1
--- /dev/null
+++ b/fp_pub.c
@@ -0,0 +1,438 @@
+/* This file is part of libbrandt.
+ * Copyright (C) 2016 GNUnet e.V.
+ *
+ * libbrandt is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version.
+ *
+ * libbrandt is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * libbrandt. If not, see .
+ */
+
+/**
+ * @file fp_pub.c
+ * @brief Implementation of the first price public outcome algorithm.
+ * @author Markus Teich
+ */
+
+#include "platform.h"
+
+#include
+
+#include "crypto.h"
+#include "internals.h"
+#include "util.h"
+
+
+void
+fp_pub_prep_outcome (struct BRANDT_Auction *ad)
+{
+ gcry_mpi_t coeff = gcry_mpi_copy (GCRYMPI_CONST_ONE);
+ gcry_mpi_point_t tmp = gcry_mpi_point_new (0);
+ gcry_mpi_point_t *tlta1;
+ gcry_mpi_point_t *tltb1;
+ gcry_mpi_point_t **tlta2;
+ gcry_mpi_point_t **tltb2;
+
+ ad->gamma2 = smc_init2 (ad->n, ad->k);
+ brandt_assert (ad->gamma2);
+
+ ad->delta2 = smc_init2 (ad->n, ad->k);
+ brandt_assert (ad->delta2);
+
+ ad->tmpa1 = smc_init1 (ad->k);
+ brandt_assert (ad->tmpa1);
+
+ ad->tmpb1 = smc_init1 (ad->k);
+ brandt_assert (ad->tmpb1);
+
+ /* create temporary lookup tables with partial sums */
+ tlta1 = smc_init1 (ad->k);
+ tltb1 = smc_init1 (ad->k);
+ tlta2 = smc_init2 (ad->n, ad->k);
+ tltb2 = smc_init2 (ad->n, ad->k);
+
+ /* temporary lookup table for sum of bid vectors */
+ for (uint16_t i = 0; i < ad->n; i++)
+ {
+ smc_sums_partial (tlta2[i], ad->alpha[i], ad->k, 1, 1);
+ smc_sums_partial (tltb2[i], ad->beta[i], ad->k, 1, 1);
+ for (uint16_t j = 0; j < ad->k; j++)
+ {
+ gcry_mpi_ec_sub (tlta2[i][j],
+ tlta2[i][ad->k - 1],
+ tlta2[i][j],
+ ec_ctx);
+ gcry_mpi_ec_sub (tltb2[i][j],
+ tltb2[i][ad->k - 1],
+ tltb2[i][j],
+ ec_ctx);
+ }
+ brandt_assert (!ec_point_cmp (ec_zero, tlta2[i][ad->k - 1]));
+ brandt_assert (!ec_point_cmp (ec_zero, tltb2[i][ad->k - 1]));
+ }
+ for (uint16_t j = 0; j < ad->k; j++)
+ {
+ smc_sum (tlta1[j], &tlta2[0][j], ad->n, ad->k);
+ smc_sum (tltb1[j], &tltb2[0][j], ad->n, ad->k);
+ }
+ smc_free2 (tlta2, ad->n, ad->k);
+ smc_free2 (tltb2, ad->n, ad->k);
+ brandt_assert (!ec_point_cmp (ec_zero, tlta1[ad->k - 1]));
+ brandt_assert (!ec_point_cmp (ec_zero, tltb1[ad->k - 1]));
+
+ /* initialize tmp array with zeroes, since we are calculating a sum */
+ for (uint16_t j = 0; j < ad->k; j++)
+ {
+ ec_point_copy (ad->tmpa1[j], ec_zero);
+ ec_point_copy (ad->tmpb1[j], ec_zero);
+ }
+ /* store the \sum_{i=1}^n2^{i-1}b_i in tmp1 until outcome determination,
+ * since it is needed each time a gamma,delta pair is received from another
+ * bidder */
+ for (uint16_t i = 0; i < ad->n; i++)
+ {
+ for (uint16_t j = 0; j < ad->k; j++)
+ {
+ gcry_mpi_ec_mul (tmp, coeff, ad->alpha[i][j], ec_ctx);
+ gcry_mpi_ec_add (ad->tmpa1[j], ad->tmpa1[j], tmp, ec_ctx);
+ gcry_mpi_ec_mul (tmp, coeff, ad->beta[i][j], ec_ctx);
+ gcry_mpi_ec_add (ad->tmpb1[j], ad->tmpb1[j], tmp, ec_ctx);
+ }
+ gcry_mpi_lshift (coeff, coeff, 1);
+ }
+
+ for (uint16_t j = 0; j < ad->k; j++)
+ {
+ /* copy unmasked outcome to all other bidder layers so they don't
+ * have to be recomputed to check the ZK proof_2dle's from other
+ * bidders when receiving their outcome messages */
+ for (uint16_t a = 0; a < ad->n; a++)
+ {
+ ec_point_copy (ad->gamma2[a][j], tlta1[j]);
+ ec_point_copy (ad->delta2[a][j], tltb1[j]);
+ }
+ }
+
+ gcry_mpi_release (coeff);
+ gcry_mpi_point_release (tmp);
+ smc_free1 (tlta1, ad->k);
+ smc_free1 (tltb1, ad->k);
+}
+
+
+/**
+ * fp_pub_compute_outcome computes the outcome for first price auctions with a
+ * public outcome and packs it into a message buffer together with proofs of
+ * correctnes.
+ *
+ * @param[in] ad Pointer to the BRANDT_Auction struct to operate on
+ * @param[out] buflen Size of the returned message buffer in bytes
+ * @return A buffer containing the encrypted outcome vectors
+ * which needs to be broadcast
+ */
+unsigned char *
+fp_pub_compute_outcome (struct BRANDT_Auction *ad, size_t *buflen)
+{
+ unsigned char *ret;
+ unsigned char *cur;
+ gcry_mpi_point_t tmpa = gcry_mpi_point_new (0);
+ gcry_mpi_point_t tmpb = gcry_mpi_point_new (0);
+ struct msg_head *head;
+ struct ec_mpi *gamma;
+ struct ec_mpi *delta;
+ struct proof_2dle *proof2;
+
+ brandt_assert (ad && buflen);
+
+ *buflen = (sizeof (*head) +
+ ad->k * (sizeof (*gamma) +
+ sizeof (*delta) +
+ sizeof (*proof2)));
+ ret = GNUNET_new_array (*buflen, unsigned char);
+
+ head = (struct msg_head *)ret;
+ head->prot_version = htonl (0);
+ head->msg_type = htonl (msg_outcome);
+ cur = ret + sizeof (*head);
+
+ for (uint16_t j = 0; j < ad->k; j++)
+ {
+ gamma = (struct ec_mpi *)cur;
+ delta = &((struct ec_mpi *)cur)[1];
+ proof2 = (struct proof_2dle *)(cur + 2 * sizeof (struct ec_mpi));
+
+ ec_point_copy (tmpa, ad->gamma2[ad->i][j]);
+ ec_point_copy (tmpb, ad->delta2[ad->i][j]);
+
+ /* apply random masking for losing bidders */
+ smc_zkp_2dle (ad->gamma2[ad->i][j],
+ ad->delta2[ad->i][j],
+ tmpa,
+ tmpb,
+ NULL,
+ proof2);
+
+ ec_point_serialize (gamma, ad->gamma2[ad->i][j]);
+ ec_point_serialize (delta, ad->delta2[ad->i][j]);
+
+ /* add winner determination for own gamma,delta */
+ gcry_mpi_ec_add (ad->gamma2[ad->i][j],
+ ad->gamma2[ad->i][j],
+ ad->tmpa1[j],
+ ec_ctx);
+ gcry_mpi_ec_add (ad->delta2[ad->i][j],
+ ad->delta2[ad->i][j],
+ ad->tmpb1[j],
+ ec_ctx);
+
+ cur += sizeof (*gamma) + sizeof (*delta) + sizeof (*proof2);
+ }
+
+ gcry_mpi_point_release (tmpa);
+ gcry_mpi_point_release (tmpb);
+ return ret;
+}
+
+
+int
+fp_pub_recv_outcome (struct BRANDT_Auction *ad,
+ const unsigned char *buf,
+ size_t buflen,
+ uint16_t sender)
+{
+ int ret = 0;
+ const unsigned char *cur = buf;
+ struct proof_2dle *proof2;
+ gcry_mpi_point_t gamma = gcry_mpi_point_new (0);
+ gcry_mpi_point_t delta = gcry_mpi_point_new (0);
+
+ brandt_assert (ad && buf);
+
+ if (buflen != (ad->k * (2 * sizeof (struct ec_mpi) + sizeof (*proof2))))
+ {
+ weprintf ("wrong size of received outcome");
+ goto quit;
+ }
+
+ for (uint16_t j = 0; j < ad->k; j++)
+ {
+ ec_point_parse (gamma, (struct ec_mpi *)cur);
+ ec_point_parse (delta, &((struct ec_mpi *)cur)[1]);
+ proof2 = (struct proof_2dle *)(cur + 2 * sizeof (struct ec_mpi));
+ if (smc_zkp_2dle_check (gamma,
+ delta,
+ ad->gamma2[sender][j],
+ ad->delta2[sender][j],
+ proof2))
+ {
+ weprintf ("wrong zkp2 for gamma, delta received");
+ goto quit;
+ }
+ ec_point_copy (ad->gamma2[sender][j], gamma);
+ ec_point_copy (ad->delta2[sender][j], delta);
+
+ /* add winner determination summand */
+ gcry_mpi_ec_add (ad->gamma2[sender][j],
+ ad->gamma2[sender][j],
+ ad->tmpa1[j],
+ ec_ctx);
+ gcry_mpi_ec_add (ad->delta2[sender][j],
+ ad->delta2[sender][j],
+ ad->tmpb1[j],
+ ec_ctx);
+
+ cur += 2 * sizeof (struct ec_mpi) + sizeof (*proof2);
+ }
+
+ ret = 1;
+quit:
+ gcry_mpi_point_release (gamma);
+ gcry_mpi_point_release (delta);
+ return ret;
+}
+
+
+void
+fp_pub_prep_decryption (struct BRANDT_Auction *ad)
+{
+ gcry_mpi_point_t tmp = gcry_mpi_point_new (0);
+
+ ad->phi2 = smc_init2 (ad->n, ad->k);
+ brandt_assert (ad->phi2);
+
+ for (uint16_t j = 0; j < ad->k; j++)
+ {
+ smc_sum (tmp, &ad->delta2[0][j], ad->n, ad->k);
+
+ /* copy still encrypted outcome to all other bidder layers so they
+ * don't have to be recomputed to check the ZK proof_2dle's from
+ * other bidders when receiving their outcome decryption messages */
+ for (uint16_t a = 0; a < ad->n; a++)
+ ec_point_copy (ad->phi2[a][j], tmp);
+ }
+
+ gcry_mpi_point_release (tmp);
+}
+
+
+/**
+ * fp_pub_decrypt_outcome decrypts part of the outcome and packs it into a
+ * message buffer together with proofs of correctnes.
+ *
+ * @param[in] ad Pointer to the BRANDT_Auction struct to operate on
+ * @param[out] buflen Size of the returned message buffer in bytes
+ * @return A buffer containing the own share of the decrypted outcome
+ * which needs to be broadcast
+ */
+unsigned char *
+fp_pub_decrypt_outcome (struct BRANDT_Auction *ad, size_t *buflen)
+{
+ unsigned char *ret;
+ unsigned char *cur;
+ gcry_mpi_point_t tmp = gcry_mpi_point_new (0);
+ struct msg_head *head;
+ struct ec_mpi *phi;
+ struct proof_2dle *proof2;
+
+ brandt_assert (ad && buflen);
+
+ *buflen = (sizeof (*head) + ad->k * (sizeof (*phi) + sizeof (*proof2)));
+ ret = GNUNET_new_array (*buflen, unsigned char);
+
+ head = (struct msg_head *)ret;
+ head->prot_version = htonl (0);
+ head->msg_type = htonl (msg_decrypt);
+ cur = ret + sizeof (*head);
+
+ for (uint16_t j = 0; j < ad->k; j++)
+ {
+ phi = (struct ec_mpi *)cur;
+ proof2 = (struct proof_2dle *)(cur + sizeof (*phi));
+
+ ec_point_copy (tmp, ad->phi2[ad->i][j]);
+
+ /* decrypt outcome component and prove the correct key was used */
+ smc_zkp_2dle (ad->phi2[ad->i][j],
+ NULL,
+ tmp,
+ ec_gen,
+ ad->x,
+ proof2);
+
+ ec_point_serialize (phi, ad->phi2[ad->i][j]);
+
+ cur += sizeof (*phi) + sizeof (*proof2);
+ }
+
+ gcry_mpi_point_release (tmp);
+ return ret;
+}
+
+
+int
+fp_pub_recv_decryption (struct BRANDT_Auction *ad,
+ const unsigned char *buf,
+ size_t buflen,
+ uint16_t sender)
+{
+ int ret = 0;
+ const unsigned char *cur = buf;
+ struct proof_2dle *proof2;
+ gcry_mpi_point_t phi = gcry_mpi_point_new (0);
+
+ brandt_assert (ad && buf);
+
+ if (buflen != (ad->k * (sizeof (struct ec_mpi) + sizeof (*proof2))))
+ {
+ weprintf ("wrong size of received outcome decryption");
+ goto quit;
+ }
+
+ for (uint16_t j = 0; j < ad->k; j++)
+ {
+ ec_point_parse (phi, (struct ec_mpi *)cur);
+ proof2 = (struct proof_2dle *)(cur + sizeof (struct ec_mpi));
+ if (smc_zkp_2dle_check (phi,
+ ad->y[sender],
+ ad->phi2[sender][j],
+ ec_gen,
+ proof2))
+ {
+ weprintf ("wrong zkp2 for phi, y received");
+ goto quit;
+ }
+ ec_point_copy (ad->phi2[sender][j], phi);
+ cur += sizeof (struct ec_mpi) + sizeof (*proof2);
+ }
+
+ ret = 1;
+quit:
+ gcry_mpi_point_release (phi);
+ return ret;
+}
+
+
+struct BRANDT_Result *
+fp_pub_determine_outcome (struct BRANDT_Auction *ad,
+ uint16_t *len)
+{
+ struct BRANDT_Result *ret;
+ int32_t price = -1;
+ int32_t winner = -1;
+ int dlogi = -1;
+ gcry_mpi_point_t sum_gamma = gcry_mpi_point_new (0);
+ gcry_mpi_point_t sum_phi = gcry_mpi_point_new (0);
+
+ brandt_assert (ad);
+
+ for (uint16_t j = ad->k - 1; j >= 0; j--)
+ {
+ smc_sum (sum_gamma, &ad->gamma2[0][j], ad->n, ad->k);
+ smc_sum (sum_phi, &ad->phi2[0][j], ad->n, ad->k);
+ gcry_mpi_ec_sub (sum_gamma, sum_gamma, sum_phi, ec_ctx);
+ /* first non-zero component determines the price */
+ if (ec_point_cmp (sum_gamma, ec_zero))
+ {
+ price = j;
+ break;
+ }
+ }
+
+ dlogi = GNUNET_CRYPTO_ecc_dlog (ec_dlogctx, sum_gamma);
+ brandt_assert (dlogi > 0);
+
+ /* all bidders participated with a multiplicative share */
+ dlogi /= ad->n;
+
+ /* can only support up to bits(dlogi) bidders */
+ brandt_assert (sizeof (int) * 8 - 1 >= ad->n);
+ for (uint16_t i = 0; i < ad->n; i++)
+ {
+ /* first set bit determines the winner */
+ if (dlogi & (1 << i))
+ {
+ winner = i;
+ break;
+ }
+ }
+
+ gcry_mpi_point_release (sum_gamma);
+ gcry_mpi_point_release (sum_phi);
+
+ if (-1 == winner || -1 == price)
+ return NULL;
+
+ ret = GNUNET_new (struct BRANDT_Result);
+ ret->bidder = winner;
+ ret->price = price;
+ ret->status = BRANDT_bidder_won;
+ if (len)
+ *len = 1;
+ return ret;
+}
diff --git a/internals.h b/internals.h
index 2b88b6f..373c3d4 100644
--- a/internals.h
+++ b/internals.h
@@ -164,4 +164,10 @@ struct BRANDT_Auction {
gcry_mpi_point_t *tmpb1; /** used for temporary storage, size: k */
};
+extern gcry_ctx_t ec_ctx;
+extern gcry_mpi_point_t ec_gen;
+extern gcry_mpi_point_t ec_zero;
+extern gcry_mpi_t ec_n;
+extern struct GNUNET_CRYPTO_EccDlogContext *ec_dlogctx;
+
#endif /* ifndef _BRANDT_INTERNALS_H */