Tor  0.4.5.0-alpha-dev
shared_random_client.c
Go to the documentation of this file.
1 /* Copyright (c) 2018-2020, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
3 
4 /**
5  * \file shared_random_client.c
6  * \brief This file contains functions that are from the shared random
7  * subsystem but used by many part of tor. The full feature is built
8  * as part of the dirauth module.
9  **/
10 
12 
13 #include "app/config/config.h"
17 #include "lib/encoding/binascii.h"
18 
20 
21 /** Convert a given srv object to a string for the control port. This doesn't
22  * fail and the srv object MUST be valid. */
23 static char *
25 {
26  char *srv_str;
27  char srv_hash_encoded[SR_SRV_VALUE_BASE64_LEN + 1];
28  tor_assert(srv);
29 
30  sr_srv_encode(srv_hash_encoded, sizeof(srv_hash_encoded), srv);
31  tor_asprintf(&srv_str, "%s", srv_hash_encoded);
32  return srv_str;
33 }
34 
35 /**
36  * If we have no consensus and we are not an authority, assume that this is
37  * the voting interval. We should never actually use this: only authorities
38  * should be trying to figure out the schedule when they don't have a
39  * consensus.
40  **/
41 #define DEFAULT_NETWORK_VOTING_INTERVAL (3600)
42 
43 /* This is an unpleasing workaround for tests. Our unit tests assume that we
44  * are scheduling all of our shared random stuff as if we were a directory
45  * authority, but they do not always set V3AuthoritativeDir.
46  */
47 #ifdef TOR_UNIT_TESTS
48 #define ASSUME_AUTHORITY_SCHEDULING 1
49 #else
50 #define ASSUME_AUTHORITY_SCHEDULING 0
51 #endif
52 
53 /** Return the voting interval of the tor vote subsystem. */
54 int
56 {
57  int interval;
58  networkstatus_t *consensus = networkstatus_get_live_consensus(time(NULL));
59 
60  if (consensus) {
61  /* Ideally we have a live consensus and we can just use that. */
62  interval = (int)(consensus->fresh_until - consensus->valid_after);
63  } else if (authdir_mode(get_options()) || ASSUME_AUTHORITY_SCHEDULING) {
64  /* If we don't have a live consensus and we're an authority,
65  * we should believe our own view of what the schedule ought to be. */
67  } else if ((consensus = networkstatus_get_latest_consensus())) {
68  /* If we're a client, then maybe a latest consensus is good enough?
69  * It's better than falling back to the non-consensus case. */
70  interval = (int)(consensus->fresh_until - consensus->valid_after);
71  } else {
72  /* We should never be reaching this point, since a client should never
73  * call this code unless they have some kind of a consensus. All we can
74  * do is hope that this network is using the default voting interval. */
75  tor_assert_nonfatal_unreached_once();
77  }
78  tor_assert(interval > 0);
79  return interval;
80 }
81 
82 /*
83  * Public API
84  */
85 
86 /** Encode the given shared random value and put it in dst. Destination
87  * buffer must be at least SR_SRV_VALUE_BASE64_LEN plus the NULL byte. */
88 void
89 sr_srv_encode(char *dst, size_t dst_len, const sr_srv_t *srv)
90 {
91  int ret;
92  /* Extra byte for the NULL terminated char. */
93  char buf[SR_SRV_VALUE_BASE64_LEN + 1];
94 
95  tor_assert(dst);
96  tor_assert(srv);
97  tor_assert(dst_len >= sizeof(buf));
98 
99  ret = base64_encode(buf, sizeof(buf), (const char *) srv->value,
100  sizeof(srv->value), 0);
101  /* Always expect the full length without the NULL byte. */
102  tor_assert(ret == (sizeof(buf) - 1));
103  tor_assert(ret <= (int) dst_len);
104  strlcpy(dst, buf, dst_len);
105 }
106 
107 /** Return the current SRV string representation for the control port. Return a
108  * newly allocated string on success containing the value else "" if not found
109  * or if we don't have a valid consensus yet. */
110 char *
112 {
113  char *srv_str;
115  if (c && c->sr_info.current_srv) {
116  srv_str = srv_to_control_string(c->sr_info.current_srv);
117  } else {
118  srv_str = tor_strdup("");
119  }
120  return srv_str;
121 }
122 
123 /** Return the previous SRV string representation for the control port. Return
124  * a newly allocated string on success containing the value else "" if not
125  * found or if we don't have a valid consensus yet. */
126 char *
128 {
129  char *srv_str;
131  if (c && c->sr_info.previous_srv) {
132  srv_str = srv_to_control_string(c->sr_info.previous_srv);
133  } else {
134  srv_str = tor_strdup("");
135  }
136  return srv_str;
137 }
138 
139 /** Return current shared random value from the latest consensus. Caller can
140  * NOT keep a reference to the returned pointer. Return NULL if none. */
141 const sr_srv_t *
143 {
144  const networkstatus_t *consensus;
145 
146  /* Use provided ns else get a live one */
147  if (ns) {
148  consensus = ns;
149  } else {
151  }
152  /* Ideally we would never be asked for an SRV without a live consensus. Make
153  * sure this assumption is correct. */
154  tor_assert_nonfatal(consensus);
155 
156  if (consensus) {
157  return consensus->sr_info.current_srv;
158  }
159  return NULL;
160 }
161 
162 /** Return previous shared random value from the latest consensus. Caller can
163  * NOT keep a reference to the returned pointer. Return NULL if none. */
164 const sr_srv_t *
166 {
167  const networkstatus_t *consensus;
168 
169  /* Use provided ns else get a live one */
170  if (ns) {
171  consensus = ns;
172  } else {
174  }
175  /* Ideally we would never be asked for an SRV without a live consensus. Make
176  * sure this assumption is correct. */
177  tor_assert_nonfatal(consensus);
178 
179  if (consensus) {
180  return consensus->sr_info.previous_srv;
181  }
182  return NULL;
183 }
184 
185 /** Parse a list of arguments from a SRV value either from a vote, consensus
186  * or from our disk state and return a newly allocated srv object. NULL is
187  * returned on error.
188  *
189  * The arguments' order:
190  * num_reveals, value
191  */
192 sr_srv_t *
194 {
195  char *value;
196  int ok, ret;
197  uint64_t num_reveals;
198  sr_srv_t *srv = NULL;
199 
200  tor_assert(args);
201 
202  if (smartlist_len(args) < 2) {
203  goto end;
204  }
205 
206  /* First argument is the number of reveal values */
207  num_reveals = tor_parse_uint64(smartlist_get(args, 0),
208  10, 0, UINT64_MAX, &ok, NULL);
209  if (!ok) {
210  goto end;
211  }
212  /* Second and last argument is the shared random value it self. */
213  value = smartlist_get(args, 1);
214  if (strlen(value) != SR_SRV_VALUE_BASE64_LEN) {
215  goto end;
216  }
217 
218  srv = tor_malloc_zero(sizeof(*srv));
219  srv->num_reveals = num_reveals;
220  /* We subtract one byte from the srclen because the function ignores the
221  * '=' character in the given buffer. This is broken but it's a documented
222  * behavior of the implementation. */
223  ret = base64_decode((char *) srv->value, sizeof(srv->value), value,
225  if (ret != sizeof(srv->value)) {
226  tor_free(srv);
227  srv = NULL;
228  goto end;
229  }
230  end:
231  return srv;
232 }
233 
234 /** Return the start time of the current SR protocol run using the times from
235  * the current consensus. For example, if the latest consensus valid-after is
236  * 23/06/2017 23:00:00 and a full SR protocol run is 24 hours, this function
237  * returns 23/06/2017 00:00:00. */
238 time_t
240 {
241  int total_rounds = SHARED_RANDOM_N_ROUNDS * SHARED_RANDOM_N_PHASES;
242  int voting_interval = get_voting_interval();
243  time_t beginning_of_curr_round;
244 
245  /* This function is not used for voting purposes, so if we have a live
246  consensus, use its valid-after as the beginning of the current round.
247  If we have no consensus but we're an authority, use our own
248  schedule. Otherwise, try using our view of the voting interval
249  to figure out when the current round _should_ be starting.
250  */
252  if (ns) {
253  beginning_of_curr_round = ns->valid_after;
254  } else if (authdir_mode(get_options()) || ASSUME_AUTHORITY_SCHEDULING) {
255  beginning_of_curr_round = dirauth_sched_get_cur_valid_after_time();
256  } else {
257  /* voting_interval comes from get_voting_interval(), so if we're in
258  * this case as a client, we already tried to get the voting interval
259  * from the latest_consensus and gave a bug warning if we couldn't.
260  *
261  * We wouldn't want to look at the latest consensus's valid_after time,
262  * since that would be out of date. */
263  beginning_of_curr_round = voting_sched_get_start_of_interval_after(
264  approx_time() - voting_interval,
265  voting_interval,
266  0);
267  }
268 
269  /* Get current SR protocol round */
270  int curr_round_slot;
271  curr_round_slot = (beginning_of_curr_round / voting_interval) % total_rounds;
272 
273  /* Get start time by subtracting the time elapsed from the beginning of the
274  protocol run */
275  time_t time_elapsed_since_start_of_run = curr_round_slot * voting_interval;
276 
277  log_debug(LD_GENERAL, "Current SRV proto run: Start of current round: %u. "
278  "Time elapsed: %u (%d)", (unsigned) beginning_of_curr_round,
279  (unsigned) time_elapsed_since_start_of_run, voting_interval);
280 
281  return beginning_of_curr_round - time_elapsed_since_start_of_run;
282 }
283 
284 /** Return the start time of the previous SR protocol run. See
285  * sr_state_get_start_time_of_current_protocol_run() for more details. */
286 time_t
288 {
289  time_t start_time_of_current_run =
291 
292  /* We get the start time of previous protocol run, by getting the start time
293  * of current run and the subtracting a full protocol run from that. */
294  return start_time_of_current_run - sr_state_get_protocol_run_duration();
295 }
296 
297 /** Return the time (in seconds) it takes to complete a full SR protocol phase
298  * (e.g. the commit phase). */
299 unsigned int
301 {
302  return SHARED_RANDOM_N_ROUNDS * get_voting_interval();
303 }
304 
305 /** Return the time (in seconds) it takes to complete a full SR protocol run */
306 unsigned int
308 {
309  int total_protocol_rounds = SHARED_RANDOM_N_ROUNDS * SHARED_RANDOM_N_PHASES;
310  return total_protocol_rounds * get_voting_interval();
311 }
dirauth_sched_get_cur_valid_after_time
time_t dirauth_sched_get_cur_valid_after_time(void)
Definition: voting_schedule.c:153
tor_free
#define tor_free(p)
Definition: malloc.h:52
sr_srv_t::num_reveals
uint64_t num_reveals
Definition: shared_random.h:64
approx_time
time_t approx_time(void)
Definition: approx_time.c:32
sr_state_get_start_time_of_previous_protocol_run
time_t sr_state_get_start_time_of_previous_protocol_run(void)
Definition: shared_random_client.c:287
tor_assert
#define tor_assert(expr)
Definition: util_bug.h:102
LD_GENERAL
#define LD_GENERAL
Definition: log.h:62
tor_parse_uint64
uint64_t tor_parse_uint64(const char *s, int base, uint64_t min, uint64_t max, int *ok, char **next)
Definition: parse_int.c:110
networkstatus_get_live_consensus
networkstatus_t * networkstatus_get_live_consensus(time_t now)
Definition: networkstatus.c:1416
sr_srv_t
Definition: shared_random.h:62
voting_sched_get_start_of_interval_after
time_t voting_sched_get_start_of_interval_after(time_t now, int interval, int offset)
Definition: networkstatus.c:2780
base64_encode
int base64_encode(char *dest, size_t destlen, const char *src, size_t srclen, int flags)
Definition: binascii.c:215
SR_SRV_VALUE_BASE64_LEN
#define SR_SRV_VALUE_BASE64_LEN
Definition: shared_random.h:48
networkstatus.h
Header file for networkstatus.c.
sr_get_current
const sr_srv_t * sr_get_current(const networkstatus_t *ns)
Definition: shared_random_client.c:142
networkstatus_get_latest_consensus
networkstatus_t * networkstatus_get_latest_consensus(void)
Definition: networkstatus.c:1390
networkstatus_t::sr_info
networkstatus_sr_info_t sr_info
Definition: networkstatus_st.h:103
authmode.h
Header file for directory authority mode.
binascii.h
Header for binascii.c.
sr_get_previous_for_control
char * sr_get_previous_for_control(void)
Definition: shared_random_client.c:127
DEFAULT_NETWORK_VOTING_INTERVAL
#define DEFAULT_NETWORK_VOTING_INTERVAL
Definition: shared_random_client.c:41
get_options
const or_options_t * get_options(void)
Definition: config.c:928
get_voting_interval
int get_voting_interval(void)
Definition: shared_random_client.c:55
srv_to_control_string
static char * srv_to_control_string(const sr_srv_t *srv)
Definition: shared_random_client.c:24
dirauth_sched_get_configured_interval
int dirauth_sched_get_configured_interval(void)
Definition: voting_schedule.c:168
sr_srv_t::value
uint8_t value[DIGEST256_LEN]
Definition: shared_random.h:66
voting_schedule.h
Header file for voting_schedule.c.
networkstatus_t::valid_after
time_t valid_after
Definition: networkstatus_st.h:33
tor_asprintf
int tor_asprintf(char **strp, const char *fmt,...)
Definition: printf.c:75
sr_get_current_for_control
char * sr_get_current_for_control(void)
Definition: shared_random_client.c:111
sr_state_get_start_time_of_current_protocol_run
time_t sr_state_get_start_time_of_current_protocol_run(void)
Definition: shared_random_client.c:239
sr_get_previous
const sr_srv_t * sr_get_previous(const networkstatus_t *ns)
Definition: shared_random_client.c:165
sr_srv_encode
void sr_srv_encode(char *dst, size_t dst_len, const sr_srv_t *srv)
Definition: shared_random_client.c:89
base64_decode
int base64_decode(char *dest, size_t destlen, const char *src, size_t srclen)
Definition: binascii.c:396
sr_state_get_protocol_run_duration
unsigned int sr_state_get_protocol_run_duration(void)
Definition: shared_random_client.c:307
shared_random_client.h
Header file for shared_random_client.c.
config.h
Header file for config.c.
networkstatus_t::fresh_until
time_t fresh_until
Definition: networkstatus_st.h:34
networkstatus_st.h
Networkstatus consensus/vote structure.
networkstatus_t
Definition: networkstatus_st.h:26
smartlist_t
Definition: smartlist_core.h:26
sr_state_get_phase_duration
unsigned int sr_state_get_phase_duration(void)
Definition: shared_random_client.c:300
sr_parse_srv
sr_srv_t * sr_parse_srv(const smartlist_t *args)
Definition: shared_random_client.c:193
authdir_mode
int authdir_mode(const or_options_t *options)
Definition: authmode.c:25