Esempio n. 1
0
static void
test_routerkeys_rsa_ed_crosscert(void *arg)
{
  (void)arg;
  ed25519_public_key_t ed;
  crypto_pk_t *rsa = pk_generate(2);

  uint8_t *cc = NULL;
  ssize_t cc_len;
  time_t expires_in = 1470846177;

  tt_int_op(0, OP_EQ, ed25519_public_from_base64(&ed,
                        "ThisStringCanContainAnythingSoNoKeyHereNowX"));
  cc_len = tor_make_rsa_ed25519_crosscert(&ed, rsa, expires_in, &cc);

  tt_int_op(cc_len, OP_GT, 0);
  tt_int_op(cc_len, OP_GT, 37); /* key, expires, siglen */
  tt_mem_op(cc, OP_EQ, ed.pubkey, 32);
  time_t expires_out = 3600 * ntohl(get_uint32(cc+32));
  tt_int_op(expires_out, OP_GE, expires_in);
  tt_int_op(expires_out, OP_LE, expires_in + 3600);

  tt_int_op(cc_len, OP_EQ, 37 + get_uint8(cc+36));

  tt_int_op(0, OP_EQ, rsa_ed25519_crosscert_check(cc, cc_len, rsa, &ed,
                                                  expires_in - 10));

  /* Now try after it has expired */
  tt_int_op(-4, OP_EQ, rsa_ed25519_crosscert_check(cc, cc_len, rsa, &ed,
                                                  expires_out + 1));

  /* Truncated object */
  tt_int_op(-2, OP_EQ, rsa_ed25519_crosscert_check(cc, cc_len - 2, rsa, &ed,
                                                  expires_in - 10));

  /* Key not as expected */
  cc[0] ^= 3;
  tt_int_op(-3, OP_EQ, rsa_ed25519_crosscert_check(cc, cc_len, rsa, &ed,
                                                  expires_in - 10));
  cc[0] ^= 3;

  /* Bad signature */
  cc[40] ^= 3;
  tt_int_op(-5, OP_EQ, rsa_ed25519_crosscert_check(cc, cc_len, rsa, &ed,
                                                   expires_in - 10));
  cc[40] ^= 3;

  /* Signature of wrong data */
  cc[0] ^= 3;
  ed.pubkey[0] ^= 3;
  tt_int_op(-6, OP_EQ, rsa_ed25519_crosscert_check(cc, cc_len, rsa, &ed,
                                                  expires_in - 10));
  cc[0] ^= 3;
  ed.pubkey[0] ^= 3;

 done:
  crypto_pk_free(rsa);
  tor_free(cc);
}
Esempio n. 2
0
/* Helper for unit tests: populate the ed25519 keys without saving or
 * loading */
void
init_mock_ed_keys(const crypto_pk_t *rsa_identity_key)
{
  routerkeys_free_all();

#define MAKEKEY(k)                                      \
  k = tor_malloc_zero(sizeof(*k));                      \
  if (ed25519_keypair_generate(k, 0) < 0) {             \
    log_warn(LD_BUG, "Couldn't make a keypair");        \
    goto err;                                           \
  }
  MAKEKEY(master_identity_key);
  MAKEKEY(master_signing_key);
  MAKEKEY(current_auth_key);
#define MAKECERT(cert, signing, signed_, type, flags)            \
  cert = tor_cert_create(signing,                                \
                         type,                                   \
                         &signed_->pubkey,                       \
                         time(NULL), 86400,                      \
                         flags);                                 \
  if (!cert) {                                                   \
    log_warn(LD_BUG, "Couldn't make a %s certificate!", #cert);  \
    goto err;                                                    \
  }

  MAKECERT(signing_key_cert,
           master_identity_key, master_signing_key, CERT_TYPE_ID_SIGNING,
           CERT_FLAG_INCLUDE_SIGNING_KEY);
  MAKECERT(auth_key_cert,
           master_signing_key, current_auth_key, CERT_TYPE_SIGNING_AUTH, 0);

  if (generate_ed_link_cert(get_options(), time(NULL), 0) < 0) {
    log_warn(LD_BUG, "Couldn't make link certificate");
    goto err;
  }

  rsa_ed_crosscert_len = tor_make_rsa_ed25519_crosscert(
                                     &master_identity_key->pubkey,
                                     rsa_identity_key,
                                     time(NULL)+86400,
                                     &rsa_ed_crosscert);

  return;

 err:
  routerkeys_free_all();
  tor_assert_nonfatal_unreached();
}
Esempio n. 3
0
/**
 * Running as a server: load, reload, or refresh our ed25519 keys and
 * certificates, creating and saving new ones as needed.
 */
int
load_ed_keys(const or_options_t *options, time_t now)
{
  ed25519_keypair_t *id = NULL;
  ed25519_keypair_t *sign = 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 *auth_cert = NULL;

#define FAIL(msg) do {                          \
    log_warn(LD_OR, (msg));                     \
    goto err;                                   \
  } while (0)
#define SET_KEY(key, newval) do {               \
    if ((key) != (newval))                      \
      ed25519_keypair_free(key);                \
    key = (newval);                             \
  } while (0)
#define SET_CERT(cert, newval) do {             \
    if ((cert) != (newval))                     \
      tor_cert_free(cert);                      \
    cert = (newval);                            \
  } while (0)
#define EXPIRES_SOON(cert, interval)            \
  (!(cert) || (cert)->valid_until < now + (interval))

  /* XXXX support encrypted identity keys fully */

  /* First try to get the signing key to see how it is. */
  {
    char *fname =
      options_get_datadir_fname2(options, "keys", "ed25519_signing");
    sign = ed_key_init_from_file(
               fname,
               INIT_ED_KEY_NEEDCERT|
               INIT_ED_KEY_INCLUDE_SIGNING_KEY_IN_CERT,
               LOG_INFO,
               NULL, 0, 0, CERT_TYPE_ID_SIGNING, &sign_cert);
    tor_free(fname);
    check_signing_cert = sign_cert;
    use_signing = sign;
  }

  if (!use_signing && master_signing_key) {
    check_signing_cert = signing_key_cert;
    use_signing = master_signing_key;
  }

  const int offline_master =
    options->OfflineMasterKey && options->command != CMD_KEYGEN;
  const int need_new_signing_key =
    NULL == use_signing ||
    EXPIRES_SOON(check_signing_cert, 0) ||
    (options->command == CMD_KEYGEN && ! options->change_key_passphrase);
  const int want_new_signing_key =
    need_new_signing_key ||
    EXPIRES_SOON(check_signing_cert, options->TestingSigningKeySlop);

  /* We can only create a master key if we haven't been told that the
   * master key will always be offline.  Also, if we have a signing key,
   * then we shouldn't make a new master ID key. */
  const int can_make_master_id_key = !offline_master &&
    NULL == use_signing;

  if (need_new_signing_key) {
    log_notice(LD_OR, "It looks like I need to generate and sign a new "
               "medium-term signing key, because %s. To do that, I need to "
               "load%s the permanent master identity key.",
            (NULL == use_signing) ? "I don't have one" :
            EXPIRES_SOON(check_signing_cert, 0) ? "the one I have is expired" :
               "you asked me to make one with --keygen",
            can_make_master_id_key ? " (or create)" : "");
  } else if (want_new_signing_key && !offline_master) {
    log_notice(LD_OR, "It looks like I should try to generate and sign a "
               "new medium-term signing key, because the one I have is "
               "going to expire soon. To do that, I'm going to have to try to "
               "load the permanent master identity key.");
  } else if (want_new_signing_key) {
    log_notice(LD_OR, "It looks like I should try to generate and sign a "
               "new medium-term signing key, because the one I have is "
               "going to expire soon. But OfflineMasterKey is set, so I "
               "won't try to load a permanent master identity key is set. "
               "You will need to use 'tor --keygen' make a new signing key "
               "and certificate.");
  }

  {
    uint32_t flags =
      (INIT_ED_KEY_SPLIT|
       INIT_ED_KEY_EXTRA_STRONG|INIT_ED_KEY_NO_REPAIR);
    if (can_make_master_id_key)
      flags |= INIT_ED_KEY_CREATE;
    if (! need_new_signing_key)
      flags |= INIT_ED_KEY_MISSING_SECRET_OK;
    if (! want_new_signing_key || offline_master)
      flags |= INIT_ED_KEY_OMIT_SECRET;
    if (offline_master)
      flags |= INIT_ED_KEY_OFFLINE_SECRET;
    if (options->command == CMD_KEYGEN)
      flags |= INIT_ED_KEY_TRY_ENCRYPTED;

    /* Check the key directory */
    if (check_private_dir(options->DataDirectory, CPD_CREATE, options->User)) {
      log_err(LD_OR, "Can't create/check datadirectory %s",
              options->DataDirectory);
      goto err;
    }
    char *fname = get_datadir_fname("keys");
    if (check_private_dir(fname, CPD_CREATE, options->User) < 0) {
      log_err(LD_OR, "Problem creating/checking key directory %s", fname);
      tor_free(fname);
      goto err;
    }
    tor_free(fname);
    if (options->master_key_fname) {
      fname = tor_strdup(options->master_key_fname);
      flags |= INIT_ED_KEY_EXPLICIT_FNAME;
    } else {
      fname = options_get_datadir_fname2(options, "keys", "ed25519_master_id");
    }
    id = ed_key_init_from_file(
             fname,
             flags,
             LOG_WARN, NULL, 0, 0, 0, NULL);
    tor_free(fname);
    if (!id) {
      if (need_new_signing_key) {
        if (offline_master)
          FAIL("Can't load master identity key; OfflineMasterKey is set.");
        else
          FAIL("Missing identity key");
      } else {
        log_warn(LD_OR, "Master public key was absent; inferring from "
                 "public key in signing certificate and saving to disk.");
        tor_assert(check_signing_cert);
        id = tor_malloc_zero(sizeof(*id));
        memcpy(&id->pubkey, &check_signing_cert->signing_key,
               sizeof(ed25519_public_key_t));
        fname = options_get_datadir_fname2(options, "keys",
                                           "ed25519_master_id_public_key");
        if (ed25519_pubkey_write_to_file(&id->pubkey, fname, "type0") < 0) {
          log_warn(LD_OR, "Error while attempting to write master public key "
                   "to disk");
          tor_free(fname);
          goto err;
        }
        tor_free(fname);
      }
    }
    if (tor_mem_is_zero((char*)id->seckey.seckey, sizeof(id->seckey)))
      sign_signing_key_with_id = NULL;
    else
      sign_signing_key_with_id = id;
  }

  if (master_identity_key &&
      !ed25519_pubkey_eq(&id->pubkey, &master_identity_key->pubkey)) {
    FAIL("Identity key on disk does not match key we loaded earlier!");
  }

  if (need_new_signing_key && NULL == sign_signing_key_with_id)
    FAIL("Can't load master key make a new signing key.");

  if (sign_cert) {
    if (! sign_cert->signing_key_included)
      FAIL("Loaded a signing cert with no key included!");
    if (! ed25519_pubkey_eq(&sign_cert->signing_key, &id->pubkey))
      FAIL("The signing cert we have was not signed with the master key "
           "we loaded!");
    if (tor_cert_checksig(sign_cert, &id->pubkey, 0) < 0)
      FAIL("The signing cert we loaded was not signed correctly!");
  }

  if (want_new_signing_key && sign_signing_key_with_id) {
    uint32_t flags = (INIT_ED_KEY_CREATE|
                      INIT_ED_KEY_REPLACE|
                      INIT_ED_KEY_EXTRA_STRONG|
                      INIT_ED_KEY_NEEDCERT|
                      INIT_ED_KEY_INCLUDE_SIGNING_KEY_IN_CERT);
    char *fname =
      options_get_datadir_fname2(options, "keys", "ed25519_signing");
    ed25519_keypair_free(sign);
    tor_cert_free(sign_cert);
    sign = ed_key_init_from_file(fname,
                                 flags, LOG_WARN,
                                 sign_signing_key_with_id, now,
                                 options->SigningKeyLifetime,
                                 CERT_TYPE_ID_SIGNING, &sign_cert);
    tor_free(fname);
    if (!sign)
      FAIL("Missing signing key");
    use_signing = sign;

    tor_assert(sign_cert->signing_key_included);
    tor_assert(ed25519_pubkey_eq(&sign_cert->signing_key, &id->pubkey));
    tor_assert(ed25519_pubkey_eq(&sign_cert->signed_key, &sign->pubkey));
  } else if (want_new_signing_key) {
    static ratelim_t missing_master = RATELIM_INIT(3600);
    log_fn_ratelim(&missing_master, LOG_WARN, LD_OR,
                   "Signing key will expire soon, but I can't load the "
                   "master key to sign a new one!");
  }

  tor_assert(use_signing);

  /* At this point we no longer need our secret identity key.  So wipe
   * it, if we loaded it in the first place. */
  memwipe(id->seckey.seckey, 0, sizeof(id->seckey));

  if (options->command == CMD_KEYGEN)
    goto end;

  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 ||
      EXPIRES_SOON(auth_key_cert, options->TestingAuthKeySlop)) {
    auth = ed_key_new(use_signing, INIT_ED_KEY_NEEDCERT,
                      now,
                      options->TestingAuthKeyLifetime,
                      CERT_TYPE_SIGNING_AUTH, &auth_cert);

    if (!auth)
      FAIL("Can't create auth key");
  }

  /* We've generated or loaded everything.  Put them in memory. */

 end:
  if (! master_identity_key) {
    SET_KEY(master_identity_key, id);
  } else {
    tor_free(id);
  }
  if (sign) {
    SET_KEY(master_signing_key, sign);
    SET_CERT(signing_key_cert, sign_cert);
  }
  if (auth) {
    SET_KEY(current_auth_key, auth);
    SET_CERT(auth_key_cert, auth_cert);
  }

  return 0;
 err:
  ed25519_keypair_free(id);
  ed25519_keypair_free(sign);
  ed25519_keypair_free(auth);
  tor_cert_free(sign_cert);
  tor_cert_free(auth_cert);
  return -1;
}
Esempio n. 4
0
/**
 * Running as a server: load, reload, or refresh our ed25519 keys and
 * certificates, creating and saving new ones as needed.
 *
 * Return -1 on failure; 0 on success if the signing key was not replaced;
 * and 1 on success if the signing key was replaced.
 */
int
load_ed_keys(const or_options_t *options, time_t now)
{
  ed25519_keypair_t *id = NULL;
  ed25519_keypair_t *sign = 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 *auth_cert = NULL;
  int signing_key_changed = 0;

  // It is later than 1972, since otherwise there would be no C compilers.
  // (Try to diagnose #22466.)
  tor_assert_nonfatal(now >= 2 * 365 * 86400);

#define FAIL(msg) do {                          \
    log_warn(LD_OR, (msg));                     \
    goto err;                                   \
  } while (0)
#define SET_KEY(key, newval) do {               \
    if ((key) != (newval))                      \
      ed25519_keypair_free(key);                \
    key = (newval);                             \
  } while (0)
#define SET_CERT(cert, newval) do {             \
    if ((cert) != (newval))                     \
      tor_cert_free(cert);                      \
    cert = (newval);                            \
  } while (0)
#define HAPPENS_SOON(when, interval)            \
  ((when) < now + (interval))
#define EXPIRES_SOON(cert, interval)            \
  (!(cert) || HAPPENS_SOON((cert)->valid_until, (interval)))

  /* XXXX support encrypted identity keys fully */

  /* First try to get the signing key to see how it is. */
  {
    char *fname =
      options_get_keydir_fname(options, "ed25519_signing");
    sign = ed_key_init_from_file(
               fname,
               INIT_ED_KEY_NEEDCERT|
               INIT_ED_KEY_INCLUDE_SIGNING_KEY_IN_CERT,
               LOG_INFO,
               NULL, 0, 0, CERT_TYPE_ID_SIGNING, &sign_cert);
    tor_free(fname);
    check_signing_cert = sign_cert;
    use_signing = sign;
  }

  if (use_signing) {
    /* We loaded a signing key with its certificate.  */
    if (! master_signing_key) {
      /* We didn't know one before! */
      signing_key_changed = 1;
    } else if (! ed25519_pubkey_eq(&use_signing->pubkey,
                                   &master_signing_key->pubkey) ||
               ! tor_memeq(use_signing->seckey.seckey,
                           master_signing_key->seckey.seckey,
                           ED25519_SECKEY_LEN)) {
      /* We loaded a different signing key than the one we knew before. */
      signing_key_changed = 1;
    }
  }

  if (!use_signing && master_signing_key) {
    /* We couldn't load a signing key, but we already had one loaded */
    check_signing_cert = signing_key_cert;
    use_signing = master_signing_key;
  }

  const int offline_master =
    options->OfflineMasterKey && options->command != CMD_KEYGEN;
  const int need_new_signing_key =
    NULL == use_signing ||
    EXPIRES_SOON(check_signing_cert, 0) ||
    (options->command == CMD_KEYGEN && ! options->change_key_passphrase);
  const int want_new_signing_key =
    need_new_signing_key ||
    EXPIRES_SOON(check_signing_cert, options->TestingSigningKeySlop);

  /* We can only create a master key if we haven't been told that the
   * master key will always be offline.  Also, if we have a signing key,
   * then we shouldn't make a new master ID key. */
  const int can_make_master_id_key = !offline_master &&
    NULL == use_signing;

  if (need_new_signing_key) {
    log_notice(LD_OR, "It looks like I need to generate and sign a new "
               "medium-term signing key, because %s. To do that, I "
               "need to load%s the permanent master identity key. "
               "If the master identity key was not moved or encrypted "
               "with a passphrase, this will be done automatically and "
               "no further action is required. Otherwise, provide the "
               "necessary data using 'tor --keygen' to do it manually.",
            (NULL == use_signing) ? "I don't have one" :
            EXPIRES_SOON(check_signing_cert, 0) ? "the one I have is expired" :
               "you asked me to make one with --keygen",
            can_make_master_id_key ? " (or create)" : "");
  } else if (want_new_signing_key && !offline_master) {
    log_notice(LD_OR, "It looks like I should try to generate and sign a "
               "new medium-term signing key, because the one I have is "
               "going to expire soon. To do that, I'm going to have to "
               "try to load the permanent master identity key. "
               "If the master identity key was not moved or encrypted "
               "with a passphrase, this will be done automatically and "
               "no further action is required. Otherwise, provide the "
               "necessary data using 'tor --keygen' to do it manually.");
  } else if (want_new_signing_key) {
    log_notice(LD_OR, "It looks like I should try to generate and sign a "
               "new medium-term signing key, because the one I have is "
               "going to expire soon. But OfflineMasterKey is set, so I "
               "won't try to load a permanent master identity key. You "
               "will need to use 'tor --keygen' to make a new signing "
               "key and certificate.");
  }

  {
    uint32_t flags =
      (INIT_ED_KEY_SPLIT|
       INIT_ED_KEY_EXTRA_STRONG|INIT_ED_KEY_NO_REPAIR);
    if (can_make_master_id_key)
      flags |= INIT_ED_KEY_CREATE;
    if (! need_new_signing_key)
      flags |= INIT_ED_KEY_MISSING_SECRET_OK;
    if (! want_new_signing_key || offline_master)
      flags |= INIT_ED_KEY_OMIT_SECRET;
    if (offline_master)
      flags |= INIT_ED_KEY_OFFLINE_SECRET;
    if (options->command == CMD_KEYGEN)
      flags |= INIT_ED_KEY_TRY_ENCRYPTED;

    /* Check/Create the key directory */
    if (create_keys_directory(options) < 0)
      return -1;

    char *fname;
    if (options->master_key_fname) {
      fname = tor_strdup(options->master_key_fname);
      flags |= INIT_ED_KEY_EXPLICIT_FNAME;
    } else {
      fname = options_get_keydir_fname(options, "ed25519_master_id");
    }
    id = ed_key_init_from_file(
             fname,
             flags,
             LOG_WARN, NULL, 0, 0, 0, NULL);
    tor_free(fname);
    if (!id) {
      if (need_new_signing_key) {
        if (offline_master)
          FAIL("Can't load master identity key; OfflineMasterKey is set.");
        else
          FAIL("Missing identity key");
      } else {
        log_warn(LD_OR, "Master public key was absent; inferring from "
                 "public key in signing certificate and saving to disk.");
        tor_assert(check_signing_cert);
        id = tor_malloc_zero(sizeof(*id));
        memcpy(&id->pubkey, &check_signing_cert->signing_key,
               sizeof(ed25519_public_key_t));
        fname = options_get_keydir_fname(options,
                                         "ed25519_master_id_public_key");
        if (ed25519_pubkey_write_to_file(&id->pubkey, fname, "type0") < 0) {
          log_warn(LD_OR, "Error while attempting to write master public key "
                   "to disk");
          tor_free(fname);
          goto err;
        }
        tor_free(fname);
      }
    }
    if (tor_mem_is_zero((char*)id->seckey.seckey, sizeof(id->seckey)))
      sign_signing_key_with_id = NULL;
    else
      sign_signing_key_with_id = id;
  }

  if (master_identity_key &&
      !ed25519_pubkey_eq(&id->pubkey, &master_identity_key->pubkey)) {
    FAIL("Identity key on disk does not match key we loaded earlier!");
  }

  if (need_new_signing_key && NULL == sign_signing_key_with_id)
    FAIL("Can't load master key make a new signing key.");

  if (sign_cert) {
    if (! sign_cert->signing_key_included)
      FAIL("Loaded a signing cert with no key included!");
    if (! ed25519_pubkey_eq(&sign_cert->signing_key, &id->pubkey))
      FAIL("The signing cert we have was not signed with the master key "
           "we loaded!");
    if (tor_cert_checksig(sign_cert, &id->pubkey, 0) < 0) {
      log_warn(LD_OR, "The signing cert we loaded was not signed "
               "correctly: %s!",
               tor_cert_describe_signature_status(sign_cert));
      goto err;
    }
  }

  if (want_new_signing_key && sign_signing_key_with_id) {
    uint32_t flags = (INIT_ED_KEY_CREATE|
                      INIT_ED_KEY_REPLACE|
                      INIT_ED_KEY_EXTRA_STRONG|
                      INIT_ED_KEY_NEEDCERT|
                      INIT_ED_KEY_INCLUDE_SIGNING_KEY_IN_CERT);
    char *fname =
      options_get_keydir_fname(options, "ed25519_signing");
    ed25519_keypair_free(sign);
    tor_cert_free(sign_cert);
    sign = ed_key_init_from_file(fname,
                                 flags, LOG_WARN,
                                 sign_signing_key_with_id, now,
                                 options->SigningKeyLifetime,
                                 CERT_TYPE_ID_SIGNING, &sign_cert);
    tor_free(fname);
    if (!sign)
      FAIL("Missing signing key");
    use_signing = sign;
    signing_key_changed = 1;

    tor_assert(sign_cert->signing_key_included);
    tor_assert(ed25519_pubkey_eq(&sign_cert->signing_key, &id->pubkey));
    tor_assert(ed25519_pubkey_eq(&sign_cert->signed_key, &sign->pubkey));
  } else if (want_new_signing_key) {
    static ratelim_t missing_master = RATELIM_INIT(3600);
    log_fn_ratelim(&missing_master, LOG_WARN, LD_OR,
                   "Signing key will expire soon, but I can't load the "
                   "master key to sign a new one!");
  }

  tor_assert(use_signing);

  /* At this point we no longer need our secret identity key.  So wipe
   * it, if we loaded it in the first place. */
  memwipe(id->seckey.seckey, 0, sizeof(id->seckey));

  if (options->command == CMD_KEYGEN)
    goto end;

  if (server_mode(options) &&
      (!rsa_ed_crosscert ||
       HAPPENS_SOON(rsa_ed_crosscert_expiration, 30*86400))) {
    uint8_t *crosscert;
    time_t expiration = now+6*30*86400; /* 6 months in the future. */
    ssize_t crosscert_len = tor_make_rsa_ed25519_crosscert(&id->pubkey,
                                                   get_server_identity_key(),
                                                   expiration,
                                                   &crosscert);
    tor_free(rsa_ed_crosscert);
    rsa_ed_crosscert_len = crosscert_len;
    rsa_ed_crosscert = crosscert;
    rsa_ed_crosscert_expiration = expiration;
  }

  if (!current_auth_key ||
      signing_key_changed ||
      EXPIRES_SOON(auth_key_cert, options->TestingAuthKeySlop)) {
    auth = ed_key_new(use_signing, INIT_ED_KEY_NEEDCERT,
                      now,
                      options->TestingAuthKeyLifetime,
                      CERT_TYPE_SIGNING_AUTH, &auth_cert);

    if (!auth)
      FAIL("Can't create auth key");
  }

  /* We've generated or loaded everything.  Put them in memory. */

 end:
  if (! master_identity_key) {
    SET_KEY(master_identity_key, id);
  } else {
    tor_free(id);
  }
  if (sign) {
    SET_KEY(master_signing_key, sign);
    SET_CERT(signing_key_cert, sign_cert);
  }
  if (auth) {
    SET_KEY(current_auth_key, auth);
    SET_CERT(auth_key_cert, auth_cert);
  }

  return signing_key_changed;
 err:
  ed25519_keypair_free(id);
  ed25519_keypair_free(sign);
  ed25519_keypair_free(auth);
  tor_cert_free(sign_cert);
  tor_cert_free(auth_cert);
  return -1;
}
Esempio n. 5
0
hs_desc_intro_point_t *
hs_helper_build_intro_point(const ed25519_keypair_t *signing_kp, time_t now,
                            const char *addr, int legacy)
{
  int ret;
  ed25519_keypair_t auth_kp;
  hs_desc_intro_point_t *intro_point = NULL;
  hs_desc_intro_point_t *ip = hs_desc_intro_point_new();

  /* For a usable intro point we need at least two link specifiers: One legacy
   * keyid and one ipv4 */
  {
    tor_addr_t a;
    tor_addr_make_unspec(&a);
    link_specifier_t *ls_legacy = link_specifier_new();
    link_specifier_t *ls_ip = link_specifier_new();
    link_specifier_set_ls_type(ls_legacy, LS_LEGACY_ID);
    memset(link_specifier_getarray_un_legacy_id(ls_legacy), 'C',
           link_specifier_getlen_un_legacy_id(ls_legacy));
    int family = tor_addr_parse(&a, addr);
    switch (family) {
    case AF_INET:
          link_specifier_set_ls_type(ls_ip, LS_IPV4);
          link_specifier_set_un_ipv4_addr(ls_ip, tor_addr_to_ipv4h(&a));
          link_specifier_set_un_ipv4_port(ls_ip, 9001);
          break;
        case AF_INET6:
          link_specifier_set_ls_type(ls_ip, LS_IPV6);
          memcpy(link_specifier_getarray_un_ipv6_addr(ls_ip),
                 tor_addr_to_in6_addr8(&a),
                 link_specifier_getlen_un_ipv6_addr(ls_ip));
          link_specifier_set_un_ipv6_port(ls_ip, 9001);
          break;
        default:
          /* Stop the test, not supposed to have an error.
           * Compare with -1 to show the actual family.
           */
          tt_int_op(family, OP_EQ, -1);
    }
    smartlist_add(ip->link_specifiers, ls_legacy);
    smartlist_add(ip->link_specifiers, ls_ip);
  }

  ret = ed25519_keypair_generate(&auth_kp, 0);
  tt_int_op(ret, ==, 0);
  ip->auth_key_cert = tor_cert_create(signing_kp, CERT_TYPE_AUTH_HS_IP_KEY,
                                      &auth_kp.pubkey, now,
                                      HS_DESC_CERT_LIFETIME,
                                      CERT_FLAG_INCLUDE_SIGNING_KEY);
  tt_assert(ip->auth_key_cert);

  if (legacy) {
    ip->legacy.key = crypto_pk_new();
    tt_assert(ip->legacy.key);
    ret = crypto_pk_generate_key(ip->legacy.key);
    tt_int_op(ret, ==, 0);
    ssize_t cert_len = tor_make_rsa_ed25519_crosscert(
                                    &signing_kp->pubkey, ip->legacy.key,
                                    now + HS_DESC_CERT_LIFETIME,
                                    &ip->legacy.cert.encoded);
    tt_assert(ip->legacy.cert.encoded);
    tt_u64_op(cert_len, OP_GT, 0);
    ip->legacy.cert.len = cert_len;
  }

  /* Encryption key. */
  {
    int signbit;
    curve25519_keypair_t curve25519_kp;
    ed25519_keypair_t ed25519_kp;
    tor_cert_t *cross_cert;

    ret = curve25519_keypair_generate(&curve25519_kp, 0);
    tt_int_op(ret, ==, 0);
    ed25519_keypair_from_curve25519_keypair(&ed25519_kp, &signbit,
                                            &curve25519_kp);
    cross_cert = tor_cert_create(signing_kp, CERT_TYPE_CROSS_HS_IP_KEYS,
                                 &ed25519_kp.pubkey, time(NULL),
                                 HS_DESC_CERT_LIFETIME,
                                 CERT_FLAG_INCLUDE_SIGNING_KEY);
    tt_assert(cross_cert);
    ip->enc_key_cert = cross_cert;
  }

  intro_point = ip;
 done:
  if (intro_point == NULL)
    tor_free(ip);

  return intro_point;
}