Commit efa21bb9 authored by Nick Mathewson's avatar Nick Mathewson 🦀
Browse files

Implement proposal 228: cross-certification with onion keys

Routers now use TAP and ntor onion keys to sign their identity keys,
and put these signatures in their descriptors.  That allows other
parties to be confident that the onion keys are indeed controlled by
the router that generated the descriptor.
parent fe5d2477
Loading
Loading
Loading
Loading
+8 −8
Original line number Diff line number Diff line
@@ -830,7 +830,7 @@ crypto_pk_public_exponent_ok(crypto_pk_t *env)
 * Note that this may leak information about the keys through timing.
 */
int
crypto_pk_cmp_keys(crypto_pk_t *a, crypto_pk_t *b)
crypto_pk_cmp_keys(const crypto_pk_t *a, const crypto_pk_t *b)
{
  int result;
  char a_is_non_null = (a != NULL) && (a->key != NULL);
@@ -856,19 +856,19 @@ crypto_pk_cmp_keys(crypto_pk_t *a, crypto_pk_t *b)
 *  Note that this may leak information about the keys through timing.
 */
int
crypto_pk_eq_keys(crypto_pk_t *a, crypto_pk_t *b)
crypto_pk_eq_keys(const crypto_pk_t *a, const crypto_pk_t *b)
{
  return (crypto_pk_cmp_keys(a, b) == 0);
}

/** Return the size of the public key modulus in <b>env</b>, in bytes. */
size_t
crypto_pk_keysize(crypto_pk_t *env)
crypto_pk_keysize(const crypto_pk_t *env)
{
  tor_assert(env);
  tor_assert(env->key);

  return (size_t) RSA_size(env->key);
  return (size_t) RSA_size((RSA*)env->key);
}

/** Return the size of the public key modulus of <b>env</b>, in bits. */
@@ -997,7 +997,7 @@ crypto_pk_private_decrypt(crypto_pk_t *env, char *to,
 * at least the length of the modulus of <b>env</b>.
 */
int
crypto_pk_public_checksig(crypto_pk_t *env, char *to,
crypto_pk_public_checksig(const crypto_pk_t *env, char *to,
                          size_t tolen,
                          const char *from, size_t fromlen)
{
@@ -1069,7 +1069,7 @@ crypto_pk_public_checksig_digest(crypto_pk_t *env, const char *data,
 * at least the length of the modulus of <b>env</b>.
 */
int
crypto_pk_private_sign(crypto_pk_t *env, char *to, size_t tolen,
crypto_pk_private_sign(const crypto_pk_t *env, char *to, size_t tolen,
                       const char *from, size_t fromlen)
{
  int r;
@@ -1084,7 +1084,7 @@ crypto_pk_private_sign(crypto_pk_t *env, char *to, size_t tolen,

  r = RSA_private_encrypt((int)fromlen,
                          (unsigned char*)from, (unsigned char*)to,
                          env->key, RSA_PKCS1_PADDING);
                          (RSA*)env->key, RSA_PKCS1_PADDING);
  if (r<0) {
    crypto_log_errors(LOG_WARN, "generating RSA signature");
    return -1;
@@ -1298,7 +1298,7 @@ crypto_pk_get_digest(const crypto_pk_t *pk, char *digest_out)
  unsigned char *buf = NULL;
  int len;

  len = i2d_RSAPublicKey(pk->key, &buf);
  len = i2d_RSAPublicKey((RSA*)pk->key, &buf);
  if (len < 0 || buf == NULL)
    return -1;
  if (crypto_digest(digest_out, (char*)buf, len) < 0) {
+5 −5
Original line number Diff line number Diff line
@@ -147,9 +147,9 @@ int crypto_pk_write_private_key_to_filename(crypto_pk_t *env,
                                            const char *fname);

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_cmp_keys(const crypto_pk_t *a, const crypto_pk_t *b);
int crypto_pk_eq_keys(const crypto_pk_t *a, const crypto_pk_t *b);
size_t crypto_pk_keysize(const crypto_pk_t *env);
int crypto_pk_num_bits(crypto_pk_t *env);
crypto_pk_t *crypto_pk_dup_key(crypto_pk_t *orig);
crypto_pk_t *crypto_pk_copy_full(crypto_pk_t *orig);
@@ -161,11 +161,11 @@ int crypto_pk_public_encrypt(crypto_pk_t *env, char *to, size_t tolen,
int crypto_pk_private_decrypt(crypto_pk_t *env, char *to, size_t tolen,
                              const char *from, size_t fromlen,
                              int padding, int warnOnFailure);
int crypto_pk_public_checksig(crypto_pk_t *env, char *to, size_t tolen,
int crypto_pk_public_checksig(const crypto_pk_t *env, char *to, size_t tolen,
                              const char *from, size_t fromlen);
int crypto_pk_public_checksig_digest(crypto_pk_t *env, const char *data,
                               size_t datalen, const char *sig, size_t siglen);
int crypto_pk_private_sign(crypto_pk_t *env, char *to, size_t tolen,
int crypto_pk_private_sign(const crypto_pk_t *env, char *to, size_t tolen,
                           const char *from, size_t fromlen);
int crypto_pk_private_sign_digest(crypto_pk_t *env, char *to, size_t tolen,
                                  const char *from, size_t fromlen);
+5 −0
Original line number Diff line number Diff line
@@ -2023,6 +2023,9 @@ typedef struct {
  curve25519_public_key_t *onion_curve25519_pkey;
  /** Certificate for ed25519 signing key */
  struct tor_cert_st *signing_key_cert;
  /** What's the earliest expiration time on all the certs in this
   * routerinfo? */
  time_t cert_expiration_time;

  char *platform; /**< What software/operating system is this OR using? */

@@ -5043,6 +5046,8 @@ typedef enum was_router_added_t {
  /* Router descriptor was rejected because it was older than
   * OLD_ROUTER_DESC_MAX_AGE. */
  ROUTER_WAS_TOO_OLD = -7, /* note contrast with 'NOT_NEW' */
  /* DOCDOC */
  ROUTER_CERTS_EXPIRED = -8
} was_router_added_t;

/********************************* routerparse.c ************************/
+71 −1
Original line number Diff line number Diff line
@@ -2000,6 +2000,8 @@ router_rebuild_descriptor(int force)
  }
  if (! (ri->cache_info.signed_descriptor_body =
          router_dump_router_to_string(ri, get_server_identity_key(),
                                       get_onion_key(),
                                       get_current_curve25519_keypair(),
                                       get_master_signing_keypair())) ) {
    log_warn(LD_BUG, "Couldn't generate router descriptor.");
    routerinfo_free(ri);
@@ -2306,7 +2308,9 @@ get_platform_str(char *platform, size_t len)
 */
char *
router_dump_router_to_string(routerinfo_t *router,
                             crypto_pk_t *ident_key,
                             const crypto_pk_t *ident_key,
                             const crypto_pk_t *tap_key,
                             const curve25519_keypair_t *ntor_keypair,
                             const ed25519_keypair_t *signing_keypair)
{
  char *address = NULL;
@@ -2325,6 +2329,8 @@ router_dump_router_to_string(routerinfo_t *router,
  char *output = NULL;
  const int emit_ed_sigs = signing_keypair && router->signing_key_cert;
  char *ed_cert_line = NULL;
  char *rsa_tap_cc_line = NULL;
  char *ntor_cc_line = NULL;

  /* Make sure the identity key matches the one in the routerinfo. */
  if (!crypto_pk_eq_keys(ident_key, router->identity_pkey)) {
@@ -2377,6 +2383,67 @@ router_dump_router_to_string(routerinfo_t *router,
    goto err;
  }

  /* Cross-certify with RSA key */
  if (tap_key && router->signing_key_cert &&
      router->signing_key_cert->signing_key_included) {
    char buf[256];
    int tap_cc_len = 0;
    uint8_t *tap_cc =
      make_tap_onion_key_crosscert(tap_key,
                                   &router->signing_key_cert->signing_key,
                                   router->identity_pkey,
                                   &tap_cc_len);
    if (!tap_cc) {
      log_warn(LD_BUG,"make_tap_onion_key_crosscert failed!");
      goto err;
    }

    if (base64_encode(buf, sizeof(buf), (const char*)tap_cc, tap_cc_len) < 0) {
      log_warn(LD_BUG,"base64_encode(rsa_crosscert) failed!");
      tor_free(tap_cc);
      goto err;
    }
    tor_free(tap_cc);

    tor_asprintf(&rsa_tap_cc_line,
                 "onion-key-crosscert\n"
                 "-----BEGIN CROSSCERT-----\n"
                 "%s"
                 "-----END CROSSCERT-----\n", buf);
  }

  /* Cross-certify with onion keys */
  if (ntor_keypair && router->signing_key_cert &&
      router->signing_key_cert->signing_key_included) {
    int sign = 0;
    char buf[256];
    /* XXXX Base the expiration date on the actual onion key expiration time?*/
    tor_cert_t *cert =
      make_ntor_onion_key_crosscert(ntor_keypair,
                                &router->signing_key_cert->signing_key,
                                router->cache_info.published_on,
                                MIN_ONION_KEY_LIFETIME, &sign);
    if (!cert) {
      log_warn(LD_BUG,"make_ntor_onion_key_crosscert failed!");
      goto err;
    }
    tor_assert(sign == 0 || sign == 1);

    if (base64_encode(buf, sizeof(buf),
                      (const char*)cert->encoded, cert->encoded_len)<0) {
      log_warn(LD_BUG,"base64_encode(ntor_crosscert) failed!");
      tor_cert_free(cert);
      goto err;
    }
    tor_cert_free(cert);

    tor_asprintf(&ntor_cc_line,
                 "ntor-onion-key-crosscert %d\n"
                 "-----BEGIN ED25519 CERT-----\n"
                 "%s"
                 "-----END ED25519 CERT-----\n", sign, buf);
  }

  /* Encode the publication time. */
  format_iso_time(published, router->cache_info.published_on);

@@ -2426,6 +2493,7 @@ router_dump_router_to_string(routerinfo_t *router,
                    "%s%s%s%s"
                    "onion-key\n%s"
                    "signing-key\n%s"
                    "%s%s"
                    "%s%s%s%s",
    router->nickname,
    address,
@@ -2446,6 +2514,8 @@ router_dump_router_to_string(routerinfo_t *router,
    (options->DownloadExtraInfo || options->V3AuthoritativeDir) ?
                         "caches-extra-info\n" : "",
    onion_pkey, identity_pkey,
    rsa_tap_cc_line ? rsa_tap_cc_line : "",
    ntor_cc_line ? ntor_cc_line : "",
    family_line,
    we_are_hibernating() ? "hibernating 1\n" : "",
    options->HidServDirectoryV2 ? "hidden-service-dir\n" : "",
+3 −1
Original line number Diff line number Diff line
@@ -91,7 +91,9 @@ int router_is_me(const routerinfo_t *router);
int router_pick_published_address(const or_options_t *options, uint32_t *addr);
int router_rebuild_descriptor(int force);
char *router_dump_router_to_string(routerinfo_t *router,
                                   crypto_pk_t *ident_key,
                                   const crypto_pk_t *ident_key,
                                   const crypto_pk_t *tap_key,
                                   const curve25519_keypair_t *ntor_keypair,
                                   const ed25519_keypair_t *signing_keypair);
char *router_dump_exit_policy_to_string(const routerinfo_t *router,
                                         int include_ipv4,
Loading