diff --git a/src/common/crypto.c b/src/common/crypto.c index 5b5fb755b2..283b00575d 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -774,6 +774,18 @@ crypto_pk_cmp_keys(crypto_pk_t *a, crypto_pk_t *b) return BN_cmp((a->key)->e, (b->key)->e); } +/** Compare the public-key components of a and b. Return non-zero iff + * a==b. A NULL key is considered to be distinct from all non-NULL + * keys, and equal to itself. + * + * Note that this may leak information about the keys through timing. + */ +int +crypto_pk_eq_keys(crypto_pk_t *a, crypto_pk_t *b) +{ + return (crypto_pk_cmp_keys(a, b) == 0); +} + /** Return the size of the public key modulus in env, in bytes. */ size_t crypto_pk_keysize(crypto_pk_t *env) diff --git a/src/common/crypto.h b/src/common/crypto.h index 456a61173f..e8248508fc 100644 --- a/src/common/crypto.h +++ b/src/common/crypto.h @@ -148,6 +148,7 @@ int crypto_pk_write_private_key_to_filename(crypto_pk_t *env, int crypto_pk_check_key(crypto_pk_t *env); int crypto_pk_cmp_keys(crypto_pk_t *a, crypto_pk_t *b); +int crypto_pk_eq_keys(crypto_pk_t *a, crypto_pk_t *b); size_t crypto_pk_keysize(crypto_pk_t *env); int crypto_pk_num_bits(crypto_pk_t *env); crypto_pk_t *crypto_pk_dup_key(crypto_pk_t *orig); diff --git a/src/or/rendservice.c b/src/or/rendservice.c index 0bfa17d108..0fa04b63fe 100644 --- a/src/or/rendservice.c +++ b/src/or/rendservice.c @@ -2730,7 +2730,7 @@ find_intro_point(origin_circuit_t *circ) if (service == NULL) return NULL; SMARTLIST_FOREACH(service->intro_nodes, rend_intro_point_t *, intro_point, - if (crypto_pk_cmp_keys(intro_point->intro_key, circ->intro_key) == 0) { + if (crypto_pk_eq_keys(intro_point->intro_key, circ->intro_key)) { return intro_point; }); diff --git a/src/or/router.c b/src/or/router.c index 052ed38074..2e80c54680 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -87,7 +87,7 @@ static authority_cert_t *legacy_key_certificate = NULL; static void set_onion_key(crypto_pk_t *k) { - if (onionkey && !crypto_pk_cmp_keys(onionkey, k)) { + if (onionkey && crypto_pk_eq_keys(onionkey, k)) { /* k is already our onion key; free it and return */ crypto_pk_free(k); return; @@ -155,12 +155,11 @@ assert_identity_keys_ok(void) if (public_server_mode(get_options())) { /* assert that we have set the client and server keys to be equal */ tor_assert(server_identitykey); - tor_assert(0==crypto_pk_cmp_keys(client_identitykey, server_identitykey)); + tor_assert(crypto_pk_eq_keys(client_identitykey, server_identitykey)); } else { /* assert that we have set the client and server keys to be unequal */ if (server_identitykey) - tor_assert(0!=crypto_pk_cmp_keys(client_identitykey, - server_identitykey)); + tor_assert(!crypto_pk_eq_keys(client_identitykey, server_identitykey)); } } @@ -400,7 +399,7 @@ load_authority_keyset(int legacy, crypto_pk_t **key_out, log_warn(LD_DIR, "Unable to parse certificate in %s", fname); goto done; } - if (crypto_pk_cmp_keys(signing_key, parsed->signing_key) != 0) { + if (!crypto_pk_eq_keys(signing_key, parsed->signing_key)) { log_warn(LD_DIR, "Stored signing key does not match signing key in " "certificate"); goto done; @@ -2008,7 +2007,7 @@ router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router, const or_options_t *options = get_options(); /* Make sure the identity key matches the one in the routerinfo. */ - if (crypto_pk_cmp_keys(ident_key, router->identity_pkey)) { + if (!crypto_pk_eq_keys(ident_key, router->identity_pkey)) { log_warn(LD_BUG,"Tried to sign a router with a private key that didn't " "match router's public key!"); return -1; diff --git a/src/or/routerlist.c b/src/or/routerlist.c index 98357d6a38..5327622f1b 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -4529,8 +4529,8 @@ router_differences_are_cosmetic(const routerinfo_t *r1, const routerinfo_t *r2) r1->ipv6_orport != r2->ipv6_orport || r1->dir_port != r2->dir_port || r1->purpose != r2->purpose || - crypto_pk_cmp_keys(r1->onion_pkey, r2->onion_pkey) || - crypto_pk_cmp_keys(r1->identity_pkey, r2->identity_pkey) || + !crypto_pk_eq_keys(r1->onion_pkey, r2->onion_pkey) || + !crypto_pk_eq_keys(r1->identity_pkey, r2->identity_pkey) || strcasecmp(r1->platform, r2->platform) || (r1->contact_info && !r2->contact_info) || /* contact_info is optional */ (!r1->contact_info && r2->contact_info) ||