Tor  0.4.4.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"
16 #include "lib/encoding/binascii.h"
17 
19 
20 /** Convert a given srv object to a string for the control port. This doesn't
21  * fail and the srv object MUST be valid. */
22 static char *
24 {
25  char *srv_str;
26  char srv_hash_encoded[SR_SRV_VALUE_BASE64_LEN + 1];
27  tor_assert(srv);
28 
29  sr_srv_encode(srv_hash_encoded, sizeof(srv_hash_encoded), srv);
30  tor_asprintf(&srv_str, "%s", srv_hash_encoded);
31  return srv_str;
32 }
33 
34 /** Return the voting interval of the tor vote subsystem. */
35 int
37 {
38  int interval;
39  networkstatus_t *consensus = networkstatus_get_live_consensus(time(NULL));
40 
41  if (consensus) {
42  interval = (int)(consensus->fresh_until - consensus->valid_after);
43  } else {
44  /* Same for both a testing and real network. We voluntarily ignore the
45  * InitialVotingInterval since it complexifies things and it doesn't
46  * affect the SR protocol. */
47  interval = get_options()->V3AuthVotingInterval;
48  }
49  tor_assert(interval > 0);
50  return interval;
51 }
52 
53 /** Given the current consensus, return the start time of the current round of
54  * the SR protocol. For example, if it's 23:47:08, the current round thus
55  * started at 23:47:00 for a voting interval of 10 seconds.
56  *
57  * This function uses the consensus voting schedule to derive its results,
58  * instead of the actual consensus we are currently using, so it should be used
59  * for voting purposes. */
60 time_t
62 {
63  const or_options_t *options = get_options();
64  int voting_interval = get_voting_interval();
65  /* First, get the start time of the next round */
66  time_t next_start = voting_schedule_get_next_valid_after_time();
67  /* Now roll back next_start by a voting interval to find the start time of
68  the current round. */
70  next_start - voting_interval - 1,
71  voting_interval,
73  return curr_start;
74 }
75 
76 /*
77  * Public API
78  */
79 
80 /** Encode the given shared random value and put it in dst. Destination
81  * buffer must be at least SR_SRV_VALUE_BASE64_LEN plus the NULL byte. */
82 void
83 sr_srv_encode(char *dst, size_t dst_len, const sr_srv_t *srv)
84 {
85  int ret;
86  /* Extra byte for the NULL terminated char. */
87  char buf[SR_SRV_VALUE_BASE64_LEN + 1];
88 
89  tor_assert(dst);
90  tor_assert(srv);
91  tor_assert(dst_len >= sizeof(buf));
92 
93  ret = base64_encode(buf, sizeof(buf), (const char *) srv->value,
94  sizeof(srv->value), 0);
95  /* Always expect the full length without the NULL byte. */
96  tor_assert(ret == (sizeof(buf) - 1));
97  tor_assert(ret <= (int) dst_len);
98  strlcpy(dst, buf, dst_len);
99 }
100 
101 /** Return the current SRV string representation for the control port. Return a
102  * newly allocated string on success containing the value else "" if not found
103  * or if we don't have a valid consensus yet. */
104 char *
106 {
107  char *srv_str;
109  if (c && c->sr_info.current_srv) {
110  srv_str = srv_to_control_string(c->sr_info.current_srv);
111  } else {
112  srv_str = tor_strdup("");
113  }
114  return srv_str;
115 }
116 
117 /** Return the previous SRV string representation for the control port. Return
118  * a newly allocated string on success containing the value else "" if not
119  * found or if we don't have a valid consensus yet. */
120 char *
122 {
123  char *srv_str;
125  if (c && c->sr_info.previous_srv) {
126  srv_str = srv_to_control_string(c->sr_info.previous_srv);
127  } else {
128  srv_str = tor_strdup("");
129  }
130  return srv_str;
131 }
132 
133 /** Return current shared random value from the latest consensus. Caller can
134  * NOT keep a reference to the returned pointer. Return NULL if none. */
135 const sr_srv_t *
137 {
138  const networkstatus_t *consensus;
139 
140  /* Use provided ns else get a live one */
141  if (ns) {
142  consensus = ns;
143  } else {
145  }
146  /* Ideally we would never be asked for an SRV without a live consensus. Make
147  * sure this assumption is correct. */
148  tor_assert_nonfatal(consensus);
149 
150  if (consensus) {
151  return consensus->sr_info.current_srv;
152  }
153  return NULL;
154 }
155 
156 /** Return previous shared random value from the latest consensus. Caller can
157  * NOT keep a reference to the returned pointer. Return NULL if none. */
158 const sr_srv_t *
160 {
161  const networkstatus_t *consensus;
162 
163  /* Use provided ns else get a live one */
164  if (ns) {
165  consensus = ns;
166  } else {
168  }
169  /* Ideally we would never be asked for an SRV without a live consensus. Make
170  * sure this assumption is correct. */
171  tor_assert_nonfatal(consensus);
172 
173  if (consensus) {
174  return consensus->sr_info.previous_srv;
175  }
176  return NULL;
177 }
178 
179 /** Parse a list of arguments from a SRV value either from a vote, consensus
180  * or from our disk state and return a newly allocated srv object. NULL is
181  * returned on error.
182  *
183  * The arguments' order:
184  * num_reveals, value
185  */
186 sr_srv_t *
188 {
189  char *value;
190  int ok, ret;
191  uint64_t num_reveals;
192  sr_srv_t *srv = NULL;
193 
194  tor_assert(args);
195 
196  if (smartlist_len(args) < 2) {
197  goto end;
198  }
199 
200  /* First argument is the number of reveal values */
201  num_reveals = tor_parse_uint64(smartlist_get(args, 0),
202  10, 0, UINT64_MAX, &ok, NULL);
203  if (!ok) {
204  goto end;
205  }
206  /* Second and last argument is the shared random value it self. */
207  value = smartlist_get(args, 1);
208  if (strlen(value) != SR_SRV_VALUE_BASE64_LEN) {
209  goto end;
210  }
211 
212  srv = tor_malloc_zero(sizeof(*srv));
213  srv->num_reveals = num_reveals;
214  /* We subtract one byte from the srclen because the function ignores the
215  * '=' character in the given buffer. This is broken but it's a documented
216  * behavior of the implementation. */
217  ret = base64_decode((char *) srv->value, sizeof(srv->value), value,
219  if (ret != sizeof(srv->value)) {
220  tor_free(srv);
221  srv = NULL;
222  goto end;
223  }
224  end:
225  return srv;
226 }
227 
228 /** Return the start time of the current SR protocol run using the times from
229  * the current consensus. For example, if the latest consensus valid-after is
230  * 23/06/2017 23:00:00 and a full SR protocol run is 24 hours, this function
231  * returns 23/06/2017 00:00:00. */
232 time_t
234 {
235  int total_rounds = SHARED_RANDOM_N_ROUNDS * SHARED_RANDOM_N_PHASES;
236  int voting_interval = get_voting_interval();
237  time_t beginning_of_curr_round;
238 
239  /* This function is not used for voting purposes, so if we have a live
240  consensus, use its valid-after as the beginning of the current round,
241  otherwise resort to the voting schedule which should always exist. */
243  if (ns) {
244  beginning_of_curr_round = ns->valid_after;
245  } else {
246  beginning_of_curr_round = get_start_time_of_current_round();
247  }
248 
249  /* Get current SR protocol round */
250  int curr_round_slot;
251  curr_round_slot = (beginning_of_curr_round / voting_interval) % total_rounds;
252 
253  /* Get start time by subtracting the time elapsed from the beginning of the
254  protocol run */
255  time_t time_elapsed_since_start_of_run = curr_round_slot * voting_interval;
256 
257  log_debug(LD_GENERAL, "Current SRV proto run: Start of current round: %u. "
258  "Time elapsed: %u (%d)", (unsigned) beginning_of_curr_round,
259  (unsigned) time_elapsed_since_start_of_run, voting_interval);
260 
261  return beginning_of_curr_round - time_elapsed_since_start_of_run;
262 }
263 
264 /** Return the start time of the previous SR protocol run. See
265  * sr_state_get_start_time_of_current_protocol_run() for more details. */
266 time_t
268 {
269  time_t start_time_of_current_run =
271 
272  /* We get the start time of previous protocol run, by getting the start time
273  * of current run and the subtracting a full protocol run from that. */
274  return start_time_of_current_run - sr_state_get_protocol_run_duration();
275 }
276 
277 /** Return the time (in seconds) it takes to complete a full SR protocol phase
278  * (e.g. the commit phase). */
279 unsigned int
281 {
282  return SHARED_RANDOM_N_ROUNDS * get_voting_interval();
283 }
284 
285 /** Return the time (in seconds) it takes to complete a full SR protocol run */
286 unsigned int
288 {
289  int total_protocol_rounds = SHARED_RANDOM_N_ROUNDS * SHARED_RANDOM_N_PHASES;
290  return total_protocol_rounds * get_voting_interval();
291 }
int get_voting_interval(void)
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
uint64_t num_reveals
Definition: shared_random.h:64
#define LD_GENERAL
Definition: log.h:62
time_t get_start_time_of_current_round(void)
char * sr_get_previous_for_control(void)
time_t sr_state_get_start_time_of_current_protocol_run(void)
Header file for config.c.
const or_options_t * get_options(void)
Definition: config.c:926
#define tor_assert(expr)
Definition: util_bug.h:102
#define tor_free(p)
Definition: malloc.h:52
#define SR_SRV_VALUE_BASE64_LEN
Definition: shared_random.h:48
networkstatus_t * networkstatus_get_live_consensus(time_t now)
sr_srv_t * sr_parse_srv(const smartlist_t *args)
time_t sr_state_get_start_time_of_previous_protocol_run(void)
networkstatus_sr_info_t sr_info
const sr_srv_t * sr_get_previous(const networkstatus_t *ns)
time_t voting_schedule_get_start_of_next_interval(time_t now, int interval, int offset)
void sr_srv_encode(char *dst, size_t dst_len, const sr_srv_t *srv)
int base64_encode(char *dest, size_t destlen, const char *src, size_t srclen, int flags)
Definition: binascii.c:215
networkstatus_t * networkstatus_get_latest_consensus(void)
static char * srv_to_control_string(const sr_srv_t *srv)
char * sr_get_current_for_control(void)
int tor_asprintf(char **strp, const char *fmt,...)
Definition: printf.c:75
uint8_t value[DIGEST256_LEN]
Definition: shared_random.h:66
unsigned int sr_state_get_protocol_run_duration(void)
Header for binascii.c.
Header file for shared_random_client.c.
Header file for voting_schedule.c.
unsigned int sr_state_get_phase_duration(void)
int base64_decode(char *dest, size_t destlen, const char *src, size_t srclen)
Definition: binascii.c:396
const sr_srv_t * sr_get_current(const networkstatus_t *ns)
time_t approx_time(void)
Definition: approx_time.c:32
int TestingV3AuthVotingStartOffset
int V3AuthVotingInterval
Header file for networkstatus.c.
Networkstatus consensus/vote structure.