shared_random_client.c 9.3 KB

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