LCOV - code coverage report
Current view: top level - feature/dirauth - shared_random_state.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 482 562 85.8 %
Date: 2021-11-24 03:28:48 Functions: 56 58 96.6 %

          Line data    Source code
       1             : /* Copyright (c) 2016-2021, The Tor Project, Inc. */
       2             : /* See LICENSE for licensing information */
       3             : 
       4             : /**
       5             :  * \file shared_random_state.c
       6             :  *
       7             :  * \brief Functions and data structures for the state of the random protocol
       8             :  *        as defined in proposal #250.
       9             :  **/
      10             : 
      11             : #define SHARED_RANDOM_STATE_PRIVATE
      12             : 
      13             : #include "core/or/or.h"
      14             : #include "app/config/config.h"
      15             : #include "lib/confmgt/confmgt.h"
      16             : #include "lib/crypt_ops/crypto_util.h"
      17             : #include "feature/dirauth/dirvote.h"
      18             : #include "feature/nodelist/networkstatus.h"
      19             : #include "feature/relay/router.h"
      20             : #include "feature/dirauth/shared_random.h"
      21             : #include "feature/hs_common/shared_random_client.h"
      22             : #include "feature/dirauth/shared_random_state.h"
      23             : #include "feature/dirauth/voting_schedule.h"
      24             : #include "lib/encoding/confline.h"
      25             : #include "lib/version/torversion.h"
      26             : 
      27             : #include "app/config/or_state_st.h"
      28             : 
      29             : /** Default filename of the shared random state on disk. */
      30             : static const char default_fname[] = "sr-state";
      31             : 
      32             : /** String representation of a protocol phase. */
      33             : static const char *phase_str[] = { "unknown", "commit", "reveal" };
      34             : 
      35             : /** Our shared random protocol state. There is only one possible state per
      36             :  * protocol run so this is the global state which is reset at every run once
      37             :  * the shared random value has been computed. */
      38             : static sr_state_t *sr_state = NULL;
      39             : 
      40             : /** Representation of our persistent state on disk. The sr_state above
      41             :  * contains the data parsed from this state. When we save to disk, we
      42             :  * translate the sr_state to this sr_disk_state. */
      43             : static sr_disk_state_t *sr_disk_state = NULL;
      44             : 
      45             : /* Disk state file keys. */
      46             : static const char dstate_commit_key[] = "Commit";
      47             : static const char dstate_prev_srv_key[] = "SharedRandPreviousValue";
      48             : static const char dstate_cur_srv_key[] = "SharedRandCurrentValue";
      49             : 
      50             : /** dummy instance of sr_disk_state_t, used for type-checking its
      51             :  * members with CONF_CHECK_VAR_TYPE. */
      52             : DUMMY_TYPECHECK_INSTANCE(sr_disk_state_t);
      53             : 
      54             : #define VAR(varname,conftype,member,initvalue)                          \
      55             :   CONFIG_VAR_ETYPE(sr_disk_state_t, varname, conftype, member, 0, initvalue)
      56             : #define V(member,conftype,initvalue)            \
      57             :   VAR(#member, conftype, member, initvalue)
      58             : 
      59             : /** Our persistent state magic number. */
      60             : #define SR_DISK_STATE_MAGIC 0x98AB1254
      61             : 
      62             : /** Array of variables that are saved to disk as a persistent state. */
      63             : // clang-format off
      64             : static const config_var_t state_vars[] = {
      65             :   V(Version,                    POSINT, "0"),
      66             :   V(TorVersion,                 STRING, NULL),
      67             :   V(ValidAfter,                 ISOTIME, NULL),
      68             :   V(ValidUntil,                 ISOTIME, NULL),
      69             : 
      70             :   V(Commit,                     LINELIST, NULL),
      71             : 
      72             :   V(SharedRandValues,           LINELIST_V, NULL),
      73             :   VAR("SharedRandPreviousValue",LINELIST_S, SharedRandValues, NULL),
      74             :   VAR("SharedRandCurrentValue", LINELIST_S, SharedRandValues, NULL),
      75             :   END_OF_CONFIG_VARS
      76             : };
      77             : // clang-format on
      78             : 
      79             : /** "Extra" variable in the state that receives lines we can't parse. This
      80             :  * lets us preserve options from versions of Tor newer than us. */
      81             : static const struct_member_t state_extra_var = {
      82             :   .name = "__extra",
      83             :   .type = CONFIG_TYPE_LINELIST,
      84             :   .offset = offsetof(sr_disk_state_t, ExtraLines),
      85             : };
      86             : 
      87             : /** Configuration format of sr_disk_state_t. */
      88             : static const config_format_t state_format = {
      89             :   .size = sizeof(sr_disk_state_t),
      90             :   .magic = {
      91             :    "sr_disk_state_t",
      92             :    SR_DISK_STATE_MAGIC,
      93             :    offsetof(sr_disk_state_t, magic_),
      94             :   },
      95             :   .vars = state_vars,
      96             :   .extra = &state_extra_var,
      97             : };
      98             : 
      99             : /** Global configuration manager for the shared-random state file */
     100             : static config_mgr_t *shared_random_state_mgr = NULL;
     101             : 
     102             : /** Return the configuration manager for the shared-random state file. */
     103             : static const config_mgr_t *
     104         217 : get_srs_mgr(void)
     105             : {
     106         217 :   if (PREDICT_UNLIKELY(shared_random_state_mgr == NULL)) {
     107          18 :     shared_random_state_mgr = config_mgr_new(&state_format);
     108          18 :     config_mgr_freeze(shared_random_state_mgr);
     109             :   }
     110         217 :   return shared_random_state_mgr;
     111             : }
     112             : 
     113             : static void state_query_del_(sr_state_object_t obj_type, void *data);
     114             : 
     115             : /** Return a string representation of a protocol phase. */
     116             : STATIC const char *
     117          17 : get_phase_str(sr_phase_t phase)
     118             : {
     119          17 :   const char *the_string = NULL;
     120             : 
     121          17 :   switch (phase) {
     122          17 :   case SR_PHASE_COMMIT:
     123             :   case SR_PHASE_REVEAL:
     124          17 :     the_string = phase_str[phase];
     125          17 :     break;
     126             :   default:
     127             :     /* Unknown phase shouldn't be possible. */
     128           0 :     tor_assert(0);
     129             :   }
     130             : 
     131          17 :   return the_string;
     132             : }
     133             : /** Return the time we should expire the state file created at <b>now</b>.
     134             :  * We expire the state file in the beginning of the next protocol run. */
     135             : STATIC time_t
     136          43 : get_state_valid_until_time(time_t now)
     137             : {
     138          43 :   int total_rounds = SHARED_RANDOM_N_ROUNDS * SHARED_RANDOM_N_PHASES;
     139          43 :   int current_round, voting_interval, rounds_left;
     140          43 :   time_t valid_until, beginning_of_current_round;
     141             : 
     142          43 :   voting_interval = get_voting_interval();
     143             :   /* Find the time the current round started. */
     144          43 :   beginning_of_current_round = dirauth_sched_get_cur_valid_after_time();
     145             : 
     146             :   /* Find how many rounds are left till the end of the protocol run */
     147          43 :   current_round = (now / voting_interval) % total_rounds;
     148          43 :   rounds_left = total_rounds - current_round;
     149             : 
     150             :   /* To find the valid-until time now, take the start time of the current
     151             :    * round and add to it the time it takes for the leftover rounds to
     152             :    * complete. */
     153          43 :   valid_until = beginning_of_current_round + (rounds_left * voting_interval);
     154             : 
     155             :   { /* Logging */
     156          43 :     char tbuf[ISO_TIME_LEN + 1];
     157          43 :     format_iso_time(tbuf, valid_until);
     158          43 :     log_debug(LD_DIR, "SR: Valid until time for state set to %s.", tbuf);
     159             :   }
     160             : 
     161          43 :   return valid_until;
     162             : }
     163             : 
     164             : /** Given the consensus 'valid-after' time, return the protocol phase we should
     165             :  * be in. */
     166             : STATIC sr_phase_t
     167          46 : get_sr_protocol_phase(time_t valid_after)
     168             : {
     169             :   /* Shared random protocol has two phases, commit and reveal. */
     170          46 :   int total_periods = SHARED_RANDOM_N_ROUNDS * SHARED_RANDOM_N_PHASES;
     171          46 :   int current_slot;
     172             : 
     173             :   /* Split time into slots of size 'voting_interval'. See which slot we are
     174             :    * currently into, and find which phase it corresponds to. */
     175          46 :   current_slot = (valid_after / get_voting_interval()) % total_periods;
     176             : 
     177          46 :   if (current_slot < SHARED_RANDOM_N_ROUNDS) {
     178             :     return SR_PHASE_COMMIT;
     179             :   } else {
     180           5 :     return SR_PHASE_REVEAL;
     181             :   }
     182             : }
     183             : 
     184             : /** Add the given <b>commit</b> to <b>state</b>. It MUST be a valid commit
     185             :  * and there shouldn't be a commit from the same authority in the state
     186             :  * already else verification hasn't been done prior. This takes ownership of
     187             :  * the commit once in our state. */
     188             : static void
     189          32 : commit_add_to_state(sr_commit_t *commit, sr_state_t *state)
     190             : {
     191          32 :   sr_commit_t *saved_commit;
     192             : 
     193          32 :   tor_assert(commit);
     194          32 :   tor_assert(state);
     195             : 
     196          32 :   saved_commit = digestmap_set(state->commits, commit->rsa_identity,
     197             :                                commit);
     198          32 :   if (saved_commit != NULL) {
     199             :     /* This means we already have that commit in our state so adding twice
     200             :      * the same commit is either a code flow error, a corrupted disk state
     201             :      * or some new unknown issue. */
     202           0 :     log_warn(LD_DIR, "SR: Commit from %s exists in our state while "
     203             :                      "adding it: '%s'", sr_commit_get_rsa_fpr(commit),
     204             :                      commit->encoded_commit);
     205           0 :     sr_commit_free(saved_commit);
     206             :   }
     207          32 : }
     208             : 
     209             : /** Helper: deallocate a commit object. (Used with digestmap_free(), which
     210             :  * requires a function pointer whose argument is void *). */
     211             : static void
     212           7 : commit_free_(void *p)
     213             : {
     214           7 :   sr_commit_free_(p);
     215           7 : }
     216             : 
     217             : #define state_free(val) \
     218             :   FREE_AND_NULL(sr_state_t, state_free_, (val))
     219             : 
     220             : /** Free a state that was allocated with state_new(). */
     221             : static void
     222           5 : state_free_(sr_state_t *state)
     223             : {
     224           5 :   if (state == NULL) {
     225             :     return;
     226             :   }
     227           5 :   tor_free(state->fname);
     228           5 :   digestmap_free(state->commits, commit_free_);
     229           5 :   tor_free(state->current_srv);
     230           5 :   tor_free(state->previous_srv);
     231           5 :   tor_free(state);
     232             : }
     233             : 
     234             : /** Allocate an sr_state_t object and returns it. If no <b>fname</b>, the
     235             :  * default file name is used. This function does NOT initialize the state
     236             :  * timestamp, phase or shared random value. NULL is never returned. */
     237             : static sr_state_t *
     238          18 : state_new(const char *fname, time_t now)
     239             : {
     240          18 :   sr_state_t *new_state = tor_malloc_zero(sizeof(*new_state));
     241             :   /* If file name is not provided, use default. */
     242          18 :   if (fname == NULL) {
     243           0 :     fname = default_fname;
     244             :   }
     245          18 :   new_state->fname = tor_strdup(fname);
     246          18 :   new_state->version = SR_PROTO_VERSION;
     247          18 :   new_state->commits = digestmap_new();
     248          18 :   new_state->phase = get_sr_protocol_phase(now);
     249          18 :   new_state->valid_until = get_state_valid_until_time(now);
     250          18 :   return new_state;
     251             : }
     252             : 
     253             : /** Set our global state pointer with the one given. */
     254             : static void
     255          18 : state_set(sr_state_t *state)
     256             : {
     257          18 :   tor_assert(state);
     258          18 :   if (sr_state != NULL) {
     259           0 :     state_free(sr_state);
     260             :   }
     261          18 :   sr_state = state;
     262          18 : }
     263             : 
     264             : #define disk_state_free(val) \
     265             :   FREE_AND_NULL(sr_disk_state_t, disk_state_free_, (val))
     266             : 
     267             : /** Free an allocated disk state. */
     268             : static void
     269           8 : disk_state_free_(sr_disk_state_t *state)
     270             : {
     271           8 :   if (state == NULL) {
     272             :     return;
     273             :   }
     274           5 :   config_free(get_srs_mgr(), state);
     275             : }
     276             : 
     277             : /** Allocate a new disk state, initialize it and return it. */
     278             : static sr_disk_state_t *
     279          18 : disk_state_new(time_t now)
     280             : {
     281          18 :   sr_disk_state_t *new_state = config_new(get_srs_mgr());
     282             : 
     283          18 :   new_state->Version = SR_PROTO_VERSION;
     284          18 :   new_state->TorVersion = tor_strdup(get_version());
     285          18 :   new_state->ValidUntil = get_state_valid_until_time(now);
     286          18 :   new_state->ValidAfter = now;
     287             : 
     288             :   /* Init config format. */
     289          18 :   config_init(get_srs_mgr(), new_state);
     290          18 :   return new_state;
     291             : }
     292             : 
     293             : /** Set our global disk state with the given state. */
     294             : static void
     295          18 : disk_state_set(sr_disk_state_t *state)
     296             : {
     297          18 :   tor_assert(state);
     298          18 :   if (sr_disk_state != NULL) {
     299           0 :     disk_state_free(sr_disk_state);
     300             :   }
     301          18 :   sr_disk_state = state;
     302          18 : }
     303             : 
     304             : /** Return -1 if the disk state is invalid (something in there that we can't or
     305             :  * shouldn't use). Return 0 if everything checks out. */
     306             : static int
     307           6 : disk_state_validate(const sr_disk_state_t *state)
     308             : {
     309           6 :   time_t now;
     310             : 
     311           6 :   tor_assert(state);
     312             : 
     313             :   /* Do we support the protocol version in the state or is it 0 meaning
     314             :    * Version wasn't found in the state file or bad anyway ? */
     315           6 :   if (state->Version == 0 || state->Version > SR_PROTO_VERSION) {
     316           0 :     goto invalid;
     317             :   }
     318             : 
     319             :   /* If the valid until time is before now, we shouldn't use that state. */
     320           6 :   now = time(NULL);
     321           6 :   if (state->ValidUntil < now) {
     322           0 :     log_info(LD_DIR, "SR: Disk state has expired. Ignoring it.");
     323           0 :     goto invalid;
     324             :   }
     325             : 
     326             :   /* Make sure we don't have a valid after time that is earlier than a valid
     327             :    * until time which would make things not work well. */
     328           6 :   if (state->ValidAfter >= state->ValidUntil) {
     329           0 :     log_info(LD_DIR, "SR: Disk state valid after/until times are invalid.");
     330           0 :     goto invalid;
     331             :   }
     332             : 
     333             :   return 0;
     334             : 
     335             :  invalid:
     336             :   return -1;
     337             : }
     338             : 
     339             : /** Parse the Commit line(s) in the disk state and translate them to the
     340             :  * the memory state. Return 0 on success else -1 on error. */
     341             : static int
     342           6 : disk_state_parse_commits(sr_state_t *state,
     343             :                          const sr_disk_state_t *disk_state)
     344             : {
     345           6 :   config_line_t *line;
     346           6 :   smartlist_t *args = NULL;
     347             : 
     348           6 :   tor_assert(state);
     349           6 :   tor_assert(disk_state);
     350             : 
     351          14 :   for (line = disk_state->Commit; line; line = line->next) {
     352           8 :     sr_commit_t *commit = NULL;
     353             : 
     354             :     /* Extra safety. */
     355           8 :     if (strcasecmp(line->key, dstate_commit_key) ||
     356           8 :         line->value == NULL) {
     357             :       /* Ignore any lines that are not commits. */
     358           0 :       tor_fragile_assert();
     359           0 :       continue;
     360             :     }
     361           8 :     args = smartlist_new();
     362           8 :     smartlist_split_string(args, line->value, " ",
     363             :                            SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
     364           8 :     if (smartlist_len(args) < 3) {
     365           0 :       log_warn(LD_BUG, "SR: Too few arguments in Commit Line: %s",
     366             :                escaped(line->value));
     367           0 :       goto error;
     368             :     }
     369           8 :     commit = sr_parse_commit(args);
     370           8 :     if (commit == NULL) {
     371             :       /* Ignore badly formed commit. It could also be a authority
     372             :        * fingerprint that we don't know about so it shouldn't be used. */
     373           0 :       smartlist_free(args);
     374           0 :       continue;
     375             :     }
     376             :     /* We consider parseable commit from our disk state to be valid because
     377             :      * they need to be in the first place to get in there. */
     378           8 :     commit->valid = 1;
     379             :     /* Add commit to our state pointer. */
     380           8 :     commit_add_to_state(commit, state);
     381             : 
     382          46 :     SMARTLIST_FOREACH(args, char *, cp, tor_free(cp));
     383           8 :     smartlist_free(args);
     384             :   }
     385             : 
     386             :   return 0;
     387             : 
     388           0 :  error:
     389           0 :   SMARTLIST_FOREACH(args, char *, cp, tor_free(cp));
     390           0 :   smartlist_free(args);
     391           0 :   return -1;
     392             : }
     393             : 
     394             : /** Parse a share random value line from the disk state and save it to dst
     395             :  * which is an allocated srv object. Return 0 on success else -1. */
     396             : static int
     397           2 : disk_state_parse_srv(const char *value, sr_srv_t *dst)
     398             : {
     399           2 :   int ret = -1;
     400           2 :   smartlist_t *args;
     401           2 :   sr_srv_t *srv;
     402             : 
     403           2 :   tor_assert(value);
     404           2 :   tor_assert(dst);
     405             : 
     406           2 :   args = smartlist_new();
     407           2 :   smartlist_split_string(args, value, " ",
     408             :                          SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
     409           2 :   if (smartlist_len(args) < 2) {
     410           0 :     log_warn(LD_BUG, "SR: Too few arguments in shared random value. "
     411             :              "Line: %s", escaped(value));
     412           0 :     goto error;
     413             :   }
     414           2 :   srv = sr_parse_srv(args);
     415           2 :   if (srv == NULL) {
     416           0 :     goto error;
     417             :   }
     418           2 :   dst->num_reveals = srv->num_reveals;
     419           2 :   memcpy(dst->value, srv->value, sizeof(dst->value));
     420           2 :   tor_free(srv);
     421           2 :   ret = 0;
     422             : 
     423           2 :  error:
     424           6 :   SMARTLIST_FOREACH(args, char *, s, tor_free(s));
     425           2 :   smartlist_free(args);
     426           2 :   return ret;
     427             : }
     428             : 
     429             : /** Parse both SharedRandCurrentValue and SharedRandPreviousValue line from
     430             :  * the state. Return 0 on success else -1. */
     431             : static int
     432           6 : disk_state_parse_sr_values(sr_state_t *state,
     433             :                            const sr_disk_state_t *disk_state)
     434             : {
     435             :   /* Only one value per type (current or previous) is allowed so we keep
     436             :    * track of it with these flag. */
     437           6 :   unsigned int seen_previous = 0, seen_current = 0;
     438           6 :   config_line_t *line;
     439           6 :   sr_srv_t *srv = NULL;
     440             : 
     441           6 :   tor_assert(state);
     442           6 :   tor_assert(disk_state);
     443             : 
     444           8 :   for (line = disk_state->SharedRandValues; line; line = line->next) {
     445           2 :     if (line->value == NULL) {
     446           0 :       continue;
     447             :     }
     448           2 :     srv = tor_malloc_zero(sizeof(*srv));
     449           2 :     if (disk_state_parse_srv(line->value, srv) < 0) {
     450           0 :       log_warn(LD_BUG, "SR: Broken current SRV line in state %s",
     451             :                escaped(line->value));
     452           0 :       goto bad;
     453             :     }
     454           2 :     if (!strcasecmp(line->key, dstate_prev_srv_key)) {
     455           1 :       if (seen_previous) {
     456           0 :         log_warn(LD_DIR, "SR: Second previous SRV value seen. Bad state");
     457           0 :         goto bad;
     458             :       }
     459           1 :       state->previous_srv = srv;
     460           1 :       seen_previous = 1;
     461           1 :     } else if (!strcasecmp(line->key, dstate_cur_srv_key)) {
     462           1 :       if (seen_current) {
     463           0 :         log_warn(LD_DIR, "SR: Second current SRV value seen. Bad state");
     464           0 :         goto bad;
     465             :       }
     466           1 :       state->current_srv = srv;
     467           1 :       seen_current = 1;
     468             :     } else {
     469             :       /* Unknown key. Ignoring. */
     470           0 :       tor_free(srv);
     471             :     }
     472             :   }
     473             : 
     474             :   return 0;
     475           0 :  bad:
     476           0 :   tor_free(srv);
     477           0 :   return -1;
     478             : }
     479             : 
     480             : /** Parse the given disk state and set a newly allocated state. On success,
     481             :  * return that state else NULL. */
     482             : static sr_state_t *
     483           6 : disk_state_parse(const sr_disk_state_t *new_disk_state)
     484             : {
     485           6 :   sr_state_t *new_state = state_new(default_fname, time(NULL));
     486             : 
     487           6 :   tor_assert(new_disk_state);
     488             : 
     489           6 :   new_state->version = new_disk_state->Version;
     490           6 :   new_state->valid_until = new_disk_state->ValidUntil;
     491           6 :   new_state->valid_after = new_disk_state->ValidAfter;
     492             : 
     493             :   /* Set our current phase according to the valid-after time in our disk
     494             :    * state. The disk state we are parsing contains everything for the phase
     495             :    * starting at valid_after so make sure our phase reflects that. */
     496           6 :   new_state->phase = get_sr_protocol_phase(new_state->valid_after);
     497             : 
     498             :   /* Parse the shared random values. */
     499           6 :   if (disk_state_parse_sr_values(new_state, new_disk_state) < 0) {
     500           0 :     goto error;
     501             :   }
     502             :   /* Parse the commits. */
     503           6 :   if (disk_state_parse_commits(new_state, new_disk_state) < 0) {
     504           0 :     goto error;
     505             :   }
     506             :   /* Great! This new state contains everything we had on disk. */
     507             :   return new_state;
     508             : 
     509           0 :  error:
     510           0 :   state_free(new_state);
     511           0 :   return NULL;
     512             : }
     513             : 
     514             : /** From a valid commit object and an allocated config line, set the line's
     515             :  * value to the state string representation of a commit. */
     516             : static void
     517          75 : disk_state_put_commit_line(const sr_commit_t *commit, config_line_t *line)
     518             : {
     519          75 :   char *reveal_str = NULL;
     520             : 
     521          75 :   tor_assert(commit);
     522          75 :   tor_assert(line);
     523             : 
     524          75 :   if (!fast_mem_is_zero(commit->encoded_reveal,
     525             :                        sizeof(commit->encoded_reveal))) {
     526             :     /* Add extra whitespace so we can format the line correctly. */
     527          69 :     tor_asprintf(&reveal_str, " %s", commit->encoded_reveal);
     528             :   }
     529          75 :   tor_asprintf(&line->value, "%u %s %s %s%s",
     530             :                SR_PROTO_VERSION,
     531          75 :                crypto_digest_algorithm_get_name(commit->alg),
     532             :                sr_commit_get_rsa_fpr(commit),
     533          75 :                commit->encoded_commit,
     534          75 :                reveal_str != NULL ? reveal_str : "");
     535          75 :   if (reveal_str != NULL) {
     536          69 :     memwipe(reveal_str, 0, strlen(reveal_str));
     537          69 :     tor_free(reveal_str);
     538             :   }
     539          75 : }
     540             : 
     541             : /** From a valid srv object and an allocated config line, set the line's
     542             :  * value to the state string representation of a shared random value. */
     543             : static void
     544          78 : disk_state_put_srv_line(const sr_srv_t *srv, config_line_t *line)
     545             : {
     546          78 :   char encoded[SR_SRV_VALUE_BASE64_LEN + 1];
     547             : 
     548          78 :   tor_assert(line);
     549             : 
     550             :   /* No SRV value thus don't add the line. This is possible since we might
     551             :    * not have a current or previous SRV value in our state. */
     552          78 :   if (srv == NULL) {
     553           0 :     return;
     554             :   }
     555          78 :   sr_srv_encode(encoded, sizeof(encoded), srv);
     556          78 :   tor_asprintf(&line->value, "%" PRIu64 " %s", srv->num_reveals, encoded);
     557             : }
     558             : 
     559             : /** Reset disk state that is free allocated memory and zeroed the object. */
     560             : static void
     561         170 : disk_state_reset(void)
     562             : {
     563             :   /* Free allocated memory */
     564         170 :   config_free_lines(sr_disk_state->Commit);
     565         170 :   config_free_lines(sr_disk_state->SharedRandValues);
     566         170 :   config_free_lines(sr_disk_state->ExtraLines);
     567         170 :   tor_free(sr_disk_state->TorVersion);
     568             : 
     569             :   /* Clear other fields. */
     570         170 :   sr_disk_state->ValidAfter = 0;
     571         170 :   sr_disk_state->ValidUntil = 0;
     572         170 :   sr_disk_state->Version = 0;
     573             : 
     574             :   /* Reset it with useful data */
     575         170 :   sr_disk_state->TorVersion = tor_strdup(get_version());
     576         170 : }
     577             : 
     578             : /** Update our disk state based on our global SR state. */
     579             : static void
     580         170 : disk_state_update(void)
     581             : {
     582         170 :   config_line_t **next, *line;
     583             : 
     584         170 :   if (BUG(!sr_disk_state))
     585           0 :     return;
     586         170 :   if (BUG(!sr_state))
     587           0 :     return;
     588             : 
     589             :   /* Reset current disk state. */
     590         170 :   disk_state_reset();
     591             : 
     592             :   /* First, update elements that we don't need to do a construction. */
     593         170 :   sr_disk_state->Version = sr_state->version;
     594         170 :   sr_disk_state->ValidUntil = sr_state->valid_until;
     595         170 :   sr_disk_state->ValidAfter = sr_state->valid_after;
     596             : 
     597             :   /* Shared random values. */
     598         170 :   next = &sr_disk_state->SharedRandValues;
     599         170 :   if (sr_state->previous_srv != NULL) {
     600          40 :     *next = line = tor_malloc_zero(sizeof(config_line_t));
     601          40 :     line->key = tor_strdup(dstate_prev_srv_key);
     602          40 :     disk_state_put_srv_line(sr_state->previous_srv, line);
     603             :     /* Go to the next shared random value. */
     604          40 :     next = &(line->next);
     605             :   }
     606         170 :   if (sr_state->current_srv != NULL) {
     607          38 :     *next = line = tor_malloc_zero(sizeof(*line));
     608          38 :     line->key = tor_strdup(dstate_cur_srv_key);
     609          38 :     disk_state_put_srv_line(sr_state->current_srv, line);
     610             :   }
     611             : 
     612             :   /* Parse the commits and construct config line(s). */
     613         170 :   next = &sr_disk_state->Commit;
     614         245 :   DIGESTMAP_FOREACH(sr_state->commits, key, sr_commit_t *, commit) {
     615          75 :     *next = line = tor_malloc_zero(sizeof(*line));
     616          75 :     line->key = tor_strdup(dstate_commit_key);
     617          75 :     disk_state_put_commit_line(commit, line);
     618          75 :     next = &(line->next);
     619         170 :   } DIGESTMAP_FOREACH_END;
     620             : }
     621             : 
     622             : /** Load state from disk and put it into our disk state. If the state passes
     623             :  * validation, our global state will be updated with it. Return 0 on
     624             :  * success. On error, -EINVAL is returned if the state on disk did contained
     625             :  * something malformed or is unreadable. -ENOENT is returned indicating that
     626             :  * the state file is either empty of non existing. */
     627             : static int
     628           6 : disk_state_load_from_disk(void)
     629             : {
     630           6 :   int ret;
     631           6 :   char *fname;
     632             : 
     633           6 :   fname = get_datadir_fname(default_fname);
     634           6 :   ret = disk_state_load_from_disk_impl(fname);
     635           6 :   tor_free(fname);
     636             : 
     637           6 :   return ret;
     638             : }
     639             : 
     640             : /** Helper for disk_state_load_from_disk(). */
     641             : STATIC int
     642           9 : disk_state_load_from_disk_impl(const char *fname)
     643             : {
     644           9 :   int ret;
     645           9 :   char *content = NULL;
     646           9 :   sr_state_t *parsed_state = NULL;
     647           9 :   sr_disk_state_t *disk_state = NULL;
     648             : 
     649             :   /* Read content of file so we can parse it. */
     650           9 :   if ((content = read_file_to_str(fname, 0, NULL)) == NULL) {
     651           3 :     log_warn(LD_FS, "SR: Unable to read SR state file %s",
     652             :              escaped(fname));
     653           3 :     ret = -errno;
     654           3 :     goto error;
     655             :   }
     656             : 
     657             :   {
     658           6 :     config_line_t *lines = NULL;
     659           6 :     char *errmsg = NULL;
     660             : 
     661             :     /* Every error in this code path will return EINVAL. */
     662           6 :     ret = -EINVAL;
     663           6 :     if (config_get_lines(content, &lines, 0) < 0) {
     664           0 :       config_free_lines(lines);
     665           0 :       goto error;
     666             :     }
     667             : 
     668           6 :     disk_state = disk_state_new(time(NULL));
     669           6 :     config_assign(get_srs_mgr(), disk_state, lines, 0, &errmsg);
     670           6 :     config_free_lines(lines);
     671           6 :     if (errmsg) {
     672           0 :       log_warn(LD_DIR, "SR: Reading state error: %s", errmsg);
     673           0 :       tor_free(errmsg);
     674           0 :       goto error;
     675             :     }
     676             :   }
     677             : 
     678             :   /* So far so good, we've loaded our state file into our disk state. Let's
     679             :    * validate it and then parse it. */
     680           6 :   if (disk_state_validate(disk_state) < 0) {
     681           0 :     ret = -EINVAL;
     682           0 :     goto error;
     683             :   }
     684             : 
     685           6 :   parsed_state = disk_state_parse(disk_state);
     686           6 :   if (parsed_state == NULL) {
     687           0 :     ret = -EINVAL;
     688           0 :     goto error;
     689             :   }
     690           6 :   state_set(parsed_state);
     691           6 :   disk_state_set(disk_state);
     692           6 :   tor_free(content);
     693           6 :   log_info(LD_DIR, "SR: State loaded successfully from file %s", fname);
     694           6 :   return 0;
     695             : 
     696           3 :  error:
     697           3 :   disk_state_free(disk_state);
     698           3 :   tor_free(content);
     699           3 :   return ret;
     700             : }
     701             : 
     702             : /** Save the disk state to disk but before that update it from the current
     703             :  * state so we always have the latest. Return 0 on success else -1. */
     704             : static int
     705         170 : disk_state_save_to_disk(void)
     706             : {
     707         170 :   int ret;
     708         170 :   char *state, *content = NULL, *fname = NULL;
     709         170 :   char tbuf[ISO_TIME_LEN + 1];
     710         170 :   time_t now = time(NULL);
     711             : 
     712             :   /* If we didn't have the opportunity to setup an internal disk state,
     713             :    * don't bother saving something to disk. */
     714         170 :   if (sr_disk_state == NULL) {
     715           0 :     ret = 0;
     716           0 :     goto done;
     717             :   }
     718             : 
     719             :   /* Make sure that our disk state is up to date with our memory state
     720             :    * before saving it to disk. */
     721         170 :   disk_state_update();
     722         170 :   state = config_dump(get_srs_mgr(), NULL, sr_disk_state, 0, 0);
     723         170 :   format_local_iso_time(tbuf, now);
     724         170 :   tor_asprintf(&content,
     725             :                "# Tor shared random state file last generated on %s "
     726             :                "local time\n"
     727             :                "# Other times below are in UTC\n"
     728             :                "# Please *do not* edit this file.\n\n%s",
     729             :                tbuf, state);
     730         170 :   tor_free(state);
     731         170 :   fname = get_datadir_fname(default_fname);
     732         170 :   if (write_str_to_file(fname, content, 0) < 0) {
     733           0 :     log_warn(LD_FS, "SR: Unable to write SR state to file %s", fname);
     734           0 :     ret = -1;
     735           0 :     goto done;
     736             :   }
     737         170 :   ret = 0;
     738         170 :   log_debug(LD_DIR, "SR: Saved state to file %s", fname);
     739             : 
     740         170 :  done:
     741         170 :   tor_free(fname);
     742         170 :   tor_free(content);
     743         170 :   return ret;
     744             : }
     745             : 
     746             : /** Reset our state to prepare for a new protocol run. Once this returns, all
     747             :  * commits in the state will be removed and freed. */
     748             : STATIC void
     749           3 : reset_state_for_new_protocol_run(time_t valid_after)
     750             : {
     751           3 :   if (BUG(!sr_state))
     752           0 :     return;
     753             : 
     754             :   /* Keep counters in track */
     755           3 :   sr_state->n_reveal_rounds = 0;
     756           3 :   sr_state->n_commit_rounds = 0;
     757           3 :   sr_state->n_protocol_runs++;
     758             : 
     759             :   /* Reset valid-until */
     760           3 :   sr_state->valid_until = get_state_valid_until_time(valid_after);
     761           3 :   sr_state->valid_after = valid_after;
     762             : 
     763             :   /* We are in a new protocol run so cleanup commits. */
     764           3 :   sr_state_delete_commits();
     765             : }
     766             : 
     767             : /** This is the first round of the new protocol run starting at
     768             :  * <b>valid_after</b>. Do the necessary housekeeping. */
     769             : STATIC void
     770           2 : new_protocol_run(time_t valid_after)
     771             : {
     772           2 :   sr_commit_t *our_commitment = NULL;
     773             : 
     774             :   /* Only compute the srv at the end of the reveal phase. */
     775           2 :   if (sr_state->phase == SR_PHASE_REVEAL) {
     776             :     /* We are about to compute a new shared random value that will be set in
     777             :      * our state as the current value so rotate values. */
     778           2 :     state_rotate_srv();
     779             :     /* Compute the shared randomness value of the day. */
     780           2 :     sr_compute_srv();
     781             :   }
     782             : 
     783             :   /* Prepare for the new protocol run by resetting the state */
     784           2 :   reset_state_for_new_protocol_run(valid_after);
     785             : 
     786             :   /* Do some logging */
     787           2 :   log_info(LD_DIR, "SR: Protocol run #%" PRIu64 " starting!",
     788             :            sr_state->n_protocol_runs);
     789             : 
     790             :   /* Generate fresh commitments for this protocol run */
     791           2 :   our_commitment = sr_generate_our_commit(valid_after,
     792           2 :                                           get_my_v3_authority_cert());
     793           2 :   if (our_commitment) {
     794             :     /* Add our commitment to our state. In case we are unable to create one
     795             :      * (highly unlikely), we won't vote for this protocol run since our
     796             :      * commitment won't be in our state. */
     797           2 :     sr_state_add_commit(our_commitment);
     798             :   }
     799           2 : }
     800             : 
     801             : /** Return 1 iff the <b>next_phase</b> is a phase transition from the current
     802             :  * phase that is it's different. */
     803             : STATIC int
     804          20 : is_phase_transition(sr_phase_t next_phase)
     805             : {
     806          20 :   return sr_state->phase != next_phase;
     807             : }
     808             : 
     809             : /** Helper function: return a commit using the RSA fingerprint of the
     810             :  * authority or NULL if no such commit is known. */
     811             : static sr_commit_t *
     812          10 : state_query_get_commit(const char *rsa_fpr)
     813             : {
     814          10 :   tor_assert(rsa_fpr);
     815          10 :   return digestmap_get(sr_state->commits, rsa_fpr);
     816             : }
     817             : 
     818             : /** Helper function: This handles the GET state action using an
     819             :  * <b>obj_type</b> and <b>data</b> needed for the action. */
     820             : static void *
     821         243 : state_query_get_(sr_state_object_t obj_type, const void *data)
     822             : {
     823         243 :   if (BUG(!sr_state))
     824           0 :     return NULL;
     825             : 
     826         243 :   void *obj = NULL;
     827             : 
     828         243 :   switch (obj_type) {
     829          10 :   case SR_STATE_OBJ_COMMIT:
     830             :   {
     831          10 :     obj = state_query_get_commit(data);
     832          10 :     break;
     833             :   }
     834          31 :   case SR_STATE_OBJ_COMMITS:
     835          31 :     obj = sr_state->commits;
     836          31 :     break;
     837          87 :   case SR_STATE_OBJ_CURSRV:
     838          87 :     obj = sr_state->current_srv;
     839          87 :     break;
     840          79 :   case SR_STATE_OBJ_PREVSRV:
     841          79 :     obj = sr_state->previous_srv;
     842          79 :     break;
     843          36 :   case SR_STATE_OBJ_PHASE:
     844          36 :     obj = &sr_state->phase;
     845          36 :     break;
     846             :   case SR_STATE_OBJ_VALID_AFTER:
     847             :   default:
     848           0 :     tor_assert(0);
     849             :   }
     850             :   return obj;
     851             : }
     852             : 
     853             : /** Helper function: This handles the PUT state action using an
     854             :  * <b>obj_type</b> and <b>data</b> needed for the action.
     855             :  * PUT frees the previous data before replacing it, if needed. */
     856             : static void
     857          87 : state_query_put_(sr_state_object_t obj_type, void *data)
     858             : {
     859          87 :   if (BUG(!sr_state))
     860           0 :     return;
     861             : 
     862          87 :   switch (obj_type) {
     863          24 :   case SR_STATE_OBJ_COMMIT:
     864             :   {
     865          24 :     sr_commit_t *commit = data;
     866          24 :     tor_assert(commit);
     867             :     /* commit_add_to_state() frees the old commit, if there is one */
     868          24 :     commit_add_to_state(commit, sr_state);
     869          24 :     break;
     870             :   }
     871          25 :   case SR_STATE_OBJ_CURSRV:
     872             :       /* Check if the new pointer is the same as the old one: if it is, it's
     873             :        * probably a bug. The caller may have confused current and previous,
     874             :        * or they may have forgotten to sr_srv_dup().
     875             :        * Putting NULL multiple times is allowed. */
     876          25 :     if (!BUG(data && sr_state->current_srv == (sr_srv_t *) data)) {
     877             :       /* We own the old SRV, so we need to free it.  */
     878          25 :       state_query_del_(SR_STATE_OBJ_CURSRV, NULL);
     879          25 :       sr_state->current_srv = (sr_srv_t *) data;
     880             :     }
     881             :     break;
     882          23 :   case SR_STATE_OBJ_PREVSRV:
     883             :       /* Check if the new pointer is the same as the old one: if it is, it's
     884             :        * probably a bug. The caller may have confused current and previous,
     885             :        * or they may have forgotten to sr_srv_dup().
     886             :        * Putting NULL multiple times is allowed. */
     887          23 :     if (!BUG(data && sr_state->previous_srv == (sr_srv_t *) data)) {
     888             :       /* We own the old SRV, so we need to free it.  */
     889          23 :       state_query_del_(SR_STATE_OBJ_PREVSRV, NULL);
     890          23 :       sr_state->previous_srv = (sr_srv_t *) data;
     891             :     }
     892             :     break;
     893          15 :   case SR_STATE_OBJ_VALID_AFTER:
     894          15 :     sr_state->valid_after = *((time_t *) data);
     895          15 :     break;
     896             :   /* It's not allowed to change the phase nor the full commitments map from
     897             :    * the state. The phase is decided during a strict process post voting and
     898             :    * the commits should be put individually. */
     899             :   case SR_STATE_OBJ_PHASE:
     900             :   case SR_STATE_OBJ_COMMITS:
     901             :   default:
     902           0 :     tor_assert(0);
     903             :   }
     904             : }
     905             : 
     906             : /** Helper function: This handles the DEL_ALL state action using an
     907             :  * <b>obj_type</b> and <b>data</b> needed for the action. */
     908             : static void
     909          12 : state_query_del_all_(sr_state_object_t obj_type)
     910             : {
     911          12 :   if (BUG(!sr_state))
     912           0 :     return;
     913             : 
     914          12 :   switch (obj_type) {
     915          12 :   case SR_STATE_OBJ_COMMIT:
     916             :   {
     917             :     /* We are in a new protocol run so cleanup commitments. */
     918          23 :     DIGESTMAP_FOREACH_MODIFY(sr_state->commits, key, sr_commit_t *, c) {
     919          11 :       sr_commit_free(c);
     920          11 :       MAP_DEL_CURRENT(key);
     921             :     } DIGESTMAP_FOREACH_END;
     922             :     break;
     923             :   }
     924             :   /* The following objects are _NOT_ supposed to be removed. */
     925             :   case SR_STATE_OBJ_CURSRV:
     926             :   case SR_STATE_OBJ_PREVSRV:
     927             :   case SR_STATE_OBJ_PHASE:
     928             :   case SR_STATE_OBJ_COMMITS:
     929             :   case SR_STATE_OBJ_VALID_AFTER:
     930             :   default:
     931           0 :     tor_assert(0);
     932             :   }
     933             : }
     934             : 
     935             : /** Helper function: This handles the DEL state action using an
     936             :  * <b>obj_type</b> and <b>data</b> needed for the action. */
     937             : static void
     938         118 : state_query_del_(sr_state_object_t obj_type, void *data)
     939             : {
     940         118 :   (void) data;
     941             : 
     942         118 :   if (BUG(!sr_state))
     943           0 :     return;
     944             : 
     945         118 :   switch (obj_type) {
     946          60 :   case SR_STATE_OBJ_PREVSRV:
     947          60 :     tor_free(sr_state->previous_srv);
     948          60 :     break;
     949          58 :   case SR_STATE_OBJ_CURSRV:
     950          58 :     tor_free(sr_state->current_srv);
     951          58 :     break;
     952             :   case SR_STATE_OBJ_COMMIT:
     953             :   case SR_STATE_OBJ_COMMITS:
     954             :   case SR_STATE_OBJ_PHASE:
     955             :   case SR_STATE_OBJ_VALID_AFTER:
     956             :   default:
     957           0 :     tor_assert(0);
     958             :   }
     959             : }
     960             : 
     961             : /** Query state using an <b>action</b> for an object type <b>obj_type</b>.
     962             :  * The <b>data</b> pointer needs to point to an object that the action needs
     963             :  * to use and if anything is required to be returned, it is stored in
     964             :  * <b>out</b>.
     965             :  *
     966             :  * This mechanism exists so we have one single point where we synchronized
     967             :  * our memory state with our disk state for every actions that changes it.
     968             :  * We then trigger a write on disk immediately.
     969             :  *
     970             :  * This should be the only entry point to our memory state. It's used by all
     971             :  * our state accessors and should be in the future. */
     972             : static void
     973         413 : state_query(sr_state_action_t action, sr_state_object_t obj_type,
     974             :             void *data, void **out)
     975             : {
     976         413 :   switch (action) {
     977         243 :   case SR_STATE_ACTION_GET:
     978         243 :     *out = state_query_get_(obj_type, data);
     979         243 :     break;
     980          87 :   case SR_STATE_ACTION_PUT:
     981          87 :     state_query_put_(obj_type, data);
     982          87 :     break;
     983          70 :   case SR_STATE_ACTION_DEL:
     984          70 :     state_query_del_(obj_type, data);
     985          70 :     break;
     986          12 :   case SR_STATE_ACTION_DEL_ALL:
     987          12 :     state_query_del_all_(obj_type);
     988          12 :     break;
     989             :   case SR_STATE_ACTION_SAVE:
     990             :     /* Only trigger a disk state save. */
     991             :     break;
     992             :   default:
     993           0 :     tor_assert(0);
     994             :   }
     995             : 
     996             :   /* If the action actually changes the state, immediately save it to disk.
     997             :    * The following will sync the state -> disk state and then save it. */
     998         413 :   if (action != SR_STATE_ACTION_GET) {
     999         170 :     disk_state_save_to_disk();
    1000             :   }
    1001         413 : }
    1002             : 
    1003             : /** Delete the current SRV value from the state freeing it and the value is set
    1004             :  * to NULL meaning empty. */
    1005             : STATIC void
    1006          33 : state_del_current_srv(void)
    1007             : {
    1008          33 :   state_query(SR_STATE_ACTION_DEL, SR_STATE_OBJ_CURSRV, NULL, NULL);
    1009          33 : }
    1010             : 
    1011             : /** Delete the previous SRV value from the state freeing it and the value is
    1012             :  * set to NULL meaning empty. */
    1013             : STATIC void
    1014          37 : state_del_previous_srv(void)
    1015             : {
    1016          37 :   state_query(SR_STATE_ACTION_DEL, SR_STATE_OBJ_PREVSRV, NULL, NULL);
    1017          37 : }
    1018             : 
    1019             : /** Rotate SRV value by setting the previous SRV to the current SRV, and
    1020             :  * clearing the current SRV. */
    1021             : STATIC void
    1022           3 : state_rotate_srv(void)
    1023             : {
    1024             :   /* First delete previous SRV from the state. Object will be freed. */
    1025           3 :   state_del_previous_srv();
    1026             :   /* Set previous SRV to a copy of the current one. */
    1027           3 :   sr_state_set_previous_srv(sr_srv_dup(sr_state_get_current_srv()));
    1028             :   /* Free and NULL the current srv. */
    1029           3 :   sr_state_set_current_srv(NULL);
    1030           3 : }
    1031             : 
    1032             : /** Set valid after time in the our state. */
    1033             : void
    1034          15 : sr_state_set_valid_after(time_t valid_after)
    1035             : {
    1036          15 :   state_query(SR_STATE_ACTION_PUT, SR_STATE_OBJ_VALID_AFTER,
    1037             :               (void *) &valid_after, NULL);
    1038          15 : }
    1039             : 
    1040             : /** Return the phase we are currently in according to our state. */
    1041             : sr_phase_t
    1042          36 : sr_state_get_phase(void)
    1043             : {
    1044          36 :   void *ptr=NULL;
    1045          36 :   state_query(SR_STATE_ACTION_GET, SR_STATE_OBJ_PHASE, NULL, &ptr);
    1046          36 :   tor_assert(ptr);
    1047          36 :   return *(sr_phase_t *) ptr;
    1048             : }
    1049             : 
    1050             : /** Return the previous SRV value from our state. Value CAN be NULL.
    1051             :  * The state object owns the SRV, so the calling code should not free the SRV.
    1052             :  * Use sr_srv_dup() if you want to keep a copy of the SRV. */
    1053             : const sr_srv_t *
    1054          79 : sr_state_get_previous_srv(void)
    1055             : {
    1056          79 :   const sr_srv_t *srv;
    1057          79 :   state_query(SR_STATE_ACTION_GET, SR_STATE_OBJ_PREVSRV, NULL,
    1058             :               (void *) &srv);
    1059          79 :   return srv;
    1060             : }
    1061             : 
    1062             : /** Set the current SRV value from our state. Value CAN be NULL. The srv
    1063             :  * object ownership is transferred to the state object. */
    1064             : void
    1065          23 : sr_state_set_previous_srv(const sr_srv_t *srv)
    1066             : {
    1067          23 :   state_query(SR_STATE_ACTION_PUT, SR_STATE_OBJ_PREVSRV, (void *) srv,
    1068             :               NULL);
    1069          23 : }
    1070             : 
    1071             : /** Return the current SRV value from our state. Value CAN be NULL.
    1072             :  * The state object owns the SRV, so the calling code should not free the SRV.
    1073             :  * Use sr_srv_dup() if you want to keep a copy of the SRV. */
    1074             : const sr_srv_t *
    1075          87 : sr_state_get_current_srv(void)
    1076             : {
    1077          87 :   const sr_srv_t *srv;
    1078          87 :   state_query(SR_STATE_ACTION_GET, SR_STATE_OBJ_CURSRV, NULL,
    1079             :               (void *) &srv);
    1080          87 :   return srv;
    1081             : }
    1082             : 
    1083             : /** Set the current SRV value from our state. Value CAN be NULL. The srv
    1084             :  * object ownership is transferred to the state object. */
    1085             : void
    1086          25 : sr_state_set_current_srv(const sr_srv_t *srv)
    1087             : {
    1088          25 :   state_query(SR_STATE_ACTION_PUT, SR_STATE_OBJ_CURSRV, (void *) srv,
    1089             :               NULL);
    1090          25 : }
    1091             : 
    1092             : /** Clean all the SRVs in our state. */
    1093             : void
    1094          29 : sr_state_clean_srvs(void)
    1095             : {
    1096             :   /* Remove SRVs from state. They will be set to NULL as "empty". */
    1097          29 :   state_del_previous_srv();
    1098          29 :   state_del_current_srv();
    1099          29 : }
    1100             : 
    1101             : /** Return a pointer to the commits map from our state. CANNOT be NULL. */
    1102             : digestmap_t *
    1103          31 : sr_state_get_commits(void)
    1104             : {
    1105          31 :   digestmap_t *commits;
    1106          31 :   state_query(SR_STATE_ACTION_GET, SR_STATE_OBJ_COMMITS,
    1107             :               NULL, (void *) &commits);
    1108          31 :   tor_assert(commits);
    1109          31 :   return commits;
    1110             : }
    1111             : 
    1112             : /** Update the current SR state as needed for the upcoming voting round at
    1113             :  * <b>valid_after</b>. */
    1114             : void
    1115          21 : sr_state_update(time_t valid_after)
    1116             : {
    1117          21 :   sr_phase_t next_phase;
    1118             : 
    1119          21 :   if (BUG(!sr_state))
    1120           0 :     return;
    1121             : 
    1122             :   /* Don't call this function twice in the same voting period. */
    1123          21 :   if (valid_after <= sr_state->valid_after) {
    1124           6 :     log_info(LD_DIR, "SR: Asked to update state twice. Ignoring.");
    1125           6 :     return;
    1126             :   }
    1127             : 
    1128             :   /* Get phase of upcoming round. */
    1129          15 :   next_phase = get_sr_protocol_phase(valid_after);
    1130             : 
    1131             :   /* If we are transitioning to a new protocol phase, prepare the stage. */
    1132          15 :   if (is_phase_transition(next_phase)) {
    1133           2 :     if (next_phase == SR_PHASE_COMMIT) {
    1134             :       /* Going into commit phase means we are starting a new protocol run. */
    1135           1 :       new_protocol_run(valid_after);
    1136             :     }
    1137             :     /* Set the new phase for this round */
    1138           2 :     sr_state->phase = next_phase;
    1139          26 :   } else if (sr_state->phase == SR_PHASE_COMMIT &&
    1140          13 :              digestmap_size(sr_state->commits) == 0) {
    1141             :     /* We are _NOT_ in a transition phase so if we are in the commit phase
    1142             :      * and have no commit, generate one. Chances are that we are booting up
    1143             :      * so let's have a commit in our state for the next voting period. */
    1144          13 :     sr_commit_t *our_commit =
    1145          13 :       sr_generate_our_commit(valid_after, get_my_v3_authority_cert());
    1146          13 :     if (our_commit) {
    1147             :       /* Add our commitment to our state. In case we are unable to create one
    1148             :        * (highly unlikely), we won't vote for this protocol run since our
    1149             :        * commitment won't be in our state. */
    1150          13 :       sr_state_add_commit(our_commit);
    1151             :     }
    1152             :   }
    1153             : 
    1154          15 :   sr_state_set_valid_after(valid_after);
    1155             : 
    1156             :   /* Count the current round */
    1157          15 :   if (sr_state->phase == SR_PHASE_COMMIT) {
    1158             :     /* invariant check: we've not entered reveal phase yet */
    1159          14 :     if (BUG(sr_state->n_reveal_rounds != 0))
    1160           0 :       return;
    1161          14 :     sr_state->n_commit_rounds++;
    1162             :   } else {
    1163           1 :     sr_state->n_reveal_rounds++;
    1164             :   }
    1165             : 
    1166             :   { /* Debugging. */
    1167          15 :     char tbuf[ISO_TIME_LEN + 1];
    1168          15 :     format_iso_time(tbuf, valid_after);
    1169          15 :     log_info(LD_DIR, "SR: State prepared for upcoming voting period (%s). "
    1170             :              "Upcoming phase is %s (counters: %d commit & %d reveal rounds).",
    1171             :              tbuf, get_phase_str(sr_state->phase),
    1172             :              sr_state->n_commit_rounds, sr_state->n_reveal_rounds);
    1173             :   }
    1174             : }
    1175             : 
    1176             : /** Return commit object from the given authority digest <b>rsa_identity</b>.
    1177             :  * Return NULL if not found. */
    1178             : sr_commit_t *
    1179          10 : sr_state_get_commit(const char *rsa_identity)
    1180             : {
    1181          10 :   sr_commit_t *commit;
    1182             : 
    1183          10 :   tor_assert(rsa_identity);
    1184             : 
    1185          10 :   state_query(SR_STATE_ACTION_GET, SR_STATE_OBJ_COMMIT,
    1186             :               (void *) rsa_identity, (void *) &commit);
    1187          10 :   return commit;
    1188             : }
    1189             : 
    1190             : /** Add <b>commit</b> to the permanent state. The commit object ownership is
    1191             :  * transferred to the state so the caller MUST not free it. */
    1192             : void
    1193          24 : sr_state_add_commit(sr_commit_t *commit)
    1194             : {
    1195          24 :   tor_assert(commit);
    1196             : 
    1197             :   /* Put the commit to the global state. */
    1198          24 :   state_query(SR_STATE_ACTION_PUT, SR_STATE_OBJ_COMMIT,
    1199             :               (void *) commit, NULL);
    1200             : 
    1201          24 :   log_debug(LD_DIR, "SR: Commit from %s has been added to our state.",
    1202             :             sr_commit_get_rsa_fpr(commit));
    1203          24 : }
    1204             : 
    1205             : /** Remove all commits from our state. */
    1206             : void
    1207          12 : sr_state_delete_commits(void)
    1208             : {
    1209          12 :   state_query(SR_STATE_ACTION_DEL_ALL, SR_STATE_OBJ_COMMIT, NULL, NULL);
    1210          12 : }
    1211             : 
    1212             : /** Copy the reveal information from <b>commit</b> into <b>saved_commit</b>.
    1213             :  * This <b>saved_commit</b> MUST come from our current SR state. Once modified,
    1214             :  * the disk state is updated. */
    1215             : void
    1216           1 : sr_state_copy_reveal_info(sr_commit_t *saved_commit, const sr_commit_t *commit)
    1217             : {
    1218           1 :   tor_assert(saved_commit);
    1219           1 :   tor_assert(commit);
    1220             : 
    1221           1 :   saved_commit->reveal_ts = commit->reveal_ts;
    1222           1 :   memcpy(saved_commit->random_number, commit->random_number,
    1223             :          sizeof(saved_commit->random_number));
    1224             : 
    1225           1 :   strlcpy(saved_commit->encoded_reveal, commit->encoded_reveal,
    1226             :           sizeof(saved_commit->encoded_reveal));
    1227           1 :   state_query(SR_STATE_ACTION_SAVE, 0, NULL, NULL);
    1228           1 :   log_debug(LD_DIR, "SR: Reveal value learned %s (for commit %s) from %s",
    1229             :             saved_commit->encoded_reveal, saved_commit->encoded_commit,
    1230             :             sr_commit_get_rsa_fpr(saved_commit));
    1231           1 : }
    1232             : 
    1233             : /** Set the fresh SRV flag from our state. This doesn't need to trigger a
    1234             :  * disk state synchronization so we directly change the state. */
    1235             : void
    1236           4 : sr_state_set_fresh_srv(void)
    1237             : {
    1238           4 :   sr_state->is_srv_fresh = 1;
    1239           4 : }
    1240             : 
    1241             : /** Unset the fresh SRV flag from our state. This doesn't need to trigger a
    1242             :  * disk state synchronization so we directly change the state. */
    1243             : void
    1244           0 : sr_state_unset_fresh_srv(void)
    1245             : {
    1246           0 :   sr_state->is_srv_fresh = 0;
    1247           0 : }
    1248             : 
    1249             : /** Return the value of the fresh SRV flag. */
    1250             : unsigned int
    1251           2 : sr_state_srv_is_fresh(void)
    1252             : {
    1253           2 :   return sr_state->is_srv_fresh;
    1254             : }
    1255             : 
    1256             : /** Cleanup and free our disk and memory state. */
    1257             : void
    1258           5 : sr_state_free_all(void)
    1259             : {
    1260           5 :   state_free(sr_state);
    1261           5 :   disk_state_free(sr_disk_state);
    1262             :   /* Nullify our global state. */
    1263           5 :   sr_state = NULL;
    1264           5 :   sr_disk_state = NULL;
    1265           5 :   config_mgr_free(shared_random_state_mgr);
    1266           5 : }
    1267             : 
    1268             : /** Save our current state in memory to disk. */
    1269             : void
    1270           0 : sr_state_save(void)
    1271             : {
    1272             :   /* Query a SAVE action on our current state so it's synced and saved. */
    1273           0 :   state_query(SR_STATE_ACTION_SAVE, 0, NULL, NULL);
    1274           0 : }
    1275             : 
    1276             : /** Return 1 iff the state has been initialized that is it exists in memory.
    1277             :  * Return 0 otherwise. */
    1278             : int
    1279          17 : sr_state_is_initialized(void)
    1280             : {
    1281          17 :   return sr_state == NULL ? 0 : 1;
    1282             : }
    1283             : 
    1284             : /** Initialize the disk and memory state.
    1285             :  *
    1286             :  * If save_to_disk is set to 1, the state is immediately saved to disk after
    1287             :  * creation else it's not thus only kept in memory.
    1288             :  * If read_from_disk is set to 1, we try to load the state from the disk and
    1289             :  * if not found, a new state is created.
    1290             :  *
    1291             :  * Return 0 on success else a negative value on error. */
    1292             : int
    1293          17 : sr_state_init(int save_to_disk, int read_from_disk)
    1294             : {
    1295          17 :   int ret = -ENOENT;
    1296          17 :   time_t now = time(NULL);
    1297             : 
    1298             :   /* We shouldn't have those assigned. */
    1299          17 :   tor_assert(sr_disk_state == NULL);
    1300          17 :   tor_assert(sr_state == NULL);
    1301             : 
    1302             :   /* First, try to load the state from disk. */
    1303          17 :   if (read_from_disk) {
    1304           6 :     ret = disk_state_load_from_disk();
    1305             :   }
    1306             : 
    1307           6 :   if (ret < 0) {
    1308          12 :     switch (-ret) {
    1309          12 :     case EINVAL:
    1310             :       /* We have a state on disk but it contains something we couldn't parse
    1311             :        * or an invalid entry in the state file. Let's remove it since it's
    1312             :        * obviously unusable and replace it by an new fresh state below. */
    1313             :     case ENOENT:
    1314             :       {
    1315             :         /* No state on disk so allocate our states for the first time. */
    1316          12 :         sr_state_t *new_state = state_new(default_fname, now);
    1317          12 :         sr_disk_state_t *new_disk_state = disk_state_new(now);
    1318          12 :         state_set(new_state);
    1319             :         /* It's important to set our disk state pointer since the save call
    1320             :          * below uses it to synchronized it with our memory state.  */
    1321          12 :         disk_state_set(new_disk_state);
    1322             :         /* No entry, let's save our new state to disk. */
    1323          12 :         if (save_to_disk && disk_state_save_to_disk() < 0) {
    1324           0 :           goto error;
    1325             :         }
    1326             :         break;
    1327             :       }
    1328             :     default:
    1329             :       /* Big problem. Not possible. */
    1330           0 :       tor_assert(0);
    1331             :     }
    1332             :   }
    1333             :   /* We have a state in memory, let's make sure it's updated for the current
    1334             :    * and next voting round. */
    1335             :   {
    1336          17 :     time_t valid_after = dirauth_sched_get_next_valid_after_time();
    1337          17 :     sr_state_update(valid_after);
    1338             :   }
    1339          17 :   return 0;
    1340             : 
    1341           0 :  error:
    1342           0 :   return -1;
    1343             : }
    1344             : 
    1345             : #ifdef TOR_UNIT_TESTS
    1346             : 
    1347             : /** Set the current phase of the protocol. Used only by unit tests. */
    1348             : void
    1349          10 : set_sr_phase(sr_phase_t phase)
    1350             : {
    1351          10 :   if (BUG(!sr_state))
    1352           0 :     return;
    1353          10 :   sr_state->phase = phase;
    1354             : }
    1355             : 
    1356             : /** Get the SR state. Used only by unit tests */
    1357             : sr_state_t *
    1358           6 : get_sr_state(void)
    1359             : {
    1360           6 :   return sr_state;
    1361             : }
    1362             : 
    1363             : #endif /* defined(TOR_UNIT_TESTS) */

Generated by: LCOV version 1.14