[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] r29719 - gnunet/src/revocation
From: |
gnunet |
Subject: |
[GNUnet-SVN] r29719 - gnunet/src/revocation |
Date: |
Mon, 30 Sep 2013 20:51:57 +0200 |
Author: grothoff
Date: 2013-09-30 20:51:56 +0200 (Mon, 30 Sep 2013)
New Revision: 29719
Added:
gnunet/src/revocation/gnunet-service-revocation.c
Modified:
gnunet/src/revocation/Makefile.am
gnunet/src/revocation/revocation_api.c
Log:
-draft for revocation service
Modified: gnunet/src/revocation/Makefile.am
===================================================================
--- gnunet/src/revocation/Makefile.am 2013-09-30 18:27:33 UTC (rev 29718)
+++ gnunet/src/revocation/Makefile.am 2013-09-30 18:51:56 UTC (rev 29719)
@@ -23,9 +23,28 @@
revocation_api.c revocation.h
libgnunetrevocation_la_LIBADD = \
$(top_builddir)/src/util/libgnunetutil.la \
- $(GN_LIBINTL) $(XLIB)
+ $(GN_LIBINTL) $(XLIB) -lgcrypt
libgnunetrevocation_la_LDFLAGS = \
$(GN_LIB_LDFLAGS) $(WINFLAGS) \
-version-info 0:0:0
+libexec_PROGRAMS = \
+ gnunet-service-revocation
+
+
+gnunet_service_revocation_SOURCES = \
+ gnunet-service-revocation.c
+gnunet_service_revocation_LDADD = \
+ $(top_builddir)/src/revocation/libgnunetrevocation.la \
+ $(top_builddir)/src/core/libgnunetcore.la \
+ $(top_builddir)/src/set/libgnunetset.la \
+ $(top_builddir)/src/statistics/libgnunetstatistics.la \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ -lm \
+ $(GN_LIBINTL)
+gnunet_service_revocation_DEPENDENCIES = \
+ libgnunetrevocation.la
+
+
+
#EXTRA_DIST =
Added: gnunet/src/revocation/gnunet-service-revocation.c
===================================================================
--- gnunet/src/revocation/gnunet-service-revocation.c
(rev 0)
+++ gnunet/src/revocation/gnunet-service-revocation.c 2013-09-30 18:51:56 UTC
(rev 29719)
@@ -0,0 +1,451 @@
+/*
+ This file is part of GNUnet.
+ (C) 2013 Christian Grothoff (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public Licerevocation as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public Licerevocation for more details.
+
+ You should have received a copy of the GNU General Public Licerevocation
+ 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.
+ */
+
+/**
+ * @file revocation/gnunet-service-revocation.c
+ * @brief key revocation service
+ * @author Christian Grothoff
+ *
+ * The purpose of this service is to allow users to permanently revoke
+ * (compromised) keys. This is done by flooding the network with the
+ * revocation requests. To reduce the attack potential offered by such
+ * flooding, revocations must include a proof of work. We use the
+ * set service for efficiently computing the union of revocations of
+ * peers that connect.
+ */
+#include "platform.h"
+#include <math.h>
+#include "gnunet_util_lib.h"
+#include "gnunet_constants.h"
+#include "gnunet_protocols.h"
+#include "gnunet_signatures.h"
+#include "gnunet_statistics_service.h"
+#include "gnunet_core_service.h"
+#include "gnunet_revocation_service.h"
+#include "gnunet_set_service.h"
+#include "revocation.h"
+#include <gcrypt.h>
+
+
+/**
+ * Per-peer information.
+ */
+struct PeerEntry
+{
+
+ /**
+ * Core handle for sending messages to this peer.
+ */
+ struct GNUNET_CORE_TransmitHandle *th;
+
+ /**
+ * What is the identity of the peer?
+ */
+ struct GNUNET_PeerIdentity id;
+
+ /**
+ * Task scheduled to send message to this peer.
+ */
+ GNUNET_SCHEDULER_TaskIdentifier transmit_task;
+
+};
+
+
+
+/**
+ * Handle to our current configuration.
+ */
+static const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+/**
+ * Handle to the statistics service.
+ */
+static struct GNUNET_STATISTICS_Handle *stats;
+
+/**
+ * Handle to the core service (for flooding)
+ */
+static struct GNUNET_CORE_Handle *coreAPI;
+
+/**
+ * Map of all connected peers.
+ */
+static struct GNUNET_CONTAINER_MultiHashMap *peers;
+
+/**
+ * The peer identity of this peer.
+ */
+static struct GNUNET_PeerIdentity my_identity;
+
+/**
+ * Handle to this serivce's server.
+ */
+static struct GNUNET_SERVER_Handle *srv;
+
+/**
+ * Amount of work required (W-bit collisions) for REVOCATION proofs, in
collision-bits.
+ */
+static unsigned long long revocation_work_required;
+
+
+/**
+ * An revoke message has been received, check that it is well-formed.
+ *
+ * @param rm the message to verify
+ * @return #GNUNET_YES if the message is verified
+ * #GNUNET_NO if the key/signature don't verify
+ */
+static int
+verify_revoke_message (const struct GNUNET_REVOCATION_RevokeMessage *rm)
+{
+ if (GNUNET_YES !=
+ GNUNET_REVOCATION_check_pow (&rm->public_key,
+ rm->proof_of_work,
+ (unsigned int) revocation_work_required))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Proof of work invalid: %llu!\n",
+ (unsigned long long)
+ GNUNET_ntohll (rm->proof_of_work));
+ GNUNET_break_op (0);
+ return GNUNET_NO;
+ }
+ if (GNUNET_OK !=
+ GNUNET_CRYPTO_ecc_verify (GNUNET_SIGNATURE_PURPOSE_REVOCATION,
+ &rm->purpose,
+ &rm->signature,
+ &rm->public_key))
+ {
+ GNUNET_break_op (0);
+ return GNUNET_NO;
+ }
+ return GNUNET_YES;
+}
+
+
+/**
+ * Handle QUERY message from client.
+ *
+ * @param cls unused
+ * @param client who sent the message
+ * @param message the message received
+ */
+static void
+handle_query_message (void *cls,
+ struct GNUNET_SERVER_Client *client,
+ const struct GNUNET_MessageHeader *message)
+{
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Received QUERY message from client\n");
+ GNUNET_break (0);
+ GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+}
+
+
+/**
+ * Handle REVOKE message from client.
+ *
+ * @param cls unused
+ * @param client who sent the message
+ * @param message the message received
+ */
+static void
+handle_revoke_message (void *cls,
+ struct GNUNET_SERVER_Client *client,
+ const struct GNUNET_MessageHeader *message)
+{
+ const struct GNUNET_REVOCATION_RevokeMessage *rm;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Received REVOKE message from client\n");
+ rm = (const struct GNUNET_REVOCATION_RevokeMessage *) message;
+ if (GNUNET_OK !=
+ verify_revoke_message (rm))
+ {
+ GNUNET_break (0);
+ GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+ }
+ GNUNET_break (0); // FIXME: TBD
+ GNUNET_SERVER_receive_done (client, GNUNET_OK);
+}
+
+
+/**
+ * Core handler for flooded revocation messages.
+ *
+ * @param cls closure unused
+ * @param message message
+ * @param peer peer identity this message is from (ignored)
+ */
+static int
+handle_p2p_revoke_message (void *cls,
+ const struct GNUNET_PeerIdentity *peer,
+ const struct GNUNET_MessageHeader *message)
+{
+ const struct GNUNET_REVOCATION_RevokeMessage *rm;
+
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Received REVOKE message from peer\n");
+ rm = (const struct GNUNET_REVOCATION_RevokeMessage *) message;
+ if (GNUNET_OK !=
+ verify_revoke_message (rm))
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ GNUNET_break (0); // FIXME: TBD
+
+#if 0
+ /* flood to rest */
+ GNUNET_CONTAINER_multihashmap_iterate (peers,
+ &do_flood,
+ &ctx);
+#endif
+ return GNUNET_OK;
+}
+
+
+/**
+ * Method called whenever a peer connects. Sets up the PeerEntry and
+ * schedules the initial revocation set exchange with this peer.
+ *
+ * @param cls closure
+ * @param peer peer identity this notification is about
+ */
+static void
+handle_core_connect (void *cls,
+ const struct GNUNET_PeerIdentity *peer)
+{
+ struct PeerEntry *peer_entry;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer `%s' connected to us\n",
+ GNUNET_i2s (peer));
+ peer_entry = GNUNET_new (struct PeerEntry);
+ peer_entry->id = *peer;
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_CONTAINER_multihashmap_put (peers, &peer->hashPubKey,
+ peer_entry,
+
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
+#if 0
+ peer_entry->transmit_task =
+ GNUNET_SCHEDULER_add_delayed (get_transmit_delay (-1), &transmit_task_cb,
+ peer_entry);
+#endif
+ GNUNET_STATISTICS_update (stats, "# peers connected", 1, GNUNET_NO);
+}
+
+
+/**
+ * Method called whenever a peer disconnects. Deletes the PeerEntry and cancels
+ * any pending transmission requests to that peer.
+ *
+ * @param cls closure
+ * @param peer peer identity this notification is about
+ */
+static void
+handle_core_disconnect (void *cls,
+ const struct GNUNET_PeerIdentity *peer)
+{
+ struct PeerEntry *pos;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Peer `%s' disconnected from us\n",
+ GNUNET_i2s (peer));
+ pos = GNUNET_CONTAINER_multihashmap_get (peers, &peer->hashPubKey);
+ if (NULL == pos)
+ {
+ GNUNET_break (0);
+ return;
+ }
+ GNUNET_assert (GNUNET_YES ==
+ GNUNET_CONTAINER_multihashmap_remove (peers,
&peer->hashPubKey,
+ pos));
+#if 0
+ if (pos->transmit_task != GNUNET_SCHEDULER_NO_TASK)
+ {
+ GNUNET_SCHEDULER_cancel (pos->transmit_task);
+ pos->transmit_task = GNUNET_SCHEDULER_NO_TASK;
+ }
+ if (NULL != pos->th)
+ {
+ GNUNET_CORE_notify_transmit_ready_cancel (pos->th);
+ pos->th = NULL;
+ }
+#endif
+ GNUNET_free (pos);
+ GNUNET_STATISTICS_update (stats, "# peers connected", -1, GNUNET_NO);
+}
+
+
+/**
+ * Task run during shutdown.
+ *
+ * @param cls unused
+ * @param tc unused
+ */
+static void
+shutdown_task (void *cls,
+ const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ if (NULL != coreAPI)
+ {
+ GNUNET_CORE_disconnect (coreAPI);
+ coreAPI = NULL;
+ }
+ if (NULL != stats)
+ {
+ GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
+ stats = NULL;
+ }
+ if (NULL != peers)
+ {
+ GNUNET_CONTAINER_multihashmap_destroy (peers);
+ peers = NULL;
+ }
+}
+
+
+/**
+ * Called on core init/fail.
+ *
+ * @param cls service closure
+ * @param identity the public identity of this peer
+ */
+static void
+core_init (void *cls,
+ const struct GNUNET_PeerIdentity *identity)
+{
+ if (NULL == identity)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Connection to core FAILED!\n");
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+ my_identity = *identity;
+}
+
+
+/**
+ * Handle network size estimate clients.
+ *
+ * @param cls closure
+ * @param server the initialized server
+ * @param c configuration to use
+ */
+static void
+run (void *cls,
+ struct GNUNET_SERVER_Handle *server,
+ const struct GNUNET_CONFIGURATION_Handle *c)
+{
+ static const struct GNUNET_SERVER_MessageHandler handlers[] = {
+ {&handle_query_message, NULL, GNUNET_MESSAGE_TYPE_REVOCATION_QUERY,
+ sizeof (struct GNUNET_REVOCATION_QueryMessage)},
+ {&handle_revoke_message, NULL, GNUNET_MESSAGE_TYPE_REVOCATION_REVOKE,
+ sizeof (struct GNUNET_REVOCATION_RevokeMessage)},
+ {NULL, NULL, 0, 0}
+ };
+ static const struct GNUNET_CORE_MessageHandler core_handlers[] = {
+ {&handle_p2p_revoke_message, GNUNET_MESSAGE_TYPE_REVOCATION_REVOKE,
+ sizeof (struct GNUNET_REVOCATION_RevokeMessage)},
+ {NULL, 0, 0}
+ };
+
+ cfg = c;
+ srv = server;
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_number (cfg, "REVOCATION", "WORKBITS",
+ &revocation_work_required))
+ {
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+ "REVOCATION",
+ "WORKBITS");
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+ if (revocation_work_required >= sizeof (struct GNUNET_HashCode) * 8)
+ {
+ GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
+ "REVOCATION",
+ "WORKBITS",
+ _("Value for WORKBITS is too large.\n"));
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+ GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task,
+ NULL);
+ peers = GNUNET_CONTAINER_multihashmap_create (128, GNUNET_NO);
+ GNUNET_SERVER_add_handlers (srv, handlers);
+ /* Connect to core service and register core handlers */
+ coreAPI = GNUNET_CORE_connect (cfg, /* Main configuration */
+ NULL, /* Closure passed to functions */
+ &core_init, /* Call core_init once
connected */
+ &handle_core_connect, /* Handle connects */
+ &handle_core_disconnect, /* Handle
disconnects */
+ NULL, /* Don't want notified about all
incoming messages */
+ GNUNET_NO, /* For header only inbound
notification */
+ NULL, /* Don't want notified about all
outbound messages */
+ GNUNET_NO, /* For header only outbound
notification */
+ core_handlers); /* Register these
handlers */
+ if (NULL == coreAPI)
+ {
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+ stats = GNUNET_STATISTICS_create ("revocation", cfg);
+}
+
+
+/**
+ * The main function for the network size estimation service.
+ *
+ * @param argc number of arguments from the command line
+ * @param argv command line arguments
+ * @return 0 ok, 1 on error
+ */
+int
+main (int argc,
+ char *const *argv)
+{
+ return (GNUNET_OK ==
+ GNUNET_SERVICE_run (argc, argv, "revocation",
GNUNET_SERVICE_OPTION_NONE,
+ &run, NULL)) ? 0 : 1;
+}
+
+
+#ifdef LINUX
+#include <malloc.h>
+
+/**
+ * MINIMIZE heap size (way below 128k) since this process doesn't need much.
+ */
+void __attribute__ ((constructor))
+GNUNET_ARM_memory_init ()
+{
+ mallopt (M_TRIM_THRESHOLD, 4 * 1024);
+ mallopt (M_TOP_PAD, 1 * 1024);
+ malloc_trim (0);
+}
+#endif
+
+
+
+/* end of gnunet-service-revocation.c */
Modified: gnunet/src/revocation/revocation_api.c
===================================================================
--- gnunet/src/revocation/revocation_api.c 2013-09-30 18:27:33 UTC (rev
29718)
+++ gnunet/src/revocation/revocation_api.c 2013-09-30 18:51:56 UTC (rev
29719)
@@ -27,6 +27,7 @@
#include "gnunet_signatures.h"
#include "gnunet_protocols.h"
#include "revocation.h"
+#include <gcrypt.h>
/**
@@ -196,20 +197,72 @@
}
+
/**
+ * Calculate the 'proof-of-work' hash (an expensive hash).
+ *
+ * @param buf data to hash
+ * @param buf_len number of bytes in @a buf
+ * @param result where to write the resulting hash
+ */
+static void
+pow_hash (const void *buf,
+ size_t buf_len,
+ struct GNUNET_HashCode *result)
+{
+ GNUNET_break (0 ==
+ gcry_kdf_derive (buf, buf_len,
+ GCRY_KDF_SCRYPT,
+ 1 /* subalgo */,
+ "gnunet-revocation-proof-of-work",
+ strlen ("gnunet-revocation-proof-of-work"),
+ 2 /* iterations; keep cost of individual op
small */,
+ sizeof (struct GNUNET_HashCode), result));
+}
+
+
+/**
+ * Count the leading zeroes in hash.
+ *
+ * @param hash to count leading zeros in
+ * @return the number of leading zero bits.
+ */
+static unsigned int
+count_leading_zeroes (const struct GNUNET_HashCode *hash)
+{
+ unsigned int hash_count;
+
+ hash_count = 0;
+ while ((0 == GNUNET_CRYPTO_hash_get_bit (hash, hash_count)))
+ hash_count++;
+ return hash_count;
+}
+
+
+/**
* Check if the given proof-of-work value
* would be acceptable for revoking the given key.
*
* @param key key to check for
* @param pow proof of work value
+ * @param matching_bits how many bits must match (configuration)
* @return #GNUNET_YES if the @a pow is acceptable, #GNUNET_NO if not
*/
int
GNUNET_REVOCATION_check_pow (const struct GNUNET_CRYPTO_EccPublicSignKey *key,
- uint64_t pow)
+ uint64_t pow,
+ unsigned int matching_bits)
{
- GNUNET_break (0);
- return GNUNET_NO;
+ char buf[sizeof (struct GNUNET_CRYPTO_EccPublicSignKey) +
+ sizeof (pow)] GNUNET_ALIGN;
+ struct GNUNET_HashCode result;
+
+ memcpy (buf, &pow, sizeof (pow));
+ memcpy (&buf[sizeof (pow)], key,
+ sizeof (struct GNUNET_CRYPTO_EccPublicSignKey));
+ pow_hash (buf, sizeof (buf), &result);
+ return (count_leading_zeroes (&result) >=
+ matching_bits) ? GNUNET_YES : GNUNET_NO;
}
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r29719 - gnunet/src/revocation,
gnunet <=