diff --git a/Makefile.am b/Makefile.am index 0f9dd23..615870f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -10,7 +10,7 @@ libbrandt_la_SOURCES = \ util.c libbrandt_la_LIBADD = \ - -lgcrypt -lgpg-error + -lgcrypt -lgpg-error -lgnunetutil libbrandt_la_LDFLAGS = \ -version-info 0:0:0 diff --git a/brandt.c b/brandt.c index d56a607..1f53b43 100644 --- a/brandt.c +++ b/brandt.c @@ -16,9 +16,12 @@ /** * @file brandt.c - * @brief \todo + * @brief Implementation of the high level libbrandt interface. * @author Markus Teich */ + +#include "brandt_config.h" + #include #include "crypto.h" @@ -33,6 +36,20 @@ typedef int uint16_t sender); +enum { + auction_firstPrice, + auction_mPlusFirstPrice, + auction_last +}; + + +enum { + outcome_private, + outcome_public, + outcome_last +}; + + /** * stores the function pointers to receive functions for each state. * @@ -43,43 +60,43 @@ typedef int * The second index denotes if the outcome should be public or private. A value * of 0 means a private outcome, while a value of 1 means public outcome. */ -static msg_recv handler_in[2][2][msg_last] = +static msg_recv handler_in[auction_last][outcome_last][msg_last] = { - [0] = + [auction_firstPrice] = { - [0] = + [outcome_private] = { - [msg_init] = smc_recv_keyshare, - [msg_bid] = smc_recv_encrypted_bid, - [msg_outcome] = fp_priv_recv_outcome, - [msg_decrypt] = fp_priv_recv_decryption, + [msg_init] = &smc_recv_keyshare, + [msg_bid] = &smc_recv_encrypted_bid, + [msg_outcome] = &fp_priv_recv_outcome, + [msg_decrypt] = &fp_priv_recv_decryption, }, - [1] = + [outcome_public] = { - [msg_init] = smc_recv_keyshare, - [msg_bid] = smc_recv_encrypted_bid, - [msg_outcome] = fp_pub_recv_outcome, - [msg_decrypt] = fp_pub_recv_decryption, + [msg_init] = &smc_recv_keyshare, + [msg_bid] = &smc_recv_encrypted_bid, + [msg_outcome] = &fp_pub_recv_outcome, + [msg_decrypt] = &fp_pub_recv_decryption, } }, - [1] = + [auction_mPlusFirstPrice] = { - [0] = + [outcome_private] = { - [msg_init] = smc_recv_keyshare, - [msg_bid] = smc_recv_encrypted_bid, + [msg_init] = &smc_recv_keyshare, + [msg_bid] = &smc_recv_encrypted_bid, }, - [1] = + [outcome_public] = { - [msg_init] = smc_recv_keyshare, - [msg_bid] = smc_recv_encrypted_bid, + [msg_init] = &smc_recv_keyshare, + [msg_bid] = &smc_recv_encrypted_bid, } } }; void -BRANDT_init () +BRANDT_init (struct GNUNET_CRYPTO_EccDlogContext *dlogctx) { gcry_error_t err = 0; @@ -97,7 +114,7 @@ BRANDT_init () gcry_strerror (err)); gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); - brandt_crypto_init (); + brandt_crypto_init (dlogctx); } @@ -107,21 +124,23 @@ BRANDT_got_message (struct BRANDT_Auction *auction, const unsigned char *msg, size_t msg_len) { - uint16_t type = *(uint16_t *)msg; - int m = !!auction->desc->m; - int pub = !!auction->desc->outcome_public; + uint16_t mtype = *(uint16_t *)msg; + int atype; + int outcome; enum rounds round = auction->cur_round; - /** todo: cache out of order messages */ + atype = auction->desc->m > 0 ? auction_mPlusFirstPrice : auction_firstPrice; + outcome = auction->desc->outcome_public ? outcome_public : outcome_private; - if (!handler_in[m][pub][round] || - !handler_in[m][pub][round](auction, - msg + sizeof (type), - msg_len - sizeof (type), - sender)) + /** \todo: cache out of order messages */ + + if (!handler_in[atype][outcome][round] || + !handler_in[atype][outcome][round](auction, + msg + sizeof (mtype), + msg_len - sizeof (mtype), + sender)) { /** \todo */ weprintf ("wow fail"); } - msg + sizeof (type); } diff --git a/brandt.h b/brandt.h index dd1c8a0..fe50896 100644 --- a/brandt.h +++ b/brandt.h @@ -26,6 +26,8 @@ #include #include +#include + /** defined in internals.h */ struct BRANDT_Auction; @@ -86,7 +88,7 @@ typedef void void -BRANDT_init (); +BRANDT_init (struct GNUNET_CRYPTO_EccDlogContext *dlogctx); /** * Join an auction described by the @a auction_data parameter. diff --git a/crypto.c b/crypto.c index 9c2e272..3140ec6 100644 --- a/crypto.c +++ b/crypto.c @@ -20,6 +20,7 @@ * @author Markus Teich */ +#include "brandt_config.h" #include #include @@ -61,17 +62,22 @@ 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 GNUNET_CRYPTO_EccDlogContext *ec_dlogctx; /** * brandt_crypto_init initializes the crypto system and must be called before * any other function from this file. + * + * @param[in] dlogctx Pointer to the prepared dlog context. */ void -brandt_crypto_init () +brandt_crypto_init (GNUNET_CRYPTO_EccDlogContext *dlogctx) { gcry_error_t rc; + ec_dlogctx = dlogctx; + rc = gcry_mpi_ec_new (&ec_ctx, NULL, CURVE); brandt_assert_gpgerr (rc); @@ -159,7 +165,7 @@ ec_keypair_create (gcry_mpi_point_t pkey, gcry_mpi_t skey) gcry_mpi_t sk; brandt_assert (NULL != pkey); - sk = (NULL == skey) ? gcry_mpi_new (0) : skey; + sk = (NULL == skey) ? gcry_mpi_new (256) : skey; ec_skey_create (sk); gcry_mpi_ec_mul (pkey, sk, ec_gen, ec_ctx); @@ -190,6 +196,25 @@ ec_keypair_create_base (gcry_mpi_point_t pkey, } +/** + * ec_point_copy creates a copy of one curve point + * + * @param[out] dst where to store the copy + * @param[in] src the input point to be copied + */ +void +ec_point_copy (gcry_mpi_point_t dst, const gcry_mpi_point_t src) +{ + gcry_mpi_t x = gcry_mpi_new (256); + gcry_mpi_t y = gcry_mpi_new (256); + gcry_mpi_t z = gcry_mpi_new (256); + + brandt_assert (dst && src); + gcry_mpi_point_get (x, y, z, src); + gcry_mpi_point_snatch_set (dst, x, y, z); +} + + /** * ec_point_cmp compares two curve points * @@ -202,10 +227,10 @@ int ec_point_cmp (const gcry_mpi_point_t a, const gcry_mpi_point_t b) { int ret = 1; - gcry_mpi_t ax = gcry_mpi_new (0); - gcry_mpi_t bx = gcry_mpi_new (0); - gcry_mpi_t ay = gcry_mpi_new (0); - gcry_mpi_t by = gcry_mpi_new (0); + gcry_mpi_t ax = gcry_mpi_new (256); + gcry_mpi_t bx = gcry_mpi_new (256); + gcry_mpi_t ay = gcry_mpi_new (256); + gcry_mpi_t by = gcry_mpi_new (256); brandt_assert (a && b); if (!ax || !bx || !ay || !by) @@ -592,8 +617,7 @@ smc_sum (gcry_mpi_point_t out, uint16_t step) { brandt_assert (NULL != out); - /**\todo: how to copy a point more efficiently? */ - gcry_mpi_ec_add (out, ec_zero, ec_zero, ec_ctx); + ec_point_copy (out, ec_zero); for (uint16_t i = 0; i < len * step; i += step) gcry_mpi_ec_add (out, out, in[i], ec_ctx); } @@ -603,12 +627,12 @@ smc_sum (gcry_mpi_point_t out, * smc_gen_keyshare creates the private additive keyshare and computes the * public multiplicative key share * - * @param[in,out] ad Pointer to the AuctionData struct to operate on + * @param[in,out] ad Pointer to the BRANDT_Auction struct to operate on * @param[out] buflen \todo * @return \todo */ unsigned char * -smc_gen_keyshare (struct AuctionData *ad, size_t *buflen) +smc_gen_keyshare (struct BRANDT_Auction *ad, size_t *buflen) { unsigned char *ret; struct proof_dl *proof1; @@ -624,7 +648,7 @@ smc_gen_keyshare (struct AuctionData *ad, size_t *buflen) proof1 = (struct proof_dl *)(ret + sizeof (struct ec_mpi)); - ad->x = gcry_mpi_new (0); + ad->x = gcry_mpi_new (256); ec_skey_create (ad->x); smc_zkp_dl (ad->y[ad->i], ad->x, proof1); ec_point_serialize ((struct ec_mpi *)ret, ad->y[ad->i]); @@ -633,8 +657,8 @@ smc_gen_keyshare (struct AuctionData *ad, size_t *buflen) int -smc_recv_keyshare (struct AuctionData *ad, - unsigned char *buf, +smc_recv_keyshare (struct BRANDT_Auction *ad, + const unsigned char *buf, size_t buflen, uint16_t sender) { @@ -658,8 +682,7 @@ smc_recv_keyshare (struct AuctionData *ad, goto quit; } - /**\todo: how to copy a point more efficiently? */ - gcry_mpi_ec_add (ad->y[sender], ec_zero, y, ec_ctx); + ec_point_copy (ad->y[sender], y); ret = 1; quit: @@ -675,7 +698,7 @@ quit: * @param buflen TODO */ unsigned char * -smc_encrypt_bid (struct AuctionData *ad, size_t *buflen) +smc_encrypt_bid (struct BRANDT_Auction *ad, size_t *buflen) { unsigned char *ret; unsigned char *cur; @@ -699,8 +722,8 @@ smc_encrypt_bid (struct AuctionData *ad, size_t *buflen) ad->Y = gcry_mpi_point_new (0); smc_sum (ad->Y, ad->y, ad->n, 1); - r_sum = gcry_mpi_new (0); - r_part = gcry_mpi_new (0); + r_sum = gcry_mpi_new (256); + r_part = gcry_mpi_new (256); for (uint16_t j = 0; j < ad->k; j++) { @@ -726,13 +749,13 @@ smc_encrypt_bid (struct AuctionData *ad, size_t *buflen) int -smc_recv_encrypted_bid (struct AuctionData *ad, - unsigned char *buf, +smc_recv_encrypted_bid (struct BRANDT_Auction *ad, + const unsigned char *buf, size_t buflen, uint16_t sender) { int ret = 0; - unsigned char *cur = buf; + const unsigned char *cur = buf; struct proof_0og *proof3; gcry_mpi_point_t **ct; /* ciphertexts */ gcry_mpi_point_t alpha_sum = gcry_mpi_point_new (0); @@ -748,8 +771,8 @@ smc_recv_encrypted_bid (struct AuctionData *ad, goto quit; } - 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); + ec_point_copy (alpha_sum, ec_zero); + ec_point_copy (beta_sum, ec_zero); for (uint16_t j = 0; j < ad->k; j++) { @@ -779,9 +802,8 @@ smc_recv_encrypted_bid (struct AuctionData *ad, for (uint16_t j = 0; j < ad->k; j++) { - /**\todo: how to copy a point more efficiently? */ - 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); + ec_point_copy (ad->alpha[sender][j], ct[0][j]); + ec_point_copy (ad->beta[sender][j], ct[1][j]); } smc_free2 (ct, 2, ad->k); @@ -794,13 +816,345 @@ quit: /** - * smc_compute_outcome \todo + * fp_pub_compute_outcome \todo * * @param ad TODO * @param buflen TODO */ unsigned char * -smc_compute_outcome (struct AuctionData *ad, size_t *buflen) +fp_pub_compute_outcome (struct BRANDT_Auction *ad, size_t *buflen) +{ + unsigned char *ret; + unsigned char *cur; + 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; + struct ec_mpi *gamma; + struct ec_mpi *delta; + struct proof_2dle *proof2; + + brandt_assert (ad && buflen); + + *buflen = (ad->k * (sizeof (*gamma) + sizeof (*delta) + sizeof (*proof2))); + if (NULL == (cur = (ret = calloc (1, *buflen))) || + NULL == (ad->gamma2 = smc_init2 (ad->n, ad->k)) || + NULL == (ad->delta2 = smc_init2 (ad->n, ad->k)) || + NULL == (ad->tmpa1 = smc_init1 (ad->k)) || + NULL == (ad->tmpb1 = smc_init1 (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); + + /* 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])); + + /* temporarily store the \sum_{i=1}^n2^{i-1}b_i in tmp1, 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_mul_ui (coeff, coeff, 2); + } + + 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)); + + /* 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]); + } + + /* apply random masking for losing bidders */ + smc_zkp_2dle (ad->gamma2[ad->i][j], + ad->delta2[ad->i][j], + tlta1[j], + tltb1[j], + 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_release (coeff); + gcry_mpi_point_release (tmp); + smc_free1 (tlta1, ad->k); + smc_free1 (tltb1, ad->k); + 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; +} + + +/** + * fp_pub_decrypt_outcome \todo + * + * @param ad TODO + * @param buflen TODO + */ +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 ec_mpi *phi; + struct proof_2dle *proof2; + + brandt_assert (ad && buflen); + + *buflen = (ad->k * (sizeof (*phi) + sizeof (*proof2))); + if (NULL == (cur = (ret = calloc (1, *buflen))) || + NULL == (ad->phi2 = smc_init2 (ad->n, ad->k))) + { + weprintf ("unable to alloc memory for first price outcome decryption"); + return NULL; + } + + for (uint16_t j = 0; j < ad->k; j++) + { + phi = (struct ec_mpi *)cur; + proof2 = (struct proof_2dle *)(cur + sizeof (*phi)); + + smc_sum (tmp, &ad->delta2[0][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->phi2[a][j], tmp); + + /* 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; +} + + +int32_t +fp_pub_determine_outcome (struct BRANDT_Auction *ad, uint16_t *winner) +{ + int32_t ret = -1; + int dlogi = -1; + gcry_mpi_t dlog = gcry_mpi_new (256); + 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)) + { + ret = j; + break; + } + } + + dlogi = GNUNET_CRYPTO_ecc_dlog (ec_dlogctx, sum_gamma); + brandt_assert (dlogi > 0); + gcry_mpi_set_ui (dlog, (unsigned long)dlogi); + + for (uint16_t i = 0; i < ad->n; i++) + { + if (gcry_mpi_test_bit (dlog, i)) + { + if (winner) + winner = i; + break; + } + } + + gcry_mpi_release (dlog); + gcry_mpi_point_release (sum_gamma); + gcry_mpi_point_release (sum_phi); + return ret; +} + + +/** + * fp_priv_compute_outcome \todo + * + * @param ad TODO + * @param buflen TODO + */ +unsigned char * +fp_priv_compute_outcome (struct BRANDT_Auction *ad, size_t *buflen) { unsigned char *ret; unsigned char *cur; @@ -821,8 +1175,8 @@ smc_compute_outcome (struct AuctionData *ad, size_t *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))) + NULL == (ad->gamma3 = smc_init3 (ad->n, ad->n, ad->k)) || + NULL == (ad->delta3 = smc_init3 (ad->n, ad->n, ad->k))) { weprintf ("unable to alloc memory for first price outcome computation"); return NULL; @@ -912,21 +1266,20 @@ smc_compute_outcome (struct AuctionData *ad, size_t *buflen) * 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); + ec_point_copy (ad->gamma3[a][i][j], tmpa); + ec_point_copy (ad->delta3[a][i][j], tmpb); } /* apply random masking for losing bidders */ - smc_zkp_2dle (ad->gamma[ad->i][i][j], - ad->delta[ad->i][i][j], + smc_zkp_2dle (ad->gamma3[ad->i][i][j], + ad->delta3[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]); + 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); } @@ -945,13 +1298,13 @@ 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) +fp_priv_recv_outcome (struct BRANDT_Auction *ad, + const unsigned char *buf, + size_t buflen, + uint16_t sender) { int ret = 0; - unsigned char *cur = buf; + 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); @@ -974,15 +1327,15 @@ smc_recv_outcome (struct AuctionData *ad, 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], + ad->gamma3[sender][i][j], + ad->delta3[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); + 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); } } @@ -996,13 +1349,13 @@ quit: /** - * smc_decrypt_outcome \todo + * fp_priv_decrypt_outcome \todo * * @param ad TODO * @param buflen TODO */ unsigned char * -smc_decrypt_outcome (struct AuctionData *ad, size_t *buflen) +fp_priv_decrypt_outcome (struct BRANDT_Auction *ad, size_t *buflen) { unsigned char *ret; unsigned char *cur; @@ -1014,7 +1367,7 @@ smc_decrypt_outcome (struct AuctionData *ad, size_t *buflen) *buflen = (ad->n * ad->k * (sizeof (*phi) + sizeof (*proof2))); if (NULL == (cur = (ret = calloc (1, *buflen))) || - NULL == (ad->phi = smc_init3 (ad->n, ad->n, ad->k))) + NULL == (ad->phi3 = smc_init3 (ad->n, ad->n, ad->k))) { weprintf ("unable to alloc memory for first price outcome decryption"); return NULL; @@ -1027,24 +1380,23 @@ smc_decrypt_outcome (struct AuctionData *ad, size_t *buflen) phi = (struct ec_mpi *)cur; proof2 = (struct proof_2dle *)(cur + sizeof (*phi)); - smc_sum (tmp, &ad->delta[0][i][j], ad->n, ad->n * ad->k); + 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++) - /**\todo: how to copy a point more efficiently? */ - gcry_mpi_ec_add (ad->phi[a][i][j], ec_zero, tmp, ec_ctx); + ec_point_copy (ad->phi3[a][i][j], tmp); /* decrypt outcome component and prove the correct key was used */ - smc_zkp_2dle (ad->phi[ad->i][i][j], + smc_zkp_2dle (ad->phi3[ad->i][i][j], NULL, tmp, ec_gen, ad->x, proof2); - ec_point_serialize (phi, ad->phi[ad->i][i][j]); + ec_point_serialize (phi, ad->phi3[ad->i][i][j]); cur += sizeof (*phi) + sizeof (*proof2); } @@ -1056,13 +1408,13 @@ smc_decrypt_outcome (struct AuctionData *ad, size_t *buflen) int -smc_recv_decryption (struct AuctionData *ad, - unsigned char *buf, - size_t buflen, - uint16_t sender) +fp_priv_recv_decryption (struct BRANDT_Auction *ad, + const unsigned char *buf, + size_t buflen, + uint16_t sender) { int ret = 0; - unsigned char *cur = buf; + const unsigned char *cur = buf; struct proof_2dle *proof2; gcry_mpi_point_t phi = gcry_mpi_point_new (0); @@ -1082,14 +1434,14 @@ smc_recv_decryption (struct AuctionData *ad, proof2 = (struct proof_2dle *)(cur + sizeof (struct ec_mpi)); if (smc_zkp_2dle_check (phi, ad->y[sender], - ad->phi[sender][i][j], + ad->phi3[sender][i][j], ec_gen, proof2)) { weprintf ("wrong zkp2 for phi, y received"); goto quit; } - gcry_mpi_ec_add (ad->phi[sender][i][j], phi, ec_zero, ec_ctx); + ec_point_copy (ad->phi3[sender][i][j], phi); cur += sizeof (struct ec_mpi) + sizeof (*proof2); } } @@ -1102,7 +1454,7 @@ quit: int32_t -smc_determine_outcome (struct AuctionData *ad) +fp_priv_determine_outcome (struct BRANDT_Auction *ad) { int32_t ret = -1; gcry_mpi_point_t sum_gamma = gcry_mpi_point_new (0); @@ -1112,8 +1464,8 @@ smc_determine_outcome (struct AuctionData *ad) for (uint16_t j = 0; j < ad->k; j++) { - smc_sum (sum_gamma, &ad->gamma[0][ad->i][j], ad->n, ad->n * ad->k); - smc_sum (sum_phi, &ad->phi[0][ad->i][j], ad->n, ad->n * ad->k); + smc_sum (sum_gamma, &ad->gamma3[0][ad->i][j], ad->n, ad->n * ad->k); + smc_sum (sum_phi, &ad->phi3[0][ad->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)) { @@ -1149,9 +1501,9 @@ smc_zkp_dl (gcry_mpi_point_t v, struct zkp_challenge_dl challenge; struct brandt_hash_code challhash; gcry_mpi_point_t a = gcry_mpi_point_new (0); - gcry_mpi_t r = gcry_mpi_new (0); - gcry_mpi_t c = gcry_mpi_new (0); - gcry_mpi_t z = gcry_mpi_new (0); + gcry_mpi_t r = gcry_mpi_new (256); + gcry_mpi_t c = gcry_mpi_new (256); + gcry_mpi_t z = gcry_mpi_new (256); /* v = xg */ gcry_mpi_ec_mul (v, x, ec_gen, ec_ctx); @@ -1197,8 +1549,8 @@ smc_zkp_dl_check (const gcry_mpi_point_t v, struct zkp_challenge_dl challenge; struct brandt_hash_code challhash; gcry_mpi_point_t a = gcry_mpi_point_new (0); - gcry_mpi_t r = gcry_mpi_new (0); - gcry_mpi_t c = gcry_mpi_new (0); + gcry_mpi_t r = gcry_mpi_new (256); + gcry_mpi_t c = gcry_mpi_new (256); gcry_mpi_point_t left = gcry_mpi_point_new (0); gcry_mpi_point_t right = gcry_mpi_point_new (0); @@ -1260,13 +1612,13 @@ smc_zkp_2dle (gcry_mpi_point_t v, 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); - gcry_mpi_t c = gcry_mpi_new (0); - gcry_mpi_t z = gcry_mpi_new (0); + gcry_mpi_t r = gcry_mpi_new (256); + gcry_mpi_t c = gcry_mpi_new (256); + gcry_mpi_t z = gcry_mpi_new (256); 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; + rx = (NULL == x) ? gcry_mpi_new (256) : x; if (NULL == x) ec_skey_create (rx); @@ -1339,8 +1691,8 @@ smc_zkp_2dle_check (const gcry_mpi_point_t v, struct brandt_hash_code challhash; 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); - gcry_mpi_t c = gcry_mpi_new (0); + gcry_mpi_t r = gcry_mpi_new (256); + gcry_mpi_t c = gcry_mpi_new (256); gcry_mpi_point_t left = gcry_mpi_point_new (0); gcry_mpi_point_t right = gcry_mpi_point_new (0); @@ -1415,15 +1767,15 @@ smc_zkp_0og (int m_is_gen, gcry_mpi_point_t a2 = gcry_mpi_point_new (0); gcry_mpi_point_t b1 = gcry_mpi_point_new (0); gcry_mpi_point_t b2 = gcry_mpi_point_new (0); - gcry_mpi_t d1 = gcry_mpi_new (0); - gcry_mpi_t d2 = gcry_mpi_new (0); - gcry_mpi_t r1 = gcry_mpi_new (0); - gcry_mpi_t r2 = gcry_mpi_new (0); - gcry_mpi_t c = gcry_mpi_new (0); + gcry_mpi_t d1 = gcry_mpi_new (256); + gcry_mpi_t d2 = gcry_mpi_new (256); + gcry_mpi_t r1 = gcry_mpi_new (256); + gcry_mpi_t r2 = gcry_mpi_new (256); + gcry_mpi_t c = gcry_mpi_new (256); gcry_mpi_t rr; - gcry_mpi_t w = gcry_mpi_new (0); + gcry_mpi_t w = gcry_mpi_new (256); - rr = (NULL == r) ? gcry_mpi_new (0) : r; + rr = (NULL == r) ? gcry_mpi_new (256) : r; /* beta = r*g */ ec_keypair_create (beta, rr); @@ -1559,12 +1911,12 @@ smc_zkp_0og_check (const gcry_mpi_point_t y, gcry_mpi_point_t a2 = gcry_mpi_point_new (0); gcry_mpi_point_t b1 = gcry_mpi_point_new (0); gcry_mpi_point_t b2 = gcry_mpi_point_new (0); - gcry_mpi_t d1 = gcry_mpi_new (0); - gcry_mpi_t d2 = gcry_mpi_new (0); - gcry_mpi_t r1 = gcry_mpi_new (0); - gcry_mpi_t r2 = gcry_mpi_new (0); - gcry_mpi_t c = gcry_mpi_new (0); - gcry_mpi_t sum = gcry_mpi_new (0); + gcry_mpi_t d1 = gcry_mpi_new (256); + gcry_mpi_t d2 = gcry_mpi_new (256); + gcry_mpi_t r1 = gcry_mpi_new (256); + gcry_mpi_t r2 = gcry_mpi_new (256); + gcry_mpi_t c = gcry_mpi_new (256); + gcry_mpi_t sum = gcry_mpi_new (256); gcry_mpi_point_t right = gcry_mpi_point_new (0); gcry_mpi_point_t tmp = gcry_mpi_point_new (0); @@ -1635,52 +1987,3 @@ smc_zkp_0og_check (const gcry_mpi_point_t y, weprintf ("ret: 0x%x", ret); return ret; } - - -/* --- unused stuff, might become useful later --- */ - -///** -// * Clear memory that was used to store a private key. -// * -// * @param skey the key -// */ -//void -//brandt_ec_key_clear (gcry_mpi_t skey) -//{ -// gcry_mpi_randomize (skey, 256, GCRY_WEAK_RANDOM); -// gcry_mpi_release (skey); -//} - - -///** -// * Generate a random value mod n. -// * -// * @param edc ECC context -// * @return random value mod n. -// */ -//gcry_mpi_t -//GNUNET_CRYPTO_ecc_random_mod_n (struct GNUNET_CRYPTO_EccDlogContext *edc) -//{ -// gcry_mpi_t n; -// unsigned int highbit; -// gcry_mpi_t r; -// -// n = gcry_mpi_ec_get_mpi ("n", edc->ctx, 1); -// -// /* check public key for number of bits, bail out if key is all zeros */ -// highbit = 256; /* Curve25519 */ -// while ( (! gcry_mpi_test_bit (n, highbit)) && -// (0 != highbit) ) -// highbit--; -// GNUNET_assert (0 != highbit); -// /* generate fact < n (without bias) */ -// GNUNET_assert (NULL != (r = gcry_mpi_new (0))); -// do { -// gcry_mpi_randomize (r, -// highbit + 1, -// GCRY_STRONG_RANDOM); -// } -// while (gcry_mpi_cmp (r, n) >= 0); -// gcry_mpi_release (n); -// return r; -//} diff --git a/crypto.h b/crypto.h index 8d2983c..6e1d938 100644 --- a/crypto.h +++ b/crypto.h @@ -26,9 +26,11 @@ #include #include +#include + #include "internals.h" -void brandt_crypto_init (); +void brandt_crypto_init (struct GNUNET_CRYPTO_EccDlogContext *dlogctx); /* --- HASHING --- */ @@ -48,6 +50,7 @@ struct ec_mpi { unsigned char data[256 / 8]; }; +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); void ec_keypair_create (gcry_mpi_point_t pkey, gcry_mpi_t skey); @@ -111,30 +114,42 @@ int smc_zkp_0og_check (const gcry_mpi_point_t y, /* --- Protocol implementation --- */ -unsigned char *smc_gen_keyshare (struct AuctionData *ad, size_t *buflen); -int smc_recv_keyshare (struct AuctionData *ad, - unsigned char *buf, +unsigned char *smc_gen_keyshare (struct BRANDT_Auction *ad, size_t *buflen); +int smc_recv_keyshare (struct BRANDT_Auction *ad, + const unsigned char *buf, size_t buflen, uint16_t sender_index); -unsigned char *smc_encrypt_bid (struct AuctionData *ad, size_t *buflen); -int smc_recv_encrypted_bid (struct AuctionData *ad, - unsigned char *buf, +unsigned char *smc_encrypt_bid (struct BRANDT_Auction *ad, size_t *buflen); +int smc_recv_encrypted_bid (struct BRANDT_Auction *ad, + const unsigned char *buf, 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); +unsigned char *fp_priv_compute_outcome (struct BRANDT_Auction *ad, size_t *buflen); +int fp_priv_recv_outcome (struct BRANDT_Auction *ad, + const unsigned char *buf, + size_t buflen, + uint16_t sender); -unsigned char *smc_decrypt_outcome (struct AuctionData *ad, size_t *buflen); -int smc_recv_decryption (struct AuctionData *ad, - unsigned char *buf, - size_t buflen, - uint16_t sender); +unsigned char *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); -int32_t smc_determine_outcome (struct AuctionData *ad); +unsigned char *fp_pub_compute_outcome (struct BRANDT_Auction *ad, size_t *buflen); +int fp_pub_recv_outcome (struct BRANDT_Auction *ad, + const unsigned char *buf, + size_t buflen, + uint16_t sender); + +unsigned char *fp_pub_decrypt_outcome (struct BRANDT_Auction *ad, size_t *buflen); +int fp_pub_recv_decryption (struct BRANDT_Auction *ad, + const unsigned char *buf, + size_t buflen, + uint16_t sender); + +int32_t fp_priv_determine_outcome (struct BRANDT_Auction *ad); #endif /* ifndef _BRANDT_CRYPTO_H */ diff --git a/internals.h b/internals.h index 7dab0d6..4624347 100644 --- a/internals.h +++ b/internals.h @@ -40,8 +40,10 @@ enum rounds { /** * This struct describes an auction and has to be followed by #description_len * bytes of arbitrary data where the description of the item to be sold is - * stored. */ -struct AuctionDescr { + * stored. + * + * \todo: align to a multiple of 64bit */ +struct BRANDT_AuctionDescrP { /** The length of the description in bytes directly following this struct */ uint32_t description_len; @@ -55,11 +57,13 @@ struct AuctionDescr { /** The amount of possible prices */ uint16_t price_range; + + /** \todo: time */ }; struct BRANDT_Auction { - struct AuctionDescr *desc; /** pointer to the auction information */ + struct BRANDT_AuctionDescrP *desc; /** pointer to the auction information */ BRANDT_CbBroadcast bcast; /** broadcast callback */ BRANDT_CbUnicast ucast; /** unicast callback */ diff --git a/test_crypto.c b/test_crypto.c index c1774e4..b039011 100644 --- a/test_crypto.c +++ b/test_crypto.c @@ -20,6 +20,8 @@ * @author Markus Teich */ +#include "brandt_config.h" + /* For testing static functions and variables we include the whole source */ #include "crypto.c" @@ -30,7 +32,7 @@ static uint16_t bidders; static uint16_t prizes; -static struct AuctionData *ad; +static struct BRANDT_Auction *ad; int test_smc_2d_array () @@ -79,8 +81,8 @@ test_serialization () { gcry_mpi_point_t oldp = gcry_mpi_point_new (0); gcry_mpi_point_t newp = gcry_mpi_point_new (0); - gcry_mpi_t oldi = gcry_mpi_new (0); - gcry_mpi_t newi = gcry_mpi_new (0); + gcry_mpi_t oldi = gcry_mpi_new (256); + gcry_mpi_t newi = gcry_mpi_new (256); struct ec_mpi serp; struct ec_mpi seri; @@ -111,7 +113,7 @@ int test_smc_zkp_dl () { struct proof_dl proof; - gcry_mpi_t x = gcry_mpi_new (0); + gcry_mpi_t x = gcry_mpi_new (256); gcry_mpi_point_t v = gcry_mpi_point_new (0); ec_skey_create (x); @@ -130,7 +132,7 @@ int test_smc_zkp_2dle () { struct proof_2dle proof; - gcry_mpi_t x = gcry_mpi_new (0); + gcry_mpi_t x = gcry_mpi_new (256); gcry_mpi_point_t g1 = gcry_mpi_point_new (0); gcry_mpi_point_t g2 = gcry_mpi_point_new (0); gcry_mpi_point_t v = gcry_mpi_point_new (0); @@ -184,7 +186,7 @@ test_setup_auction_data () { uint16_t i; - ad = calloc (bidders, sizeof (struct AuctionData)); + ad = calloc (bidders, sizeof (struct BRANDT_Auction)); for (i = 0; i < bidders; i++) { @@ -266,7 +268,7 @@ test_round2 () for (i = 0; i < bidders; i++) { - bufs[i] = smc_compute_outcome (&ad[i], &lens[i]); + bufs[i] = fp_priv_compute_outcome (&ad[i], &lens[i]); check (bufs[i], "failed to compute outcome"); } @@ -276,7 +278,7 @@ test_round2 () { if (s == i) continue; - check (smc_recv_outcome (&ad[i], bufs[s], lens[s], s), + check (fp_priv_recv_outcome (&ad[i], bufs[s], lens[s], s), "failed checking outcome"); } } @@ -296,7 +298,7 @@ test_round3 () for (i = 0; i < bidders; i++) { - bufs[i] = smc_decrypt_outcome (&ad[i], &lens[i]); + bufs[i] = fp_priv_decrypt_outcome (&ad[i], &lens[i]); check (bufs[i], "failed to decrypt outcome"); } @@ -306,7 +308,7 @@ test_round3 () { if (s == i) continue; - check (smc_recv_decryption (&ad[i], bufs[s], lens[s], s), + check (fp_priv_recv_decryption (&ad[i], bufs[s], lens[s], s), "failed checking decrypted outcome"); } } @@ -324,7 +326,7 @@ test_outcome () for (uint16_t i = 0; i < ad->n; i++) { - if (-1 != smc_determine_outcome (&ad[i])) + if (-1 != fp_priv_determine_outcome (&ad[i])) { check (-1 == ret, "multiple winners detected"); ret = i; @@ -346,9 +348,14 @@ cleanup_auction_data () smc_free1 (ad[i].y, ad[i].n); smc_free2 (ad[i].alpha, ad[i].n, ad[i].k); smc_free2 (ad[i].beta, ad[i].n, ad[i].k); - smc_free3 (ad[i].gamma, ad[i].n, ad[i].n, ad[i].k); - smc_free3 (ad[i].delta, ad[i].n, ad[i].n, ad[i].k); - smc_free3 (ad[i].phi, ad[i].n, ad[i].n, ad[i].k); + smc_free2 (ad[i].gamma2, ad[i].n, ad[i].k); + smc_free2 (ad[i].delta2, ad[i].n, ad[i].k); + smc_free2 (ad[i].phi2, ad[i].n, ad[i].k); + smc_free3 (ad[i].gamma3, ad[i].n, ad[i].n, ad[i].k); + smc_free3 (ad[i].delta3, ad[i].n, ad[i].n, ad[i].k); + smc_free3 (ad[i].phi3, ad[i].n, ad[i].n, ad[i].k); + smc_free1 (ad[i].tmpa1, ad[i].k); + smc_free1 (ad[i].tmpb1, ad[i].k); } free (ad); } @@ -358,11 +365,13 @@ int main (int argc, char *argv[]) { int repeat = 8; + struct GNUNET_CRYPTO_EccDlogContext *edc; bidders = 2; prizes = 2 * bidders; - BRANDT_init (); + edc = GNUNET_CRYPTO_ecc_dlog_prepare (1024 * 1024, 1024); + BRANDT_init (edc); /* tests that need to run only once */ run (test_smc_2d_array); @@ -384,5 +393,6 @@ main (int argc, char *argv[]) cleanup_auction_data (); } + GNUNET_CRYPTO_ecc_dlog_release (edc); return ret; } diff --git a/tex-stuff/math.tex b/tex-stuff/math.tex index e274e39..c515973 100644 --- a/tex-stuff/math.tex +++ b/tex-stuff/math.tex @@ -76,7 +76,7 @@ case, in other words, it is shown that $M \in \{0, G\}$. \\ Proof: & $A_1, A_2, B_1, B_2, d_1, d_2, r_1, r_2$ \end{tabular} -\subsection{Protocol} +\subsection{First Price Auction Protocol With Private Outcome} Let $n$ be the number of participating bidders/agents in the protocol and $k$ be the amount of possible valuations/prices for the sold good. Let $G$ be the @@ -131,6 +131,8 @@ each $i, j$ and $h \neq i$ after having received all of them. \item If $\exists w: V_{aw} = 0$, then bidder $a$ is the winner of the auction. $p_w$ is the selling price. \end{enumerate} +\subsection{First Price Auction Protocol With Public Outcome} + diff --git a/util.c b/util.c index 1eff0d4..76ceab8 100644 --- a/util.c +++ b/util.c @@ -19,6 +19,9 @@ * @brief Implementation of common utility functions. * @author Markus Teich */ + +#include "brandt_config.h" + #include #include #include