diff --git a/brandt.c b/brandt.c index 685c878..1c42d41 100644 --- a/brandt.c +++ b/brandt.c @@ -287,6 +287,7 @@ BRANDT_destroy (struct BRANDT_Auction *auction) smc_free3 (auction->delta3, auction->n, auction->n, auction->k); smc_free2 (auction->phi2, auction->n, auction->k); smc_free3 (auction->phi3, auction->n, auction->n, auction->k); + free (auction->phiproofs3); smc_free1 (auction->tmpa1, auction->k); smc_free1 (auction->tmpb1, auction->k); } @@ -304,56 +305,75 @@ advance_round (struct BRANDT_Auction *ad, /* if we did not got the current round message from all participants, don't * advance to the next round yet. Early return, since we have to wait for - * the other participants messages. */ + * the other participants messages. In the msg_decrypt round as a bidder we + * only need the one message from the seller. */ for (uint16_t i = 0; i < ad->n; i++) - if (!gcry_mpi_test_bit (ad->round_progress, i)) + if (!gcry_mpi_test_bit (ad->round_progress, i) && + (ad->seller_mode || msg_decrypt != ad->cur_round)) return; - /* current round finished, clear round progress and advance to next one */ - gcry_mpi_clear_highbit (ad->round_progress, 0); - if (msg_last == ++(ad->cur_round)) + /* Do not advance to the next round if we are the seller and got all + * msg_decrypt messages from the bidders. We need to broadcast our combined + * msg_decrypt message back to the sellers first */ + if (!ad->seller_mode || msg_decrypt != ad->cur_round) + { + /* clear old round progress and advance to next one */ + gcry_mpi_clear_highbit (ad->round_progress, 0); + ad->cur_round++; + + /* prepare next round. */ + if (handler_prep[atype][outcome][ad->cur_round]) + handler_prep[atype][outcome][ad->cur_round] (ad); + + /** \todo: setup round timeout trigger */ + if (ad->seller_mode) + { + } + } + + /* send next message if we are not done yet */ + if ((!ad->seller_mode && msg_last > ad->cur_round) || + (ad->seller_mode && msg_decrypt == ad->cur_round && + gcry_mpi_test_bit (ad->round_progress, 0))) + { + if (!handler_out[atype][outcome][ad->cur_round] || + !(buf = handler_out[atype][outcome][ad->cur_round](ad, &buflen))) + { + weprintf ("failed to create message %d buffer", ad->cur_round); + return; + } + + /* msg_decrypt unicast to seller or broadcast from seller. + * All other messages are broadcasted */ + if (msg_decrypt == ad->cur_round && !ad->seller_mode) + { + if (0 == ad->ucast (ad->closure, buf, buflen)) + gcry_mpi_set_bit (ad->round_progress, ad->i); + } + else + { + if (!ad->seller_mode && 0 == ad->bcast (ad->closure, buf, buflen)) + gcry_mpi_set_bit (ad->round_progress, ad->i); + } + } + + if (msg_last == ad->cur_round || + (msg_decrypt == ad->cur_round && ad->seller_mode && + gcry_mpi_test_bit (ad->round_progress, 0))) { /* done with all rounds, determine outcome here */ if (!handler_res[atype][outcome] || !(res = handler_res[atype][outcome] (ad, &reslen))) { - /** \todo */ - weprintf ("wow fail result"); + weprintf ("failed to determine result"); /** \todo: call result with null pointer here? */ return; } ad->result (ad->closure, res, reslen); - return; - } - - if (handler_prep[atype][outcome][ad->cur_round]) - handler_prep[atype][outcome][ad->cur_round] (ad); - - if (ad->seller_mode) - { - /** \todo: setup round timeout trigger */ - return; - } - - if (!handler_out[atype][outcome][ad->cur_round] || - !(buf = handler_out[atype][outcome][ad->cur_round](ad, &buflen))) - { - /** \todo */ - weprintf ("wow fail out"); - return; - } - - /* last message only sent to seller, others are broadcasted */ - if (msg_decrypt == ad->cur_round) - { - if (0 == ad->ucast (ad->closure, buf, buflen)) - gcry_mpi_set_bit (ad->round_progress, ad->i); - } - else - { - if (0 == ad->bcast (ad->closure, buf, buflen)) - gcry_mpi_set_bit (ad->round_progress, ad->i); + /* seller still needs to broadcast the decryption to all bidders */ + if (!ad->seller_mode) + return; } } @@ -400,6 +420,5 @@ BRANDT_got_message (struct BRANDT_Auction *auction, gcry_mpi_set_bit (auction->round_progress, sender); DM(auction->round_progress); - /** \todo: seller_mode and new task for round timing */ advance_round (auction, atype, outcome); } diff --git a/crypto.c b/crypto.c index edd51ad..eb7e944 100644 --- a/crypto.c +++ b/crypto.c @@ -455,18 +455,11 @@ gcry_mpi_point_t ** smc_init2 (uint16_t size1, uint16_t size2) { gcry_mpi_point_t **ret; - gcry_mpi_point_t *data; - if (NULL == (ret = calloc (size1, sizeof (*ret) + size2 * sizeof (**ret)))) - { - weprintf ("could not alloc memory for 2 dimensional point array"); - return NULL; - } + ret = GNUNET_new_array_2d (size1, size2, gcry_mpi_point_t); - data = (gcry_mpi_point_t *)&ret[size1]; for (uint16_t i = 0; i < size1; i++) { - ret[i] = &data[i * size2]; for (uint16_t j = 0; j < size2; j++) { if (NULL == (ret[i][j] = gcry_mpi_point_new (0))) @@ -523,25 +516,13 @@ gcry_mpi_point_t *** smc_init3 (uint16_t size1, uint16_t size2, uint16_t size3) { gcry_mpi_point_t ***ret; - gcry_mpi_point_t **layer1; - gcry_mpi_point_t *layer2; - if (NULL == (ret = calloc (size1, sizeof (*ret) + - size2 * sizeof (**ret) + - size2 * size3 * sizeof (***ret)))) - { - weprintf ("could not alloc memory for 3 dimensional point array"); - return NULL; - } + ret = GNUNET_new_array_3d (size1, size2, size3, gcry_mpi_point_t); - layer1 = (gcry_mpi_point_t **)&ret[size1]; - layer2 = (gcry_mpi_point_t *)&layer1[size1 * size2]; for (uint16_t i = 0; i < size1; i++) { - ret[i] = &layer1[i * size2]; for (uint16_t j = 0; j < size2; j++) { - layer1[i * size2 + j] = &layer2[(i * size2 + j) * size3]; for (uint16_t k = 0; k < size3; k++) { if (NULL == (ret[i][j][k] = gcry_mpi_point_new (0))) @@ -1476,6 +1457,12 @@ fp_priv_prep_decryption (struct BRANDT_Auction *ad) 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++) @@ -1494,17 +1481,8 @@ fp_priv_prep_decryption (struct BRANDT_Auction *ad) } -/** - * fp_priv_decrypt_outcome decrypts the own shares of the outcome 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 own share of the decrypted outcome - * which needs to be broadcast - */ -unsigned char * -fp_priv_decrypt_outcome (struct BRANDT_Auction *ad, size_t *buflen) +static unsigned char * +fp_priv_decrypt_outcome_seller (struct BRANDT_Auction *ad, size_t *buflen) { unsigned char *ret; unsigned char *cur; @@ -1513,7 +1491,51 @@ fp_priv_decrypt_outcome (struct BRANDT_Auction *ad, size_t *buflen) struct ec_mpi *phi; struct proof_2dle *proof2; - brandt_assert (ad && buflen); + *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))); @@ -1552,22 +1574,42 @@ fp_priv_decrypt_outcome (struct BRANDT_Auction *ad, size_t *buflen) } -int -fp_priv_recv_decryption (struct BRANDT_Auction *ad, - const unsigned char *buf, - size_t buflen, - uint16_t sender) +/** + * 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); - brandt_assert (ad && buf); - if (buflen != (ad->n * ad->k * (sizeof (struct ec_mpi) + sizeof (*proof2)))) { - weprintf ("wrong size of received outcome decryption"); + weprintf ("wrong size of received outcome decryption from bidder"); goto quit; } @@ -1583,9 +1625,13 @@ fp_priv_recv_decryption (struct BRANDT_Auction *ad, ec_gen, proof2)) { - weprintf ("wrong zkp2 for phi, y received"); + 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); } @@ -1598,6 +1644,79 @@ quit: } +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) { diff --git a/internals.h b/internals.h index d88e779..5290110 100644 --- a/internals.h +++ b/internals.h @@ -154,6 +154,10 @@ struct BRANDT_Auction { gcry_mpi_point_t **phi2; /** phi2, for public outcome, size: n*k */ gcry_mpi_point_t ***phi3; /** phi3, for private outcome, size: n*n*k */ + /** proofs for the correctnes of the phi values for private outcomes, + * size: n*n*k */ + struct proof_2dle ***phiproofs3; + gcry_mpi_point_t *tmpa1; /** used for temporary storage, size: k */ gcry_mpi_point_t *tmpb1; /** used for temporary storage, size: k */ }; diff --git a/test_brandt.c b/test_brandt.c index 274762d..0c7e4e2 100644 --- a/test_brandt.c +++ b/test_brandt.c @@ -91,6 +91,7 @@ cb_broadcast (void *auction_closure, { uint16_t *s = (uint16_t *)auction_closure; struct msg *m; + for (uint16_t i = 0; i <= bidders; i++) { if (i == *s) @@ -112,6 +113,18 @@ cb_unicast (void *auction_closure, const void *msg, size_t msg_len) { + uint16_t *s = (uint16_t *)auction_closure; + struct msg *m; + + m = GNUNET_new (struct msg); + m->sender = *s; + m->receiver = bidders; /* == seller */ + m->buf = GNUNET_new_array (msg_len, unsigned char); + memcpy (m->buf, msg, msg_len); + m->buf_len = msg_len; + GNUNET_SCHEDULER_add_now (&transfer_message, m); + + return 0; } @@ -145,7 +158,7 @@ run_new_join (void *arg) GNUNET_TIME_UNIT_MINUTES, prizes, /* amount of possible prizes */ 0, /* m */ - 1); + 0); if (!ad[bidders]) { weprintf ("BRANDT_new() failed."); diff --git a/test_crypto.c b/test_crypto.c index 2d1b50a..2a04c1d 100644 --- a/test_crypto.c +++ b/test_crypto.c @@ -209,11 +209,14 @@ test_setup_auction_data () { \ handler_prep[type][oc][index] (&ad[i]); \ bufs[i] = handler_out[type][oc][index] (&ad[i], &lens[i]); \ - CHECK (bufs[i], "failed to gen keyshare"); \ + CHECK (bufs[i], "failed to gen message buffer"); \ } \ \ for (uint16_t i = 0; i < bidders; i++) \ { \ + /* enable seller mode for receiving decryption messages */ \ + if (msg_decrypt == index) \ + ad[i].seller_mode = 1; \ for (uint16_t s = 0; s < bidders; s++) \ { \ if (s == i) \ @@ -224,8 +227,11 @@ test_setup_auction_data () lens[s] - \ sizeof (struct msg_head), \ s), \ - "failed checking keyshare"); \ + "failed to parse message buffer"); \ } \ + /* disable seller mode again */ \ + if (msg_decrypt == index) \ + ad[i].seller_mode = 0; \ } \ \ for (uint16_t i = 0; i < bidders; i++) \