Commit aae034d1 authored by Nick Mathewson's avatar Nick Mathewson 🥄
Browse files

Write a bunch of module documentation.

This commit adds or improves the module-level documenation for:

  buffers.c circuitstats.c command.c connection_edge.c control.c
  cpuworker.c crypto_curve25519.c crypto_curve25519.h
  crypto_ed25519.c crypto_format.c dircollate.c dirserv.c dns.c
  dns_structs.h fp_pair.c geoip.c hibernate.c keypin.c ntmain.c
  onion.c onion_fast.c onion_ntor.c onion_tap.c periodic.c
  protover.c protover.h reasons.c rephist.c replaycache.c
  routerlist.c routerparse.c routerset.c statefile.c status.c
  tor_main.c workqueue.c

In particular, I've tried to explain (for each documented module)
what each module does, what's in it, what the big idea is, why it
belongs in Tor, and who calls it.  In a few cases, I've added TODO
notes about refactoring opportunities.

I've also renamed an argument, and fixed a few DOCDOC comments.
parent 55c468c5
...@@ -5,6 +5,14 @@ ...@@ -5,6 +5,14 @@
* \file crypto_curve25519.c * \file crypto_curve25519.c
* *
* \brief Wrapper code for a curve25519 implementation. * \brief Wrapper code for a curve25519 implementation.
*
* Curve25519 is an Elliptic-Curve Diffie Hellman handshake, designed by
* Dan Bernstein. For more information, see https://cr.yp.to/ecdh.html
*
* Tor uses Curve25519 as the basis of its "ntor" circuit extension
* handshake, and in related code. The functions in this module are
* used to find the most suitable available Curve25519 implementation,
* to provide wrappers around it, and so on.
*/ */
#define CRYPTO_CURVE25519_PRIVATE #define CRYPTO_CURVE25519_PRIVATE
...@@ -39,15 +47,23 @@ int curve25519_donna(uint8_t *mypublic, ...@@ -39,15 +47,23 @@ int curve25519_donna(uint8_t *mypublic,
static void pick_curve25519_basepoint_impl(void); static void pick_curve25519_basepoint_impl(void);
/** This is set to 1 if we have an optimized Ed25519-based
* implementation for multiplying a value by the basepoint; to 0 if we
* don't, and to -1 if we haven't checked. */
static int curve25519_use_ed = -1; static int curve25519_use_ed = -1;
/**
* Helper function: call the most appropriate backend to compute the
* scalar "secret" times the point "point". Store the result in
* "output". Return 0 on success, negative on failure.
**/
STATIC int STATIC int
curve25519_impl(uint8_t *output, const uint8_t *secret, curve25519_impl(uint8_t *output, const uint8_t *secret,
const uint8_t *basepoint) const uint8_t *point)
{ {
uint8_t bp[CURVE25519_PUBKEY_LEN]; uint8_t bp[CURVE25519_PUBKEY_LEN];
int r; int r;
memcpy(bp, basepoint, CURVE25519_PUBKEY_LEN); memcpy(bp, point, CURVE25519_PUBKEY_LEN);
/* Clear the high bit, in case our backend foolishly looks at it. */ /* Clear the high bit, in case our backend foolishly looks at it. */
bp[31] &= 0x7f; bp[31] &= 0x7f;
#ifdef USE_CURVE25519_DONNA #ifdef USE_CURVE25519_DONNA
...@@ -61,6 +77,11 @@ curve25519_impl(uint8_t *output, const uint8_t *secret, ...@@ -61,6 +77,11 @@ curve25519_impl(uint8_t *output, const uint8_t *secret,
return r; return r;
} }
/**
* Helper function: Multiply the scalar "secret" by the Curve25519
* basepoint (X=9), and store the result in "output". Return 0 on
* success, -1 on false.
*/
STATIC int STATIC int
curve25519_basepoint_impl(uint8_t *output, const uint8_t *secret) curve25519_basepoint_impl(uint8_t *output, const uint8_t *secret)
{ {
...@@ -85,6 +106,10 @@ curve25519_basepoint_impl(uint8_t *output, const uint8_t *secret) ...@@ -85,6 +106,10 @@ curve25519_basepoint_impl(uint8_t *output, const uint8_t *secret)
return r; return r;
} }
/**
* Override the decision of whether to use the Ed25519-based basepoint
* multiply function. Used for testing.
*/
void void
curve25519_set_impl_params(int use_ed) curve25519_set_impl_params(int use_ed)
{ {
...@@ -142,6 +167,10 @@ curve25519_secret_key_generate(curve25519_secret_key_t *key_out, ...@@ -142,6 +167,10 @@ curve25519_secret_key_generate(curve25519_secret_key_t *key_out,
return 0; return 0;
} }
/**
* Given a secret key in <b>seckey</b>, create the corresponding public
* key in <b>key_out</b>.
*/
void void
curve25519_public_key_generate(curve25519_public_key_t *key_out, curve25519_public_key_generate(curve25519_public_key_t *key_out,
const curve25519_secret_key_t *seckey) const curve25519_secret_key_t *seckey)
...@@ -149,6 +178,11 @@ curve25519_public_key_generate(curve25519_public_key_t *key_out, ...@@ -149,6 +178,11 @@ curve25519_public_key_generate(curve25519_public_key_t *key_out,
curve25519_basepoint_impl(key_out->public_key, seckey->secret_key); curve25519_basepoint_impl(key_out->public_key, seckey->secret_key);
} }
/**
* Construct a new keypair in *<b>keypair_out</b>. If <b>extra_strong</b>
* is true, this key is possibly going to get used more than once, so
* use a better-than-usual RNG. Return 0 on success, -1 on failure. */
*/
int int
curve25519_keypair_generate(curve25519_keypair_t *keypair_out, curve25519_keypair_generate(curve25519_keypair_t *keypair_out,
int extra_strong) int extra_strong)
...@@ -159,7 +193,13 @@ curve25519_keypair_generate(curve25519_keypair_t *keypair_out, ...@@ -159,7 +193,13 @@ curve25519_keypair_generate(curve25519_keypair_t *keypair_out,
return 0; return 0;
} }
/* DOCDOC */ /** Store the keypair <b>keypair</b>, including its secret and public
* parts, to the file <b>fname</b>. Use the string tag <b>tag</b> to
* distinguish this from other Curve25519 keypairs. Return 0 on success,
* -1 on failure.
*
* See crypto_write_tagged_contents_to_file() for more information on
* the metaformat used for these keys.*/
int int
curve25519_keypair_write_to_file(const curve25519_keypair_t *keypair, curve25519_keypair_write_to_file(const curve25519_keypair_t *keypair,
const char *fname, const char *fname,
...@@ -182,7 +222,10 @@ curve25519_keypair_write_to_file(const curve25519_keypair_t *keypair, ...@@ -182,7 +222,10 @@ curve25519_keypair_write_to_file(const curve25519_keypair_t *keypair,
return r; return r;
} }
/* DOCDOC */ /** Read a curve25519 keypair from a file named <b>fname</b> created by
* curve25519_keypair_write_to_file(). Store the keypair in
* <b>keypair_out</b>, and the associated tag string in <b>tag_out</b>.
* Return 0 on success, and -1 on failure. */
int int
curve25519_keypair_read_from_file(curve25519_keypair_t *keypair_out, curve25519_keypair_read_from_file(curve25519_keypair_t *keypair_out,
char **tag_out, char **tag_out,
...@@ -197,6 +240,7 @@ curve25519_keypair_read_from_file(curve25519_keypair_t *keypair_out, ...@@ -197,6 +240,7 @@ curve25519_keypair_read_from_file(curve25519_keypair_t *keypair_out,
if (len != sizeof(content)) if (len != sizeof(content))
goto end; goto end;
/* Make sure that the public key matches the secret key */
memcpy(keypair_out->seckey.secret_key, content, CURVE25519_SECKEY_LEN); memcpy(keypair_out->seckey.secret_key, content, CURVE25519_SECKEY_LEN);
curve25519_public_key_generate(&keypair_out->pubkey, &keypair_out->seckey); curve25519_public_key_generate(&keypair_out->pubkey, &keypair_out->seckey);
if (tor_memneq(keypair_out->pubkey.public_key, if (tor_memneq(keypair_out->pubkey.public_key,
......
...@@ -14,12 +14,20 @@ ...@@ -14,12 +14,20 @@
/** Length of the result of a curve25519 handshake. */ /** Length of the result of a curve25519 handshake. */
#define CURVE25519_OUTPUT_LEN 32 #define CURVE25519_OUTPUT_LEN 32
/** Wrapper type for a curve25519 public key */ /** Wrapper type for a curve25519 public key.
*
* (We define a separate type for these to make it less likely that we'll
* mistake them for secret keys.)
* */
typedef struct curve25519_public_key_t { typedef struct curve25519_public_key_t {
uint8_t public_key[CURVE25519_PUBKEY_LEN]; uint8_t public_key[CURVE25519_PUBKEY_LEN];
} curve25519_public_key_t; } curve25519_public_key_t;
/** Wrapper type for a curve25519 secret key */ /** Wrapper type for a curve25519 secret key
*
* (We define a separate type for these to make it less likely that we'll
* mistake them for public keys.)
**/
typedef struct curve25519_secret_key_t { typedef struct curve25519_secret_key_t {
uint8_t secret_key[CURVE25519_SECKEY_LEN]; uint8_t secret_key[CURVE25519_SECKEY_LEN];
} curve25519_secret_key_t; } curve25519_secret_key_t;
......
...@@ -5,6 +5,14 @@ ...@@ -5,6 +5,14 @@
* \file crypto_ed25519.c * \file crypto_ed25519.c
* *
* \brief Wrapper code for an ed25519 implementation. * \brief Wrapper code for an ed25519 implementation.
*
* Ed25519 is a Schnorr signature on a Twisted Edwards curve, defined
* by Dan Bernstein. For more information, see https://ed25519.cr.yp.to/
*
* This module wraps our choice of Ed25519 backend, and provides a few
* convenience functions for checking and generating signatures. It also
* provides Tor-specific tools for key blinding and for converting Ed25519
* keys to and from the corresponding Curve25519 keys.
*/ */
#include "orconfig.h" #include "orconfig.h"
...@@ -28,7 +36,7 @@ ...@@ -28,7 +36,7 @@
static void pick_ed25519_impl(void); static void pick_ed25519_impl(void);
static int ed25519_impl_spot_check(void); static int ed25519_impl_spot_check(void);
/** An Ed25519 implementation */ /** An Ed25519 implementation, as a set of function pointers. */
typedef struct { typedef struct {
int (*selftest)(void); int (*selftest)(void);
...@@ -53,6 +61,8 @@ typedef struct { ...@@ -53,6 +61,8 @@ typedef struct {
int); int);
} ed25519_impl_t; } ed25519_impl_t;
/** The Ref10 Ed25519 implementation. This one is pure C and lightly
* optimized. */
static const ed25519_impl_t impl_ref10 = { static const ed25519_impl_t impl_ref10 = {
NULL, NULL,
...@@ -71,6 +81,8 @@ static const ed25519_impl_t impl_ref10 = { ...@@ -71,6 +81,8 @@ static const ed25519_impl_t impl_ref10 = {
ed25519_ref10_pubkey_from_curve25519_pubkey, ed25519_ref10_pubkey_from_curve25519_pubkey,
}; };
/** The Ref10 Ed25519 implementation. This one is heavily optimized, but still
* mostly C. The C still tends to be heavily platform-specific. */
static const ed25519_impl_t impl_donna = { static const ed25519_impl_t impl_donna = {
ed25519_donna_selftest, ed25519_donna_selftest,
...@@ -89,8 +101,15 @@ static const ed25519_impl_t impl_donna = { ...@@ -89,8 +101,15 @@ static const ed25519_impl_t impl_donna = {
ed25519_donna_pubkey_from_curve25519_pubkey, ed25519_donna_pubkey_from_curve25519_pubkey,
}; };
/** Which Ed25519 implementation are we using? NULL if we haven't decided
* yet. */
static const ed25519_impl_t *ed25519_impl = NULL; static const ed25519_impl_t *ed25519_impl = NULL;
/** Helper: Return our chosen Ed25519 implementation.
*
* This should only be called after we've picked an implementation, but
* it _does_ recover if you forget this.
**/
static inline const ed25519_impl_t * static inline const ed25519_impl_t *
get_ed_impl(void) get_ed_impl(void)
{ {
...@@ -101,7 +120,12 @@ get_ed_impl(void) ...@@ -101,7 +120,12 @@ get_ed_impl(void)
} }
#ifdef TOR_UNIT_TESTS #ifdef TOR_UNIT_TESTS
/** For testing: used to remember our actual choice of Ed25519
* implementation */
static const ed25519_impl_t *saved_ed25519_impl = NULL; static const ed25519_impl_t *saved_ed25519_impl = NULL;
/** For testing: Use the Ed25519 implementation called <b>name</b> until
* crypto_ed25519_testing_restore_impl is called. Recognized names are
* "donna" and "ref10". */
void void
crypto_ed25519_testing_force_impl(const char *name) crypto_ed25519_testing_force_impl(const char *name)
{ {
...@@ -114,6 +138,9 @@ crypto_ed25519_testing_force_impl(const char *name) ...@@ -114,6 +138,9 @@ crypto_ed25519_testing_force_impl(const char *name)
ed25519_impl = &impl_ref10; ed25519_impl = &impl_ref10;
} }
} }
/** For testing: go back to whatever Ed25519 implementation we had picked
* before crypto_ed25519_testing_force_impl was called.
*/
void void
crypto_ed25519_testing_restore_impl(void) crypto_ed25519_testing_restore_impl(void)
{ {
......
...@@ -123,6 +123,10 @@ crypto_read_tagged_contents_from_file(const char *fname, ...@@ -123,6 +123,10 @@ crypto_read_tagged_contents_from_file(const char *fname,
return r; return r;
} }
/** Encode <b>pkey</b> as a base64-encoded string, without trailing "="
* characters, in the buffer <b>output</b>, which must have at least
* CURVE25519_BASE64_PADDED_LEN+1 bytes available. Return 0 on success, -1 on
* failure. */
int int
curve25519_public_to_base64(char *output, curve25519_public_to_base64(char *output,
const curve25519_public_key_t *pkey) const curve25519_public_key_t *pkey)
...@@ -135,6 +139,9 @@ curve25519_public_to_base64(char *output, ...@@ -135,6 +139,9 @@ curve25519_public_to_base64(char *output,
return 0; return 0;
} }
/** Try to decode a base64-encoded curve25519 public key from <b>input</b>
* into the object at <b>pkey</b>. Return 0 on success, -1 on failure.
* Accepts keys with or without a trailing "=". */
int int
curve25519_public_from_base64(curve25519_public_key_t *pkey, curve25519_public_from_base64(curve25519_public_key_t *pkey,
const char *input) const char *input)
......
...@@ -6,6 +6,20 @@ ...@@ -6,6 +6,20 @@
* *
* \brief Implements worker threads, queues of work for them, and mechanisms * \brief Implements worker threads, queues of work for them, and mechanisms
* for them to send answers back to the main thread. * for them to send answers back to the main thread.
*
* The main structure here is a threadpool_t : it manages a set of worker
* threads, a queue of pending work, and a reply queue. Every piece of work
* is a workqueue_entry_t, containing data to process and a function to
* process it with.
*
* The main thread informs the worker threads of pending work by using a
* condition variable. The workers inform the main process of completed work
* by using an alert_sockets_t object, as implemented in compat_threads.c.
*
* The main thread can also queue an "update" that will be handled by all the
* workers. This is useful for updating state that all the workers share.
*
* In Tor today, there is currently only one thread pool, used in cpuworker.c.
*/ */
#include "orconfig.h" #include "orconfig.h"
......
...@@ -6,10 +6,22 @@ ...@@ -6,10 +6,22 @@
/** /**
* \file buffers.c * \file buffers.c
* \brief Implements a generic interface buffer. Buffers are * \brief Implements a generic buffer interface.
* fairly opaque string holders that can read to or flush from: *
* memory, file descriptors, or TLS connections. Buffers are implemented * A buf_t is a (fairly) opaque byte-oriented FIFO that can read to or flush
* as linked lists of memory chunks. * from memory, sockets, file descriptors, TLS connections, or another buf_t.
* Buffers are implemented as linked lists of memory chunks.
*
* All socket-backed and TLS-based connection_t objects have a pair of
* buffers: one for incoming data, and one for outcoming data. These are fed
* and drained from functions in connection.c, trigged by events that are
* monitored in main.c.
*
* This module has basic support for reading and writing on buf_t objects. It
* also contains specialized functions for handling particular protocols
* on a buf_t backend, including SOCKS (used in connection_edge.c), Tor cells
* (used in connection_or.c and channeltls.c), HTTP (used in directory.c), and
* line-oriented communication (used in control.c).
**/ **/
#define BUFFERS_PRIVATE #define BUFFERS_PRIVATE
#include "or.h" #include "or.h"
......
...@@ -9,6 +9,18 @@ ...@@ -9,6 +9,18 @@
* *
* \brief Maintains and analyzes statistics about circuit built times, so we * \brief Maintains and analyzes statistics about circuit built times, so we
* can tell how long we may need to wait for a fast circuit to be constructed. * can tell how long we may need to wait for a fast circuit to be constructed.
*
* By keeping these statistics, a client learns when it should time out a slow
* circuit for being too slow, and when it should keep a circuit open in order
* to wait for it to complete.
*
* The information here is kept in a circuit_built_times_t structure, which is
* currently a singleton, but doesn't need to be. It's updated by calls to
* circuit_build_times_count_timeout() from circuituse.c,
* circuit_build_times_count_close() from circuituse.c, and
* circuit_build_times_add_time() from circuitbuild.c, and inspected by other
* calls into this module, mostly from circuitlist.c. Observations are
* persisted to disk via the or_state_t-related calls.
*/ */
#define CIRCUITSTATS_PRIVATE #define CIRCUITSTATS_PRIVATE
...@@ -329,7 +341,6 @@ circuit_build_times_min_timeout(void) ...@@ -329,7 +341,6 @@ circuit_build_times_min_timeout(void)
"circuit_build_times_min_timeout() called, cbtmintimeout is %d", "circuit_build_times_min_timeout() called, cbtmintimeout is %d",
num); num);
} }
return num; return num;
} }
......
...@@ -7,6 +7,26 @@ ...@@ -7,6 +7,26 @@
/** /**
* \file command.c * \file command.c
* \brief Functions for processing incoming cells. * \brief Functions for processing incoming cells.
*
* When we receive a cell from a client or a relay, it arrives on some
* channel, and tells us what to do with it. In this module, we dispatch based
* on the cell type using the functions command_process_cell() and
* command_process_var_cell(), and deal with the cell accordingly. (These
* handlers are installed on a channel with the command_setup_channel()
* function.)
*
* Channels have a chance to handle some cell types on their own before they
* are ever passed here --- typically, they do this for cells that are
* specific to a given channel type. For example, in channeltls.c, the cells
* for the initial connection handshake are handled before we get here. (Of
* course, the fact that there _is_ only one channel type for now means that
* we may have gotten the factoring wrong here.)
*
* Handling other cell types is mainly farmed off to other modules, after
* initial sanity-checking. CREATE* cells are handled ultimately in onion.c,
* CREATED* cells trigger circuit creation in circuitbuild.c, DESTROY cells
* are handled here (since they're simple), and RELAY cells, in all their
* complexity, are passed off to relay.c.
**/ **/
/* In-points to command.c: /* In-points to command.c:
......
...@@ -7,6 +7,51 @@ ...@@ -7,6 +7,51 @@
/** /**
* \file connection_edge.c * \file connection_edge.c
* \brief Handle edge streams. * \brief Handle edge streams.
*
* An edge_connection_t is a subtype of a connection_t, and represents two
* critical concepts in Tor: a stream, and an edge connection. From the Tor
* protocol's point of view, a stream is a bi-directional channel that is
* multiplexed on a single circuit. Each stream on a circuit is identified
* with a separate 16-bit stream ID, local to the (circuit,exit) pair.
* Streams are created in response to client requests.
*
* An edge connection is one thing that can implement a stream: it is either a
* TCP application socket that has arrived via (e.g.) a SOCKS request, or an
* exit connection.
*
* Not every instance of edge_connection_t truly represents an edge connction,
* however. (Sorry!) We also create edge_connection_t objects for streams that
* we will not be handling with TCP. The types of these streams are:
* <ul>
* <li>DNS lookup streams, created on the client side in response to
* a UDP DNS request received on a DNSPort, or a RESOLVE command
* on a controller.
* <li>DNS lookup streams, created on the exit side in response to
* a RELAY_RESOLVE cell from a client.
* <li>Tunneled directory streams, created on the directory cache side
* in response to a RELAY_BEGINDIR cell. These streams attach directly
* to a dir_connection_t object without ever using TCP.
* </ul>
*
* This module handles general-purpose functionality having to do with
* edge_connection_t. On the client side, it accepts various types of
* application requests on SocksPorts, TransPorts, and NATDPorts, and
* creates streams appropriately.
*
* This module is also responsible for implementing stream isolation:
* ensuring that streams that should not be linkable to one another are
* kept to different circuits.
*
* On the exit side, this module handles the various stream-creating
* type of RELAY cells by launching appropriate outgoing connections,
* DNS requests, or directory connection objects.
*
* And for all edge connections, this module is responsible for handling
* incoming and outdoing data as it arrives or leaves in the relay.c
* module. (Outgoing data will be packaged in
* connection_edge_process_inbuf() as it calls
* connection_edge_package_raw_inbuf(); incoming data from RELAY_DATA
* cells is applied in connection_edge_process_relay_cell().)
**/ **/
#define CONNECTION_EDGE_PRIVATE #define CONNECTION_EDGE_PRIVATE
......
...@@ -5,7 +5,31 @@ ...@@ -5,7 +5,31 @@
/** /**
* \file control.c * \file control.c
* \brief Implementation for Tor's control-socket interface. * \brief Implementation for Tor's control-socket interface.
* See doc/spec/control-spec.txt for full details on protocol. *
* A "controller" is an external program that monitors and controls a Tor
* instance via a text-based protocol. It connects to Tor via a connection
* to a local socket.
*
* The protocol is line-driven. The controller sends commands terminated by a
* CRLF. Tor sends lines that are either <em>replies</em> to what the
* controller has said, or <em>events</em> that Tor sends to the controller
* asynchronously based on occurrences in the Tor network model.
*
* See the control-spec.txt file in the torspec.git repository for full
* details on protocol.
*
* This module generally has two kinds of entry points: those based on having
* received a command on a controller socket, which are handled in
* connection_control_process_inbuf(), and dispatched to individual functions
* with names like control_handle_COMMANDNAME(); and those based on events
* that occur elsewhere in Tor, which are handled by functions with names like
* control_event_EVENTTYPE().
*
* Controller events are not sent immediately; rather, they are inserted into
* the queued_control_events array, and flushed later from
* flush_queued_events_cb(). Doing this simplifies our callgraph greatly,
* by limiting the number of places in Tor that can call back into the network
* stack.
**/ **/
#define CONTROL_PRIVATE #define CONTROL_PRIVATE
......
...@@ -8,7 +8,11 @@ ...@@ -8,7 +8,11 @@
* \brief Uses the workqueue/threadpool code to farm CPU-intensive activities * \brief Uses the workqueue/threadpool code to farm CPU-intensive activities
* out to subprocesses. * out to subprocesses.
* *
* Right now, we only use this for processing onionskins. * The multithreading backend for this module is in workqueue.c; this module
* specializes workqueue.c.
*
* Right now, we only use this for processing onionskins, and invoke it mostly
* from onion.c.
**/ **/
#include "or.h" #include "or.h"
#include "channel.h" #include "channel.h"
......
...@@ -8,6 +8,17 @@ ...@@ -8,6 +8,17 @@
* *
* \brief Collation code for figuring out which identities to vote for in * \brief Collation code for figuring out which identities to vote for in
* the directory voting process. * the directory voting process.
*
* During the consensus calculation, when an authority is looking at the vote
* documents from all the authorities, it needs to compute the consensus for
* each relay listed by at least one authority. But the notion of "each
* relay" can be tricky: some relays have Ed25519 keys, and others don't.
*
* Moreover, older consensus methods did RSA-based ID collation alone, and
* ignored Ed25519 keys. We need to support those too until we're completely
* sure that authorities will never downgrade.
*
* This module is invoked exclusively from dirvote.c.
*/ */
#define DIRCOLLATE_PRIVATE #define DIRCOLLATE_PRIVATE
...@@ -21,6 +32,9 @@ static void dircollator_collate_by_ed25519(dircollator_t *dc); ...@@ -21,6 +32,9 @@ static void dircollator_collate_by_ed25519(dircollator_t *dc);
* RSA SHA1 digest) to an array of vote_routerstatus_t. */ * RSA SHA1 digest) to an array of vote_routerstatus_t. */
typedef struct ddmap_entry_s { typedef struct ddmap_entry_s {
HT_ENTRY(ddmap_entry_s) node; HT_ENTRY(ddmap_entry_s) node;
/** A SHA1-RSA1024 identity digest and Ed25519 identity key,
* concatenated. (If there is no ed25519 identity key, there is no
* entry in this table.) */
uint8_t d[DIGEST_LEN + DIGEST256_LEN]; uint8_t d[DIGEST_LEN + DIGEST256_LEN];
/* The nth member of this array corresponds to the vote_routerstatus_t (if /* The nth member of this array corresponds to the vote_routerstatus_t (if
* any) received for this digest pair from the nth voter. */ * any) received for this digest pair from the nth voter. */
...@@ -43,12 +57,16 @@ ddmap_entry_new(int n_votes) ...@@ -43,12 +57,16 @@ ddmap_entry_new(int n_votes)
sizeof(vote_routerstatus_t *) * n_votes); sizeof(vote_routerstatus_t *) * n_votes);
} }
/** Helper: compute a hash of a single ddmap_entry_t's identity (or
* identities) */
static unsigned static unsigned
ddmap_entry_hash(const ddmap_entry_t *ent) ddmap_entry_hash(const ddmap_entry_t *ent)
{ {
return (unsigned) siphash24g(ent->d, sizeof(ent->d)); return (unsigned) siphash24g(ent->d, sizeof(ent->d));
} }
/** Helper: return true if <b>a</b> and <b>b</b> have the same