aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crypto.c380
-rw-r--r--crypto.h5
-rw-r--r--test_crypto.c31
3 files changed, 340 insertions, 76 deletions
diff --git a/crypto.c b/crypto.c
index b8e995e..bdc5842 100644
--- a/crypto.c
+++ b/crypto.c
@@ -238,18 +238,13 @@ ec_point_cmp (const gcry_mpi_point_t a, const gcry_mpi_point_t b)
void
mpi_serialize (struct ec_mpi *dst, gcry_mpi_t src)
{
- size_t rsize = 0;
- unsigned int nbits;
- const void *vp;
- char *cp = (char *)dst;
- gcry_error_t rc;
-
+ size_t rsize = 0;
if (gcry_mpi_get_flag (src, GCRYMPI_FLAG_OPAQUE))
- {
- /* Store opaque MPIs left aligned into the buffer. Used by Ed25519 point
- * compression */
- vp = gcry_mpi_get_opaque (src, &nbits);
+ { /* Store opaque MPIs left aligned. Used by Ed25519 point compression */
+ unsigned int nbits;
+ const void *vp = gcry_mpi_get_opaque (src, &nbits);
+
brandt_assert (vp);
rsize = (nbits + 7) / 8;
if (rsize > sizeof (struct ec_mpi))
@@ -259,8 +254,10 @@ mpi_serialize (struct ec_mpi *dst, gcry_mpi_t src)
memset (((char *)dst) + rsize, 0, sizeof (struct ec_mpi) - rsize);
}
else
- {
- /* Store regular MPIs as unsigned ints right aligned into the buffer. */
+ { /* Store regular MPIs as unsigned ints right aligned into the buffer. */
+ char *cp = (char *)dst;
+ gcry_error_t rc;
+
rc = gcry_mpi_print (GCRYMPI_FMT_USG, (void *)dst,
sizeof (struct ec_mpi), &rsize, src);
brandt_assert_gpgerr (rc);
@@ -366,6 +363,57 @@ ec_point_parse (gcry_mpi_point_t dst, const struct ec_mpi *src)
/**
+ * smc_free1 releases all points in @a dst and frees the memory
+ *
+ * @param[in,out] dst The 1 dimensional array to clean up
+ * @param[in] size1 size of the first dimension
+ */
+static void
+smc_free1 (gcry_mpi_point_t *dst, uint16_t size1)
+{
+ if (NULL == dst)
+ return;
+
+ for (uint16_t i = 0; i < size1; i++)
+ if (NULL != dst[i])
+ gcry_mpi_point_release (dst[i]);
+ free (dst);
+}
+
+
+/**
+ * smc_init1 creates a 1 dimensional array of curve points
+ *
+ * @param[in] size1 size of the first dimension
+ * @return a pointer to the array or NULL on error.
+ * If not used anymore use smc_free2 to reclaim the memory.
+ */
+static gcry_mpi_point_t *
+smc_init1 (uint16_t size1)
+{
+ gcry_mpi_point_t *ret;
+
+ if (NULL == (ret = calloc (size1, sizeof (*ret))))
+ {
+ weprintf ("could not alloc memory for 1 dimensional point array");
+ return NULL;
+ }
+
+ for (uint16_t i = 0; i < size1; i++)
+ {
+ if (NULL == (ret[i] = gcry_mpi_point_new (0)))
+ {
+ weprintf ("could not init point in 1 dimensional array. "
+ "out of memory?");
+ smc_free1 (ret, size1);
+ return NULL;
+ }
+ }
+ return ret;
+}
+
+
+/**
* smc_free2 releases all points in @a dst and frees the memory
*
* @param[in,out] dst The 2 dimensional array to clean up
@@ -375,14 +423,11 @@ ec_point_parse (gcry_mpi_point_t dst, const struct ec_mpi *src)
static void
smc_free2 (gcry_mpi_point_t **dst, uint16_t size1, uint16_t size2)
{
- uint16_t i;
- uint16_t j;
-
if (NULL == dst)
return;
- for (i = 0; i < size1; i++)
- for (j = 0; j < size2; j++)
+ for (uint16_t i = 0; i < size1; i++)
+ for (uint16_t j = 0; j < size2; j++)
if (NULL != dst[i][j])
gcry_mpi_point_release (dst[i][j]);
free (dst);
@@ -400,8 +445,6 @@ smc_free2 (gcry_mpi_point_t **dst, uint16_t size1, uint16_t size2)
static gcry_mpi_point_t **
smc_init2 (uint16_t size1, uint16_t size2)
{
- uint16_t i;
- uint16_t j;
gcry_mpi_point_t **ret;
gcry_mpi_point_t *data;
@@ -412,10 +455,10 @@ smc_init2 (uint16_t size1, uint16_t size2)
}
data = (gcry_mpi_point_t *)&ret[size1];
- for (i = 0; i < size1; i++)
+ for (uint16_t i = 0; i < size1; i++)
{
ret[i] = &data[i * size2];
- for (j = 0; j < size2; j++)
+ for (uint16_t j = 0; j < size2; j++)
{
if (NULL == (ret[i][j] = gcry_mpi_point_new (0)))
{
@@ -444,16 +487,12 @@ smc_free3 (gcry_mpi_point_t ***dst,
uint16_t size2,
uint16_t size3)
{
- uint16_t i;
- uint16_t j;
- uint16_t k;
-
if (NULL == dst)
return;
- for (i = 0; i < size1; i++)
- for (j = 0; j < size2; j++)
- for (k = 0; k < size3; k++)
+ for (uint16_t i = 0; i < size1; i++)
+ for (uint16_t j = 0; j < size2; j++)
+ for (uint16_t k = 0; k < size3; k++)
if (NULL != dst[i][j][k])
gcry_mpi_point_release (dst[i][j][k]);
free (dst);
@@ -472,9 +511,6 @@ smc_free3 (gcry_mpi_point_t ***dst,
static gcry_mpi_point_t ***
smc_init3 (uint16_t size1, uint16_t size2, uint16_t size3)
{
- uint16_t i;
- uint16_t j;
- uint16_t k;
gcry_mpi_point_t ***ret;
gcry_mpi_point_t **layer1;
gcry_mpi_point_t *layer2;
@@ -489,13 +525,13 @@ smc_init3 (uint16_t size1, uint16_t size2, uint16_t size3)
layer1 = (gcry_mpi_point_t **)&ret[size1];
layer2 = (gcry_mpi_point_t *)&layer1[size1 * size2];
- for (i = 0; i < size1; i++)
+ for (uint16_t i = 0; i < size1; i++)
{
ret[i] = &layer1[i * size2];
- for (j = 0; j < size2; j++)
+ for (uint16_t j = 0; j < size2; j++)
{
layer1[i * size2 + j] = &layer2[(i * size2 + j) * size3];
- for (k = 0; k < size3; k++)
+ for (uint16_t k = 0; k < size3; k++)
{
if (NULL == (ret[i][j][k] = gcry_mpi_point_new (0)))
{
@@ -515,23 +551,26 @@ smc_init3 (uint16_t size1, uint16_t size2, uint16_t size3)
* smc_sums_partial calculates sums up until the current index and stores them
* in @a out. \f$\forall i \leq len: out_i=\sum_{h=1}^iin_h\f$
*
- * @param[out] out Where to store the resulting sums. Points may be given
- * uninitialized, but the appropriate amount of memory has to be allocated
- * beforehand.
+ * @param[out] out Where to store the resulting sums. Points must already be
+ * initialized beforehand.
* @param[in] in Input points.
- * @param[in] len The length of both @a out and @a in.
+ * @param[in] len The length of @a out. @a in must be at least @a step times @a
+ * len elements long.
+ * @param[in] stepi The amount of items to advance in @a in each step. Can be
+ * used to sum over multi-dimensional arrays.
+ * @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
-smc_sums_partial (gcry_mpi_point_t out[], gcry_mpi_point_t in[], uint16_t len)
+smc_sums_partial (gcry_mpi_point_t out[],
+ gcry_mpi_point_t in[],
+ uint16_t len,
+ uint16_t stepi,
+ uint16_t stepo)
{
- uint16_t i;
-
- for (i = 0; i < len; i++)
- {
- out[i] = gcry_mpi_point_new (0);
- gcry_mpi_ec_add (out[i], in[i], (i ? out[i - 1] : ec_zero), ec_ctx);
- brandt_assert (NULL != out[i]);
- }
+ brandt_assert (NULL != out);
+ for (uint16_t i = 0, o = 0; o < len * stepo; i += stepi, o += stepo)
+ gcry_mpi_ec_add (out[o], (o ? out[o - stepo] : ec_zero), in[i], ec_ctx);
}
@@ -541,17 +580,21 @@ smc_sums_partial (gcry_mpi_point_t out[], gcry_mpi_point_t in[], uint16_t len)
*
* @param[out] out Where to store the result
* @param[in] in Input points.
- * @param[in] len The length of @a in.
+ * @param[in] len The amount of summands to use from @a in. @a in must be at
+ * least @a step times @a len elements long.
+ * @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
-smc_sum (gcry_mpi_point_t out, gcry_mpi_point_t in[], uint16_t len)
+smc_sum (gcry_mpi_point_t out,
+ gcry_mpi_point_t in[],
+ uint16_t len,
+ uint16_t step)
{
- uint16_t i;
-
brandt_assert (NULL != out);
/**\todo: how to copy a point more efficiently? */
gcry_mpi_ec_add (out, ec_zero, ec_zero, ec_ctx);
- for (i = 0; i < len; i++)
+ for (uint16_t i = 0; i < len; i += step)
gcry_mpi_ec_add (out, out, in[i], ec_ctx);
}
@@ -567,7 +610,6 @@ smc_sum (gcry_mpi_point_t out, gcry_mpi_point_t in[], uint16_t len)
unsigned char *
smc_gen_keyshare (struct AuctionData *ad, size_t *buflen)
{
- uint16_t i;
unsigned char *ret;
struct proof_dl *proof1;
@@ -581,7 +623,7 @@ smc_gen_keyshare (struct AuctionData *ad, size_t *buflen)
}
proof1 = (struct proof_dl *)(ret + sizeof (struct ec_mpi));
- for (i = 0; i < ad->n; i++)
+ for (uint16_t i = 0; i < ad->n; i++)
ad->y[i] = gcry_mpi_point_new (0);
ad->x = gcry_mpi_new (0);
@@ -596,7 +638,7 @@ int
smc_recv_keyshare (struct AuctionData *ad,
unsigned char *buf,
size_t buflen,
- uint16_t sender_index)
+ uint16_t sender)
{
int ret = 0;
struct proof_dl *proof1;
@@ -619,7 +661,7 @@ smc_recv_keyshare (struct AuctionData *ad,
}
/**\todo: how to copy a point more efficiently? */
- gcry_mpi_ec_add (ad->y[sender_index], ec_zero, y, ec_ctx);
+ gcry_mpi_ec_add (ad->y[sender], ec_zero, y, ec_ctx);
ret = 1;
quit:
@@ -637,7 +679,6 @@ quit:
unsigned char *
smc_encrypt_bid (struct AuctionData *ad, size_t *buflen)
{
- uint16_t j;
unsigned char *ret;
unsigned char *cur;
struct proof_0og *proof3;
@@ -658,12 +699,12 @@ smc_encrypt_bid (struct AuctionData *ad, size_t *buflen)
}
ad->Y = gcry_mpi_point_new (0);
- smc_sum (ad->Y, ad->y, ad->n);
+ smc_sum (ad->Y, ad->y, ad->n, 1);
r_sum = gcry_mpi_new (0);
r_part = gcry_mpi_new (0);
- for (j = 0; j < ad->k; j++)
+ for (uint16_t j = 0; j < ad->k; j++)
{
proof3 = (struct proof_0og *)(cur + 2 * sizeof (struct ec_mpi));
smc_zkp_0og (j == ad->b,
@@ -690,10 +731,9 @@ int
smc_recv_encrypted_bid (struct AuctionData *ad,
unsigned char *buf,
size_t buflen,
- uint16_t sender_index)
+ uint16_t sender)
{
int ret = 0;
- uint16_t j;
unsigned char *cur = buf;
struct proof_0og *proof3;
gcry_mpi_point_t **ct; /* ciphertexts */
@@ -713,7 +753,7 @@ smc_recv_encrypted_bid (struct AuctionData *ad,
gcry_mpi_ec_mul (alpha_sum, GCRYMPI_CONST_ONE, ec_zero, ec_ctx);
gcry_mpi_ec_mul (beta_sum, GCRYMPI_CONST_ONE, ec_zero, ec_ctx);
- for (j = 0; j < ad->k; j++)
+ for (uint16_t j = 0; j < ad->k; j++)
{
ec_point_parse (ct[0][j], (struct ec_mpi *)cur);
ec_point_parse (ct[1][j], &((struct ec_mpi *)cur)[1]);
@@ -739,11 +779,11 @@ smc_recv_encrypted_bid (struct AuctionData *ad,
goto quit;
}
- for (j = 0; j < ad->k; j++)
+ for (uint16_t j = 0; j < ad->k; j++)
{
/**\todo: how to copy a point more efficiently? */
- gcry_mpi_ec_add (ad->alpha[sender_index][j], ec_zero, ct[0][j], ec_ctx);
- gcry_mpi_ec_add (ad->beta[sender_index][j], ec_zero, ct[1][j], ec_ctx);
+ gcry_mpi_ec_add (ad->alpha[sender][j], ec_zero, ct[0][j], ec_ctx);
+ gcry_mpi_ec_add (ad->beta[sender][j], ec_zero, ct[1][j], ec_ctx);
}
smc_free2 (ct, 2, ad->k);
@@ -759,21 +799,201 @@ quit:
* smc_compute_outcome \todo
*
* @param ad TODO
+ * @param buflen TODO
*/
-void
-smc_compute_outcome (struct AuctionData *ad)
+unsigned char *
+smc_compute_outcome (struct AuctionData *ad, size_t *buflen)
{
- uint16_t i;
- uint16_t j;
+ 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);
+ 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;
+ struct ec_mpi *gamma;
+ struct ec_mpi *delta;
+ struct proof_2dle *proof2;
- // create temporary table with partial sums
+ brandt_assert (ad && buflen);
+ *buflen = (ad->n * ad->k * /* nk * (gamma, delta, proof2) */
+ (sizeof (*gamma) + sizeof (*delta) + sizeof (*proof2)));
+ if (NULL == (cur = (ret = calloc (1, *buflen))) ||
+ NULL == (ad->gamma = smc_init3 (ad->n, ad->n, ad->k)) ||
+ NULL == (ad->delta = smc_init3 (ad->n, ad->n, ad->k)))
+ {
+ weprintf ("unable to alloc memory for first price outcome computation");
+ return NULL;
+ }
+
+ /* 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++)
+ {
+ gamma = (struct ec_mpi *)cur;
+ delta = &((struct ec_mpi *)cur)[1];
+ proof2 = (struct proof_2dle *)(cur + 2 * sizeof (struct ec_mpi));
+
+ /* 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++)
+ {
+ /**\todo: how to copy a point more efficiently? */
+ gcry_mpi_ec_add (ad->gamma[a][i][j], ec_zero, tmpa, ec_ctx);
+ gcry_mpi_ec_add (ad->delta[a][i][j], ec_zero, tmpb, ec_ctx);
+ }
+
+ /* apply random masking for losing bidders */
+ smc_zkp_2dle (ad->gamma[ad->i][i][j],
+ ad->delta[ad->i][i][j],
+ tmpa,
+ tmpb,
+ NULL,
+ proof2);
+
+ ec_point_serialize (gamma, ad->gamma[ad->i][i][j]);
+ ec_point_serialize (delta, ad->delta[ad->i][i][j]);
- for (i = 0; i < ad->n; i++)
+ cur += sizeof (*gamma) + sizeof (*delta) + sizeof (*proof2);
+ }
+ }
+
+ gcry_mpi_point_release (tmpa);
+ gcry_mpi_point_release (tmpb);
+ smc_free1 (tlta1, ad->n);
+ smc_free1 (tltb1, ad->n);
+ 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);
+ return ret;
+}
+
+
+int
+smc_recv_outcome (struct AuctionData *ad,
+ unsigned char *buf,
+ size_t buflen,
+ uint16_t sender)
+{
+ int ret = 0;
+ 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 encrypted bid");
+ 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->gamma[sender][i][j],
+ ad->delta[sender][i][j],
+ proof2))
+ {
+ weprintf ("wrong zkp2 for gamma, delta received");
+ goto quit;
+ }
+ gcry_mpi_ec_add (ad->gamma[sender][i][j], gamma, ec_zero, ec_ctx);
+ gcry_mpi_ec_add (ad->delta[sender][i][j], delta, ec_zero, ec_ctx);
+ cur += 2 * sizeof (struct ec_mpi) + sizeof (*proof2);
+ }
}
- /*\todo ZKP*/
+
+ ret = 1;
+quit:
+ gcry_mpi_point_release (gamma);
+ gcry_mpi_point_release (delta);
+ return ret;
}
@@ -885,7 +1105,8 @@ smc_zkp_dl_check (const gcry_mpi_point_t v,
* Must be known to the verifier.
* @param[in] g1 first base point. Must be known to the verifier.
* @param[in] g2 second base point. Must be known to the verifier.
- * @param[in] x private number to prove knowledge of.
+ * @param[in] x private number to prove knowledge of. May be NULL if not used by
+ * the caller.
* @param[out] proof pointer where to save the output proof structure. Must be
* shared with the verifier.
*/
@@ -901,6 +1122,7 @@ smc_zkp_2dle (gcry_mpi_point_t v,
struct brandt_hash_code challhash;
gcry_mpi_point_t rv;
gcry_mpi_point_t rw;
+ gcry_mpi_t rx;
gcry_mpi_point_t a = gcry_mpi_point_new (0);
gcry_mpi_point_t b = gcry_mpi_point_new (0);
gcry_mpi_t r = gcry_mpi_new (0);
@@ -909,12 +1131,16 @@ smc_zkp_2dle (gcry_mpi_point_t v,
rv = (NULL == v) ? gcry_mpi_point_new (0) : v;
rw = (NULL == w) ? gcry_mpi_point_new (0) : w;
+ rx = (NULL == x) ? gcry_mpi_new (0) : x;
+
+ if (NULL == x)
+ ec_skey_create (rx);
/* v = x*g1 */
- gcry_mpi_ec_mul (rv, x, g1, ec_ctx);
+ gcry_mpi_ec_mul (rv, rx, g1, ec_ctx);
/* w = x*g2 */
- gcry_mpi_ec_mul (rw, x, g2, ec_ctx);
+ gcry_mpi_ec_mul (rw, rx, g2, ec_ctx);
/* a = z*g1 */
ec_keypair_create_base (a, z, g1);
@@ -934,7 +1160,7 @@ smc_zkp_2dle (gcry_mpi_point_t v,
gcry_mpi_mod (c, c, ec_n);
/* r = z + cx */
- gcry_mpi_mulm (r, c, x, ec_n);
+ gcry_mpi_mulm (r, c, rx, ec_n);
gcry_mpi_addm (r, r, z, ec_n);
mpi_serialize (&proof->r, r);
@@ -945,6 +1171,8 @@ smc_zkp_2dle (gcry_mpi_point_t v,
gcry_mpi_point_release (rv);
if (NULL == w)
gcry_mpi_point_release (rw);
+ if (NULL == x)
+ gcry_mpi_release (rx);
gcry_mpi_point_release (a);
gcry_mpi_point_release (b);
gcry_mpi_release (r);
diff --git a/crypto.h b/crypto.h
index 77e1848..4e93e03 100644
--- a/crypto.h
+++ b/crypto.h
@@ -123,4 +123,9 @@ int smc_recv_encrypted_bid (struct AuctionData *ad,
size_t buflen,
uint16_t sender_index);
+unsigned char *smc_compute_outcome (struct AuctionData *ad, size_t *buflen);
+int smc_recv_outcome (struct AuctionData *ad,
+ unsigned char *buf,
+ size_t buflen,
+ uint16_t sender);
#endif /* ifndef _BRANDT_CRYPTO_H */
diff --git a/test_crypto.c b/test_crypto.c
index c0e9740..52db0f3 100644
--- a/test_crypto.c
+++ b/test_crypto.c
@@ -257,6 +257,36 @@ test_round1 ()
}
+int
+test_round2 ()
+{
+ uint16_t i, s;
+ unsigned char *bufs[bidders];
+ size_t lens[bidders];
+
+ for (i = 0; i < bidders; i++)
+ {
+ bufs[i] = smc_compute_outcome (&ad[i], &lens[i]);
+ check (bufs[i], "failed to encrypt bid");
+ }
+
+ for (i = 0; i < bidders; i++)
+ {
+ for (s = 0; s < bidders; s++)
+ {
+ if (s == i)
+ continue;
+ check (smc_recv_outcome (&ad[i], bufs[s], lens[s], s),
+ "failed checking outcome");
+ }
+ }
+
+ for (i = 0; i < bidders; i++)
+ free (bufs[i]);
+ return 1;
+}
+
+
void
cleanup_auction_data ()
{
@@ -299,6 +329,7 @@ main (int argc, char *argv[])
run (test_setup_auction_data);
run (test_prologue);
run (test_round1);
+ run (test_round2);
cleanup_auction_data ();
}