/*
This file is part of GNUnet.
- (C) 2013, 2014 Christian Grothoff (and other contributing authors)
+ Copyright (C) 2013, 2014, 2016 GNUnet e.V.
GNUnet is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
You should have received a copy of the GNU General Public License
along with GNUnet; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
*/
/**
* @file scalarproduct/gnunet-service-scalarproduct_bob.c
*/
struct GNUNET_SET_OperationHandle *intersection_op;
+ /**
+ * CADET port we are listening on.
+ */
+ struct GNUNET_CADET_Port *port;
+
/**
* a(Alice)
*/
*/
struct CadetIncomingSession *cadet;
- /**
- * The computed scalar
- */
- gcry_mpi_t product;
-
/**
* How many elements will be supplied in total from the client.
*/
uint32_t cadet_transmitted_element_count;
/**
- * Is this session active (#GNUNET_YES), Concluded (#GNUNET_NO), or had an error (#GNUNET_SYSERR)
+ * State of this session. In
+ * #GNUNET_SCALARPRODUCT_STATUS_ACTIVE while operation is
+ * ongoing, afterwards in #GNUNET_SCALARPRODUCT_STATUS_SUCCESS or
+ * #GNUNET_SCALARPRODUCT_STATUS_FAILURE.
*/
- int32_t active;
+ enum GNUNET_SCALARPRODUCT_ResponseStatus status;
/**
* Are we already in #destroy_service_session()?
}
+/**
+ * Callback used to free the elements in the map.
+ *
+ * @param cls NULL
+ * @param key key of the element
+ * @param value the value to free
+ */
+static int
+free_element_cb (void *cls,
+ const struct GNUNET_HashCode *key,
+ void *value)
+{
+ struct GNUNET_SCALARPRODUCT_Element *element = value;
+
+ GNUNET_free (element);
+ return GNUNET_OK;
+}
+
+
/**
* Destroy session state, we are done with it.
*
s));
if (NULL != s->intersected_elements)
{
- /* FIXME: free elements */
+ GNUNET_CONTAINER_multihashmap_iterate (s->intersected_elements,
+ &free_element_cb,
+ NULL);
GNUNET_CONTAINER_multihashmap_destroy (s->intersected_elements);
s->intersected_elements = NULL;
}
GNUNET_free (s->r_prime);
s->r_prime = NULL;
}
- if (NULL != s->product)
- {
- gcry_mpi_release (s->product);
- s->product = NULL;
- }
+ GNUNET_CADET_close_port (s->port);
GNUNET_free (s);
}
struct ClientResponseMessage *msg;
struct GNUNET_MQ_Envelope *e;
+ if (NULL == session->client_mq)
+ return; /* no client left to be notified */
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Sending session-end notification with status %d to client for session %s\n",
- session->active,
+ session->status,
GNUNET_h2s (&session->session_id));
e = GNUNET_MQ_msg (msg,
GNUNET_MESSAGE_TYPE_SCALARPRODUCT_RESULT);
msg->range = 0;
msg->product_length = htonl (0);
- msg->status = htonl (session->active);
+ msg->status = htonl (session->status);
GNUNET_MQ_send (session->client_mq,
e);
}
"Peer disconnected, terminating session %s with peer %s\n",
GNUNET_h2s (&in->session_id),
GNUNET_i2s (&in->peer));
- in->channel = NULL;
if (NULL != (s = in->s))
{
- if (GNUNET_YES == s->active)
+ if (GNUNET_SCALARPRODUCT_STATUS_ACTIVE == s->status)
{
- s->active = GNUNET_SYSERR;
+ s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE;
prepare_client_end_notification (s);
}
}
+ if (NULL != in->cadet_mq)
+ {
+ GNUNET_MQ_destroy (in->cadet_mq);
+ in->cadet_mq = NULL;
+ }
+ in->channel = NULL;
destroy_cadet_session (in);
}
{
struct BobServiceSession *session = cls;
- session->active = GNUNET_NO; /* that means, done */
+ session->status = GNUNET_SCALARPRODUCT_STATUS_SUCCESS;
prepare_client_end_notification (session);
}
/**
* Maximum count of elements we can put into a multipart message
*/
-#define ELEMENT_CAPACITY ((GNUNET_SERVER_MAX_MESSAGE_SIZE - 1 - sizeof (struct BobCryptodataMultipartMessage)) / sizeof (struct GNUNET_CRYPTO_PaillierCiphertext))
+#define ELEMENT_CAPACITY ((GNUNET_CONSTANTS_MAX_CADET_MESSAGE_SIZE - 1 - sizeof (struct BobCryptodataMultipartMessage)) / sizeof (struct GNUNET_CRYPTO_PaillierCiphertext))
/**
for (i = s->cadet_transmitted_element_count, j = 0; i < s->cadet_transmitted_element_count + todo_count; i++)
{
//r[i][p] and r[i][q]
- memcpy (&payload[j++],
+ GNUNET_memcpy (&payload[j++],
&s->r[i],
sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
- memcpy (&payload[j++],
+ GNUNET_memcpy (&payload[j++],
&s->r_prime[i],
sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
}
GNUNET_MQ_send (s->cadet->cadet_mq,
e);
}
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "All values queued for Alice, Bob is done\n");
}
struct GNUNET_CRYPTO_PaillierCiphertext *payload;
unsigned int i;
- s->cadet_transmitted_element_count = (GNUNET_SERVER_MAX_MESSAGE_SIZE - 1 - sizeof (struct BobCryptodataMessage)) /
- (sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) * 2) - 2;
+ s->cadet_transmitted_element_count
+ = ((GNUNET_CONSTANTS_MAX_CADET_MESSAGE_SIZE - 1 - sizeof (struct BobCryptodataMessage))
+ / sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) / 2) - 1;
if (s->cadet_transmitted_element_count > s->used_element_count)
s->cadet_transmitted_element_count = s->used_element_count;
(2 + s->cadet_transmitted_element_count * 2)
* sizeof (struct GNUNET_CRYPTO_PaillierCiphertext),
GNUNET_MESSAGE_TYPE_SCALARPRODUCT_BOB_CRYPTODATA);
- msg->reserved = htonl (0);
- msg->intersection_element_count = htonl (s->used_element_count);
msg->contained_element_count = htonl (s->cadet_transmitted_element_count);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
(unsigned int) s->used_element_count);
payload = (struct GNUNET_CRYPTO_PaillierCiphertext *) &msg[1];
- memcpy (&payload[0],
+ GNUNET_memcpy (&payload[0],
&s->s,
sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
- memcpy (&payload[1],
+ GNUNET_memcpy (&payload[1],
&s->s_prime,
sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
for (i = 0; i < s->cadet_transmitted_element_count; i++)
{
//k[i][p] and k[i][q]
- memcpy (&payload[i * 2],
+ GNUNET_memcpy (&payload[i * 2],
&s->r[i],
sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
- memcpy (&payload[i * 2 + 1],
+ GNUNET_memcpy (&payload[i * 2 + 1],
&s->r_prime[i],
sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
}
e);
transmit_bobs_cryptodata_message_multipart (s);
}
+#undef ELEMENT_CAPACITY
/**
* S': $S' := E_A(sum r_i^2)$
*
* @param request the requesting session + bob's requesting peer
+ * @return #GNUNET_OK on success
*/
-static void
+static int
compute_service_response (struct BobServiceSession *session)
{
uint32_t i;
// E(S - r_pi - b_pi)
gcry_mpi_sub (tmp, my_offset, rand[p[i]]);
gcry_mpi_sub (tmp, tmp, b[p[i]].value);
- GNUNET_CRYPTO_paillier_encrypt (&session->cadet->remote_pubkey,
- tmp,
- 2,
- &r[i]);
+ GNUNET_assert (2 ==
+ GNUNET_CRYPTO_paillier_encrypt (&session->cadet->remote_pubkey,
+ tmp,
+ 2,
+ &r[i]));
// E(S - r_pi - b_pi) * E(S + a_pi) == E(2*S + a - r - b)
- GNUNET_CRYPTO_paillier_hom_add (&session->cadet->remote_pubkey,
- &r[i],
- &a[p[i]],
- &r[i]);
+ if (GNUNET_OK !=
+ GNUNET_CRYPTO_paillier_hom_add (&session->cadet->remote_pubkey,
+ &r[i],
+ &a[p[i]],
+ &r[i]))
+ {
+ GNUNET_break_op (0);
+ goto error_cleanup;
+ }
}
// Calculate Kq = E(S + a_qi) (+) E(S - r_qi)
{
// E(S - r_qi)
gcry_mpi_sub (tmp, my_offset, rand[q[i]]);
- GNUNET_assert (2 == GNUNET_CRYPTO_paillier_encrypt (&session->cadet->remote_pubkey,
- tmp,
- 2,
- &r_prime[i]));
+ GNUNET_assert (2 ==
+ GNUNET_CRYPTO_paillier_encrypt (&session->cadet->remote_pubkey,
+ tmp,
+ 2,
+ &r_prime[i]));
// E(S - r_qi) * E(S + a_qi) == E(2*S + a_qi - r_qi)
- GNUNET_assert (1 == GNUNET_CRYPTO_paillier_hom_add (&session->cadet->remote_pubkey,
- &r_prime[i],
- &a[q[i]],
- &r_prime[i]));
+ if (GNUNET_OK !=
+ GNUNET_CRYPTO_paillier_hom_add (&session->cadet->remote_pubkey,
+ &r_prime[i],
+ &a[q[i]],
+ &r_prime[i]))
+ {
+ GNUNET_break_op (0);
+ goto error_cleanup;
+ }
}
+ gcry_mpi_release (tmp);
// Calculate S' = E(SUM( r_i^2 ))
tmp = compute_square_sum (rand, count);
- GNUNET_CRYPTO_paillier_encrypt (&session->cadet->remote_pubkey,
- tmp,
- 1,
- &session->s_prime);
+ GNUNET_assert (1 ==
+ GNUNET_CRYPTO_paillier_encrypt (&session->cadet->remote_pubkey,
+ tmp,
+ 1,
+ &session->s_prime));
+ gcry_mpi_release (tmp);
// Calculate S = E(SUM( (r_i + b_i)^2 ))
for (i = 0; i < count; i++)
gcry_mpi_add (rand[i], rand[i], b[i].value);
tmp = compute_square_sum (rand, count);
- GNUNET_CRYPTO_paillier_encrypt (&session->cadet->remote_pubkey,
- tmp,
- 1,
- &session->s);
+ GNUNET_assert (1 ==
+ GNUNET_CRYPTO_paillier_encrypt (&session->cadet->remote_pubkey,
+ tmp,
+ 1,
+ &session->s));
+ gcry_mpi_release (tmp);
session->r = r;
session->r_prime = r_prime;
- // release rand, b and a
for (i = 0; i < count; i++)
gcry_mpi_release (rand[i]);
- gcry_mpi_release (tmp);
GNUNET_free (session->e_a);
session->e_a = NULL;
GNUNET_free (p);
GNUNET_free (q);
GNUNET_free (rand);
+ return GNUNET_OK;
- // copy the r[], r_prime[], S and Stick into a new message, prepare_service_response frees these
+ error_cleanup:
+ GNUNET_free (r);
+ GNUNET_free (r_prime);
+ gcry_mpi_release (tmp);
+ GNUNET_free (p);
+ GNUNET_free (q);
+ for (i = 0; i < count; i++)
+ gcry_mpi_release (rand[i]);
+ GNUNET_free (rand);
+ return GNUNET_SYSERR;
}
static void
transmit_cryptographic_reply (struct BobServiceSession *s)
{
+ struct GNUNET_CADET_Channel *channel;
+
/* TODO: code duplication with Alice! */
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Received everything, building reply for Alice\n");
s->used_element_count,
sizeof (struct MpiElement),
&element_cmp);
- compute_service_response (s);
+ if (GNUNET_OK !=
+ compute_service_response (s))
+ {
+ channel = s->cadet->channel;
+ s->cadet->channel = NULL;
+ GNUNET_CADET_channel_destroy (channel);
+ return;
+ }
transmit_bobs_cryptodata_message (s);
}
if (NULL == s->e_a)
s->e_a = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) *
max);
- memcpy (&s->e_a[s->cadet_received_element_count],
+ GNUNET_memcpy (&s->e_a[s->cadet_received_element_count],
payload,
sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) * contained_elements);
s->cadet_received_element_count += contained_elements;
CADET response(s) */
transmit_cryptographic_reply (s);
}
+ GNUNET_CADET_receive_done (s->cadet->channel);
return GNUNET_OK;
}
return;
case GNUNET_SET_STATUS_DONE:
s->intersection_op = NULL;
- s->intersection_set = NULL;
+ GNUNET_break (NULL == s->intersection_set);
+ GNUNET_CADET_receive_done (s->cadet->channel);
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Finished intersection, %d items remain\n",
GNUNET_CONTAINER_multihashmap_size (s->intersected_elements));
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Set intersection failed!\n");
s->intersection_op = NULL;
- s->intersection_set = NULL;
- s->active = GNUNET_SYSERR;
+ if (NULL != s->intersection_set)
+ {
+ GNUNET_SET_destroy (s->intersection_set);
+ s->intersection_set = NULL;
+ }
+ s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE;
prepare_client_end_notification (s);
return;
default:
GNUNET_SET_RESULT_REMOVED,
&cb_intersection_element_removed,
s);
- GNUNET_SET_commit (s->intersection_op,
- s->intersection_set);
+ if (GNUNET_OK !=
+ GNUNET_SET_commit (s->intersection_op,
+ s->intersection_set))
+ {
+ GNUNET_break (0);
+ s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE;
+ prepare_client_end_notification (s);
+ return;
+ }
+ GNUNET_SET_destroy (s->intersection_set);
+ s->intersection_set = NULL;
}
struct BobServiceSession *s;
const struct ServiceRequestMessage *msg;
- if (ntohs (message->size) != sizeof (struct ServiceRequestMessage))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
msg = (const struct ServiceRequestMessage *) message;
if (GNUNET_YES == in->in_map)
{
* preliminary initialization, more happens after we get Alice's first
* message.
*
- * @param cls closure
+ * @param cls closure with the `struct BobServiceSession`
* @param channel new handle to the channel
* @param initiator peer that started the channel
* @param port unused
cb_channel_incoming (void *cls,
struct GNUNET_CADET_Channel *channel,
const struct GNUNET_PeerIdentity *initiator,
- uint32_t port,
+ const struct GNUNET_HashCode *port,
enum GNUNET_CADET_ChannelOption options)
{
struct CadetIncomingSession *in;
in = GNUNET_new (struct CadetIncomingSession);
in->peer = *initiator;
in->channel = channel;
+ in->cadet_mq = GNUNET_CADET_mq_create (in->channel);
return in;
}
elements = (const struct GNUNET_SCALARPRODUCT_Element *) &msg[1];
for (i = 0; i < contained_count; i++)
{
- if (0 == GNUNET_ntohll (elements[i].value))
- continue;
elem = GNUNET_new (struct GNUNET_SCALARPRODUCT_Element);
- memcpy (elem,
+ GNUNET_memcpy (elem,
&elements[i],
sizeof (struct GNUNET_SCALARPRODUCT_Element));
if (GNUNET_SYSERR ==
GNUNET_SYSERR);
return;
}
- if (NULL != find_matching_client_session (&msg->session_key))
- {
- GNUNET_break (0);
- GNUNET_SERVER_receive_done (client,
- GNUNET_SYSERR);
- return;
- }
s = GNUNET_new (struct BobServiceSession);
- s->active = GNUNET_YES;
+ s->status = GNUNET_SCALARPRODUCT_STATUS_ACTIVE;
s->client = client;
s->client_mq = GNUNET_MQ_queue_for_server_client (client);
s->total = total_count;
s->client_received_element_count = contained_count;
s->session_id = msg->session_key;
+ s->port = GNUNET_CADET_open_port (my_cadet,
+ &msg->session_key,
+ &cb_channel_incoming,
+ s);
+ if (NULL == s->port)
+ {
+ GNUNET_break (0);
+ GNUNET_SERVER_receive_done (client,
+ GNUNET_SYSERR);
+ GNUNET_free (s);
+ return;
+ }
+
GNUNET_break (GNUNET_YES ==
GNUNET_CONTAINER_multihashmap_put (client_sessions,
&s->session_id,
if (0 == GNUNET_ntohll (elements[i].value))
continue;
elem = GNUNET_new (struct GNUNET_SCALARPRODUCT_Element);
- memcpy (elem,
+ GNUNET_memcpy (elem,
&elements[i],
sizeof (struct GNUNET_SCALARPRODUCT_Element));
if (GNUNET_SYSERR ==
* Task run during shutdown.
*
* @param cls unused
- * @param tc unused
*/
static void
-shutdown_task (void *cls,
- const struct GNUNET_SCHEDULER_TaskContext *tc)
+shutdown_task (void *cls)
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Shutting down, initiating cleanup.\n");
- // FIXME: do we have to cut our connections to CADET first?
+ // FIXME: we have to cut our connections to CADET first!
if (NULL != my_cadet)
{
GNUNET_CADET_disconnect (my_cadet);
if (NULL == client)
return;
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Client disconnected from us.\n",
- client);
+ "Client disconnected from us.\n");
s = GNUNET_SERVER_client_get_user_context (client,
struct BobServiceSession);
if (NULL == s)
GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_TO_BOB,
0},
{ &GSS_handle_bob_client_message_multipart, NULL,
- GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_MUTLIPART_BOB,
+ GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_MULTIPART_BOB,
0},
{ NULL, NULL, 0, 0}
};
0},
{ NULL, 0, 0}
};
- static const uint32_t ports[] = {
- GNUNET_APPLICATION_TYPE_SCALARPRODUCT,
- 0
- };
cfg = c;
/*
cadet_sessions = GNUNET_CONTAINER_multihashmap_create (128,
GNUNET_YES);
my_cadet = GNUNET_CADET_connect (cfg, NULL,
- &cb_channel_incoming,
&cb_channel_destruction,
- cadet_handlers,
- ports);
+ cadet_handlers);
if (NULL == my_cadet)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
GNUNET_SCHEDULER_shutdown ();
return;
}
- GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
- &shutdown_task,
- NULL);
+ GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
+ NULL);
}