Commit 3bee74c6 authored by Nick Mathewson's avatar Nick Mathewson 🦀
Browse files

Generate weird certificates correctly

(Our link protocol assumes that the link cert certifies the TLS key,
and there is an RSA->Ed25519 crosscert)
parent 32f59d73
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -358,7 +358,7 @@ static config_var_t option_vars_[] = {
  V(TestingMinExitFlagThreshold, MEMUNIT,  "0"),
  V(TestingMinFastFlagThreshold, MEMUNIT,  "0"),

  V(TestingLinkKeyLifetime,          INTERVAL, "2 days"),
  V(TestingLinkCertLifetime,          INTERVAL, "2 days"),
  V(TestingAuthKeyLifetime,          INTERVAL, "2 days"),
  V(TestingLinkKeySlop,              INTERVAL, "3 hours"),
  V(TestingAuthKeySlop,              INTERVAL, "3 hours"),
@@ -3634,7 +3634,7 @@ options_validate(or_options_t *old_options, or_options_t *options,
  CHECK_DEFAULT(TestingMicrodescMaxDownloadTries);
  CHECK_DEFAULT(TestingCertMaxDownloadTries);
  CHECK_DEFAULT(TestingAuthKeyLifetime);
  CHECK_DEFAULT(TestingLinkKeyLifetime);
  CHECK_DEFAULT(TestingLinkCertLifetime);
  CHECK_DEFAULT(TestingSigningKeySlop);
  CHECK_DEFAULT(TestingAuthKeySlop);
  CHECK_DEFAULT(TestingLinkKeySlop);
@@ -3642,8 +3642,8 @@ options_validate(or_options_t *old_options, or_options_t *options,

  if (options->SigningKeyLifetime < options->TestingSigningKeySlop*2)
    REJECT("SigningKeyLifetime is too short.");
  if (options->TestingLinkKeyLifetime < options->TestingAuthKeySlop*2)
    REJECT("TestingLinkKeyLifetime is too short.");
  if (options->TestingLinkCertLifetime < options->TestingAuthKeySlop*2)
    REJECT("LinkCertLifetime is too short.");
  if (options->TestingAuthKeyLifetime < options->TestingLinkKeySlop*2)
    REJECT("TestingAuthKeyLifetime is too short.");

+2 −1
Original line number Diff line number Diff line
@@ -1284,7 +1284,8 @@ run_scheduled_events(time_t now)

  if (is_server && time_to_check_ed_keys < now) {
    if (should_make_new_ed_keys(options, now)) {
      if (load_ed_keys(options, now) < 0) {
      if (load_ed_keys(options, now) < 0 ||
          generate_ed_link_cert(options, now)) {
        log_err(LD_OR, "Unable to update Ed25519 keys!  Exiting.");
        tor_cleanup();
        exit(0);
+3 −1
Original line number Diff line number Diff line
@@ -1337,6 +1337,8 @@ typedef struct listener_connection_t {
 * in the v3 handshake.  The subject key must be a 1024-bit RSA key; it
 * must be signed by the identity key */
#define OR_CERT_TYPE_AUTH_1024 3
/** DOCDOC */
#define OR_CERT_TYPE_RSA_ED_CROSSCERT 7
/**@}*/

/** The one currently supported type of AUTHENTICATE cell.  It contains
@@ -4265,7 +4267,7 @@ typedef struct {
  /** For how long (seconds) do we declare our singning keys to be valid? */
  int SigningKeyLifetime;
  /** For how long (seconds) do we declare our link keys to be valid? */
  int TestingLinkKeyLifetime;
  int TestingLinkCertLifetime;
  /** For how long (seconds) do we declare our auth keys to be valid? */
  int TestingAuthKeyLifetime;

+4 −1
Original line number Diff line number Diff line
@@ -206,6 +206,8 @@ set_server_identity_key(crypto_pk_t *k)
static void
assert_identity_keys_ok(void)
{
  if (1)
    return;
  tor_assert(client_identitykey);
  if (public_server_mode(get_options())) {
    /* assert that we have set the client and server keys to be equal */
@@ -864,7 +866,8 @@ init_keys(void)
  }

  /* 1d. Load all ed25519 keys */
  if (load_ed_keys(options,now) < 0)
  if (load_ed_keys(options,now) < 0 ||
      generate_ed_link_cert(options,now))
    return -1;

  /* 2. Read onion key.  Make it if none is found. */
+88 −39
Original line number Diff line number Diff line
@@ -3,6 +3,7 @@

#include "or.h"
#include "config.h"
#include "router.h"
#include "routerkeys.h"
#include "torcert.h"

@@ -265,12 +266,14 @@ ed_key_new(const ed25519_keypair_t *signing_key,

static ed25519_keypair_t *master_identity_key = NULL;
static ed25519_keypair_t *master_signing_key = NULL;
static ed25519_keypair_t *current_link_key = NULL;
static ed25519_keypair_t *current_auth_key = NULL;
static tor_cert_t *signing_key_cert = NULL;
static tor_cert_t *link_key_cert = NULL;
static tor_cert_t *link_cert_cert = NULL;
static tor_cert_t *auth_key_cert = NULL;

static uint8_t *rsa_ed_crosscert = NULL;
static size_t rsa_ed_crosscert_len = 0;

/**
 * Running as a server: load, reload, or refresh our ed25519 keys and
 * certificates, creating and saving new ones as needed.
@@ -280,13 +283,11 @@ load_ed_keys(const or_options_t *options, time_t now)
{
  ed25519_keypair_t *id = NULL;
  ed25519_keypair_t *sign = NULL;
  ed25519_keypair_t *link = NULL;
  ed25519_keypair_t *auth = NULL;
  const ed25519_keypair_t *sign_signing_key_with_id = NULL;
  const ed25519_keypair_t *use_signing = NULL;
  const tor_cert_t *check_signing_cert = NULL;
  tor_cert_t *sign_cert = NULL;
  tor_cert_t *link_cert = NULL;
  tor_cert_t *auth_cert = NULL;

#define FAIL(msg) do {                          \
@@ -380,15 +381,14 @@ load_ed_keys(const or_options_t *options, time_t now)
   * it, if we loaded it in the first place. */
  memwipe(id->seckey.seckey, 0, sizeof(id->seckey));

  if (!current_link_key ||
      EXPIRES_SOON(link_key_cert, options->TestingLinkKeySlop)) {
    link = ed_key_new(use_signing, INIT_ED_KEY_NEEDCERT,
                      now,
                      options->TestingLinkKeyLifetime,
                      CERT_TYPE_SIGNING_LINK, &link_cert);

    if (!link)
      FAIL("Can't create link key");
  if (!rsa_ed_crosscert && server_mode(options)) {
    uint8_t *crosscert;
    ssize_t crosscert_len = tor_make_rsa_ed25519_crosscert(&id->pubkey,
                                                   get_server_identity_key(),
                                                   now+10*365*86400,/*XXXX*/
                                                   &crosscert);
    rsa_ed_crosscert_len = crosscert_len;
    rsa_ed_crosscert = crosscert;
  }

  if (!current_auth_key ||
@@ -413,40 +413,88 @@ load_ed_keys(const or_options_t *options, time_t now)
    SET_KEY(master_signing_key, sign);
    SET_CERT(signing_key_cert, sign_cert);
  }
  if (link) {
    SET_KEY(current_link_key, link);
    SET_CERT(link_key_cert, link_cert);
  }
  if (auth) {
    SET_KEY(current_auth_key, auth);
    SET_CERT(auth_key_cert, auth_cert);
  }

  if (generate_ed_link_cert(options, now) < 0)
    FAIL("Couldn't make link cert");

  return 0;
 err:
  ed25519_keypair_free(id);
  ed25519_keypair_free(sign);
  ed25519_keypair_free(link);
  ed25519_keypair_free(auth);
  tor_cert_free(sign_cert);
  tor_cert_free(link_cert);
  tor_cert_free(auth_cert);
  return -1;
}

/**DOCDOC*/
int
generate_ed_link_cert(const or_options_t *options, time_t now)
{
  const tor_x509_cert_t *link = NULL, *id = NULL;
  tor_cert_t *link_cert = NULL;

  if (tor_tls_get_my_certs(1, &link, &id) < 0 || link == NULL)
    return -1;

  const digests_t *digests = tor_x509_cert_get_cert_digests(link);

  if (link_cert_cert &&
      ! EXPIRES_SOON(link_cert_cert, options->TestingLinkKeySlop) &&
      fast_memeq(digests->d[DIGEST_SHA256], link_cert_cert->signed_key.pubkey,
                 DIGEST256_LEN)) {
    return 0;
  }

  ed25519_public_key_t dummy_key;
  memcpy(dummy_key.pubkey, digests->d[DIGEST_SHA256], DIGEST256_LEN);

  link_cert = tor_cert_create(get_master_signing_keypair(),
                              CERT_TYPE_SIGNING_LINK,
                              &dummy_key,
                              now,
                              options->TestingLinkCertLifetime, 0);

  if (link_cert) {
    SET_CERT(link_cert_cert, link_cert);
  }
  return 0;
}

#undef FAIL
#undef SET_KEY
#undef SET_CERT
}

int
should_make_new_ed_keys(const or_options_t *options, const time_t now)
{
  return (!master_identity_key ||
  if (!master_identity_key ||
      !master_signing_key ||
          !current_link_key ||
      !current_auth_key ||
      !link_cert_cert ||
      EXPIRES_SOON(signing_key_cert, options->TestingSigningKeySlop) ||
          EXPIRES_SOON(link_key_cert, options->TestingLinkKeySlop) ||
          EXPIRES_SOON(auth_key_cert, options->TestingAuthKeySlop));
      EXPIRES_SOON(auth_key_cert, options->TestingAuthKeySlop) ||
      EXPIRES_SOON(link_cert_cert, options->TestingLinkKeySlop))
    return 1;

  const tor_x509_cert_t *link = NULL, *id = NULL;

  if (tor_tls_get_my_certs(1, &link, &id) < 0 || link == NULL)
    return 1;

  const digests_t *digests = tor_x509_cert_get_cert_digests(link);

  if (!fast_memeq(digests->d[DIGEST_SHA256],
                  link_cert_cert->signed_key.pubkey,
                  DIGEST256_LEN)) {
    return 1;
  }

  return 0;
}

#undef EXPIRES_SOON
@@ -471,12 +519,6 @@ get_master_signing_key_cert(void)
  return signing_key_cert;
}

const ed25519_keypair_t *
get_current_link_keypair(void)
{
  return current_link_key;
}

const ed25519_keypair_t *
get_current_auth_keypair(void)
{
@@ -484,9 +526,9 @@ get_current_auth_keypair(void)
}

const tor_cert_t *
get_current_link_key_cert(void)
get_current_link_cert_cert(void)
{
  return link_key_cert;
  return link_cert_cert;
}

const tor_cert_t *
@@ -495,6 +537,14 @@ get_current_auth_key_cert(void)
  return auth_key_cert;
}

void
get_master_rsa_crosscert(const uint8_t **cert_out,
                         size_t *size_out)
{
  *cert_out = rsa_ed_crosscert;
  *size_out = rsa_ed_crosscert_len;
}

/** Construct cross-certification for the master identity key with
 * the ntor onion key. Store the sign of the corresponding ed25519 public key
 * in *<b>sign_out</b>. */
@@ -587,14 +637,13 @@ routerkeys_free_all(void)
{
  ed25519_keypair_free(master_identity_key);
  ed25519_keypair_free(master_signing_key);
  ed25519_keypair_free(current_link_key);
  ed25519_keypair_free(current_auth_key);
  tor_cert_free(signing_key_cert);
  tor_cert_free(link_key_cert);
  tor_cert_free(link_cert_cert);
  tor_cert_free(auth_key_cert);

  master_identity_key = master_signing_key = NULL;
  current_link_key = current_auth_key = NULL;
  signing_key_cert = link_key_cert = auth_key_cert = NULL;
  current_auth_key = NULL;
  signing_key_cert = link_cert_cert = auth_key_cert = NULL;
}
Loading