From 75cfa6370bc902765c26b50bb858c9a5bc1e8e48 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 18 Apr 2021 21:11:08 +0200 Subject: SCALARPRODUCT: migrating logic from libgcrypt to libsodium (#6818). --- src/include/gnunet_crypto_lib.h | 132 +++--- src/include/gnunet_scalarproduct_service.h | 50 +- src/scalarproduct/Makefile.am | 4 +- .../gnunet-service-scalarproduct-ecc_alice.c | 297 ++++++------ .../gnunet-service-scalarproduct-ecc_bob.c | 131 ++--- src/scalarproduct/perf_scalarproduct.sh | 19 +- src/scalarproduct/scalarproduct_api.c | 50 +- src/scalarproduct/test_ecc_scalarproduct.c | 211 +++++---- src/scalarproduct/test_scalarproduct_negative.sh | 3 + src/util/Makefile.am | 3 +- src/util/crypto_ecc_dlog.c | 525 +++++++-------------- src/util/perf_crypto_ecc_dlog.c | 118 ++--- src/util/test_crypto_ecc_dlog.c | 141 +++--- 13 files changed, 767 insertions(+), 917 deletions(-) diff --git a/src/include/gnunet_crypto_lib.h b/src/include/gnunet_crypto_lib.h index d01457b4a..2a552e212 100644 --- a/src/include/gnunet_crypto_lib.h +++ b/src/include/gnunet_crypto_lib.h @@ -1443,9 +1443,16 @@ struct GNUNET_CRYPTO_EccPoint * Q consists of an x- and a y-value, each mod p (256 bits), given * here in affine coordinates and Ed25519 standard compact format. */ - unsigned char q_y[256 / 8]; + unsigned char v[256 / 8]; }; +/** + * A ECC scalar for use in point multiplications + */ +struct GNUNET_CRYPTO_EccScalar +{ + unsigned char v[256 / 8]; +}; /** * Do pre-calculation for ECC discrete logarithm for small factors. @@ -1455,7 +1462,8 @@ struct GNUNET_CRYPTO_EccPoint * @return NULL on error */ struct GNUNET_CRYPTO_EccDlogContext * -GNUNET_CRYPTO_ecc_dlog_prepare (unsigned int max, unsigned int mem); +GNUNET_CRYPTO_ecc_dlog_prepare (unsigned int max, + unsigned int mem); /** @@ -1468,7 +1476,7 @@ GNUNET_CRYPTO_ecc_dlog_prepare (unsigned int max, unsigned int mem); */ int GNUNET_CRYPTO_ecc_dlog (struct GNUNET_CRYPTO_EccDlogContext *edc, - gcry_mpi_point_t input); + const struct GNUNET_CRYPTO_EccPoint *input); /** @@ -1479,138 +1487,107 @@ GNUNET_CRYPTO_ecc_dlog (struct GNUNET_CRYPTO_EccDlogContext *edc, * convert a point back to an integer (as long as the * integer is smaller than the MAX of the @a edc context). * - * @param edc calculation context for ECC operations * @param val value to encode into a point - * @return representation of the value as an ECC point, - * must be freed using #GNUNET_CRYPTO_ecc_free() + * @param r where to write the point (must be allocated) */ -gcry_mpi_point_t -GNUNET_CRYPTO_ecc_dexp (struct GNUNET_CRYPTO_EccDlogContext *edc, int val); +void +GNUNET_CRYPTO_ecc_dexp (int val, + struct GNUNET_CRYPTO_EccPoint*r); /** * Multiply the generator g of the elliptic curve by @a val * to obtain the point on the curve representing @a val. * - * @param edc calculation context for ECC operations * @param val (positive) value to encode into a point - * @return representation of the value as an ECC point, - * must be freed using #GNUNET_CRYPTO_ecc_free() + * @param r where to write the point (must be allocated) + * @return #GNUNET_OK on success. */ -gcry_mpi_point_t -GNUNET_CRYPTO_ecc_dexp_mpi (struct GNUNET_CRYPTO_EccDlogContext *edc, - gcry_mpi_t val); +enum GNUNET_GenericReturnValue +GNUNET_CRYPTO_ecc_dexp_mpi (const struct GNUNET_CRYPTO_EccScalar *val, + struct GNUNET_CRYPTO_EccPoint *r); /** * Multiply the point @a p on the elliptic curve by @a val. * - * @param edc calculation context for ECC operations * @param p point to multiply * @param val (positive) value to encode into a point - * @return representation of the value as an ECC point, - * must be freed using #GNUNET_CRYPTO_ecc_free() - */ -gcry_mpi_point_t -GNUNET_CRYPTO_ecc_pmul_mpi (struct GNUNET_CRYPTO_EccDlogContext *edc, - gcry_mpi_point_t p, - gcry_mpi_t val); - - -/** - * Convert point value to binary representation. - * - * @param edc calculation context for ECC operations - * @param point computational point representation - * @param[out] bin binary point representation - */ -void -GNUNET_CRYPTO_ecc_point_to_bin (struct GNUNET_CRYPTO_EccDlogContext *edc, - gcry_mpi_point_t point, - struct GNUNET_CRYPTO_EccPoint *bin); - - -/** - * Convert binary representation of a point to computational representation. - * - * @param edc calculation context for ECC operations - * @param bin binary point representation - * @return computational representation + * @param r where to write the point (must be allocated) + * @return #GNUNET_OK on success. */ -gcry_mpi_point_t -GNUNET_CRYPTO_ecc_bin_to_point (struct GNUNET_CRYPTO_EccDlogContext *edc, - const struct GNUNET_CRYPTO_EccPoint *bin); +enum GNUNET_GenericReturnValue +GNUNET_CRYPTO_ecc_pmul_mpi (const struct GNUNET_CRYPTO_EccPoint *p, + const struct GNUNET_CRYPTO_EccScalar *val, + struct GNUNET_CRYPTO_EccPoint *r); /** * Add two points on the elliptic curve. * - * @param edc calculation context for ECC operations * @param a some value * @param b some value - * @return @a a + @a b, must be freed using #GNUNET_CRYPTO_ecc_free() + * @param r where to write the point (must be allocated) + * @return #GNUNET_OK on success. */ -gcry_mpi_point_t -GNUNET_CRYPTO_ecc_add (struct GNUNET_CRYPTO_EccDlogContext *edc, - gcry_mpi_point_t a, - gcry_mpi_point_t b); +enum GNUNET_GenericReturnValue +GNUNET_CRYPTO_ecc_add (const struct GNUNET_CRYPTO_EccPoint *a, + const struct GNUNET_CRYPTO_EccPoint *b, + struct GNUNET_CRYPTO_EccPoint *r); /** * Obtain a random point on the curve and its - * additive inverse. Both returned values - * must be freed using #GNUNET_CRYPTO_ecc_free(). + * additive inverse. * - * @param edc calculation context for ECC operations * @param[out] r set to a random point on the curve * @param[out] r_inv set to the additive inverse of @a r + * @return #GNUNET_OK on success. */ -void -GNUNET_CRYPTO_ecc_rnd (struct GNUNET_CRYPTO_EccDlogContext *edc, - gcry_mpi_point_t *r, - gcry_mpi_point_t *r_inv); +enum GNUNET_GenericReturnValue +GNUNET_CRYPTO_ecc_rnd (struct GNUNET_CRYPTO_EccPoint *r, + struct GNUNET_CRYPTO_EccPoint *r_inv); /** * Obtain a random scalar for point multiplication on the curve and - * its multiplicative inverse. + * its additive inverse. * - * @param edc calculation context for ECC operations * @param[out] r set to a random scalar on the curve - * @param[out] r_inv set to the multiplicative inverse of @a r + * @param[out] r_neg set to the negation of @a */ void -GNUNET_CRYPTO_ecc_rnd_mpi (struct GNUNET_CRYPTO_EccDlogContext *edc, - gcry_mpi_t *r, - gcry_mpi_t *r_inv); +GNUNET_CRYPTO_ecc_rnd_mpi (struct GNUNET_CRYPTO_EccScalar *r, + struct GNUNET_CRYPTO_EccScalar *r_neg); /** * Generate a random value mod n. * - * @param edc ECC context - * @return random value mod n. + * @param[out] r random value mod n. */ -gcry_mpi_t -GNUNET_CRYPTO_ecc_random_mod_n (struct GNUNET_CRYPTO_EccDlogContext *edc); +void +GNUNET_CRYPTO_ecc_random_mod_n (struct GNUNET_CRYPTO_EccScalar*r); /** - * Free a point value returned by the API. + * Release precalculated values. * - * @param p point to free + * @param dlc dlog context */ void -GNUNET_CRYPTO_ecc_free (gcry_mpi_point_t p); +GNUNET_CRYPTO_ecc_dlog_release (struct GNUNET_CRYPTO_EccDlogContext *dlc); /** - * Release precalculated values. + * Create a scalar from int value. * - * @param dlc dlog context + * @param val the int value + * @param[out] r where to write the salar */ void -GNUNET_CRYPTO_ecc_dlog_release (struct GNUNET_CRYPTO_EccDlogContext *dlc); +GNUNET_CRYPTO_ecc_scalar_from_int (int64_t val, + struct GNUNET_CRYPTO_EccScalar *r); /** @@ -1643,6 +1620,7 @@ GNUNET_CRYPTO_eddsa_ecdh (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, const struct GNUNET_CRYPTO_EcdhePublicKey *pub, struct GNUNET_HashCode *key_material); + /** * @ingroup crypto * Derive key material from a ECDH public key and a private ECDSA key. @@ -1937,7 +1915,9 @@ GNUNET_CRYPTO_ecdsa_public_key_derive ( * @param val value to write to @a buf */ void -GNUNET_CRYPTO_mpi_print_unsigned (void *buf, size_t size, gcry_mpi_t val); +GNUNET_CRYPTO_mpi_print_unsigned (void *buf, + size_t size, + gcry_mpi_t val); /** diff --git a/src/include/gnunet_scalarproduct_service.h b/src/include/gnunet_scalarproduct_service.h index b12a19a2f..1d775f659 100644 --- a/src/include/gnunet_scalarproduct_service.h +++ b/src/include/gnunet_scalarproduct_service.h @@ -17,7 +17,6 @@ SPDX-License-Identifier: AGPL3.0-or-later */ - /** * @author Christian M. Fuchs * @author Gaurav Kukreja @@ -118,10 +117,9 @@ GNUNET_NETWORK_STRUCT_END * @param status Status of the request */ typedef void -(*GNUNET_SCALARPRODUCT_ContinuationWithStatus) (void *cls, - enum - GNUNET_SCALARPRODUCT_ResponseStatus - status); +(*GNUNET_SCALARPRODUCT_ContinuationWithStatus) ( + void *cls, + enum GNUNET_SCALARPRODUCT_ResponseStatus status); /** @@ -132,10 +130,10 @@ typedef void * @param result result of the computation */ typedef void -(*GNUNET_SCALARPRODUCT_DatumProcessor) (void *cls, - enum GNUNET_SCALARPRODUCT_ResponseStatus - status, - gcry_mpi_t result); +(*GNUNET_SCALARPRODUCT_DatumProcessor) ( + void *cls, + enum GNUNET_SCALARPRODUCT_ResponseStatus status, + gcry_mpi_t result); /** @@ -157,16 +155,14 @@ struct GNUNET_SCALARPRODUCT_ComputationHandle; * @return a new handle for this computation */ struct GNUNET_SCALARPRODUCT_ComputationHandle * -GNUNET_SCALARPRODUCT_start_computation (const struct - GNUNET_CONFIGURATION_Handle *cfg, - const struct - GNUNET_HashCode *session_key, - const struct GNUNET_PeerIdentity *peer, - const struct - GNUNET_SCALARPRODUCT_Element *elements, - uint32_t element_count, - GNUNET_SCALARPRODUCT_DatumProcessor cont, - void *cont_cls); +GNUNET_SCALARPRODUCT_start_computation ( + const struct GNUNET_CONFIGURATION_Handle *cfg, + const struct GNUNET_HashCode *session_key, + const struct GNUNET_PeerIdentity *peer, + const struct GNUNET_SCALARPRODUCT_Element *elements, + uint32_t element_count, + GNUNET_SCALARPRODUCT_DatumProcessor cont, + void *cont_cls); /** @@ -181,15 +177,13 @@ GNUNET_SCALARPRODUCT_start_computation (const struct * @return a new handle for this computation */ struct GNUNET_SCALARPRODUCT_ComputationHandle * -GNUNET_SCALARPRODUCT_accept_computation (const struct - GNUNET_CONFIGURATION_Handle *cfg, - const struct GNUNET_HashCode *key, - const struct - GNUNET_SCALARPRODUCT_Element *elements, - uint32_t element_count, - GNUNET_SCALARPRODUCT_ContinuationWithStatus - cont, - void *cont_cls); +GNUNET_SCALARPRODUCT_accept_computation ( + const struct GNUNET_CONFIGURATION_Handle *cfg, + const struct GNUNET_HashCode *key, + const struct GNUNET_SCALARPRODUCT_Element *elements, + uint32_t element_count, + GNUNET_SCALARPRODUCT_ContinuationWithStatus cont, + void *cont_cls); /** diff --git a/src/scalarproduct/Makefile.am b/src/scalarproduct/Makefile.am index f3448725a..cf05e8377 100644 --- a/src/scalarproduct/Makefile.am +++ b/src/scalarproduct/Makefile.am @@ -63,6 +63,7 @@ gnunet_service_scalarproduct_ecc_alice_LDADD = \ $(top_builddir)/src/cadet/libgnunetcadet.la \ $(top_builddir)/src/seti/libgnunetseti.la \ $(LIBGCRYPT_LIBS) \ + -lsodium \ -lgcrypt \ $(GN_LIBINTL) @@ -74,6 +75,7 @@ gnunet_service_scalarproduct_ecc_bob_LDADD = \ $(top_builddir)/src/cadet/libgnunetcadet.la \ $(top_builddir)/src/seti/libgnunetseti.la \ $(LIBGCRYPT_LIBS) \ + -lsodium \ -lgcrypt \ $(GN_LIBINTL) @@ -111,4 +113,4 @@ test_ecc_scalarproduct_SOURCES = \ test_ecc_scalarproduct.c test_ecc_scalarproduct_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ - -lgcrypt + -lsodium diff --git a/src/scalarproduct/gnunet-service-scalarproduct-ecc_alice.c b/src/scalarproduct/gnunet-service-scalarproduct-ecc_alice.c index 447451aef..e33d589be 100644 --- a/src/scalarproduct/gnunet-service-scalarproduct-ecc_alice.c +++ b/src/scalarproduct/gnunet-service-scalarproduct-ecc_alice.c @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - Copyright (C) 2013-2017 GNUnet e.V. + Copyright (C) 2013-2017, 2021 GNUnet e.V. GNUnet is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published @@ -69,7 +69,7 @@ struct MpiElement /** * a_i value, not disclosed to Bob. */ - gcry_mpi_t value; + int64_t value; }; @@ -138,9 +138,9 @@ struct AliceServiceSession struct MpiElement *sorted_elements; /** - * The computed scalar + * The computed scalar product. INT_MAX if the computation failed. */ - gcry_mpi_t product; + int product; /** * How many elements we were supplied with from the client (total @@ -190,12 +190,12 @@ static struct GNUNET_CRYPTO_EccDlogContext *edc; /** * Alice's private key ('a'). */ -static gcry_mpi_t my_privkey; +static struct GNUNET_CRYPTO_EccScalar my_privkey; /** * Inverse of Alice's private key ('a_inv'). */ -static gcry_mpi_t my_privkey_inv; +static struct GNUNET_CRYPTO_EccScalar my_privkey_inv; /** * Handle to the CADET service. @@ -212,7 +212,9 @@ static struct GNUNET_CADET_Handle *my_cadet; * @return #GNUNET_OK (continue to iterate) */ static int -free_element_cb (void *cls, const struct GNUNET_HashCode *key, void *value) +free_element_cb (void *cls, + const struct GNUNET_HashCode *key, + void *value) { struct GNUNET_SCALARPRODUCT_Element *e = value; @@ -229,8 +231,6 @@ free_element_cb (void *cls, const struct GNUNET_HashCode *key, void *value) static void destroy_service_session (struct AliceServiceSession *s) { - unsigned int i; - if (GNUNET_YES == s->in_destroy) return; s->in_destroy = GNUNET_YES; @@ -261,7 +261,8 @@ destroy_service_session (struct AliceServiceSession *s) } if (NULL != s->intersection_op) { - LOG (GNUNET_ERROR_TYPE_DEBUG, "Set intersection, op still ongoing!\n"); + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Set intersection, op still ongoing!\n"); GNUNET_SETI_operation_cancel (s->intersection_op); s->intersection_op = NULL; } @@ -272,16 +273,9 @@ destroy_service_session (struct AliceServiceSession *s) } if (NULL != s->sorted_elements) { - for (i = 0; i < s->used_element_count; i++) - gcry_mpi_release (s->sorted_elements[i].value); GNUNET_free (s->sorted_elements); s->sorted_elements = NULL; } - if (NULL != s->product) - { - gcry_mpi_release (s->product); - s->product = NULL; - } GNUNET_free (s); } @@ -305,10 +299,12 @@ prepare_client_end_notification (struct AliceServiceSession *session) "Sending session-end notification with status %d to client for session %s\n", session->status, GNUNET_h2s (&session->session_id)); - e = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_SCALARPRODUCT_RESULT); + e = GNUNET_MQ_msg (msg, + GNUNET_MESSAGE_TYPE_SCALARPRODUCT_RESULT); msg->product_length = htonl (0); msg->status = htonl (session->status); - GNUNET_MQ_send (session->client_mq, e); + GNUNET_MQ_send (session->client_mq, + e); } @@ -327,41 +323,41 @@ transmit_client_response (struct AliceServiceSession *s) size_t product_length = 0; int32_t range; gcry_error_t rc; - int sign; gcry_mpi_t value; - if (NULL == s->product) + if (INT_MAX == s->product) { GNUNET_break (0); prepare_client_end_notification (s); return; } - value = gcry_mpi_new (0); - sign = gcry_mpi_cmp_ui (s->product, 0); - if (0 > sign) + value = gcry_mpi_new (32); + if (0 > s->product) { range = -1; - gcry_mpi_sub (value, value, s->product); + gcry_mpi_set_ui (value, + -s->product); } - else if (0 < sign) + else if (0 < s->product) { range = 1; - gcry_mpi_add (value, value, s->product); + gcry_mpi_set_ui (value, + s->product); } else { /* result is exactly zero */ range = 0; } - gcry_mpi_release (s->product); - s->product = NULL; - - if ((0 != range) && (0 != (rc = gcry_mpi_aprint (GCRYMPI_FMT_STD, - &product_exported, - &product_length, - value)))) + if ( (0 != range) && + (0 != (rc = gcry_mpi_aprint (GCRYMPI_FMT_STD, + &product_exported, + &product_length, + value)))) { - LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc); + LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, + "gcry_mpi_scan", + rc); prepare_client_end_notification (s); return; } @@ -374,10 +370,13 @@ transmit_client_response (struct AliceServiceSession *s) msg->product_length = htonl (product_length); if (NULL != product_exported) { - GNUNET_memcpy (&msg[1], product_exported, product_length); + GNUNET_memcpy (&msg[1], + product_exported, + product_length); GNUNET_free (product_exported); } - GNUNET_MQ_send (s->client_mq, e); + GNUNET_MQ_send (s->client_mq, + e); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sent result to client, session %s has ended!\n", GNUNET_h2s (&s->session_id)); @@ -394,7 +393,8 @@ transmit_client_response (struct AliceServiceSession *s) * @param channel connection to the other end (henceforth invalid) */ static void -cb_channel_destruction (void *cls, const struct GNUNET_CADET_Channel *channel) +cb_channel_destruction (void *cls, + const struct GNUNET_CADET_Channel *channel) { struct AliceServiceSession *s = cls; @@ -412,51 +412,6 @@ cb_channel_destruction (void *cls, const struct GNUNET_CADET_Channel *channel) } -/** - * Compute our scalar product, done by Alice - * - * @param session the session associated with this computation - * @param prod_g_i_b_i value from Bob - * @param prod_h_i_b_i value from Bob - * @return product as MPI, never NULL - */ -static gcry_mpi_t -compute_scalar_product (struct AliceServiceSession *session, - gcry_mpi_point_t prod_g_i_b_i, - gcry_mpi_point_t prod_h_i_b_i) -{ - gcry_mpi_point_t g_i_b_i_a_inv; - gcry_mpi_point_t g_ai_bi; - int ai_bi; - gcry_mpi_t ret; - - g_i_b_i_a_inv = - GNUNET_CRYPTO_ecc_pmul_mpi (edc, prod_g_i_b_i, my_privkey_inv); - g_ai_bi = GNUNET_CRYPTO_ecc_add (edc, g_i_b_i_a_inv, prod_h_i_b_i); - gcry_mpi_point_release (g_i_b_i_a_inv); - ai_bi = GNUNET_CRYPTO_ecc_dlog (edc, g_ai_bi); - gcry_mpi_point_release (g_ai_bi); - if (INT_MAX == ai_bi) - { - /* result too big */ - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Scalar product result out of range\n"); - return NULL; - } - ret = gcry_mpi_new (0); - if (ai_bi > 0) - { - gcry_mpi_set_ui (ret, ai_bi); - } - else - { - gcry_mpi_set_ui (ret, -ai_bi); - gcry_mpi_neg (ret, ret); - } - return ret; -} - - /** * Handle a response we got from another service we wanted to * calculate a scalarproduct with. @@ -469,8 +424,6 @@ handle_bobs_cryptodata_message (void *cls, const struct EccBobCryptodataMessage *msg) { struct AliceServiceSession *s = cls; - gcry_mpi_point_t prod_g_i_b_i; - gcry_mpi_point_t prod_h_i_b_i; uint32_t contained; contained = ntohl (msg->contained_element_count); @@ -494,16 +447,33 @@ handle_bobs_cryptodata_message (void *cls, destroy_service_session (s); return; } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received %u crypto values from Bob\n", (unsigned int) contained); GNUNET_CADET_receive_done (s->channel); - prod_g_i_b_i = GNUNET_CRYPTO_ecc_bin_to_point (edc, &msg->prod_g_i_b_i); - prod_h_i_b_i = GNUNET_CRYPTO_ecc_bin_to_point (edc, &msg->prod_h_i_b_i); - s->product = compute_scalar_product (s, prod_g_i_b_i, prod_h_i_b_i); - gcry_mpi_point_release (prod_g_i_b_i); - gcry_mpi_point_release (prod_h_i_b_i); + { + struct GNUNET_CRYPTO_EccPoint g_i_b_i_a_inv; + struct GNUNET_CRYPTO_EccPoint g_ai_bi; + + GNUNET_assert ( + GNUNET_OK == + GNUNET_CRYPTO_ecc_pmul_mpi (&msg->prod_g_i_b_i, + &my_privkey_inv, + &g_i_b_i_a_inv)); + GNUNET_assert ( + GNUNET_OK == + GNUNET_CRYPTO_ecc_add (&g_i_b_i_a_inv, + &msg->prod_h_i_b_i, + &g_ai_bi)); + s->product = GNUNET_CRYPTO_ecc_dlog (edc, + &g_ai_bi); + if (INT_MAX == s->product) + { + /* result too big */ + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Scalar product result out of range\n"); + } + } transmit_client_response (s); } @@ -517,20 +487,15 @@ handle_bobs_cryptodata_message (void *cls, * @param value the `struct GNUNET_SCALARPRODUCT_Element *` */ static int -copy_element_cb (void *cls, const struct GNUNET_HashCode *key, void *value) +copy_element_cb (void *cls, + const struct GNUNET_HashCode *key, + void *value) { struct AliceServiceSession *s = cls; struct GNUNET_SCALARPRODUCT_Element *e = value; - gcry_mpi_t mval; - int64_t val; - mval = gcry_mpi_new (0); - val = (int64_t) GNUNET_ntohll (e->value); - if (0 > val) - gcry_mpi_sub_ui (mval, mval, -val); - else - gcry_mpi_add_ui (mval, mval, val); - s->sorted_elements[s->used_element_count].value = mval; + s->sorted_elements[s->used_element_count].value = (int64_t) GNUNET_ntohll ( + e->value); s->sorted_elements[s->used_element_count].key = &e->key; s->used_element_count++; return GNUNET_OK; @@ -545,12 +510,14 @@ copy_element_cb (void *cls, const struct GNUNET_HashCode *key, void *value) * @return -1 for a < b, 0 for a=b, 1 for a > b. */ static int -element_cmp (const void *a, const void *b) +element_cmp (const void *a, + const void *b) { const struct MpiElement *ma = a; const struct MpiElement *mb = b; - return GNUNET_CRYPTO_hash_cmp (ma->key, mb->key); + return GNUNET_CRYPTO_hash_cmp (ma->key, + mb->key); } @@ -576,9 +543,8 @@ send_alices_cryptodata_message (struct AliceServiceSession *s) struct EccAliceCryptodataMessage *msg; struct GNUNET_MQ_Envelope *e; struct GNUNET_CRYPTO_EccPoint *payload; - gcry_mpi_t r_ia; - gcry_mpi_t r_ia_ai; - unsigned int i; + struct GNUNET_CRYPTO_EccScalar r_ia; + struct GNUNET_CRYPTO_EccScalar r_ia_ai; unsigned int off; unsigned int todo_count; @@ -614,31 +580,53 @@ send_alices_cryptodata_message (struct AliceServiceSession *s) GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ECC_ALICE_CRYPTODATA); msg->contained_element_count = htonl (todo_count); payload = (struct GNUNET_CRYPTO_EccPoint *) &msg[1]; - r_ia = gcry_mpi_new (0); - r_ia_ai = gcry_mpi_new (0); - for (i = off; i < off + todo_count; i++) + for (unsigned int i = off; i < off + todo_count; i++) { - gcry_mpi_t r_i; - gcry_mpi_point_t g_i; - gcry_mpi_point_t h_i; - - r_i = GNUNET_CRYPTO_ecc_random_mod_n (edc); - g_i = GNUNET_CRYPTO_ecc_dexp_mpi (edc, r_i); + struct GNUNET_CRYPTO_EccScalar r_i; + struct GNUNET_CRYPTO_EccPoint g_i; + struct GNUNET_CRYPTO_EccPoint h_i; + + /* r_i = random() mod n */ + GNUNET_CRYPTO_ecc_random_mod_n (&r_i); + /* g_i = g^{r_i} */ + GNUNET_assert (GNUNET_OK == + GNUNET_CRYPTO_ecc_dexp_mpi (&r_i, + &g_i)); /* r_ia = r_i * a */ - gcry_mpi_mul (r_ia, r_i, my_privkey); - gcry_mpi_release (r_i); + crypto_core_ed25519_scalar_mul (r_ia.v, + r_i.v, + my_privkey.v); /* r_ia_ai = r_ia + a_i */ - gcry_mpi_add (r_ia_ai, r_ia, s->sorted_elements[i].value); - h_i = GNUNET_CRYPTO_ecc_dexp_mpi (edc, r_ia_ai); - GNUNET_CRYPTO_ecc_point_to_bin (edc, g_i, &payload[(i - off) * 2]); - GNUNET_CRYPTO_ecc_point_to_bin (edc, h_i, &payload[(i - off) * 2 + 1]); - gcry_mpi_point_release (g_i); - gcry_mpi_point_release (h_i); + { + int64_t val = s->sorted_elements[i].value; + struct GNUNET_CRYPTO_EccScalar vali; + + GNUNET_assert (INT64_MIN != val); + GNUNET_CRYPTO_ecc_scalar_from_int (val > 0 ? val : -val, + &vali); + if (val > 0) + crypto_core_ed25519_scalar_add (r_ia_ai.v, + r_ia.v, + vali.v); + else + crypto_core_ed25519_scalar_sub (r_ia_ai.v, + r_ia.v, + vali.v); + } + /* h_i = g^{r_ia_ai} */ + GNUNET_assert (GNUNET_OK == + GNUNET_CRYPTO_ecc_dexp_mpi (&r_ia_ai, + &h_i)); + memcpy (&payload[(i - off) * 2], + &g_i, + sizeof (g_i)); + memcpy (&payload[(i - off) * 2 + 1], + &h_i, + sizeof (h_i)); } - gcry_mpi_release (r_ia); - gcry_mpi_release (r_ia_ai); off += todo_count; - GNUNET_MQ_send (s->cadet_mq, e); + GNUNET_MQ_send (s->cadet_mq, + e); } } @@ -740,16 +728,17 @@ cb_intersection_request_alice (void *cls, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received intersection request from %s!\n", GNUNET_i2s (other_peer)); - if (0 != GNUNET_memcmp (other_peer, &s->peer)) + if (0 != GNUNET_memcmp (other_peer, + &s->peer)) { GNUNET_break_op (0); return; } - s->intersection_op = GNUNET_SETI_accept (request, - (struct - GNUNET_SETI_Option[]){ { 0 } }, - &cb_intersection_element_removed, - s); + s->intersection_op + = GNUNET_SETI_accept (request, + (struct GNUNET_SETI_Option[]){ { 0 } }, + &cb_intersection_element_removed, + s); if (NULL == s->intersection_op) { GNUNET_break (0); @@ -757,7 +746,9 @@ cb_intersection_request_alice (void *cls, prepare_client_end_notification (s); return; } - if (GNUNET_OK != GNUNET_SETI_commit (s->intersection_op, s->intersection_set)) + if (GNUNET_OK != + GNUNET_SETI_commit (s->intersection_op, + s->intersection_set)) { GNUNET_break (0); s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE; @@ -775,12 +766,13 @@ cb_intersection_request_alice (void *cls, static void client_request_complete_alice (struct AliceServiceSession *s) { - struct GNUNET_MQ_MessageHandler cadet_handlers[] = - { GNUNET_MQ_hd_fixed_size (bobs_cryptodata_message, + struct GNUNET_MQ_MessageHandler cadet_handlers[] = { + GNUNET_MQ_hd_fixed_size (bobs_cryptodata_message, GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ECC_BOB_CRYPTODATA, struct EccBobCryptodataMessage, s), - GNUNET_MQ_handler_end () }; + GNUNET_MQ_handler_end () + }; struct EccServiceRequestMessage *msg; struct GNUNET_MQ_Envelope *e; struct GNUNET_HashCode set_sid; @@ -982,17 +974,17 @@ handle_alice_client_message (void *cls, s->session_id = msg->session_key; elements = (const struct GNUNET_SCALARPRODUCT_Element *) &msg[1]; s->intersected_elements = - GNUNET_CONTAINER_multihashmap_create (s->total, GNUNET_YES); + GNUNET_CONTAINER_multihashmap_create (s->total, + GNUNET_YES); s->intersection_set = GNUNET_SETI_create (cfg); for (uint32_t i = 0; i < contained_count; i++) { if (0 == GNUNET_ntohll (elements[i].value)) continue; elem = GNUNET_new (struct GNUNET_SCALARPRODUCT_Element); - GNUNET_memcpy (elem, - &elements[i], - sizeof(struct GNUNET_SCALARPRODUCT_Element)); - if (GNUNET_SYSERR == GNUNET_CONTAINER_multihashmap_put ( + *elem = elements[i]; + if (GNUNET_SYSERR == + GNUNET_CONTAINER_multihashmap_put ( s->intersected_elements, &elem->key, elem, @@ -1006,7 +998,10 @@ handle_alice_client_message (void *cls, set_elem.data = &elem->key; set_elem.size = sizeof(elem->key); set_elem.element_type = 0; - GNUNET_SETI_add_element (s->intersection_set, &set_elem, NULL, NULL); + GNUNET_SETI_add_element (s->intersection_set, + &set_elem, + NULL, + NULL); s->used_element_count++; } GNUNET_SERVICE_client_continue (s->client); @@ -1017,7 +1012,8 @@ handle_alice_client_message (void *cls, "Received partial client request, waiting for more!\n"); return; } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Launching computation\n"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Launching computation\n"); client_request_complete_alice (s); } @@ -1031,7 +1027,8 @@ handle_alice_client_message (void *cls, static void shutdown_task (void *cls) { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutting down, initiating cleanup.\n"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Shutting down, initiating cleanup.\n"); // FIXME: we have to cut our connections to CADET first! if (NULL != my_cadet) { @@ -1109,17 +1106,21 @@ run (void *cls, struct GNUNET_SERVICE_Handle *service) { cfg = c; - edc = GNUNET_CRYPTO_ecc_dlog_prepare (MAX_RESULT, MAX_RAM); + edc = GNUNET_CRYPTO_ecc_dlog_prepare (MAX_RESULT, + MAX_RAM); /* Select a random 'a' value for Alice */ - GNUNET_CRYPTO_ecc_rnd_mpi (edc, &my_privkey, &my_privkey_inv); + GNUNET_CRYPTO_ecc_rnd_mpi (&my_privkey, + &my_privkey_inv); my_cadet = GNUNET_CADET_connect (cfg); if (NULL == my_cadet) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _ ("Connect to CADET failed\n")); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _ ("Connect to CADET failed\n")); GNUNET_SCHEDULER_shutdown (); return; } - GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL); + GNUNET_SCHEDULER_add_shutdown (&shutdown_task, + NULL); } diff --git a/src/scalarproduct/gnunet-service-scalarproduct-ecc_bob.c b/src/scalarproduct/gnunet-service-scalarproduct-ecc_bob.c index 4c835d52a..02a62c164 100644 --- a/src/scalarproduct/gnunet-service-scalarproduct-ecc_bob.c +++ b/src/scalarproduct/gnunet-service-scalarproduct-ecc_bob.c @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - Copyright (C) 2013-2017 GNUnet e.V. + Copyright (C) 2013-2017, 2021 GNUnet e.V. GNUnet is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published @@ -54,7 +54,7 @@ struct MpiElement /** * Value represented (a). */ - gcry_mpi_t value; + int64_t value; }; @@ -104,12 +104,12 @@ struct BobServiceSession /** * Product of the g_i^{b_i} */ - gcry_mpi_point_t prod_g_i_b_i; + struct GNUNET_CRYPTO_EccPoint prod_g_i_b_i; /** * Product of the h_i^{b_i} */ - gcry_mpi_point_t prod_h_i_b_i; + struct GNUNET_CRYPTO_EccPoint prod_h_i_b_i; /** * How many elements will be supplied in total from the client. @@ -213,8 +213,6 @@ free_element_cb (void *cls, static void destroy_service_session (struct BobServiceSession *s) { - unsigned int i; - if (GNUNET_YES == s->in_destroy) return; s->in_destroy = GNUNET_YES; @@ -245,21 +243,9 @@ destroy_service_session (struct BobServiceSession *s) } if (NULL != s->sorted_elements) { - for (i = 0; i < s->used_element_count; i++) - gcry_mpi_release (s->sorted_elements[i].value); GNUNET_free (s->sorted_elements); s->sorted_elements = NULL; } - if (NULL != s->prod_g_i_b_i) - { - gcry_mpi_point_release (s->prod_g_i_b_i); - s->prod_g_i_b_i = NULL; - } - if (NULL != s->prod_h_i_b_i) - { - gcry_mpi_point_release (s->prod_h_i_b_i); - s->prod_h_i_b_i = NULL; - } if (NULL != s->port) { GNUNET_CADET_close_port (s->port); @@ -364,14 +350,8 @@ transmit_bobs_cryptodata_message (struct BobServiceSession *s) e = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ECC_BOB_CRYPTODATA); msg->contained_element_count = htonl (2); - if (NULL != s->prod_g_i_b_i) - GNUNET_CRYPTO_ecc_point_to_bin (edc, - s->prod_g_i_b_i, - &msg->prod_g_i_b_i); - if (NULL != s->prod_h_i_b_i) - GNUNET_CRYPTO_ecc_point_to_bin (edc, - s->prod_h_i_b_i, - &msg->prod_h_i_b_i); + msg->prod_g_i_b_i = s->prod_g_i_b_i; + msg->prod_h_i_b_i = s->prod_h_i_b_i; GNUNET_MQ_notify_sent (e, &bob_cadet_done_cb, s); @@ -384,10 +364,9 @@ transmit_bobs_cryptodata_message (struct BobServiceSession *s) * Iterator to copy over messages from the hash map * into an array for sorting. * - * @param cls the `struct BobServiceSession *` + * @param cls the `struct AliceServiceSession *` * @param key the key (unused) * @param value the `struct GNUNET_SCALARPRODUCT_Element *` - * TODO: code duplication with Alice! */ static int copy_element_cb (void *cls, @@ -396,17 +375,10 @@ copy_element_cb (void *cls, { struct BobServiceSession *s = cls; struct GNUNET_SCALARPRODUCT_Element *e = value; - gcry_mpi_t mval; - int64_t val; - - mval = gcry_mpi_new (0); - val = (int64_t) GNUNET_ntohll (e->value); - if (0 > val) - gcry_mpi_sub_ui (mval, mval, -val); - else - gcry_mpi_add_ui (mval, mval, val); - s->sorted_elements [s->used_element_count].value = mval; - s->sorted_elements [s->used_element_count].key = &e->key; + + s->sorted_elements[s->used_element_count].value = (int64_t) GNUNET_ntohll ( + e->value); + s->sorted_elements[s->used_element_count].key = &e->key; s->used_element_count++; return GNUNET_OK; } @@ -490,13 +462,10 @@ handle_alices_cryptodata_message (void *cls, const struct GNUNET_CRYPTO_EccPoint *payload; uint32_t contained_elements; unsigned int max; - unsigned int i; - const struct MpiElement *b_i; - gcry_mpi_point_t tmp; - gcry_mpi_point_t g_i; - gcry_mpi_point_t h_i; - gcry_mpi_point_t g_i_b_i; - gcry_mpi_point_t h_i_b_i; + const struct GNUNET_CRYPTO_EccPoint *g_i; + const struct GNUNET_CRYPTO_EccPoint *h_i; + struct GNUNET_CRYPTO_EccPoint g_i_b_i; + struct GNUNET_CRYPTO_EccPoint h_i_b_i; contained_elements = ntohl (msg->contained_element_count); max = GNUNET_CONTAINER_multihashmap_size (s->intersected_elements); @@ -522,21 +491,29 @@ handle_alices_cryptodata_message (void *cls, (unsigned int) contained_elements); payload = (const struct GNUNET_CRYPTO_EccPoint *) &msg[1]; - for (i = 0; i < contained_elements; i++) + for (unsigned int i = 0; i < contained_elements; i++) { - b_i = &s->sorted_elements[i + s->cadet_received_element_count]; - g_i = GNUNET_CRYPTO_ecc_bin_to_point (edc, - &payload[i * 2]); - g_i_b_i = GNUNET_CRYPTO_ecc_pmul_mpi (edc, - g_i, - b_i->value); - gcry_mpi_point_release (g_i); - h_i = GNUNET_CRYPTO_ecc_bin_to_point (edc, - &payload[i * 2 + 1]); - h_i_b_i = GNUNET_CRYPTO_ecc_pmul_mpi (edc, - h_i, - b_i->value); - gcry_mpi_point_release (h_i); + int64_t val = s->sorted_elements[i + s->cadet_received_element_count].value; + struct GNUNET_CRYPTO_EccScalar vali; + + GNUNET_assert (INT64_MIN != val); + GNUNET_CRYPTO_ecc_scalar_from_int (val > 0 ? val : -val, + &vali); + if (val < 0) + crypto_core_ed25519_scalar_negate (vali.v, + vali.v); + g_i = &payload[i * 2]; + /* g_i_b_i = g_i^vali */ + GNUNET_assert (GNUNET_OK == + GNUNET_CRYPTO_ecc_pmul_mpi (g_i, + &vali, + &g_i_b_i)); + h_i = &payload[i * 2 + 1]; + /* h_i_b_i = h_i^vali */ + GNUNET_assert (GNUNET_OK == + GNUNET_CRYPTO_ecc_pmul_mpi (h_i, + &vali, + &h_i_b_i)); if (0 == i + s->cadet_received_element_count) { /* first iteration, nothing to add */ @@ -546,18 +523,14 @@ handle_alices_cryptodata_message (void *cls, else { /* further iterations, cummulate resulting value */ - tmp = GNUNET_CRYPTO_ecc_add (edc, - s->prod_g_i_b_i, - g_i_b_i); - gcry_mpi_point_release (s->prod_g_i_b_i); - gcry_mpi_point_release (g_i_b_i); - s->prod_g_i_b_i = tmp; - tmp = GNUNET_CRYPTO_ecc_add (edc, - s->prod_h_i_b_i, - h_i_b_i); - gcry_mpi_point_release (s->prod_h_i_b_i); - gcry_mpi_point_release (h_i_b_i); - s->prod_h_i_b_i = tmp; + GNUNET_assert (GNUNET_OK == + GNUNET_CRYPTO_ecc_add (&s->prod_g_i_b_i, + &g_i_b_i, + &s->prod_g_i_b_i)); + GNUNET_assert (GNUNET_OK == + GNUNET_CRYPTO_ecc_add (&s->prod_h_i_b_i, + &h_i_b_i, + &s->prod_h_i_b_i)); } } s->cadet_received_element_count += contained_elements; @@ -747,10 +720,9 @@ cb_channel_incoming (void *cls, * @return #GNUNET_OK if @a msg is well-formed */ static int -check_bob_client_message_multipart (void *cls, - const struct - ComputationBobCryptodataMultipartMessage * - msg) +check_bob_client_message_multipart ( + void *cls, + const struct ComputationBobCryptodataMultipartMessage *msg) { struct BobServiceSession *s = cls; uint32_t contained_count; @@ -781,10 +753,9 @@ check_bob_client_message_multipart (void *cls, * @param msg the actual message */ static void -handle_bob_client_message_multipart (void *cls, - const struct - ComputationBobCryptodataMultipartMessage * - msg) +handle_bob_client_message_multipart ( + void *cls, + const struct ComputationBobCryptodataMultipartMessage *msg) { struct BobServiceSession *s = cls; uint32_t contained_count; diff --git a/src/scalarproduct/perf_scalarproduct.sh b/src/scalarproduct/perf_scalarproduct.sh index a7935873e..b15465c9a 100755 --- a/src/scalarproduct/perf_scalarproduct.sh +++ b/src/scalarproduct/perf_scalarproduct.sh @@ -1,7 +1,7 @@ #!/bin/bash # Computes a simple scalar product, with configurable vector size. # -# Some results (wall-clock for Alice+Bob, single-core, i7): +# Some results (wall-clock for Alice+Bob, single-core, i7, libgcrypt): # SIZE 2048-H(s) 2048-O(s) 1024-O(s) ECC-2^20-H(s) ECC-2^28-H(s) # 25 10 14 3 2 29 # 50 17 21 5 2 29 @@ -11,8 +11,21 @@ # 800 304 32 OOR 33 # Bandwidth (including set intersection): -# RSA-2048 ECC -# 800: 3846 kb 70 kb +# RSA-1024 RSA-2048 ECC +# 800: 629 kb 1234 kb 65 kb +# +# LIBSODIUM, AMD Threadripper 1950: +# +# SIZE 2048-O(s) 1024-O(s) ECC-2^20-H(s) ECC-2^28-H(s) +# 25 4.3 0.7 0.129 4.233 +# 50 7.7 1.2 0.143 4.267 +# 100 10.3 2.4 0.163 4.282 +# 200 19.8 3.0 0.192 4.326 +# 400 35.9 6.0 0.253 4.358 +# 800 73.7 12.6 0.379 4.533 + +# +# # Configure benchmark size: SIZE=800 # diff --git a/src/scalarproduct/scalarproduct_api.c b/src/scalarproduct/scalarproduct_api.c index b2a90c222..4ac39614a 100644 --- a/src/scalarproduct/scalarproduct_api.c +++ b/src/scalarproduct/scalarproduct_api.c @@ -42,14 +42,10 @@ * @param status processing status code */ typedef void -(*GNUNET_SCALARPRODUCT_ResponseMessageHandler) (struct - GNUNET_SCALARPRODUCT_ComputationHandle - *h, - const struct - ClientResponseMessage *msg, - enum - GNUNET_SCALARPRODUCT_ResponseStatus - status); +(*GNUNET_SCALARPRODUCT_ResponseMessageHandler) ( + struct GNUNET_SCALARPRODUCT_ComputationHandle *h, + const struct ClientResponseMessage *msg, + enum GNUNET_SCALARPRODUCT_ResponseStatus status); /** @@ -172,13 +168,12 @@ check_unique (const struct GNUNET_SCALARPRODUCT_Element *elements, uint32_t element_count) { struct GNUNET_CONTAINER_MultiHashMap *map; - uint32_t i; int ok; ok = GNUNET_OK; map = GNUNET_CONTAINER_multihashmap_create (2 * element_count, GNUNET_YES); - for (i = 0; i < element_count; i++) + for (uint32_t i = 0; i < element_count; i++) if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (map, &elements[i].key, @@ -227,16 +222,13 @@ mq_error_handler (void *cls, * @return a new handle for this computation */ struct GNUNET_SCALARPRODUCT_ComputationHandle * -GNUNET_SCALARPRODUCT_accept_computation (const struct - GNUNET_CONFIGURATION_Handle *cfg, - const struct - GNUNET_HashCode *session_key, - const struct - GNUNET_SCALARPRODUCT_Element *elements, - uint32_t element_count, - GNUNET_SCALARPRODUCT_ContinuationWithStatus - cont, - void *cont_cls) +GNUNET_SCALARPRODUCT_accept_computation ( + const struct GNUNET_CONFIGURATION_Handle *cfg, + const struct GNUNET_HashCode *session_key, + const struct GNUNET_SCALARPRODUCT_Element *elements, + uint32_t element_count, + GNUNET_SCALARPRODUCT_ContinuationWithStatus cont, + void *cont_cls) { struct GNUNET_SCALARPRODUCT_ComputationHandle *h = GNUNET_new (struct GNUNET_SCALARPRODUCT_ComputationHandle); @@ -389,16 +381,14 @@ process_result_message (struct GNUNET_SCALARPRODUCT_ComputationHandle *h, * @return a new handle for this computation */ struct GNUNET_SCALARPRODUCT_ComputationHandle * -GNUNET_SCALARPRODUCT_start_computation (const struct - GNUNET_CONFIGURATION_Handle *cfg, - const struct - GNUNET_HashCode *session_key, - const struct GNUNET_PeerIdentity *peer, - const struct - GNUNET_SCALARPRODUCT_Element *elements, - uint32_t element_count, - GNUNET_SCALARPRODUCT_DatumProcessor cont, - void *cont_cls) +GNUNET_SCALARPRODUCT_start_computation ( + const struct GNUNET_CONFIGURATION_Handle *cfg, + const struct GNUNET_HashCode *session_key, + const struct GNUNET_PeerIdentity *peer, + const struct GNUNET_SCALARPRODUCT_Element *elements, + uint32_t element_count, + GNUNET_SCALARPRODUCT_DatumProcessor cont, + void *cont_cls) { struct GNUNET_SCALARPRODUCT_ComputationHandle *h = GNUNET_new (struct GNUNET_SCALARPRODUCT_ComputationHandle); diff --git a/src/scalarproduct/test_ecc_scalarproduct.c b/src/scalarproduct/test_ecc_scalarproduct.c index eced3ef6a..85460cb05 100644 --- a/src/scalarproduct/test_ecc_scalarproduct.c +++ b/src/scalarproduct/test_ecc_scalarproduct.c @@ -45,20 +45,12 @@ test_sp (const unsigned int *avec, const unsigned int *bvec) { unsigned int len; - unsigned int i; - gcry_mpi_t a; - gcry_mpi_t a_inv; - gcry_mpi_t ri; - gcry_mpi_t val; - gcry_mpi_t ria; - gcry_mpi_t tmp; - gcry_mpi_point_t *g; - gcry_mpi_point_t *h; - gcry_mpi_point_t pg; - gcry_mpi_point_t ph; - gcry_mpi_point_t pgi; - gcry_mpi_point_t gsp; - int sp; + struct GNUNET_CRYPTO_EccScalar a; + struct GNUNET_CRYPTO_EccScalar a_neg; + struct GNUNET_CRYPTO_EccPoint *g; + struct GNUNET_CRYPTO_EccPoint *h; + struct GNUNET_CRYPTO_EccPoint pg; + struct GNUNET_CRYPTO_EccPoint ph; /* determine length */ for (len = 0; 0 != avec[len]; len++) @@ -67,90 +59,133 @@ test_sp (const unsigned int *avec, return 0; /* Alice */ - GNUNET_CRYPTO_ecc_rnd_mpi (edc, - &a, &a_inv); + GNUNET_CRYPTO_ecc_rnd_mpi (&a, + &a_neg); g = GNUNET_new_array (len, - gcry_mpi_point_t); + struct GNUNET_CRYPTO_EccPoint); h = GNUNET_new_array (len, - gcry_mpi_point_t); - ria = gcry_mpi_new (0); - tmp = gcry_mpi_new (0); - for (i = 0; i < len; i++) + struct GNUNET_CRYPTO_EccPoint); + for (unsigned int i = 0; i < len; i++) { - ri = GNUNET_CRYPTO_ecc_random_mod_n (edc); - g[i] = GNUNET_CRYPTO_ecc_dexp_mpi (edc, - ri); - /* ria = ri * a */ - gcry_mpi_mul (ria, - ri, - a); + struct GNUNET_CRYPTO_EccScalar tmp; + struct GNUNET_CRYPTO_EccScalar ri; + struct GNUNET_CRYPTO_EccScalar ria; + + GNUNET_CRYPTO_ecc_random_mod_n (&ri); + GNUNET_assert (GNUNET_OK == + GNUNET_CRYPTO_ecc_dexp_mpi (&ri, + &g[i])); + /* ria = ri * a mod L, where L is the order of the main subgroup */ + crypto_core_ed25519_scalar_mul (ria.v, + ri.v, + a.v); /* tmp = ria + avec[i] */ - gcry_mpi_add_ui (tmp, - ria, - avec[i]); - h[i] = GNUNET_CRYPTO_ecc_dexp_mpi (edc, - tmp); + { + int64_t val = avec[i]; + struct GNUNET_CRYPTO_EccScalar vali; + + GNUNET_assert (INT64_MIN != val); + GNUNET_CRYPTO_ecc_scalar_from_int (val > 0 ? val : -val, + &vali); + if (val > 0) + crypto_core_ed25519_scalar_add (tmp.v, + ria.v, + vali.v); + else + crypto_core_ed25519_scalar_sub (tmp.v, + ria.v, + vali.v); + } + /* h[i] = g^tmp = g^{ria + avec[i]} */ + GNUNET_assert (GNUNET_OK == + GNUNET_CRYPTO_ecc_dexp_mpi (&tmp, + &h[i])); } - gcry_mpi_release (ria); - gcry_mpi_release (tmp); /* Bob */ - val = gcry_mpi_new (0); - gcry_mpi_set_ui (val, bvec[0]); - pg = GNUNET_CRYPTO_ecc_pmul_mpi (edc, - g[0], - val); - ph = GNUNET_CRYPTO_ecc_pmul_mpi (edc, - h[0], - val); - for (i = 1; i < len; i++) + for (unsigned int i = 0; i < len; i++) { - gcry_mpi_point_t m; - gcry_mpi_point_t tmp; - - gcry_mpi_set_ui (val, bvec[i]); - m = GNUNET_CRYPTO_ecc_pmul_mpi (edc, - g[i], - val); - tmp = GNUNET_CRYPTO_ecc_add (edc, - m, - pg); - gcry_mpi_point_release (m); - gcry_mpi_point_release (pg); - gcry_mpi_point_release (g[i]); - pg = tmp; - - m = GNUNET_CRYPTO_ecc_pmul_mpi (edc, - h[i], - val); - tmp = GNUNET_CRYPTO_ecc_add (edc, - m, - ph); - gcry_mpi_point_release (m); - gcry_mpi_point_release (ph); - gcry_mpi_point_release (h[i]); - ph = tmp; + struct GNUNET_CRYPTO_EccPoint gm; + struct GNUNET_CRYPTO_EccPoint hm; + + { + int64_t val = bvec[i]; + struct GNUNET_CRYPTO_EccScalar vali; + + GNUNET_assert (INT64_MIN != val); + GNUNET_CRYPTO_ecc_scalar_from_int (val > 0 ? val : -val, + &vali); + if (val < 0) + crypto_core_ed25519_scalar_negate (vali.v, + vali.v); + /* gm = g[i]^vali */ + GNUNET_assert (GNUNET_OK == + GNUNET_CRYPTO_ecc_pmul_mpi (&g[i], + &vali, + &gm)); + /* hm = h[i]^vali */ + GNUNET_assert (GNUNET_OK == + GNUNET_CRYPTO_ecc_pmul_mpi (&h[i], + &vali, + &hm)); + } + if (0 != i) + { + /* pg += gm */ + GNUNET_assert (GNUNET_OK == + GNUNET_CRYPTO_ecc_add (&gm, + &pg, + &pg)); + /* ph += hm */ + GNUNET_assert (GNUNET_OK == + GNUNET_CRYPTO_ecc_add (&hm, + &ph, + &ph)); + } + else + { + pg = gm; + ph = hm; + } } - gcry_mpi_release (val); GNUNET_free (g); GNUNET_free (h); /* Alice */ - pgi = GNUNET_CRYPTO_ecc_pmul_mpi (edc, - pg, - a_inv); - gsp = GNUNET_CRYPTO_ecc_add (edc, - pgi, - ph); - gcry_mpi_point_release (pgi); - gcry_mpi_point_release (ph); - sp = GNUNET_CRYPTO_ecc_dlog (edc, - gsp); - gcry_mpi_point_release (gsp); - return sp; + { + struct GNUNET_CRYPTO_EccPoint pgi; + struct GNUNET_CRYPTO_EccPoint gsp; + + /* pgi = pg^inv */ + GNUNET_assert (GNUNET_OK == + GNUNET_CRYPTO_ecc_pmul_mpi (&pg, + &a_neg, + &pgi)); + /* gsp = pgi + ph */ + GNUNET_assert (GNUNET_OK == + GNUNET_CRYPTO_ecc_add (&pgi, + &ph, + &gsp)); + return GNUNET_CRYPTO_ecc_dlog (edc, + &gsp); + } } +/** + * Macro that checks that @a want is equal to @a have and + * if not returns with a failure code. + */ +#define CHECK(want,have) do { \ + if (want != have) { \ + GNUNET_break (0); \ + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, \ + "Wanted %d, got %d\n", want, have); \ + GNUNET_CRYPTO_ecc_dlog_release (edc); \ + return 1; \ + } } while (0) + + int main (int argc, char *argv[]) { @@ -163,12 +198,12 @@ main (int argc, char *argv[]) "WARNING", NULL); edc = GNUNET_CRYPTO_ecc_dlog_prepare (128, 128); - GNUNET_assert (2 == test_sp (v11, v11)); - GNUNET_assert (4 == test_sp (v22, v11)); - GNUNET_assert (8 == test_sp (v35, v11)); - GNUNET_assert (26 == test_sp (v35, v24)); - GNUNET_assert (26 == test_sp (v24, v35)); - GNUNET_assert (16 == test_sp (v22, v35)); + CHECK (2, test_sp (v11, v11)); + CHECK (4, test_sp (v22, v11)); + CHECK (8, test_sp (v35, v11)); + CHECK (26, test_sp (v35, v24)); + CHECK (26, test_sp (v24, v35)); + CHECK (16, test_sp (v22, v35)); GNUNET_CRYPTO_ecc_dlog_release (edc); return 0; } diff --git a/src/scalarproduct/test_scalarproduct_negative.sh b/src/scalarproduct/test_scalarproduct_negative.sh index b08e4527f..459406836 100755 --- a/src/scalarproduct/test_scalarproduct_negative.sh +++ b/src/scalarproduct/test_scalarproduct_negative.sh @@ -5,6 +5,9 @@ INPUTALICE="-k CCC -e 'AB,10;RO,-3;FL,-3;LOL,1;'" INPUTBOB="-k CCC -e 'BC,-20000;RO,1000;FL,100;LOL,24;'" # necessary to make the testing prefix deterministic, so we can access the config files +unset XDG_DATA_HOME +unset XDG_CONFIG_HOME + PREFIX=/tmp/test-scalarproduct`date +%H%M%S` # where can we find the peers config files? diff --git a/src/util/Makefile.am b/src/util/Makefile.am index e2614e5e3..f05fc7bf7 100644 --- a/src/util/Makefile.am +++ b/src/util/Makefile.am @@ -460,6 +460,7 @@ if HAVE_NOLIBGCRYPT19 test_crypto_ecc_dlog_SOURCES = \ test_crypto_ecc_dlog.c test_crypto_ecc_dlog_LDADD = \ + -lsodium \ libgnunetutil.la \ $(LIBGCRYPT_LIBS) endif @@ -610,7 +611,7 @@ perf_crypto_ecc_dlog_SOURCES = \ perf_crypto_ecc_dlog.c perf_crypto_ecc_dlog_LDADD = \ libgnunetutil.la \ - -lgcrypt + -lsodium endif perf_crypto_rsa_SOURCES = \ diff --git a/src/util/crypto_ecc_dlog.c b/src/util/crypto_ecc_dlog.c index 408d64e58..916acd9dd 100644 --- a/src/util/crypto_ecc_dlog.c +++ b/src/util/crypto_ecc_dlog.c @@ -31,35 +31,6 @@ #include "gnunet_container_lib.h" -/** - * Name of the curve we are using. Note that we have hard-coded - * structs that use 256 bits, so using a bigger curve will require - * changes that break stuff badly. The name of the curve given here - * must be agreed by all peers and be supported by libgcrypt. - */ -#define CURVE "Ed25519" - - -/** - * - */ -static void -extract_pk (gcry_mpi_point_t pt, - gcry_ctx_t ctx, - struct GNUNET_PeerIdentity *pid) -{ - gcry_mpi_t q_y; - - GNUNET_assert (0 == gcry_mpi_ec_set_point ("q", pt, ctx)); - q_y = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0); - GNUNET_assert (q_y); - GNUNET_CRYPTO_mpi_print_unsigned (pid->public_key.q_y, - sizeof(pid->public_key.q_y), - q_y); - gcry_mpi_release (q_y); -} - - /** * Internal structure used to cache pre-calculated values for DLOG calculation. */ @@ -90,160 +61,105 @@ struct GNUNET_CRYPTO_EccDlogContext }; -/** - * Convert point value to binary representation. - * - * @param edc calculation context for ECC operations - * @param point computational point representation - * @param[out] bin binary point representation - */ -void -GNUNET_CRYPTO_ecc_point_to_bin (struct GNUNET_CRYPTO_EccDlogContext *edc, - gcry_mpi_point_t point, - struct GNUNET_CRYPTO_EccPoint *bin) -{ - gcry_mpi_t q_y; - - GNUNET_assert (0 == gcry_mpi_ec_set_point ("q", point, edc->ctx)); - q_y = gcry_mpi_ec_get_mpi ("q@eddsa", edc->ctx, 0); - GNUNET_assert (q_y); - GNUNET_CRYPTO_mpi_print_unsigned (bin->q_y, - sizeof(bin->q_y), - q_y); - gcry_mpi_release (q_y); -} - - -/** - * Convert binary representation of a point to computational representation. - * - * @param edc calculation context for ECC operations - * @param bin binary point representation - * @return computational representation - */ -gcry_mpi_point_t -GNUNET_CRYPTO_ecc_bin_to_point (struct GNUNET_CRYPTO_EccDlogContext *edc, - const struct GNUNET_CRYPTO_EccPoint *bin) -{ - gcry_sexp_t pub_sexpr; - gcry_ctx_t ctx; - gcry_mpi_point_t q; - - (void) edc; - if (0 != gcry_sexp_build (&pub_sexpr, NULL, - "(public-key(ecc(curve " CURVE ")(q %b)))", - (int) sizeof(bin->q_y), - bin->q_y)) - { - GNUNET_break (0); - return NULL; - } - GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL)); - gcry_sexp_release (pub_sexpr); - q = gcry_mpi_ec_get_point ("q", ctx, 0); - gcry_ctx_release (ctx); - return q; -} - - -/** - * Do pre-calculation for ECC discrete logarithm for small factors. - * - * @param max maximum value the factor can be - * @param mem memory to use (should be smaller than @a max), must not be zero. - * @return NULL on error - */ struct GNUNET_CRYPTO_EccDlogContext * GNUNET_CRYPTO_ecc_dlog_prepare (unsigned int max, unsigned int mem) { struct GNUNET_CRYPTO_EccDlogContext *edc; - unsigned int K = ((max + (mem - 1)) / mem); - gcry_mpi_point_t g; - struct GNUNET_PeerIdentity key; - gcry_mpi_point_t gKi; - gcry_mpi_t fact; - gcry_mpi_t n; - unsigned int i; + int K = ((max + (mem - 1)) / mem); GNUNET_assert (max < INT32_MAX); edc = GNUNET_new (struct GNUNET_CRYPTO_EccDlogContext); edc->max = max; edc->mem = mem; - edc->map = GNUNET_CONTAINER_multipeermap_create (mem * 2, GNUNET_NO); - - GNUNET_assert (0 == gcry_mpi_ec_new (&edc->ctx, - NULL, - CURVE)); - g = gcry_mpi_ec_get_point ("g", edc->ctx, 0); - GNUNET_assert (NULL != g); - fact = gcry_mpi_new (0); - gKi = gcry_mpi_point_new (0); - for (i = 0; i <= mem; i++) + for (int i = -(int) mem; i <= (int) mem; i++) { - gcry_mpi_set_ui (fact, i * K); - gcry_mpi_ec_mul (gKi, fact, g, edc->ctx); - extract_pk (gKi, edc->ctx, &key); + struct GNUNET_CRYPTO_EccScalar Ki; + struct GNUNET_PeerIdentity key; + + GNUNET_CRYPTO_ecc_scalar_from_int (K * i, + &Ki); + if (0 == i) /* libsodium does not like to multiply with zero */ + GNUNET_assert ( + 0 == + crypto_core_ed25519_sub ((unsigned char *) &key, + (unsigned char *) &key, + (unsigned char *) &key)); + else + GNUNET_assert ( + 0 == + crypto_scalarmult_ed25519_base_noclamp ((unsigned char*) &key, + Ki.v)); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "K*i: %d (mem=%u, i=%d) => %s\n", + K * i, + mem, + i, + GNUNET_i2s (&key)); GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (edc->map, &key, (void *) (long) i + max, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); } - /* negative values */ - n = gcry_mpi_ec_get_mpi ("n", edc->ctx, 1); - for (i = 1; i < mem; i++) - { - gcry_mpi_set_ui (fact, i * K); - gcry_mpi_sub (fact, n, fact); - gcry_mpi_ec_mul (gKi, fact, g, edc->ctx); - extract_pk (gKi, edc->ctx, &key); - GNUNET_assert (GNUNET_OK == - GNUNET_CONTAINER_multipeermap_put (edc->map, - &key, - (void *) (long) max - i, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); - } - gcry_mpi_release (fact); - gcry_mpi_release (n); - gcry_mpi_point_release (gKi); - gcry_mpi_point_release (g); return edc; } -/** - * Calculate ECC discrete logarithm for small factors. - * - * @param edc precalculated values, determine range of factors - * @param input point on the curve to factor - * @return INT_MAX if dlog failed, otherwise the factor - */ int GNUNET_CRYPTO_ecc_dlog (struct GNUNET_CRYPTO_EccDlogContext *edc, - gcry_mpi_point_t input) + const struct GNUNET_CRYPTO_EccPoint *input) { unsigned int K = ((edc->max + (edc->mem - 1)) / edc->mem); - gcry_mpi_point_t g; - struct GNUNET_PeerIdentity key; - gcry_mpi_point_t q; - unsigned int i; int res; - void *retp; - - g = gcry_mpi_ec_get_point ("g", edc->ctx, 0); - GNUNET_assert (NULL != g); - q = gcry_mpi_point_new (0); + struct GNUNET_CRYPTO_EccPoint g; + struct GNUNET_CRYPTO_EccPoint q; + struct GNUNET_CRYPTO_EccPoint nq; + { + struct GNUNET_CRYPTO_EccScalar fact; + + memset (&fact, + 0, + sizeof (fact)); + sodium_increment (fact.v, + sizeof (fact.v)); + GNUNET_assert (0 == + crypto_scalarmult_ed25519_base_noclamp (g.v, + fact.v)); + } + /* make compiler happy: initialize q and nq, technically not needed! */ + memset (&q, + 0, + sizeof (q)); + memset (&nq, + 0, + sizeof (nq)); res = INT_MAX; - for (i = 0; i <= edc->max / edc->mem; i++) + for (unsigned int i = 0; i <= edc->max / edc->mem; i++) { + struct GNUNET_PeerIdentity key; + void *retp; + + GNUNET_assert (sizeof (key) == crypto_scalarmult_BYTES); if (0 == i) - extract_pk (input, edc->ctx, &key); + { + memcpy (&key, + input, + sizeof (key)); + } else - extract_pk (q, edc->ctx, &key); + { + memcpy (&key, + &q, + sizeof (key)); + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Trying offset i=%u): %s\n", + i, + GNUNET_i2s (&key)); retp = GNUNET_CONTAINER_multipeermap_get (edc->map, &key); if (NULL != retp) @@ -257,248 +173,163 @@ GNUNET_CRYPTO_ecc_dlog (struct GNUNET_CRYPTO_EccDlogContext *edc, break; /* q = q + g */ if (0 == i) - gcry_mpi_ec_add (q, input, g, edc->ctx); + { + GNUNET_assert (0 == + crypto_core_ed25519_add (q.v, + input->v, + g.v)); + } else - gcry_mpi_ec_add (q, q, g, edc->ctx); + { + GNUNET_assert (0 == + crypto_core_ed25519_add (q.v, + q.v, + g.v)); + } } - gcry_mpi_point_release (g); - gcry_mpi_point_release (q); - return res; } -/** - * 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) +void +GNUNET_CRYPTO_ecc_random_mod_n (struct GNUNET_CRYPTO_EccScalar *r) { - 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; + crypto_core_ed25519_scalar_random (r->v); } -/** - * Release precalculated values. - * - * @param edc dlog context - */ void GNUNET_CRYPTO_ecc_dlog_release (struct GNUNET_CRYPTO_EccDlogContext *edc) { - gcry_ctx_release (edc->ctx); GNUNET_CONTAINER_multipeermap_destroy (edc->map); GNUNET_free (edc); } -/** - * Multiply the generator g of the elliptic curve by @a val - * to obtain the point on the curve representing @a val. - * Afterwards, point addition will correspond to integer - * addition. #GNUNET_CRYPTO_ecc_dlog() can be used to - * convert a point back to an integer (as long as the - * integer is smaller than the MAX of the @a edc context). - * - * @param edc calculation context for ECC operations - * @param val value to encode into a point - * @return representation of the value as an ECC point, - * must be freed using #GNUNET_CRYPTO_ecc_free() - */ -gcry_mpi_point_t -GNUNET_CRYPTO_ecc_dexp (struct GNUNET_CRYPTO_EccDlogContext *edc, - int val) +void +GNUNET_CRYPTO_ecc_dexp (int val, + struct GNUNET_CRYPTO_EccPoint *r) { - gcry_mpi_t fact; - gcry_mpi_t n; - gcry_mpi_point_t g; - gcry_mpi_point_t r; - - g = gcry_mpi_ec_get_point ("g", edc->ctx, 0); - GNUNET_assert (NULL != g); - fact = gcry_mpi_new (0); - if (val < 0) - { - n = gcry_mpi_ec_get_mpi ("n", edc->ctx, 1); - gcry_mpi_set_ui (fact, -val); - gcry_mpi_sub (fact, n, fact); - gcry_mpi_release (n); - } - else - { - gcry_mpi_set_ui (fact, val); - } - r = gcry_mpi_point_new (0); - gcry_mpi_ec_mul (r, fact, g, edc->ctx); - gcry_mpi_release (fact); - gcry_mpi_point_release (g); - return r; + struct GNUNET_CRYPTO_EccScalar fact; + + GNUNET_CRYPTO_ecc_scalar_from_int (val, + &fact); + crypto_scalarmult_ed25519_base_noclamp (r->v, + fact.v); } -/** - * Multiply the generator g of the elliptic curve by @a val - * to obtain the point on the curve representing @a val. - * - * @param edc calculation context for ECC operations - * @param val (positive) value to encode into a point - * @return representation of the value as an ECC point, - * must be freed using #GNUNET_CRYPTO_ecc_free() - */ -gcry_mpi_point_t -GNUNET_CRYPTO_ecc_dexp_mpi (struct GNUNET_CRYPTO_EccDlogContext *edc, - gcry_mpi_t val) +enum GNUNET_GenericReturnValue +GNUNET_CRYPTO_ecc_dexp_mpi (const struct GNUNET_CRYPTO_EccScalar *val, + struct GNUNET_CRYPTO_EccPoint *r) { - gcry_mpi_point_t g; - gcry_mpi_point_t r; - - g = gcry_mpi_ec_get_point ("g", edc->ctx, 0); - GNUNET_assert (NULL != g); - r = gcry_mpi_point_new (0); - gcry_mpi_ec_mul (r, val, g, edc->ctx); - gcry_mpi_point_release (g); - return r; + if (0 == + crypto_scalarmult_ed25519_base_noclamp (r->v, + val->v)) + return GNUNET_OK; + return GNUNET_SYSERR; } -/** - * Add two points on the elliptic curve. - * - * @param edc calculation context for ECC operations - * @param a some value - * @param b some value - * @return @a a + @a b, must be freed using #GNUNET_CRYPTO_ecc_free() - */ -gcry_mpi_point_t -GNUNET_CRYPTO_ecc_add (struct GNUNET_CRYPTO_EccDlogContext *edc, - gcry_mpi_point_t a, - gcry_mpi_point_t b) +enum GNUNET_GenericReturnValue +GNUNET_CRYPTO_ecc_add (const struct GNUNET_CRYPTO_EccPoint *a, + const struct GNUNET_CRYPTO_EccPoint *b, + struct GNUNET_CRYPTO_EccPoint *r) { - gcry_mpi_point_t r; - - r = gcry_mpi_point_new (0); - gcry_mpi_ec_add (r, a, b, edc->ctx); - return r; + if (0 == + crypto_core_ed25519_add (r->v, + a->v, + b->v)) + return GNUNET_OK; + return GNUNET_SYSERR; } -/** - * Multiply the point @a p on the elliptic curve by @a val. - * - * @param edc calculation context for ECC operations - * @param p point to multiply - * @param val (positive) value to encode into a point - * @return representation of the value as an ECC point, - * must be freed using #GNUNET_CRYPTO_ecc_free() - */ -gcry_mpi_point_t -GNUNET_CRYPTO_ecc_pmul_mpi (struct GNUNET_CRYPTO_EccDlogContext *edc, - gcry_mpi_point_t p, - gcry_mpi_t val) +enum GNUNET_GenericReturnValue +GNUNET_CRYPTO_ecc_pmul_mpi (const struct GNUNET_CRYPTO_EccPoint *p, + const struct GNUNET_CRYPTO_EccScalar *val, + struct GNUNET_CRYPTO_EccPoint *r) { - gcry_mpi_point_t r; - - r = gcry_mpi_point_new (0); - gcry_mpi_ec_mul (r, val, p, edc->ctx); - return r; + if (0 == + crypto_scalarmult_ed25519_noclamp (r->v, + val->v, + p->v)) + return GNUNET_OK; + return GNUNET_SYSERR; } -/** - * Obtain a random point on the curve and its - * additive inverse. Both returned values - * must be freed using #GNUNET_CRYPTO_ecc_free(). - * - * @param edc calculation context for ECC operations - * @param[out] r set to a random point on the curve - * @param[out] r_inv set to the additive inverse of @a r - */ -void -GNUNET_CRYPTO_ecc_rnd (struct GNUNET_CRYPTO_EccDlogContext *edc, - gcry_mpi_point_t *r, - gcry_mpi_point_t *r_inv) +enum GNUNET_GenericReturnValue +GNUNET_CRYPTO_ecc_rnd (struct GNUNET_CRYPTO_EccPoint *r, + struct GNUNET_CRYPTO_EccPoint *r_inv) { - gcry_mpi_t fact; - gcry_mpi_t n; - gcry_mpi_point_t g; - - fact = GNUNET_CRYPTO_ecc_random_mod_n (edc); - - /* calculate 'r' */ - g = gcry_mpi_ec_get_point ("g", edc->ctx, 0); - GNUNET_assert (NULL != g); - *r = gcry_mpi_point_new (0); - gcry_mpi_ec_mul (*r, fact, g, edc->ctx); - - /* calculate 'r_inv' */ - n = gcry_mpi_ec_get_mpi ("n", edc->ctx, 1); - gcry_mpi_sub (fact, n, fact); /* fact = n - fact = - fact */ - *r_inv = gcry_mpi_point_new (0); - gcry_mpi_ec_mul (*r_inv, fact, g, edc->ctx); - - gcry_mpi_release (n); - gcry_mpi_release (fact); - gcry_mpi_point_release (g); + struct GNUNET_CRYPTO_EccScalar s; + unsigned char inv_s[crypto_scalarmult_ed25519_SCALARBYTES]; + + GNUNET_CRYPTO_ecc_random_mod_n (&s); + if (0 != + crypto_scalarmult_ed25519_base_noclamp (r->v, + s.v)) + return GNUNET_SYSERR; + crypto_core_ed25519_scalar_negate (inv_s, + s.v); + if (0 != + crypto_scalarmult_ed25519_base_noclamp (r_inv->v, + inv_s)) + return GNUNET_SYSERR; + return GNUNET_OK; } -/** - * Obtain a random scalar for point multiplication on the curve and - * its multiplicative inverse. - * - * @param edc calculation context for ECC operations - * @param[out] r set to a random scalar on the curve - * @param[out] r_inv set to the multiplicative inverse of @a r - */ void -GNUNET_CRYPTO_ecc_rnd_mpi (struct GNUNET_CRYPTO_EccDlogContext *edc, - gcry_mpi_t *r, - gcry_mpi_t *r_inv) +GNUNET_CRYPTO_ecc_rnd_mpi (struct GNUNET_CRYPTO_EccScalar *r, + struct GNUNET_CRYPTO_EccScalar *r_neg) { - gcry_mpi_t n; - - *r = GNUNET_CRYPTO_ecc_random_mod_n (edc); - /* r_inv = n - r = - r */ - *r_inv = gcry_mpi_new (0); - n = gcry_mpi_ec_get_mpi ("n", edc->ctx, 1); - gcry_mpi_sub (*r_inv, n, *r); + GNUNET_CRYPTO_ecc_random_mod_n (r); + crypto_core_ed25519_scalar_negate (r_neg->v, + r->v); } -/** - * Free a point value returned by the API. - * - * @param p point to free - */ void -GNUNET_CRYPTO_ecc_free (gcry_mpi_point_t p) +GNUNET_CRYPTO_ecc_scalar_from_int (int64_t val, + struct GNUNET_CRYPTO_EccScalar *r) { - gcry_mpi_point_release (p); + unsigned char fact[crypto_scalarmult_ed25519_SCALARBYTES]; + uint64_t valBe; + + GNUNET_assert (sizeof (*r) == sizeof (fact)); + if (val < 0) + { + if (INT64_MIN == val) + valBe = GNUNET_htonll ((uint64_t) INT64_MAX); + else + valBe = GNUNET_htonll ((uint64_t) (-val)); + } + else + { + valBe = GNUNET_htonll ((uint64_t) val); + } + memset (fact, + 0, + sizeof (fact)); + for (unsigned int i = 0; i < sizeof (val); i++) + fact[i] = ((unsigned char*) &valBe)[sizeof (val) - 1 - i]; + if (val < 0) + { + if (INT64_MIN == val) + /* See above: fact is one too small, increment now that we can */ + sodium_increment (fact, + sizeof (fact)); + crypto_core_ed25519_scalar_negate (r->v, + fact); + } + else + { + memcpy (r, + fact, + sizeof (fact)); + } } diff --git a/src/util/perf_crypto_ecc_dlog.c b/src/util/perf_crypto_ecc_dlog.c index 8a0e4676b..f32ffbd67 100644 --- a/src/util/perf_crypto_ecc_dlog.c +++ b/src/util/perf_crypto_ecc_dlog.c @@ -52,72 +52,88 @@ */ #define TEST_ITER 10 -/** - * Range of values to use for MATH tests. - */ -#define MATH_MAX 500000 - /** * Do some DLOG operations for testing. * * @param edc context for ECC operations - * @param do_dlog #GNUNET_YES if we want to actually do the bencharked operation + * @param do_dlog true if we want to actually do the bencharked operation */ static void test_dlog (struct GNUNET_CRYPTO_EccDlogContext *edc, - int do_dlog) + bool do_dlog) { - gcry_mpi_t fact; - gcry_mpi_t n; - gcry_ctx_t ctx; - gcry_mpi_point_t q; - gcry_mpi_point_t g; - unsigned int i; - int x; - int iret; - - GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE)); - g = gcry_mpi_ec_get_point ("g", ctx, 0); - GNUNET_assert (NULL != g); - n = gcry_mpi_ec_get_mpi ("n", ctx, 0); - q = gcry_mpi_point_new (0); - fact = gcry_mpi_new (0); - for (i = 0; i < TEST_ITER; i++) + for (unsigned int i = 0; i < TEST_ITER; i++) { + struct GNUNET_CRYPTO_EccScalar fact; + struct GNUNET_CRYPTO_EccScalar n; + struct GNUNET_CRYPTO_EccPoint q; + int x; + fprintf (stderr, "."); x = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, MAX_FACT); + memset (&n, + 0, + sizeof (n)); + for (unsigned int j = 0; j < x; j++) + sodium_increment (n.v, + sizeof (n.v)); if (0 == GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 2)) { - gcry_mpi_set_ui (fact, x); - gcry_mpi_sub (fact, n, fact); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Trying negative %d\n", + -x); + crypto_core_ed25519_scalar_negate (fact.v, + n.v); x = -x; } else { - gcry_mpi_set_ui (fact, x); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Trying positive %d\n", + x); + fact = n; } - gcry_mpi_ec_mul (q, fact, g, ctx); - if ((GNUNET_YES == do_dlog) && - (x != - (iret = GNUNET_CRYPTO_ecc_dlog (edc, - q)))) + if (0 == x) { - fprintf (stderr, - "DLOG failed for value %d (%d)\n", - x, - iret); - GNUNET_assert (0); + /* libsodium does not like to multiply with zero; make sure + 'q' is a valid point (g) first, then use q = q - q to get + the product with zero */ + sodium_increment (fact.v, + sizeof (fact.v)); + GNUNET_assert (0 == + crypto_scalarmult_ed25519_base_noclamp (q.v, + fact.v)); + GNUNET_assert ( + 0 == + crypto_core_ed25519_sub (q.v, + q.v, + q.v)); + } + else + GNUNET_assert (0 == + crypto_scalarmult_ed25519_base_noclamp (q.v, + fact.v)); + if (do_dlog) + { + int iret; + + if (x != + (iret = GNUNET_CRYPTO_ecc_dlog (edc, + &q))) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "DLOG failed for value %d (got: %d)\n", + x, + iret); + GNUNET_assert (0); + } } } - gcry_mpi_release (fact); - gcry_mpi_release (n); - gcry_mpi_point_release (g); - gcry_mpi_point_release (q); - gcry_ctx_release (ctx); - fprintf (stderr, "\n"); + fprintf (stderr, + "\n"); } @@ -128,17 +144,6 @@ main (int argc, char *argv[]) struct GNUNET_TIME_Absolute start; struct GNUNET_TIME_Relative delta; - if (! gcry_check_version ("1.6.0")) - { - fprintf (stderr, - _ - ( - "libgcrypt has not the expected version (version %s is required).\n"), - "1.6.0"); - return 0; - } - if (getenv ("GNUNET_GCRYPT_DEBUG")) - gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0); GNUNET_log_setup ("perf-crypto-ecc-dlog", "WARNING", NULL); @@ -154,10 +159,10 @@ main (int argc, char *argv[]) (start).rel_value_us / 1000LL, "ms/op"); start = GNUNET_TIME_absolute_get (); /* first do a baseline run without the DLOG */ - test_dlog (edc, GNUNET_NO); + test_dlog (edc, false); delta = GNUNET_TIME_absolute_get_duration (start); start = GNUNET_TIME_absolute_get (); - test_dlog (edc, GNUNET_YES); + test_dlog (edc, true); delta = GNUNET_TIME_relative_subtract (GNUNET_TIME_absolute_get_duration ( start), delta); @@ -165,7 +170,8 @@ main (int argc, char *argv[]) TEST_ITER, GNUNET_STRINGS_relative_time_to_string (delta, GNUNET_YES)); - GAUGER ("UTIL", "ECC DLOG operations", + GAUGER ("UTIL", + "ECC DLOG operations", delta.rel_value_us / 1000LL / TEST_ITER, "ms/op"); diff --git a/src/util/test_crypto_ecc_dlog.c b/src/util/test_crypto_ecc_dlog.c index a2c02a94e..51f290d51 100644 --- a/src/util/test_crypto_ecc_dlog.c +++ b/src/util/test_crypto_ecc_dlog.c @@ -49,7 +49,7 @@ /** * How many values do we test? */ -#define TEST_ITER 10 +#define TEST_ITER 100 /** * Range of values to use for MATH tests. @@ -65,55 +65,76 @@ static void test_dlog (struct GNUNET_CRYPTO_EccDlogContext *edc) { - gcry_mpi_t fact; - gcry_mpi_t n; - gcry_ctx_t ctx; - gcry_mpi_point_t q; - gcry_mpi_point_t g; - unsigned int i; - int x; - int iret; - - GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE)); - g = gcry_mpi_ec_get_point ("g", ctx, 0); - GNUNET_assert (NULL != g); - n = gcry_mpi_ec_get_mpi ("n", ctx, 0); - q = gcry_mpi_point_new (0); - fact = gcry_mpi_new (0); - for (i = 0; i < TEST_ITER; i++) + for (unsigned int i = 0; i < TEST_ITER; i++) { + struct GNUNET_CRYPTO_EccScalar fact; + struct GNUNET_CRYPTO_EccScalar n; + struct GNUNET_CRYPTO_EccPoint q; + int x; + fprintf (stderr, "."); x = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, MAX_FACT); + memset (&n, + 0, + sizeof (n)); + for (unsigned int j = 0; j < x; j++) + sodium_increment (n.v, + sizeof (n.v)); if (0 == GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 2)) { - gcry_mpi_set_ui (fact, x); - gcry_mpi_sub (fact, n, fact); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Trying negative %d\n", + -x); + crypto_core_ed25519_scalar_negate (fact.v, + n.v); x = -x; } else { - gcry_mpi_set_ui (fact, x); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Trying positive %d\n", + x); + fact = n; } - gcry_mpi_ec_mul (q, fact, g, ctx); - if (x != - (iret = GNUNET_CRYPTO_ecc_dlog (edc, - q))) + if (0 == x) { - fprintf (stderr, - "DLOG failed for value %d (%d)\n", - x, - iret); - GNUNET_assert (0); + /* libsodium does not like to multiply with zero; make sure + 'q' is a valid point (g) first, then use q = q - q to get + the product with zero */ + sodium_increment (fact.v, + sizeof (fact.v)); + GNUNET_assert (0 == + crypto_scalarmult_ed25519_base_noclamp (q.v, + fact.v)); + GNUNET_assert ( + 0 == + crypto_core_ed25519_sub (q.v, + q.v, + q.v)); + } + else + GNUNET_assert (0 == + crypto_scalarmult_ed25519_base_noclamp (q.v, + fact.v)); + { + int iret; + + if (x != + (iret = GNUNET_CRYPTO_ecc_dlog (edc, + &q))) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "DLOG failed for value %d (got: %d)\n", + x, + iret); + GNUNET_assert (0); + } } } - gcry_mpi_release (fact); - gcry_mpi_release (n); - gcry_mpi_point_release (g); - gcry_mpi_point_release (q); - gcry_ctx_release (ctx); - fprintf (stderr, "\n"); + fprintf (stderr, + "\n"); } @@ -127,38 +148,40 @@ test_math (struct GNUNET_CRYPTO_EccDlogContext *edc) { int i; int j; - gcry_mpi_point_t ip; - gcry_mpi_point_t jp; - gcry_mpi_point_t r; - gcry_mpi_point_t ir; - gcry_mpi_point_t irj; - gcry_mpi_point_t r_inv; - gcry_mpi_point_t sum; + struct GNUNET_CRYPTO_EccPoint ip; + struct GNUNET_CRYPTO_EccPoint jp; + struct GNUNET_CRYPTO_EccPoint r; + struct GNUNET_CRYPTO_EccPoint ir; + struct GNUNET_CRYPTO_EccPoint irj; + struct GNUNET_CRYPTO_EccPoint r_inv; + struct GNUNET_CRYPTO_EccPoint sum; for (i = -MATH_MAX; i < MATH_MAX; i++) { - ip = GNUNET_CRYPTO_ecc_dexp (edc, i); + GNUNET_CRYPTO_ecc_dexp (i, &ip); for (j = -MATH_MAX; j < MATH_MAX; j++) { fprintf (stderr, "."); - jp = GNUNET_CRYPTO_ecc_dexp (edc, j); - GNUNET_CRYPTO_ecc_rnd (edc, - &r, + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "%d + %d\n", + i, + j); + GNUNET_CRYPTO_ecc_dexp (j, &jp); + GNUNET_CRYPTO_ecc_rnd (&r, &r_inv); - ir = GNUNET_CRYPTO_ecc_add (edc, ip, r); - irj = GNUNET_CRYPTO_ecc_add (edc, ir, jp); - sum = GNUNET_CRYPTO_ecc_add (edc, irj, r_inv); - GNUNET_assert (i + j == - GNUNET_CRYPTO_ecc_dlog (edc, - sum)); - GNUNET_CRYPTO_ecc_free (jp); - GNUNET_CRYPTO_ecc_free (ir); - GNUNET_CRYPTO_ecc_free (irj); - GNUNET_CRYPTO_ecc_free (r); - GNUNET_CRYPTO_ecc_free (r_inv); - GNUNET_CRYPTO_ecc_free (sum); + GNUNET_CRYPTO_ecc_add (&ip, &r, &ir); + GNUNET_CRYPTO_ecc_add (&ir, &jp, &irj); + GNUNET_CRYPTO_ecc_add (&irj, &r_inv, &sum); + int res = GNUNET_CRYPTO_ecc_dlog (edc, &sum); + if (i + j != res) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Got %d, expected %d\n", + res, + i + j); + // GNUNET_assert (0); + } } - GNUNET_CRYPTO_ecc_free (ip); } fprintf (stderr, "\n"); } -- cgit v1.2.3