Tor  0.4.6.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 the
37  * voting interval. This can be used while bootstrapping as a relay and we are
38  * asked to initialize HS stats (see rep_hist_hs_stats_init()) */
39 #define DEFAULT_NETWORK_VOTING_INTERVAL (3600)
40 #define TESTING_DEFAULT_NETWORK_VOTING_INTERVAL (20)
41 
42 /* This is an unpleasing workaround for tests. Our unit tests assume that we
43  * are scheduling all of our shared random stuff as if we were a directory
44  * authority, but they do not always set V3AuthoritativeDir.
45  */
46 #ifdef TOR_UNIT_TESTS
47 #define ASSUME_AUTHORITY_SCHEDULING 1
48 #else
49 #define ASSUME_AUTHORITY_SCHEDULING 0
50 #endif
51 
52 /** Return the voting interval of the tor vote subsystem. */
53 int
55 {
56  int interval;
57  networkstatus_t *consensus = networkstatus_get_live_consensus(time(NULL));
58 
59  if (consensus) {
60  /* Ideally we have a live consensus and we can just use that. */
61  interval = (int)(consensus->fresh_until - consensus->valid_after);
62  } else if (authdir_mode(get_options()) || ASSUME_AUTHORITY_SCHEDULING) {
63  /* If we don't have a live consensus and we're an authority,
64  * we should believe our own view of what the schedule ought to be. */
66  } else if ((consensus = networkstatus_get_latest_consensus())) {
67  /* If we're a client, then maybe a latest consensus is good enough?
68  * It's better than falling back to the non-consensus case. */
69  interval = (int)(consensus->fresh_until - consensus->valid_after);
70  } else {
71  /* We can reach this as a relay when bootstrapping and we are asked to
72  * initialize HS stats (see rep_hist_hs_stats_init()). */
74  interval = TESTING_DEFAULT_NETWORK_VOTING_INTERVAL;
75  } else {
77  }
78  }
79  tor_assert(interval > 0);
80  return interval;
81 }
82 
83 /*
84  * Public API
85  */
86 
87 /** Encode the given shared random value and put it in dst. Destination
88  * buffer must be at least SR_SRV_VALUE_BASE64_LEN plus the NULL byte. */
89 void
90 sr_srv_encode(char *dst, size_t dst_len, const sr_srv_t *srv)
91 {
92  int ret;
93  /* Extra byte for the NULL terminated char. */
94  char buf[SR_SRV_VALUE_BASE64_LEN + 1];
95 
96  tor_assert(dst);
97  tor_assert(srv);
98  tor_assert(dst_len >= sizeof(buf));
99 
100  ret = base64_encode(buf, sizeof(buf), (const char *) srv->value,
101  sizeof(srv->value), 0);
102  /* Always expect the full length without the NULL byte. */
103  tor_assert(ret == (sizeof(buf) - 1));
104  tor_assert(ret <= (int) dst_len);
105  strlcpy(dst, buf, dst_len);
106 }
107 
108 /** Return the current SRV string representation for the control port. Return a
109  * newly allocated string on success containing the value else "" if not found
110  * or if we don't have a valid consensus yet. */
111 char *
113 {
114  char *srv_str;
116  if (c && c->sr_info.current_srv) {
117  srv_str = srv_to_control_string(c->sr_info.current_srv);
118  } else {
119  srv_str = tor_strdup("");
120  }
121  return srv_str;
122 }
123 
124 /** Return the previous SRV string representation for the control port. Return
125  * a newly allocated string on success containing the value else "" if not
126  * found or if we don't have a valid consensus yet. */
127 char *
129 {
130  char *srv_str;
132  if (c && c->sr_info.previous_srv) {
133  srv_str = srv_to_control_string(c->sr_info.previous_srv);
134  } else {
135  srv_str = tor_strdup("");
136  }
137  return srv_str;
138 }
139 
140 /** Return current shared random value from the latest consensus. Caller can
141  * NOT keep a reference to the returned pointer. Return NULL if none. */
142 const sr_srv_t *
144 {
145  const networkstatus_t *consensus;
146 
147  /* Use provided ns else get a live one */
148  if (ns) {
149  consensus = ns;
150  } else {
152  }
153  /* Ideally we would never be asked for an SRV without a live consensus. Make
154  * sure this assumption is correct. */
155  tor_assert_nonfatal(consensus);
156 
157  if (consensus) {
158  return consensus->sr_info.current_srv;
159  }
160  return NULL;
161 }
162 
163 /** Return previous shared random value from the latest consensus. Caller can
164  * NOT keep a reference to the returned pointer. Return NULL if none. */
165 const sr_srv_t *
167 {
168  const networkstatus_t *consensus;
169 
170  /* Use provided ns else get a live one */
171  if (ns) {
172  consensus = ns;
173  } else {
175  }
176  /* Ideally we would never be asked for an SRV without a live consensus. Make
177  * sure this assumption is correct. */
178  tor_assert_nonfatal(consensus);
179 
180  if (consensus) {
181  return consensus->sr_info.previous_srv;
182  }
183  return NULL;
184 }
185 
186 /** Parse a list of arguments from a SRV value either from a vote, consensus
187  * or from our disk state and return a newly allocated srv object. NULL is
188  * returned on error.
189  *
190  * The arguments' order:
191  * num_reveals, value
192  */
193 sr_srv_t *
195 {
196  char *value;
197  int ok, ret;
198  uint64_t num_reveals;
199  sr_srv_t *srv = NULL;
200 
201  tor_assert(args);
202 
203  if (smartlist_len(args) < 2) {
204  goto end;
205  }
206 
207  /* First argument is the number of reveal values */
208  num_reveals = tor_parse_uint64(smartlist_get(args, 0),
209  10, 0, UINT64_MAX, &ok, NULL);
210  if (!ok) {
211  goto end;
212  }
213  /* Second and last argument is the shared random value it self. */
214  value = smartlist_get(args, 1);
215  if (strlen(value) != SR_SRV_VALUE_BASE64_LEN) {
216  goto end;
217  }
218 
219  srv = tor_malloc_zero(sizeof(*srv));
220  srv->num_reveals = num_reveals;
221  /* We subtract one byte from the srclen because the function ignores the
222  * '=' character in the given buffer. This is broken but it's a documented
223  * behavior of the implementation. */
224  ret = base64_decode((char *) srv->value, sizeof(srv->value), value,
226  if (ret != sizeof(srv->value)) {
227  tor_free(srv);
228  srv = NULL;
229  goto end;
230  }
231  end:
232  return srv;
233 }
234 
235 /** Return the start time of the current SR protocol run using the times from
236  * the current consensus. For example, if the latest consensus valid-after is
237  * 23/06/2017 23:00:00 and a full SR protocol run is 24 hours, this function
238  * returns 23/06/2017 00:00:00. */
239 time_t
241 {
242  int total_rounds = SHARED_RANDOM_N_ROUNDS * SHARED_RANDOM_N_PHASES;
243  int voting_interval = get_voting_interval();
244  time_t beginning_of_curr_round;
245 
246  /* This function is not used for voting purposes, so if we have a live
247  consensus, use its valid-after as the beginning of the current round.
248  If we have no consensus but we're an authority, use our own
249  schedule. Otherwise, try using our view of the voting interval
250  to figure out when the current round _should_ be starting.
251  */
253  if (ns) {
254  beginning_of_curr_round = ns->valid_after;
255  } else if (authdir_mode(get_options()) || ASSUME_AUTHORITY_SCHEDULING) {
256  beginning_of_curr_round = dirauth_sched_get_cur_valid_after_time();
257  } else {
258  /* voting_interval comes from get_voting_interval(), so if we're in
259  * this case as a client, we already tried to get the voting interval
260  * from the latest_consensus and gave a bug warning if we couldn't.
261  *
262  * We wouldn't want to look at the latest consensus's valid_after time,
263  * since that would be out of date. */
264  beginning_of_curr_round = voting_sched_get_start_of_interval_after(
265  approx_time() - voting_interval,
266  voting_interval,
267  0);
268  }
269 
270  /* Get current SR protocol round */
271  int curr_round_slot;
272  curr_round_slot = (beginning_of_curr_round / voting_interval) % total_rounds;
273 
274  /* Get start time by subtracting the time elapsed from the beginning of the
275  protocol run */
276  time_t time_elapsed_since_start_of_run = curr_round_slot * voting_interval;
277 
278  return beginning_of_curr_round - time_elapsed_since_start_of_run;
279 }
280 
281 /** Return the start time of the previous SR protocol run. See
282  * sr_state_get_start_time_of_current_protocol_run() for more details. */
283 time_t
285 {
286  time_t start_time_of_current_run =
288 
289  /* We get the start time of previous protocol run, by getting the start time
290  * of current run and the subtracting a full protocol run from that. */
291  return start_time_of_current_run - sr_state_get_protocol_run_duration();
292 }
293 
294 /** Return the time (in seconds) it takes to complete a full SR protocol phase
295  * (e.g. the commit phase). */
296 unsigned int
298 {
299  return SHARED_RANDOM_N_ROUNDS * get_voting_interval();
300 }
301 
302 /** Return the time (in seconds) it takes to complete a full SR protocol run */
303 unsigned int
305 {
306  int total_protocol_rounds = SHARED_RANDOM_N_ROUNDS * SHARED_RANDOM_N_PHASES;
307  return total_protocol_rounds * get_voting_interval();
308 }
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:284
tor_assert
#define tor_assert(expr)
Definition: util_bug.h:102
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:2785
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:143
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:128
DEFAULT_NETWORK_VOTING_INTERVAL
#define DEFAULT_NETWORK_VOTING_INTERVAL
Definition: shared_random_client.c:39
get_options
const or_options_t * get_options(void)
Definition: config.c:932
get_voting_interval
int get_voting_interval(void)
Definition: shared_random_client.c:54
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:112
or_options_t::TestingTorNetwork
int TestingTorNetwork
Definition: or_options_st.h:814
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:240
sr_get_previous
const sr_srv_t * sr_get_previous(const networkstatus_t *ns)
Definition: shared_random_client.c:166
sr_srv_encode
void sr_srv_encode(char *dst, size_t dst_len, const sr_srv_t *srv)
Definition: shared_random_client.c:90
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:304
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:297
sr_parse_srv
sr_srv_t * sr_parse_srv(const smartlist_t *args)
Definition: shared_random_client.c:194
authdir_mode
int authdir_mode(const or_options_t *options)
Definition: authmode.c:25