gnunet-svn
[Top][All Lists]
Advanced

[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;
 }
 
 




reply via email to

[Prev in Thread] Current Thread [Next in Thread]