diff options
| -rw-r--r-- | Makefile.am | 2 | ||||
| -rw-r--r-- | crypto.c | 978 | ||||
| -rw-r--r-- | crypto.h | 13 | ||||
| -rw-r--r-- | fp_priv.c | 584 | ||||
| -rw-r--r-- | fp_pub.c | 438 | ||||
| -rw-r--r-- | internals.h | 6 | 
6 files changed, 1050 insertions, 971 deletions
| 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 = \ @@ -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. @@ -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 <http://www.gnu.org/licenses/>. + */ + +/** + * @file fp_pub.c + * @brief Implementation of the first price public outcome algorithm. + * @author Markus Teich + */ + +#include "platform.h" + +#include <gcrypt.h> + +#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 <http://www.gnu.org/licenses/>. + */ + +/** + * @file fp_pub.c + * @brief Implementation of the first price public outcome algorithm. + * @author Markus Teich + */ + +#include "platform.h" + +#include <gcrypt.h> + +#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 */ | 
