From 2e0713222b3c0049d930aff52c86dd646d424c83 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 4 Jun 2007 22:57:23 +0000 Subject: [PATCH] r13252@catbus: nickm | 2007-06-04 18:57:21 -0400 Code to check signatures on consensus directories. svn:r10492 --- doc/TODO | 2 +- src/or/dirvote.c | 62 ++++++++++++++++++++++++++++++++++++++++++++ src/or/or.h | 6 ++++- src/or/routerparse.c | 2 ++ 4 files changed, 70 insertions(+), 2 deletions(-) diff --git a/doc/TODO b/doc/TODO index f5130aeb09..08d6e04f16 100644 --- a/doc/TODO +++ b/doc/TODO @@ -79,7 +79,7 @@ Things we'd like to do in 0.2.0.x: o Code to generate votes o Code to generate consensus from a list of votes - Add a signature to a consensus. - - Code to check signatures on a consensus + o Code to check signatures on a consensus - Push/pull documents as appropriate. o Have clients know which authorities are v3 authorities, and what their keys are. diff --git a/src/or/dirvote.c b/src/or/dirvote.c index ea6e8b1f04..bfdafbd512 100644 --- a/src/or/dirvote.c +++ b/src/or/dirvote.c @@ -293,6 +293,7 @@ networkstatus_compute_consensus(smartlist_t *votes, int j; SMARTLIST_FOREACH(votes, networkstatus_vote_t *, v, { + tor_assert(v->is_vote); smartlist_add(va_times, &v->valid_after); smartlist_add(fu_times, &v->fresh_until); smartlist_add(vu_times, &v->valid_until); @@ -629,3 +630,64 @@ networkstatus_compute_consensus(smartlist_t *votes, return result; } +/** DOCDOC */ +int +networkstatus_check_consensus_signature(networkstatus_vote_t *consensus) +{ + int n_good = 0; + int n_missing_key = 0; + int n_bad = 0; + int n_unknown = 0; + + tor_assert(! consensus->is_vote); + + SMARTLIST_FOREACH(consensus->voters, networkstatus_voter_info_t *, voter, + { + trusted_dir_server_t *ds = + trusteddirserver_get_by_v3_auth_digest(voter->identity_digest); + if (!ds) { + ++n_unknown; + continue; + } + if (voter->pending_signature) { + char d[DIGEST_LEN]; + char *signed_digest; + size_t signed_digest_len; + tor_assert(!voter->good_signature && !voter->bad_signature); + if (!ds->v3_cert) { + ++n_missing_key; + continue; + } + /*XXXX020 check return*/ + crypto_pk_get_digest(ds->v3_cert->signing_key, d); + if (memcmp(voter->signing_key_digest, d, DIGEST_LEN)) { + ++n_missing_key; + continue; + } + signed_digest_len = crypto_pk_keysize(ds->v3_cert->signing_key); + signed_digest = tor_malloc(signed_digest_len); + if (crypto_pk_public_checksig(ds->v3_cert->signing_key, + signed_digest, + voter->pending_signature, + voter->pending_signature_len) != DIGEST_LEN || + memcmp(signed_digest, consensus->networkstatus_digest, DIGEST_LEN)) { + log_warn(LD_DIR, "Got a bad signature."); /*XXXX020 say more*/ + voter->bad_signature = 1; + } else { + voter->good_signature = 1; + } + tor_free(voter->pending_signature); + } + if (voter->good_signature) + ++n_good; + else if (voter->bad_signature) + ++n_bad; + else + tor_assert(0); + }); + + /* XXXX020 actually use the result. */ + + return 0; +} + diff --git a/src/or/or.h b/src/or/or.h index cfb6fb7d21..304352be43 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -1314,7 +1314,8 @@ typedef struct networkstatus_voter_info_t { char *pending_signature; int pending_signature_len; - int bad_signature; + unsigned int bad_signature : 1; + unsigned int good_signature : 1; } networkstatus_voter_info_t; /*XXXX020 rename to networkstatus_t once it works. */ @@ -1336,6 +1337,8 @@ typedef struct networkstatus_vote_t { struct authority_cert_t *cert; /* vote only. */ + char networkstatus_digest[DIGEST_LEN]; + smartlist_t *routerstatus_list; /* holds vote_routerstatus_t if is_vote, * otherwise just routerstatus_t. */ } networkstatus_vote_t; @@ -2732,6 +2735,7 @@ char *networkstatus_compute_consensus(smartlist_t *votes, networkstatus_voter_info_t *networkstatus_get_voter_by_id( networkstatus_vote_t *vote, const char *identity); +int networkstatus_check_consensus_signature(networkstatus_vote_t *consensus); /********************************* dns.c ***************************/ diff --git a/src/or/routerparse.c b/src/or/routerparse.c index 2eee814d2e..47015e531d 100644 --- a/src/or/routerparse.c +++ b/src/or/routerparse.c @@ -1801,6 +1801,7 @@ networkstatus_parse_vote_from_string(const char *s, int is_vote) } ns = tor_malloc_zero(sizeof(networkstatus_vote_t)); + memcpy(ns->networkstatus_digest, ns_digest, DIGEST_LEN); if (is_vote) { const char *end_of_cert = NULL; @@ -2036,6 +2037,7 @@ networkstatus_parse_vote_from_string(const char *s, int is_vote) if (check_signature_token(ns_digest, tok, ns->cert->signing_key, 0, "network-status vote")) goto err; + v->good_signature = 1; } else { v->pending_signature = tor_memdup(tok->object_body, tok->object_size);