shared_random_client.c 7.9 KB

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