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.c
6 : *
7 : * \brief Functions and data structure needed to accomplish the shared
8 : * random protocol as defined in proposal #250.
9 : *
10 : * \details
11 : *
12 : * This file implements the dirauth-only commit-and-reveal protocol specified
13 : * by proposal #250. The protocol has two phases (sr_phase_t): the commitment
14 : * phase and the reveal phase (see get_sr_protocol_phase()).
15 : *
16 : * During the protocol, directory authorities keep state in memory (using
17 : * sr_state_t) and in disk (using sr_disk_state_t). The synchronization between
18 : * these two data structures happens in disk_state_update() and
19 : * disk_state_parse().
20 : *
21 : * Here is a rough protocol outline:
22 : *
23 : * 1) In the beginning of the commitment phase, dirauths generate a
24 : * commitment/reveal value for the current protocol run (see
25 : * new_protocol_run() and sr_generate_our_commit()).
26 : *
27 : * 2) During voting, dirauths publish their commits in their votes
28 : * depending on the current phase. Dirauths also include the two
29 : * latest shared random values (SRV) in their votes.
30 : * (see sr_get_string_for_vote())
31 : *
32 : * 3) Upon receiving a commit from a vote, authorities parse it, verify
33 : * it, and attempt to save any new commitment or reveal information in
34 : * their state file (see extract_shared_random_commits() and
35 : * sr_handle_received_commits()). They also parse SRVs from votes to
36 : * decide which SRV should be included in the final consensus (see
37 : * extract_shared_random_srvs()).
38 : *
39 : * 3) After voting is done, we count the SRVs we extracted from the votes,
40 : * to find the one voted by the majority of dirauths which should be
41 : * included in the final consensus (see get_majority_srv_from_votes()).
42 : * If an appropriate SRV is found, it is embedded in the consensus (see
43 : * sr_get_string_for_consensus()).
44 : *
45 : * 4) At the end of the reveal phase, dirauths compute a fresh SRV for the
46 : * day using the active commits (see sr_compute_srv()). This new SRV
47 : * is embedded in the votes as described above.
48 : *
49 : * Some more notes:
50 : *
51 : * - To support rebooting authorities and to avoid double voting, each dirauth
52 : * saves the current state of the protocol on disk so that it can resume
53 : * normally in case of reboot. The disk state (sr_disk_state_t) is managed by
54 : * shared_random_state.c:state_query() and we go to extra lengths to ensure
55 : * that the state is flushed on disk every time we receive any useful
56 : * information like commits or SRVs.
57 : *
58 : * - When we receive a commit from a vote, we examine it to see if it's useful
59 : * to us and whether it's appropriate to receive it according to the current
60 : * phase of the protocol (see should_keep_commit()). If the commit is useful
61 : * to us, we save it in our disk state using save_commit_to_state(). When we
62 : * receive the reveal information corresponding to a commitment, we verify
63 : * that they indeed match using verify_commit_and_reveal().
64 : *
65 : * - We treat consensuses as the ground truth, so every time we generate a new
66 : * consensus we update our SR state accordingly even if our local view was
67 : * different (see sr_act_post_consensus()).
68 : *
69 : * - After a consensus has been composed, the SR protocol state gets prepared
70 : * for the next voting session using sr_state_update(). That function takes
71 : * care of housekeeping and also rotates the SRVs and commits in case a new
72 : * protocol run is coming up. We also call sr_state_update() on bootup (in
73 : * sr_state_init()), to prepare the state for the very first voting session.
74 : *
75 : * Terminology:
76 : *
77 : * - "Commitment" is the commitment value of the commit-and-reveal protocol.
78 : *
79 : * - "Reveal" is the reveal value of the commit-and-reveal protocol.
80 : *
81 : * - "Commit" is a struct (sr_commit_t) that contains a commitment value and
82 : * optionally also a corresponding reveal value.
83 : *
84 : * - "SRV" is the Shared Random Value that gets generated as the result of the
85 : * commit-and-reveal protocol.
86 : **/
87 :
88 : #define SHARED_RANDOM_PRIVATE
89 :
90 : #include "core/or/or.h"
91 : #include "feature/dirauth/shared_random.h"
92 : #include "app/config/config.h"
93 : #include "lib/confmgt/confmgt.h"
94 : #include "lib/crypt_ops/crypto_rand.h"
95 : #include "lib/crypt_ops/crypto_util.h"
96 : #include "feature/nodelist/networkstatus.h"
97 : #include "feature/relay/router.h"
98 : #include "feature/relay/routerkeys.h"
99 : #include "feature/nodelist/dirlist.h"
100 : #include "feature/hs_common/shared_random_client.h"
101 : #include "feature/dirauth/shared_random_state.h"
102 : #include "feature/dirauth/voting_schedule.h"
103 :
104 : #include "feature/dirauth/dirvote.h"
105 : #include "feature/dirauth/authmode.h"
106 : #include "feature/dirauth/dirauth_sys.h"
107 :
108 : #include "feature/dirauth/dirauth_options_st.h"
109 : #include "feature/nodelist/authority_cert_st.h"
110 : #include "feature/nodelist/networkstatus_st.h"
111 :
112 : /** String prefix of shared random values in votes/consensuses. */
113 : static const char previous_srv_str[] = "shared-rand-previous-value";
114 : static const char current_srv_str[] = "shared-rand-current-value";
115 : static const char commit_ns_str[] = "shared-rand-commit";
116 : static const char sr_flag_ns_str[] = "shared-rand-participate";
117 :
118 : /** The value of the consensus param AuthDirNumSRVAgreements found in the
119 : * vote. This is set once the consensus creation subsystem requests the
120 : * SRV(s) that should be put in the consensus. We use this value to decide
121 : * if we keep or not an SRV. */
122 : static int32_t num_srv_agreements_from_vote;
123 :
124 : /** Return a heap allocated copy of the SRV <b>orig</b>. */
125 : sr_srv_t *
126 8 : sr_srv_dup(const sr_srv_t *orig)
127 : {
128 8 : sr_srv_t *duplicate = NULL;
129 :
130 8 : if (!orig) {
131 : return NULL;
132 : }
133 :
134 7 : duplicate = tor_malloc_zero(sizeof(sr_srv_t));
135 7 : duplicate->num_reveals = orig->num_reveals;
136 7 : memcpy(duplicate->value, orig->value, sizeof(duplicate->value));
137 7 : return duplicate;
138 : }
139 :
140 : /** Allocate a new commit object and initializing it with <b>rsa_identity</b>
141 : * that MUST be provided. The digest algorithm is set to the default one
142 : * that is supported. The rest is uninitialized. This never returns NULL. */
143 : static sr_commit_t *
144 1889 : commit_new(const char *rsa_identity)
145 : {
146 1889 : sr_commit_t *commit;
147 :
148 1889 : tor_assert(rsa_identity);
149 :
150 1889 : commit = tor_malloc_zero(sizeof(*commit));
151 1889 : commit->alg = SR_DIGEST_ALG;
152 1889 : memcpy(commit->rsa_identity, rsa_identity, sizeof(commit->rsa_identity));
153 1889 : base16_encode(commit->rsa_identity_hex, sizeof(commit->rsa_identity_hex),
154 : commit->rsa_identity, sizeof(commit->rsa_identity));
155 1889 : return commit;
156 : }
157 :
158 : /** Issue a log message describing <b>commit</b>. */
159 : static void
160 25 : commit_log(const sr_commit_t *commit)
161 : {
162 25 : tor_assert(commit);
163 :
164 25 : log_debug(LD_DIR, "SR: Commit from %s", sr_commit_get_rsa_fpr(commit));
165 25 : log_debug(LD_DIR, "SR: Commit: [TS: %" PRIu64 "] [Encoded: %s]",
166 : commit->commit_ts, commit->encoded_commit);
167 25 : log_debug(LD_DIR, "SR: Reveal: [TS: %" PRIu64 "] [Encoded: %s]",
168 : commit->reveal_ts, safe_str(commit->encoded_reveal));
169 25 : }
170 :
171 : /** Make sure that the commitment and reveal information in <b>commit</b>
172 : * match. If they match return 0, return -1 otherwise. This function MUST be
173 : * used every time we receive a new reveal value. Furthermore, the commit
174 : * object MUST have a reveal value and the hash of the reveal value. */
175 : STATIC int
176 7 : verify_commit_and_reveal(const sr_commit_t *commit)
177 : {
178 7 : tor_assert(commit);
179 :
180 7 : log_debug(LD_DIR, "SR: Validating commit from authority %s",
181 : sr_commit_get_rsa_fpr(commit));
182 :
183 : /* Check that the timestamps match. */
184 7 : if (commit->commit_ts != commit->reveal_ts) {
185 1 : log_warn(LD_BUG, "SR: Commit timestamp %" PRIu64 " doesn't match reveal "
186 : "timestamp %" PRIu64, commit->commit_ts,
187 : commit->reveal_ts);
188 1 : goto invalid;
189 : }
190 :
191 : /* Verify that the hashed_reveal received in the COMMIT message, matches
192 : * the reveal we just received. */
193 : {
194 : /* We first hash the reveal we just received. */
195 6 : char received_hashed_reveal[sizeof(commit->hashed_reveal)];
196 :
197 : /* Only sha3-256 is supported. */
198 6 : if (commit->alg != SR_DIGEST_ALG) {
199 2 : goto invalid;
200 : }
201 :
202 : /* Use the invariant length since the encoded reveal variable has an
203 : * extra byte for the NUL terminated byte. */
204 6 : if (crypto_digest256(received_hashed_reveal, commit->encoded_reveal,
205 : SR_REVEAL_BASE64_LEN, commit->alg) < 0) {
206 : /* Unable to digest the reveal blob, this is unlikely. */
207 0 : goto invalid;
208 : }
209 :
210 : /* Now compare that with the hashed_reveal we received in COMMIT. */
211 6 : if (fast_memneq(received_hashed_reveal, commit->hashed_reveal,
212 : sizeof(received_hashed_reveal))) {
213 2 : log_warn(LD_BUG, "SR: Received reveal value from authority %s "
214 : "doesn't match the commit value.",
215 : sr_commit_get_rsa_fpr(commit));
216 2 : goto invalid;
217 : }
218 : }
219 :
220 4 : return 0;
221 : invalid:
222 : return -1;
223 : }
224 :
225 : /** Return true iff the commit contains an encoded reveal value. */
226 : STATIC int
227 16 : commit_has_reveal_value(const sr_commit_t *commit)
228 : {
229 16 : return !fast_mem_is_zero(commit->encoded_reveal,
230 : sizeof(commit->encoded_reveal));
231 : }
232 :
233 : /** Parse the encoded commit. The format is:
234 : * base64-encode( TIMESTAMP || H(REVEAL) )
235 : *
236 : * If successfully decoded and parsed, commit is updated and 0 is returned.
237 : * On error, return -1. */
238 : STATIC int
239 1866 : commit_decode(const char *encoded, sr_commit_t *commit)
240 : {
241 1866 : int decoded_len = 0;
242 1866 : size_t offset = 0;
243 1866 : char b64_decoded[SR_COMMIT_LEN];
244 :
245 1866 : tor_assert(encoded);
246 1866 : tor_assert(commit);
247 :
248 1866 : if (strlen(encoded) > SR_COMMIT_BASE64_LEN) {
249 : /* This means that if we base64 decode successfully the reveiced commit,
250 : * we'll end up with a bigger decoded commit thus unusable. */
251 124 : goto error;
252 : }
253 :
254 : /* Decode our encoded commit. Let's be careful here since _encoded_ is
255 : * coming from the network in a dirauth vote so we expect nothing more
256 : * than the base64 encoded length of a commit. */
257 1742 : decoded_len = base64_decode(b64_decoded, sizeof(b64_decoded),
258 : encoded, strlen(encoded));
259 1742 : if (decoded_len < 0) {
260 569 : log_warn(LD_BUG, "SR: Commit from authority %s can't be decoded.",
261 : sr_commit_get_rsa_fpr(commit));
262 569 : goto error;
263 : }
264 :
265 1173 : if (decoded_len != SR_COMMIT_LEN) {
266 236 : log_warn(LD_BUG, "SR: Commit from authority %s decoded length doesn't "
267 : "match the expected length (%d vs %u).",
268 : sr_commit_get_rsa_fpr(commit), decoded_len,
269 : (unsigned)SR_COMMIT_LEN);
270 236 : goto error;
271 : }
272 :
273 : /* First is the timestamp (8 bytes). */
274 937 : commit->commit_ts = tor_ntohll(get_uint64(b64_decoded));
275 937 : offset += sizeof(uint64_t);
276 : /* Next is hashed reveal. */
277 937 : memcpy(commit->hashed_reveal, b64_decoded + offset,
278 : sizeof(commit->hashed_reveal));
279 : /* Copy the base64 blob to the commit. Useful for voting. */
280 937 : strlcpy(commit->encoded_commit, encoded, sizeof(commit->encoded_commit));
281 :
282 937 : return 0;
283 :
284 : error:
285 : return -1;
286 : }
287 :
288 : /** Parse the b64 blob at <b>encoded</b> containing reveal information and
289 : * store the information in-place in <b>commit</b>. Return 0 on success else
290 : * a negative value. */
291 : STATIC int
292 640 : reveal_decode(const char *encoded, sr_commit_t *commit)
293 : {
294 640 : int decoded_len = 0;
295 640 : char b64_decoded[SR_REVEAL_LEN];
296 :
297 640 : tor_assert(encoded);
298 640 : tor_assert(commit);
299 :
300 640 : if (strlen(encoded) > SR_REVEAL_BASE64_LEN) {
301 : /* This means that if we base64 decode successfully the received reveal
302 : * value, we'll end up with a bigger decoded value thus unusable. */
303 22 : goto error;
304 : }
305 :
306 : /* Decode our encoded reveal. Let's be careful here since _encoded_ is
307 : * coming from the network in a dirauth vote so we expect nothing more
308 : * than the base64 encoded length of our reveal. */
309 618 : decoded_len = base64_decode(b64_decoded, sizeof(b64_decoded),
310 : encoded, strlen(encoded));
311 618 : if (decoded_len < 0) {
312 224 : log_warn(LD_BUG, "SR: Reveal from authority %s can't be decoded.",
313 : sr_commit_get_rsa_fpr(commit));
314 224 : goto error;
315 : }
316 :
317 394 : if (decoded_len != SR_REVEAL_LEN) {
318 193 : log_warn(LD_BUG, "SR: Reveal from authority %s decoded length is "
319 : "doesn't match the expected length (%d vs %u)",
320 : sr_commit_get_rsa_fpr(commit), decoded_len,
321 : (unsigned)SR_REVEAL_LEN);
322 193 : goto error;
323 : }
324 :
325 201 : commit->reveal_ts = tor_ntohll(get_uint64(b64_decoded));
326 : /* Copy the last part, the random value. */
327 201 : memcpy(commit->random_number, b64_decoded + 8,
328 : sizeof(commit->random_number));
329 : /* Also copy the whole message to use during verification */
330 201 : strlcpy(commit->encoded_reveal, encoded, sizeof(commit->encoded_reveal));
331 :
332 201 : return 0;
333 :
334 : error:
335 : return -1;
336 : }
337 :
338 : /** Encode a reveal element using a given commit object to dst which is a
339 : * buffer large enough to put the base64-encoded reveal construction. The
340 : * format is as follow:
341 : * REVEAL = base64-encode( TIMESTAMP || H(RN) )
342 : * Return base64 encoded length on success else a negative value.
343 : */
344 : STATIC int
345 26 : reveal_encode(const sr_commit_t *commit, char *dst, size_t len)
346 : {
347 26 : int ret;
348 26 : size_t offset = 0;
349 26 : char buf[SR_REVEAL_LEN] = {0};
350 :
351 26 : tor_assert(commit);
352 26 : tor_assert(dst);
353 :
354 26 : set_uint64(buf, tor_htonll(commit->reveal_ts));
355 26 : offset += sizeof(uint64_t);
356 26 : memcpy(buf + offset, commit->random_number,
357 : sizeof(commit->random_number));
358 :
359 : /* Let's clean the buffer and then b64 encode it. */
360 26 : memset(dst, 0, len);
361 26 : ret = base64_encode(dst, len, buf, sizeof(buf), 0);
362 : /* Wipe this buffer because it contains our random value. */
363 26 : memwipe(buf, 0, sizeof(buf));
364 26 : return ret;
365 : }
366 :
367 : /** Encode the given commit object to dst which is a buffer large enough to
368 : * put the base64-encoded commit. The format is as follow:
369 : * COMMIT = base64-encode( TIMESTAMP || H(H(RN)) )
370 : * Return base64 encoded length on success else a negative value.
371 : */
372 : STATIC int
373 26 : commit_encode(const sr_commit_t *commit, char *dst, size_t len)
374 : {
375 26 : size_t offset = 0;
376 26 : char buf[SR_COMMIT_LEN] = {0};
377 :
378 26 : tor_assert(commit);
379 26 : tor_assert(dst);
380 :
381 : /* First is the timestamp (8 bytes). */
382 26 : set_uint64(buf, tor_htonll(commit->commit_ts));
383 26 : offset += sizeof(uint64_t);
384 : /* and then the hashed reveal. */
385 26 : memcpy(buf + offset, commit->hashed_reveal,
386 : sizeof(commit->hashed_reveal));
387 :
388 : /* Clean the buffer and then b64 encode it. */
389 26 : memset(dst, 0, len);
390 26 : return base64_encode(dst, len, buf, sizeof(buf), 0);
391 : }
392 :
393 : /** Cleanup both our global state and disk state. */
394 : static void
395 0 : sr_cleanup(void)
396 : {
397 0 : sr_state_free_all();
398 0 : }
399 :
400 : /** Using <b>commit</b>, return a newly allocated string containing the commit
401 : * information that should be used during SRV calculation. It's the caller
402 : * responsibility to free the memory. Return NULL if this is not a commit to be
403 : * used for SRV calculation. */
404 : static char *
405 4 : get_srv_element_from_commit(const sr_commit_t *commit)
406 : {
407 4 : char *element;
408 4 : tor_assert(commit);
409 :
410 4 : if (!commit_has_reveal_value(commit)) {
411 : return NULL;
412 : }
413 :
414 3 : tor_asprintf(&element, "%s%s", sr_commit_get_rsa_fpr(commit),
415 3 : commit->encoded_reveal);
416 3 : return element;
417 : }
418 :
419 : /** Return a srv object that is built with the construction:
420 : * SRV = SHA3-256("shared-random" | INT_8(reveal_num) |
421 : * INT_4(version) | HASHED_REVEALS | previous_SRV)
422 : * This function cannot fail. */
423 : static sr_srv_t *
424 3 : generate_srv(const char *hashed_reveals, uint64_t reveal_num,
425 : const sr_srv_t *previous_srv)
426 : {
427 3 : char msg[DIGEST256_LEN + SR_SRV_MSG_LEN] = {0};
428 3 : size_t offset = 0;
429 3 : sr_srv_t *srv;
430 :
431 3 : tor_assert(hashed_reveals);
432 :
433 : /* Add the invariant token. */
434 3 : memcpy(msg, SR_SRV_TOKEN, SR_SRV_TOKEN_LEN);
435 3 : offset += SR_SRV_TOKEN_LEN;
436 3 : set_uint64(msg + offset, tor_htonll(reveal_num));
437 3 : offset += sizeof(uint64_t);
438 3 : set_uint32(msg + offset, htonl(SR_PROTO_VERSION));
439 3 : offset += sizeof(uint32_t);
440 3 : memcpy(msg + offset, hashed_reveals, DIGEST256_LEN);
441 3 : offset += DIGEST256_LEN;
442 3 : if (previous_srv != NULL) {
443 2 : memcpy(msg + offset, previous_srv->value, sizeof(previous_srv->value));
444 : }
445 :
446 : /* Ok we have our message and key for the HMAC computation, allocate our
447 : * srv object and do the last step. */
448 3 : srv = tor_malloc_zero(sizeof(*srv));
449 3 : crypto_digest256((char *) srv->value, msg, sizeof(msg), SR_DIGEST_ALG);
450 3 : srv->num_reveals = reveal_num;
451 :
452 : {
453 : /* Debugging. */
454 3 : char srv_hash_encoded[SR_SRV_VALUE_BASE64_LEN + 1];
455 3 : sr_srv_encode(srv_hash_encoded, sizeof(srv_hash_encoded), srv);
456 3 : log_info(LD_DIR, "SR: Generated SRV: %s", srv_hash_encoded);
457 : }
458 3 : return srv;
459 : }
460 :
461 : /** Compare reveal values and return the result. This should exclusively be
462 : * used by smartlist_sort(). */
463 : static int
464 5 : compare_reveal_(const void **_a, const void **_b)
465 : {
466 5 : const sr_commit_t *a = *_a, *b = *_b;
467 5 : return fast_memcmp(a->hashed_reveal, b->hashed_reveal,
468 : sizeof(a->hashed_reveal));
469 : }
470 :
471 : /** Given <b>commit</b> give the line that we should place in our votes.
472 : * It's the responsibility of the caller to free the string. */
473 : static char *
474 28 : get_vote_line_from_commit(const sr_commit_t *commit, sr_phase_t phase)
475 : {
476 28 : char *vote_line = NULL;
477 :
478 28 : switch (phase) {
479 27 : case SR_PHASE_COMMIT:
480 54 : tor_asprintf(&vote_line, "%s %u %s %s %s\n",
481 : commit_ns_str,
482 : SR_PROTO_VERSION,
483 27 : crypto_digest_algorithm_get_name(commit->alg),
484 : sr_commit_get_rsa_fpr(commit),
485 27 : commit->encoded_commit);
486 27 : break;
487 1 : case SR_PHASE_REVEAL:
488 : {
489 : /* Send a reveal value for this commit if we have one. */
490 1 : const char *reveal_str = commit->encoded_reveal;
491 1 : if (fast_mem_is_zero(commit->encoded_reveal,
492 : sizeof(commit->encoded_reveal))) {
493 0 : reveal_str = "";
494 : }
495 2 : tor_asprintf(&vote_line, "%s %u %s %s %s %s\n",
496 : commit_ns_str,
497 : SR_PROTO_VERSION,
498 1 : crypto_digest_algorithm_get_name(commit->alg),
499 : sr_commit_get_rsa_fpr(commit),
500 1 : commit->encoded_commit, reveal_str);
501 1 : break;
502 : }
503 : default:
504 0 : tor_assert(0);
505 : }
506 :
507 28 : log_debug(LD_DIR, "SR: Commit vote line: %s", vote_line);
508 28 : return vote_line;
509 : }
510 :
511 : /** Return a heap allocated string that contains the given <b>srv</b> string
512 : * representation formatted for a networkstatus document using the
513 : * <b>key</b> as the start of the line. This doesn't return NULL. */
514 : static char *
515 2 : srv_to_ns_string(const sr_srv_t *srv, const char *key)
516 : {
517 2 : char *srv_str;
518 2 : char srv_hash_encoded[SR_SRV_VALUE_BASE64_LEN + 1];
519 2 : tor_assert(srv);
520 2 : tor_assert(key);
521 :
522 2 : sr_srv_encode(srv_hash_encoded, sizeof(srv_hash_encoded), srv);
523 2 : tor_asprintf(&srv_str, "%s %" PRIu64 " %s\n", key,
524 2 : srv->num_reveals, srv_hash_encoded);
525 2 : log_debug(LD_DIR, "SR: Consensus SRV line: %s", srv_str);
526 2 : return srv_str;
527 : }
528 :
529 : /** Given the previous SRV and the current SRV, return a heap allocated
530 : * string with their data that could be put in a vote or a consensus. Caller
531 : * must free the returned string. Return NULL if no SRVs were provided. */
532 : static char *
533 52 : get_ns_str_from_sr_values(const sr_srv_t *prev_srv, const sr_srv_t *cur_srv)
534 : {
535 52 : smartlist_t *chunks = NULL;
536 52 : char *srv_str;
537 :
538 52 : if (!prev_srv && !cur_srv) {
539 : return NULL;
540 : }
541 :
542 1 : chunks = smartlist_new();
543 :
544 1 : if (prev_srv) {
545 1 : char *srv_line = srv_to_ns_string(prev_srv, previous_srv_str);
546 1 : smartlist_add(chunks, srv_line);
547 : }
548 :
549 1 : if (cur_srv) {
550 1 : char *srv_line = srv_to_ns_string(cur_srv, current_srv_str);
551 1 : smartlist_add(chunks, srv_line);
552 : }
553 :
554 : /* Join the line(s) here in one string to return. */
555 1 : srv_str = smartlist_join_strings(chunks, "", 0, NULL);
556 3 : SMARTLIST_FOREACH(chunks, char *, s, tor_free(s));
557 1 : smartlist_free(chunks);
558 :
559 1 : return srv_str;
560 : }
561 :
562 : /** Return 1 iff the two commits have the same commitment values. This
563 : * function does not care about reveal values. */
564 : STATIC int
565 8 : commitments_are_the_same(const sr_commit_t *commit_one,
566 : const sr_commit_t *commit_two)
567 : {
568 8 : tor_assert(commit_one);
569 8 : tor_assert(commit_two);
570 :
571 8 : if (strcmp(commit_one->encoded_commit, commit_two->encoded_commit)) {
572 2 : return 0;
573 : }
574 : return 1;
575 : }
576 :
577 : /** We just received a commit from the vote of authority with
578 : * <b>identity_digest</b>. Return 1 if this commit is authorititative that
579 : * is, it belongs to the authority that voted it. Else return 0 if not. */
580 : STATIC int
581 12 : commit_is_authoritative(const sr_commit_t *commit,
582 : const char *voter_key)
583 : {
584 12 : tor_assert(commit);
585 12 : tor_assert(voter_key);
586 :
587 12 : return fast_memeq(commit->rsa_identity, voter_key,
588 : sizeof(commit->rsa_identity));
589 : }
590 :
591 : /** Decide if the newly received <b>commit</b> should be kept depending on
592 : * the current phase and state of the protocol. The <b>voter_key</b> is the
593 : * RSA identity key fingerprint of the authority's vote from which the
594 : * commit comes from. The <b>phase</b> is the phase we should be validating
595 : * the commit for. Return 1 if the commit should be added to our state or 0
596 : * if not. */
597 : STATIC int
598 10 : should_keep_commit(const sr_commit_t *commit, const char *voter_key,
599 : sr_phase_t phase)
600 : {
601 10 : const sr_commit_t *saved_commit;
602 :
603 10 : tor_assert(commit);
604 10 : tor_assert(voter_key);
605 :
606 10 : log_debug(LD_DIR, "SR: Inspecting commit from %s (voter: %s)?",
607 : sr_commit_get_rsa_fpr(commit),
608 : hex_str(voter_key, DIGEST_LEN));
609 :
610 : /* For a commit to be considered, it needs to be authoritative (it should
611 : * be the voter's own commit). */
612 10 : if (!commit_is_authoritative(commit, voter_key)) {
613 2 : log_debug(LD_DIR, "SR: Ignoring non-authoritative commit.");
614 2 : goto ignore;
615 : }
616 :
617 : /* Let's make sure, for extra safety, that this fingerprint is known to
618 : * us. Even though this comes from a vote, doesn't hurt to be
619 : * extracareful. */
620 8 : if (trusteddirserver_get_by_v3_auth_digest(commit->rsa_identity) == NULL) {
621 0 : log_warn(LD_DIR, "SR: Fingerprint %s is not from a recognized "
622 : "authority. Discarding commit.",
623 : escaped(commit->rsa_identity));
624 0 : goto ignore;
625 : }
626 :
627 : /* Check if the authority that voted for <b>commit</b> has already posted
628 : * a commit before. */
629 8 : saved_commit = sr_state_get_commit(commit->rsa_identity);
630 :
631 8 : switch (phase) {
632 3 : case SR_PHASE_COMMIT:
633 : /* Already having a commit for an authority so ignore this one. */
634 3 : if (saved_commit) {
635 : /* Receiving known commits should happen naturally since commit phase
636 : lasts multiple rounds. However if the commitment value changes
637 : during commit phase, it might be a bug so log more loudly. */
638 1 : if (!commitments_are_the_same(commit, saved_commit)) {
639 0 : log_info(LD_DIR,
640 : "SR: Received altered commit from %s in commit phase.",
641 : sr_commit_get_rsa_fpr(commit));
642 : } else {
643 1 : log_debug(LD_DIR, "SR: Ignoring known commit during commit phase.");
644 : }
645 1 : goto ignore;
646 : }
647 :
648 : /* A commit with a reveal value during commitment phase is very wrong. */
649 2 : if (commit_has_reveal_value(commit)) {
650 1 : log_warn(LD_DIR, "SR: Commit from authority %s has a reveal value "
651 : "during COMMIT phase. (voter: %s)",
652 : sr_commit_get_rsa_fpr(commit),
653 : hex_str(voter_key, DIGEST_LEN));
654 1 : goto ignore;
655 : }
656 : break;
657 5 : case SR_PHASE_REVEAL:
658 : /* We are now in reveal phase. We keep a commit if and only if:
659 : *
660 : * - We have already seen a commit by this auth, AND
661 : * - the saved commit has the same commitment value as this one, AND
662 : * - the saved commit has no reveal information, AND
663 : * - this commit does have reveal information, AND
664 : * - the reveal & commit information are matching.
665 : *
666 : * If all the above are true, then we are interested in this new commit
667 : * for its reveal information. */
668 :
669 5 : if (!saved_commit) {
670 1 : log_debug(LD_DIR, "SR: Ignoring commit first seen in reveal phase.");
671 1 : goto ignore;
672 : }
673 :
674 4 : if (!commitments_are_the_same(commit, saved_commit)) {
675 1 : log_warn(LD_DIR, "SR: Commit from authority %s is different from "
676 : "previous commit in our state (voter: %s)",
677 : sr_commit_get_rsa_fpr(commit),
678 : hex_str(voter_key, DIGEST_LEN));
679 1 : goto ignore;
680 : }
681 :
682 3 : if (commit_has_reveal_value(saved_commit)) {
683 0 : log_debug(LD_DIR, "SR: Ignoring commit with known reveal info.");
684 0 : goto ignore;
685 : }
686 :
687 3 : if (!commit_has_reveal_value(commit)) {
688 1 : log_debug(LD_DIR, "SR: Ignoring commit without reveal value.");
689 1 : goto ignore;
690 : }
691 :
692 2 : if (verify_commit_and_reveal(commit) < 0) {
693 1 : log_warn(LD_BUG, "SR: Commit from authority %s has an invalid "
694 : "reveal value. (voter: %s)",
695 : sr_commit_get_rsa_fpr(commit),
696 : hex_str(voter_key, DIGEST_LEN));
697 1 : goto ignore;
698 : }
699 : break;
700 : default:
701 0 : tor_assert(0);
702 : }
703 :
704 : return 1;
705 :
706 : ignore:
707 : return 0;
708 : }
709 :
710 : /** We are in reveal phase and we found a valid and verified <b>commit</b> in
711 : * a vote that contains reveal values that we could use. Update the commit
712 : * we have in our state. Never call this with an unverified commit. */
713 : STATIC void
714 1 : save_commit_during_reveal_phase(const sr_commit_t *commit)
715 : {
716 1 : sr_commit_t *saved_commit;
717 :
718 1 : tor_assert(commit);
719 :
720 : /* Get the commit from our state. */
721 1 : saved_commit = sr_state_get_commit(commit->rsa_identity);
722 1 : tor_assert(saved_commit);
723 : /* Safety net. They can not be different commitments at this point. */
724 1 : int same_commits = commitments_are_the_same(commit, saved_commit);
725 1 : tor_assert(same_commits);
726 :
727 : /* Copy reveal information to our saved commit. */
728 1 : sr_state_copy_reveal_info(saved_commit, commit);
729 1 : }
730 :
731 : /** Save <b>commit</b> to our persistent state. Depending on the current
732 : * phase, different actions are taken. Steals reference of <b>commit</b>.
733 : * The commit object MUST be valid and verified before adding it to the
734 : * state. */
735 : STATIC void
736 5 : save_commit_to_state(sr_commit_t *commit)
737 : {
738 5 : sr_phase_t phase = sr_state_get_phase();
739 :
740 5 : ASSERT_COMMIT_VALID(commit);
741 :
742 5 : switch (phase) {
743 4 : case SR_PHASE_COMMIT:
744 : /* During commit phase, just save any new authoritative commit */
745 4 : sr_state_add_commit(commit);
746 4 : break;
747 1 : case SR_PHASE_REVEAL:
748 1 : save_commit_during_reveal_phase(commit);
749 1 : sr_commit_free(commit);
750 1 : break;
751 : default:
752 0 : tor_assert(0);
753 : }
754 5 : }
755 :
756 : /** Return 1 if we should we keep an SRV voted by <b>n_agreements</b> auths.
757 : * Return 0 if we should ignore it. */
758 : static int
759 3 : should_keep_srv(int n_agreements)
760 : {
761 : /* Check if the most popular SRV has reached majority. */
762 3 : int n_voters = get_n_authorities(V3_DIRINFO);
763 3 : int votes_required_for_majority = (n_voters / 2) + 1;
764 :
765 : /* We need at the very least majority to keep a value. */
766 3 : if (n_agreements < votes_required_for_majority) {
767 1 : log_notice(LD_DIR, "SR: SRV didn't reach majority [%d/%d]!",
768 : n_agreements, votes_required_for_majority);
769 1 : return 0;
770 : }
771 :
772 : /* When we just computed a new SRV, we need to have super majority in order
773 : * to keep it. */
774 2 : if (sr_state_srv_is_fresh()) {
775 : /* Check if we have super majority for this new SRV value. */
776 2 : if (n_agreements < num_srv_agreements_from_vote) {
777 1 : log_notice(LD_DIR, "SR: New SRV didn't reach agreement [%d/%d]!",
778 : n_agreements, num_srv_agreements_from_vote);
779 1 : return 0;
780 : }
781 : }
782 :
783 : return 1;
784 : }
785 :
786 : /** Helper: compare two DIGEST256_LEN digests. */
787 : static int
788 16 : compare_srvs_(const void **_a, const void **_b)
789 : {
790 16 : const sr_srv_t *a = *_a, *b = *_b;
791 16 : return tor_memcmp(a->value, b->value, sizeof(a->value));
792 : }
793 :
794 : /** Return the most frequent member of the sorted list of DIGEST256_LEN
795 : * digests in <b>sl</b> with the count of that most frequent element. */
796 : static sr_srv_t *
797 51 : smartlist_get_most_frequent_srv(const smartlist_t *sl, int *count_out)
798 : {
799 51 : return smartlist_get_most_frequent_(sl, compare_srvs_, count_out);
800 : }
801 :
802 : /** Compare two SRVs. Used in smartlist sorting. */
803 : static int
804 28 : compare_srv_(const void **_a, const void **_b)
805 : {
806 28 : const sr_srv_t *a = *_a, *b = *_b;
807 28 : return fast_memcmp(a->value, b->value,
808 : sizeof(a->value));
809 : }
810 :
811 : /** Using a list of <b>votes</b>, return the SRV object from them that has
812 : * been voted by the majority of dirauths. If <b>current</b> is set, we look
813 : * for the current SRV value else the previous one. The returned pointer is
814 : * an object located inside a vote. NULL is returned if no appropriate value
815 : * could be found. */
816 : STATIC sr_srv_t *
817 51 : get_majority_srv_from_votes(const smartlist_t *votes, int current)
818 : {
819 51 : int count = 0;
820 51 : sr_srv_t *most_frequent_srv = NULL;
821 51 : sr_srv_t *the_srv = NULL;
822 51 : smartlist_t *srv_list;
823 :
824 51 : tor_assert(votes);
825 :
826 51 : srv_list = smartlist_new();
827 :
828 : /* Walk over votes and register any SRVs found. */
829 214 : SMARTLIST_FOREACH_BEGIN(votes, networkstatus_t *, v) {
830 163 : sr_srv_t *srv_tmp = NULL;
831 :
832 163 : if (!v->sr_info.participate) {
833 : /* Ignore vote that do not participate. */
834 0 : continue;
835 : }
836 : /* Do we want previous or current SRV? */
837 163 : srv_tmp = current ? v->sr_info.current_srv : v->sr_info.previous_srv;
838 163 : if (!srv_tmp) {
839 144 : continue;
840 : }
841 :
842 19 : smartlist_add(srv_list, srv_tmp);
843 163 : } SMARTLIST_FOREACH_END(v);
844 :
845 51 : smartlist_sort(srv_list, compare_srv_);
846 51 : most_frequent_srv = smartlist_get_most_frequent_srv(srv_list, &count);
847 51 : if (!most_frequent_srv) {
848 48 : goto end;
849 : }
850 :
851 : /* Was this SRV voted by enough auths for us to keep it? */
852 3 : if (!should_keep_srv(count)) {
853 2 : goto end;
854 : }
855 :
856 : /* We found an SRV that we can use! Habemus SRV! */
857 1 : the_srv = most_frequent_srv;
858 :
859 : {
860 : /* Debugging */
861 1 : char encoded[SR_SRV_VALUE_BASE64_LEN + 1];
862 1 : sr_srv_encode(encoded, sizeof(encoded), the_srv);
863 1 : log_debug(LD_DIR, "SR: Chosen SRV by majority: %s (%d votes)", encoded,
864 : count);
865 : }
866 :
867 51 : end:
868 : /* We do not free any sr_srv_t values, we don't have the ownership. */
869 51 : smartlist_free(srv_list);
870 51 : return the_srv;
871 : }
872 :
873 : /** Free a commit object. */
874 : void
875 4702 : sr_commit_free_(sr_commit_t *commit)
876 : {
877 4702 : if (commit == NULL) {
878 : return;
879 : }
880 : /* Make sure we do not leave OUR random number in memory. */
881 1879 : memwipe(commit->random_number, 0, sizeof(commit->random_number));
882 1879 : tor_free(commit);
883 : }
884 :
885 : /** Generate the commitment/reveal value for the protocol run starting at
886 : * <b>timestamp</b>. <b>my_rsa_cert</b> is our authority RSA certificate. */
887 : sr_commit_t *
888 25 : sr_generate_our_commit(time_t timestamp, const authority_cert_t *my_rsa_cert)
889 : {
890 25 : sr_commit_t *commit = NULL;
891 25 : char digest[DIGEST_LEN];
892 :
893 25 : tor_assert(my_rsa_cert);
894 :
895 : /* Get our RSA identity fingerprint */
896 25 : if (crypto_pk_get_digest(my_rsa_cert->identity_key, digest) < 0) {
897 0 : goto error;
898 : }
899 :
900 : /* New commit with our identity key. */
901 25 : commit = commit_new(digest);
902 :
903 : /* Generate the reveal random value */
904 25 : crypto_strongest_rand(commit->random_number,
905 : sizeof(commit->random_number));
906 25 : commit->commit_ts = commit->reveal_ts = timestamp;
907 :
908 : /* Now get the base64 blob that corresponds to our reveal */
909 25 : if (reveal_encode(commit, commit->encoded_reveal,
910 : sizeof(commit->encoded_reveal)) < 0) {
911 0 : log_err(LD_DIR, "SR: Unable to encode our reveal value!");
912 0 : goto error;
913 : }
914 :
915 : /* Now let's create the commitment */
916 25 : tor_assert(commit->alg == SR_DIGEST_ALG);
917 : /* The invariant length is used here since the encoded reveal variable
918 : * has an extra byte added for the NULL terminated byte. */
919 25 : if (crypto_digest256(commit->hashed_reveal, commit->encoded_reveal,
920 : SR_REVEAL_BASE64_LEN, commit->alg) < 0) {
921 0 : goto error;
922 : }
923 :
924 : /* Now get the base64 blob that corresponds to our commit. */
925 25 : if (commit_encode(commit, commit->encoded_commit,
926 : sizeof(commit->encoded_commit)) < 0) {
927 0 : log_err(LD_DIR, "SR: Unable to encode our commit value!");
928 0 : goto error;
929 : }
930 :
931 25 : log_debug(LD_DIR, "SR: Generated our commitment:");
932 25 : commit_log(commit);
933 : /* Our commit better be valid :). */
934 25 : commit->valid = 1;
935 25 : return commit;
936 :
937 0 : error:
938 0 : sr_commit_free(commit);
939 0 : return NULL;
940 : }
941 :
942 : /** Compute the shared random value based on the active commits in our
943 : * state. */
944 : void
945 3 : sr_compute_srv(void)
946 : {
947 3 : uint64_t reveal_num = 0;
948 3 : char *reveals = NULL;
949 3 : smartlist_t *chunks, *commits;
950 3 : digestmap_t *state_commits;
951 :
952 : /* Computing a shared random value in the commit phase is very wrong. This
953 : * should only happen at the very end of the reveal phase when a new
954 : * protocol run is about to start. */
955 3 : if (BUG(sr_state_get_phase() != SR_PHASE_REVEAL))
956 0 : return;
957 3 : state_commits = sr_state_get_commits();
958 :
959 3 : commits = smartlist_new();
960 3 : chunks = smartlist_new();
961 :
962 : /* We must make a list of commit ordered by authority fingerprint in
963 : * ascending order as specified by proposal 250. */
964 8 : DIGESTMAP_FOREACH(state_commits, key, sr_commit_t *, c) {
965 : /* Extra safety net, make sure we have valid commit before using it. */
966 5 : ASSERT_COMMIT_VALID(c);
967 : /* Let's not use a commit from an authority that we don't know. It's
968 : * possible that an authority could be removed during a protocol run so
969 : * that commit value should never be used in the SRV computation. */
970 5 : if (trusteddirserver_get_by_v3_auth_digest(c->rsa_identity) == NULL) {
971 1 : log_warn(LD_DIR, "SR: Fingerprint %s is not from a recognized "
972 : "authority. Discarding commit for the SRV computation.",
973 : sr_commit_get_rsa_fpr(c));
974 1 : continue;
975 : }
976 : /* We consider this commit valid. */
977 4 : smartlist_add(commits, c);
978 3 : } DIGESTMAP_FOREACH_END;
979 3 : smartlist_sort(commits, compare_reveal_);
980 :
981 : /* Now for each commit for that sorted list in ascending order, we'll
982 : * build the element for each authority that needs to go into the srv
983 : * computation. */
984 7 : SMARTLIST_FOREACH_BEGIN(commits, const sr_commit_t *, c) {
985 4 : char *element = get_srv_element_from_commit(c);
986 4 : if (element) {
987 3 : smartlist_add(chunks, element);
988 3 : reveal_num++;
989 : }
990 4 : } SMARTLIST_FOREACH_END(c);
991 3 : smartlist_free(commits);
992 :
993 : {
994 : /* Join all reveal values into one giant string that we'll hash so we
995 : * can generated our shared random value. */
996 3 : sr_srv_t *current_srv;
997 3 : char hashed_reveals[DIGEST256_LEN];
998 3 : reveals = smartlist_join_strings(chunks, "", 0, NULL);
999 6 : SMARTLIST_FOREACH(chunks, char *, s, tor_free(s));
1000 3 : smartlist_free(chunks);
1001 3 : if (crypto_digest256(hashed_reveals, reveals, strlen(reveals),
1002 : SR_DIGEST_ALG) < 0) {
1003 0 : goto end;
1004 : }
1005 3 : current_srv = generate_srv(hashed_reveals, reveal_num,
1006 : sr_state_get_previous_srv());
1007 3 : sr_state_set_current_srv(current_srv);
1008 : /* We have a fresh SRV, flag our state. */
1009 3 : sr_state_set_fresh_srv();
1010 : }
1011 :
1012 3 : end:
1013 3 : tor_free(reveals);
1014 : }
1015 :
1016 : /** Parse a commit from a vote or from our disk state and return a newly
1017 : * allocated commit object. NULL is returned on error.
1018 : *
1019 : * The commit's data is in <b>args</b> and the order matters very much:
1020 : * version, algname, RSA fingerprint, commit value[, reveal value]
1021 : */
1022 : sr_commit_t *
1023 4687 : sr_parse_commit(const smartlist_t *args)
1024 : {
1025 4687 : uint32_t version;
1026 4687 : char *value, digest[DIGEST_LEN];
1027 4687 : digest_algorithm_t alg;
1028 4687 : const char *rsa_identity_fpr;
1029 4687 : sr_commit_t *commit = NULL;
1030 :
1031 4687 : if (smartlist_len(args) < 4) {
1032 650 : goto error;
1033 : }
1034 :
1035 : /* First is the version number of the SR protocol which indicates at which
1036 : * version that commit was created. */
1037 4037 : value = smartlist_get(args, 0);
1038 4037 : version = (uint32_t) tor_parse_ulong(value, 10, 1, UINT32_MAX, NULL, NULL);
1039 4037 : if (version > SR_PROTO_VERSION) {
1040 195 : log_info(LD_DIR, "SR: Commit version %" PRIu32 " (%s) is not supported.",
1041 : version, escaped(value));
1042 195 : goto error;
1043 : }
1044 :
1045 : /* Second is the algorithm. */
1046 3842 : value = smartlist_get(args, 1);
1047 3842 : alg = crypto_digest_algorithm_parse_name(value);
1048 3842 : if (alg != SR_DIGEST_ALG) {
1049 1440 : log_warn(LD_BUG, "SR: Commit algorithm %s is not recognized.",
1050 : escaped(value));
1051 1440 : goto error;
1052 : }
1053 :
1054 : /* Third argument is the RSA fingerprint of the auth and turn it into a
1055 : * digest value. */
1056 2402 : rsa_identity_fpr = smartlist_get(args, 2);
1057 2402 : if (base16_decode(digest, DIGEST_LEN, rsa_identity_fpr,
1058 : HEX_DIGEST_LEN) < 0) {
1059 538 : log_warn(LD_DIR, "SR: RSA fingerprint %s not decodable",
1060 : escaped(rsa_identity_fpr));
1061 538 : goto error;
1062 : }
1063 :
1064 : /* Allocate commit since we have a valid identity now. */
1065 1864 : commit = commit_new(digest);
1066 :
1067 : /* Fourth argument is the commitment value base64-encoded. */
1068 1864 : value = smartlist_get(args, 3);
1069 1864 : if (commit_decode(value, commit) < 0) {
1070 929 : goto error;
1071 : }
1072 :
1073 : /* (Optional) Fifth argument is the revealed value. */
1074 935 : if (smartlist_len(args) > 4) {
1075 638 : value = smartlist_get(args, 4);
1076 638 : if (reveal_decode(value, commit) < 0) {
1077 439 : goto error;
1078 : }
1079 : }
1080 :
1081 : return commit;
1082 :
1083 4191 : error:
1084 4191 : sr_commit_free(commit);
1085 4191 : return NULL;
1086 : }
1087 :
1088 : /** Called when we are done parsing a vote by <b>voter_key</b> that might
1089 : * contain some useful <b>commits</b>. Find if any of them should be kept
1090 : * and update our state accordingly. Once done, the list of commitments will
1091 : * be empty. */
1092 : void
1093 19 : sr_handle_received_commits(smartlist_t *commits, crypto_pk_t *voter_key)
1094 : {
1095 19 : char rsa_identity[DIGEST_LEN];
1096 :
1097 19 : tor_assert(voter_key);
1098 :
1099 : /* It's possible that the vote has _NO_ commits. */
1100 19 : if (commits == NULL) {
1101 19 : return;
1102 : }
1103 :
1104 : /* Get the RSA identity fingerprint of this voter */
1105 0 : if (crypto_pk_get_digest(voter_key, rsa_identity) < 0) {
1106 : return;
1107 : }
1108 :
1109 0 : SMARTLIST_FOREACH_BEGIN(commits, sr_commit_t *, commit) {
1110 : /* We won't need the commit in this list anymore, kept or not. */
1111 0 : SMARTLIST_DEL_CURRENT(commits, commit);
1112 : /* Check if this commit is valid and should be stored in our state. */
1113 0 : if (!should_keep_commit(commit, rsa_identity,
1114 : sr_state_get_phase())) {
1115 0 : sr_commit_free(commit);
1116 0 : continue;
1117 : }
1118 : /* Ok, we have a valid commit now that we are about to put in our state.
1119 : * so flag it valid from now on. */
1120 0 : commit->valid = 1;
1121 : /* Everything lines up: save this commit to state then! */
1122 0 : save_commit_to_state(commit);
1123 0 : } SMARTLIST_FOREACH_END(commit);
1124 : }
1125 :
1126 : /** Return a heap-allocated string containing commits that should be put in
1127 : * the votes. It's the responsibility of the caller to free the string.
1128 : * This always return a valid string, either empty or with line(s). */
1129 : char *
1130 28 : sr_get_string_for_vote(void)
1131 : {
1132 28 : char *vote_str = NULL;
1133 28 : digestmap_t *state_commits;
1134 28 : smartlist_t *chunks = smartlist_new();
1135 28 : const dirauth_options_t *options = dirauth_get_options();
1136 :
1137 : /* Are we participating in the protocol? */
1138 28 : if (!options->AuthDirSharedRandomness) {
1139 0 : goto end;
1140 : }
1141 :
1142 28 : log_debug(LD_DIR, "SR: Preparing our vote info:");
1143 :
1144 : /* First line, put in the vote the participation flag. */
1145 : {
1146 28 : char *sr_flag_line;
1147 28 : tor_asprintf(&sr_flag_line, "%s\n", sr_flag_ns_str);
1148 28 : smartlist_add(chunks, sr_flag_line);
1149 : }
1150 :
1151 : /* In our vote we include every commitment in our permanent state. */
1152 28 : state_commits = sr_state_get_commits();
1153 28 : smartlist_t *state_commit_vote_lines = smartlist_new();
1154 56 : DIGESTMAP_FOREACH(state_commits, key, const sr_commit_t *, commit) {
1155 28 : char *line = get_vote_line_from_commit(commit, sr_state_get_phase());
1156 28 : smartlist_add(state_commit_vote_lines, line);
1157 28 : } DIGESTMAP_FOREACH_END;
1158 :
1159 : /* Sort the commit strings by version (string, not numeric), algorithm,
1160 : * and fingerprint. This makes sure the commit lines in votes are in a
1161 : * recognisable, stable order. */
1162 28 : smartlist_sort_strings(state_commit_vote_lines);
1163 :
1164 : /* Now add the sorted list of commits to the vote */
1165 28 : smartlist_add_all(chunks, state_commit_vote_lines);
1166 28 : smartlist_free(state_commit_vote_lines);
1167 :
1168 : /* Add the SRV value(s) if any. */
1169 : {
1170 28 : char *srv_lines = get_ns_str_from_sr_values(sr_state_get_previous_srv(),
1171 : sr_state_get_current_srv());
1172 28 : if (srv_lines) {
1173 1 : smartlist_add(chunks, srv_lines);
1174 : }
1175 : }
1176 :
1177 27 : end:
1178 28 : vote_str = smartlist_join_strings(chunks, "", 0, NULL);
1179 85 : SMARTLIST_FOREACH(chunks, char *, s, tor_free(s));
1180 28 : smartlist_free(chunks);
1181 28 : return vote_str;
1182 : }
1183 :
1184 : /** Return a heap-allocated string that should be put in the consensus and
1185 : * contains the shared randomness values. It's the responsibility of the
1186 : * caller to free the string. NULL is returned if no SRV(s) available.
1187 : *
1188 : * This is called when a consensus (any flavor) is bring created thus it
1189 : * should NEVER change the state nor the state should be changed in between
1190 : * consensus creation.
1191 : *
1192 : * <b>num_srv_agreements</b> is taken from the votes thus the voted value
1193 : * that should be used.
1194 : * */
1195 : char *
1196 24 : sr_get_string_for_consensus(const smartlist_t *votes,
1197 : int32_t num_srv_agreements)
1198 : {
1199 24 : char *srv_str;
1200 24 : const dirauth_options_t *options = dirauth_get_options();
1201 :
1202 24 : tor_assert(votes);
1203 :
1204 : /* Not participating, avoid returning anything. */
1205 24 : if (!options->AuthDirSharedRandomness) {
1206 0 : log_info(LD_DIR, "SR: Support disabled (AuthDirSharedRandomness %d)",
1207 : options->AuthDirSharedRandomness);
1208 0 : goto end;
1209 : }
1210 :
1211 : /* Set the global value of AuthDirNumSRVAgreements found in the votes. */
1212 24 : num_srv_agreements_from_vote = num_srv_agreements;
1213 :
1214 : /* Check the votes and figure out if SRVs should be included in the final
1215 : * consensus. */
1216 24 : sr_srv_t *prev_srv = get_majority_srv_from_votes(votes, 0);
1217 24 : sr_srv_t *cur_srv = get_majority_srv_from_votes(votes, 1);
1218 24 : srv_str = get_ns_str_from_sr_values(prev_srv, cur_srv);
1219 24 : if (!srv_str) {
1220 24 : goto end;
1221 : }
1222 :
1223 : return srv_str;
1224 : end:
1225 : return NULL;
1226 : }
1227 :
1228 : /** We just computed a new <b>consensus</b>. Update our state with the SRVs
1229 : * from the consensus (might be NULL as well). Register the SRVs in our SR
1230 : * state and prepare for the upcoming protocol round. */
1231 : void
1232 17 : sr_act_post_consensus(const networkstatus_t *consensus)
1233 : {
1234 17 : const or_options_t *options = get_options();
1235 :
1236 : /* Don't act if our state hasn't been initialized. We can be called during
1237 : * boot time when loading consensus from disk which is prior to the
1238 : * initialization of the SR subsystem. We also should not be doing
1239 : * anything if we are _not_ a directory authority and if we are a bridge
1240 : * authority. */
1241 17 : if (!sr_state_is_initialized() || !authdir_mode_v3(options) ||
1242 0 : authdir_mode_bridge(options)) {
1243 17 : return;
1244 : }
1245 :
1246 : /* Set the majority voted SRVs in our state even if both are NULL. It
1247 : * doesn't matter this is what the majority has decided. Obviously, we can
1248 : * only do that if we have a consensus. */
1249 0 : if (consensus) {
1250 : /* Start by freeing the current SRVs since the SRVs we believed during
1251 : * voting do not really matter. Now that all the votes are in, we use the
1252 : * majority's opinion on which are the active SRVs. */
1253 0 : sr_state_clean_srvs();
1254 : /* Reset the fresh flag of the SRV so we know that from now on we don't
1255 : * have a new SRV to vote for. We just used the one from the consensus
1256 : * decided by the majority. */
1257 0 : sr_state_unset_fresh_srv();
1258 : /* Set the SR values from the given consensus. */
1259 0 : sr_state_set_previous_srv(sr_srv_dup(consensus->sr_info.previous_srv));
1260 0 : sr_state_set_current_srv(sr_srv_dup(consensus->sr_info.current_srv));
1261 : }
1262 :
1263 : /* Prepare our state so that it's ready for the next voting period. */
1264 0 : sr_state_update(dirauth_sched_get_next_valid_after_time());
1265 : }
1266 :
1267 : /** Initialize shared random subsystem. This MUST be called early in the boot
1268 : * process of tor. Return 0 on success else -1 on error. */
1269 : int
1270 6 : sr_init(int save_to_disk)
1271 : {
1272 6 : return sr_state_init(save_to_disk, 1);
1273 : }
1274 :
1275 : /** Save our state to disk and cleanup everything. */
1276 : void
1277 0 : sr_save_and_cleanup(void)
1278 : {
1279 0 : sr_state_save();
1280 0 : sr_cleanup();
1281 0 : }
1282 :
1283 : #ifdef TOR_UNIT_TESTS
1284 :
1285 : /** Set the global value of number of SRV agreements so the test can play
1286 : * along by calling specific functions that don't parse the votes prior for
1287 : * the AuthDirNumSRVAgreements value. */
1288 : void
1289 2 : set_num_srv_agreements(int32_t value)
1290 : {
1291 2 : num_srv_agreements_from_vote = value;
1292 2 : }
1293 :
1294 : #endif /* defined(TOR_UNIT_TESTS) */
|