New AuthDirPinKeys option to enable/disable keypinning enforcement

Implements ticket #17135.  We're going to need this one to avoid
chaos as everybody figures out how ed25519 keys work.
This commit is contained in:
Nick Mathewson 2015-09-23 11:22:26 -04:00
parent efea1e904a
commit 01733e2b15
4 changed files with 51 additions and 26 deletions

View File

@ -248,6 +248,7 @@ dirserv_router_get_status(const routerinfo_t *router, const char **msg,
int severity)
{
char d[DIGEST_LEN];
const int key_pinning = get_options()->AuthDirPinKeys;
if (crypto_pk_get_digest(router->identity_pkey, d)) {
log_warn(LD_BUG,"Error computing fingerprint");
@ -261,14 +262,16 @@ dirserv_router_get_status(const routerinfo_t *router, const char **msg,
if (KEYPIN_MISMATCH ==
keypin_check((const uint8_t*)router->cache_info.identity_digest,
router->signing_key_cert->signing_key.pubkey)) {
if (msg) {
*msg = "Ed25519 identity key or RSA identity key has changed.";
}
log_fn(severity, LD_DIR,
"Descriptor from router %s has an Ed25519 key, "
"but the <rsa,ed25519> keys don't match what they were before.",
router_describe(router));
return FP_REJECT;
if (key_pinning) {
if (msg) {
*msg = "Ed25519 identity key or RSA identity key has changed.";
}
return FP_REJECT;
}
}
} else {
/* No ed25519 key */
@ -277,13 +280,15 @@ dirserv_router_get_status(const routerinfo_t *router, const char **msg,
log_fn(severity, LD_DIR,
"Descriptor from router %s has no Ed25519 key, "
"when we previously knew an Ed25519 for it. Ignoring for now, "
"since Tor 0.2.6 is under development.",
"since Ed25519 keys are fairly new.",
router_describe(router));
#ifdef DISABLE_DISABLING_ED25519
if (msg) {
*msg = "Ed25519 identity key has disappeared.";
if (key_pinning) {
if (msg) {
*msg = "Ed25519 identity key has disappeared.";
}
return FP_REJECT;
}
return FP_REJECT;
#endif
}
}
@ -582,6 +587,7 @@ dirserv_add_descriptor(routerinfo_t *ri, const char **msg, const char *source)
char *desc, *nickname;
const size_t desclen = ri->cache_info.signed_descriptor_len +
ri->cache_info.annotations_len;
const int key_pinning = get_options()->AuthDirPinKeys;
*msg = NULL;
/* If it's too big, refuse it now. Otherwise we'll cache it all over the
@ -626,7 +632,8 @@ dirserv_add_descriptor(routerinfo_t *ri, const char **msg, const char *source)
if (ri->signing_key_cert) {
keypin_status = keypin_check_and_add(
(const uint8_t*)ri->cache_info.identity_digest,
ri->signing_key_cert->signing_key.pubkey);
ri->signing_key_cert->signing_key.pubkey,
! key_pinning);
} else {
keypin_status = keypin_check_lone_rsa(
(const uint8_t*)ri->cache_info.identity_digest);
@ -635,7 +642,7 @@ dirserv_add_descriptor(routerinfo_t *ri, const char **msg, const char *source)
keypin_status = KEYPIN_NOT_FOUND;
#endif
}
if (keypin_status == KEYPIN_MISMATCH) {
if (keypin_status == KEYPIN_MISMATCH && key_pinning) {
log_info(LD_DIRSERV, "Dropping descriptor from %s (source: %s) because "
"its key did not match an older RSA/Ed25519 keypair",
router_describe(ri), source);

View File

@ -48,7 +48,9 @@ static int keypin_journal_append_entry(const uint8_t *rsa_id_digest,
const uint8_t *ed25519_id_key);
static int keypin_check_and_add_impl(const uint8_t *rsa_id_digest,
const uint8_t *ed25519_id_key,
int do_not_add);
const int do_not_add,
const int replace);
static int keypin_add_or_replace_entry_in_map(keypin_ent_t *ent);
static HT_HEAD(rsamap, keypin_ent_st) the_rsa_map = HT_INITIALIZER();
static HT_HEAD(edmap, keypin_ent_st) the_ed_map = HT_INITIALIZER();
@ -100,12 +102,17 @@ HT_GENERATE2(edmap, keypin_ent_st, edmap_node, keypin_ent_hash_ed,
* return KEYPIN_FOUND. If we find an entry that matches one key but
* not the other, return KEYPIN_MISMATCH. If we have no entry for either
* key, add such an entry to the table and return KEYPIN_ADDED.
*
* If <b>replace_existing_entry</b> is true, then any time we would have said
* KEYPIN_FOUND, we instead add this entry anyway and return KEYPIN_ADDED.
*/
int
keypin_check_and_add(const uint8_t *rsa_id_digest,
const uint8_t *ed25519_id_key)
const uint8_t *ed25519_id_key,
const int replace_existing_entry)
{
return keypin_check_and_add_impl(rsa_id_digest, ed25519_id_key, 0);
return keypin_check_and_add_impl(rsa_id_digest, ed25519_id_key, 0,
replace_existing_entry);
}
/**
@ -116,7 +123,7 @@ int
keypin_check(const uint8_t *rsa_id_digest,
const uint8_t *ed25519_id_key)
{
return keypin_check_and_add_impl(rsa_id_digest, ed25519_id_key, 1);
return keypin_check_and_add_impl(rsa_id_digest, ed25519_id_key, 1, 0);
}
/**
@ -125,7 +132,8 @@ keypin_check(const uint8_t *rsa_id_digest,
static int
keypin_check_and_add_impl(const uint8_t *rsa_id_digest,
const uint8_t *ed25519_id_key,
int do_not_add)
const int do_not_add,
const int replace)
{
keypin_ent_t search, *ent;
memset(&search, 0, sizeof(search));
@ -139,18 +147,21 @@ keypin_check_and_add_impl(const uint8_t *rsa_id_digest,
if (tor_memeq(ent->ed25519_key, ed25519_id_key,sizeof(ent->ed25519_key))) {
return KEYPIN_FOUND; /* Match on both keys. Great. */
} else {
return KEYPIN_MISMATCH; /* Found RSA with different Ed key */
if (!replace)
return KEYPIN_MISMATCH; /* Found RSA with different Ed key */
}
}
/* See if we know a different RSA key for this ed key */
ent = HT_FIND(edmap, &the_ed_map, &search);
if (ent) {
/* If we got here, then the ed key matches and the RSA doesn't */
tor_assert(fast_memeq(ent->ed25519_key, ed25519_id_key,
sizeof(ent->ed25519_key)));
tor_assert(fast_memneq(ent->rsa_id, rsa_id_digest, sizeof(ent->rsa_id)));
return KEYPIN_MISMATCH;
if (! replace) {
ent = HT_FIND(edmap, &the_ed_map, &search);
if (ent) {
/* If we got here, then the ed key matches and the RSA doesn't */
tor_assert(fast_memeq(ent->ed25519_key, ed25519_id_key,
sizeof(ent->ed25519_key)));
tor_assert(fast_memneq(ent->rsa_id, rsa_id_digest, sizeof(ent->rsa_id)));
return KEYPIN_MISMATCH;
}
}
/* Okay, this one is new to us. */
@ -158,7 +169,12 @@ keypin_check_and_add_impl(const uint8_t *rsa_id_digest,
return KEYPIN_NOT_FOUND;
ent = tor_memdup(&search, sizeof(search));
keypin_add_entry_to_map(ent);
int r = keypin_add_or_replace_entry_in_map(ent);
if (! replace) {
tor_assert(r == 1);
} else {
tor_assert(r != 0);
}
keypin_journal_append_entry(rsa_id_digest, ed25519_id_key);
return KEYPIN_ADDED;
}

View File

@ -7,7 +7,8 @@
#include "testsupport.h"
int keypin_check_and_add(const uint8_t *rsa_id_digest,
const uint8_t *ed25519_id_key);
const uint8_t *ed25519_id_key,
const int replace_existing_entry);
int keypin_check(const uint8_t *rsa_id_digest,
const uint8_t *ed25519_id_key);

View File

@ -131,7 +131,8 @@ test_keypin_parse_file(void *arg)
smartlist_free(mock_addent_got);
}
#define ADD(a,b) keypin_check_and_add((const uint8_t*)(a),(const uint8_t*)(b))
#define ADD(a,b) keypin_check_and_add((const uint8_t*)(a),\
(const uint8_t*)(b),0)
#define LONE_RSA(a) keypin_check_lone_rsa((const uint8_t*)(a))
static void