Exemplo n.º 1
0
/**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) {
    log_warn(LD_OR, "Can't get my x509 link cert.");
    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;
}
Exemplo n.º 2
0
/** 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>. */
tor_cert_t *
make_ntor_onion_key_crosscert(const curve25519_keypair_t *onion_key,
      const ed25519_public_key_t *master_id_key, time_t now, time_t lifetime,
      int *sign_out)
{
  tor_cert_t *cert = NULL;
  ed25519_keypair_t ed_onion_key;

  if (ed25519_keypair_from_curve25519_keypair(&ed_onion_key, sign_out,
                                              onion_key) < 0)
    goto end;

  cert = tor_cert_create(&ed_onion_key, CERT_TYPE_ONION_ID, master_id_key,
      now, lifetime, 0);

 end:
  memwipe(&ed_onion_key, 0, sizeof(ed_onion_key));
  return cert;
}
Exemplo n.º 3
0
/**
 * Retrieve our currently-in-use Ed25519 link certificate and id certificate,
 * and, if they would expire soon (based on the time <b>now</b>, generate new
 * certificates (without embedding the public part of the signing key inside).
 * If <b>force</b> is true, always generate a new certificate.
 *
 * The signed_key from the current id->signing certificate will be used to
 * sign the new key within newly generated X509 certificate.
 *
 * Returns -1 upon error.  Otherwise, returns 0 upon success (either when the
 * current certificate is still valid, or when a new certificate was
 * successfully generated, or no certificate was needed).
 */
int
generate_ed_link_cert(const or_options_t *options, time_t now,
                      int force)
{
  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) {
    if (!server_mode(options)) {
        /* No need to make an Ed25519->Link cert: we are a client */
      return 0;
    }
    log_warn(LD_OR, "Can't get my x509 link cert.");
    return -1;
  }

  const common_digests_t *digests = tor_x509_cert_get_cert_digests(link_);

  if (force == 0 &&
      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;
}
Exemplo n.º 4
0
/**
 * Create a new signing key and (optionally) certficiate; do not read or write
 * from disk.  See ed_key_init_from_file() for more information.
 */
ed25519_keypair_t *
ed_key_new(const ed25519_keypair_t *signing_key,
           uint32_t flags,
           time_t now,
           time_t lifetime,
           uint8_t cert_type,
           struct tor_cert_st **cert_out)
{
  if (cert_out)
    *cert_out = NULL;

  const int extra_strong = !! (flags & INIT_ED_KEY_EXTRA_STRONG);
  ed25519_keypair_t *keypair = tor_malloc_zero(sizeof(ed25519_keypair_t));
  if (ed25519_keypair_generate(keypair, extra_strong) < 0)
    goto err;

  if (! (flags & INIT_ED_KEY_NEEDCERT))
    return keypair;

  tor_assert(signing_key);
  tor_assert(cert_out);
  uint32_t cert_flags = 0;
  if (flags & INIT_ED_KEY_INCLUDE_SIGNING_KEY_IN_CERT)
    cert_flags |= CERT_FLAG_INCLUDE_SIGNING_KEY;
  tor_cert_t *cert = tor_cert_create(signing_key, cert_type,
                                     &keypair->pubkey,
                                     now, lifetime,
                                     cert_flags);
  if (! cert)
    goto err;

  *cert_out = cert;
  return keypair;

 err:
  tor_free(keypair);
  return NULL;
}
Exemplo n.º 5
0
/**
 * Read an ed25519 key and associated certificates from files beginning with
 * <b>fname</b>, with certificate type <b>cert_type</b>.  On failure, return
 * NULL; on success return the keypair.
 *
 * If INIT_ED_KEY_CREATE is set in <b>flags</b>, then create the key (and
 * certificate if requested) if it doesn't exist, and save it to disk.
 *
 * If INIT_ED_KEY_NEEDCERT is set in <b>flags</b>, load/create a certificate
 * too and store it in *<b>cert_out</b>.  Fail if the cert can't be
 * found/created.  To create a certificate, <b>signing_key</b> must be set to
 * the key that should sign it; <b>now</b> to the current time, and
 * <b>lifetime</b> to the lifetime of the key.
 *
 * If INIT_ED_KEY_REPLACE is set in <b>flags</b>, then create and save new key
 * whether we can read the old one or not.
 *
 * If INIT_ED_KEY_EXTRA_STRONG is set in <b>flags</b>, set the extra_strong
 * flag when creating the secret key.
 *
 * If INIT_ED_KEY_INCLUDE_SIGNING_KEY_IN_CERT is set in <b>flags</b>, and
 * we create a new certificate, create it with the signing key embedded.
 *
 * If INIT_ED_KEY_SPLIT is set in <b>flags</b>, and we create a new key,
 * store the public key in a separate file from the secret key.
 *
 * If INIT_ED_KEY_MISSING_SECRET_OK is set in <b>flags</b>, and we find a
 * public key file but no secret key file, return successfully anyway.
 *
 * If INIT_ED_KEY_OMIT_SECRET is set in <b>flags</b>, do not try to load a
 * secret key unless no public key is found.  Do not return a secret key. (but
 * create and save one if needed).
 *
 * If INIT_ED_KEY_NO_LOAD_SECRET is set in <b>flags</b>, don't try to load
 * a secret key, no matter what.
 *
 * If INIT_ED_KEY_TRY_ENCRYPTED is set, we look for an encrypted secret key
 * and consider encrypting any new secret key.
 *
 * If INIT_ED_KEY_NO_REPAIR is set, and there is any issue loading the keys
 * from disk _other than their absence_ (full or partial), we do not try to
 * replace them.
 *
 * If INIT_ED_KEY_SUGGEST_KEYGEN is set, have log messages about failures
 * refer to the --keygen option.
 *
 * If INIT_ED_KEY_EXPLICIT_FNAME is set, use the provided file name for the
 * secret key file, encrypted or not.
 */
ed25519_keypair_t *
ed_key_init_from_file(const char *fname, uint32_t flags,
                      int severity,
                      const ed25519_keypair_t *signing_key,
                      time_t now,
                      time_t lifetime,
                      uint8_t cert_type,
                      struct tor_cert_st **cert_out)
{
  char *secret_fname = NULL;
  char *encrypted_secret_fname = NULL;
  char *public_fname = NULL;
  char *cert_fname = NULL;
  const char *loaded_secret_fname = NULL;
  int created_pk = 0, created_sk = 0, created_cert = 0;
  const int try_to_load = ! (flags & INIT_ED_KEY_REPLACE);
  const int encrypt_key = !! (flags & INIT_ED_KEY_TRY_ENCRYPTED);
  const int norepair = !! (flags & INIT_ED_KEY_NO_REPAIR);
  const int split = !! (flags & INIT_ED_KEY_SPLIT);
  const int omit_secret = !! (flags & INIT_ED_KEY_OMIT_SECRET);
  const int offline_secret = !! (flags & INIT_ED_KEY_OFFLINE_SECRET);
  const int explicit_fname = !! (flags & INIT_ED_KEY_EXPLICIT_FNAME);

  /* we don't support setting both of these flags at once. */
  tor_assert((flags & (INIT_ED_KEY_NO_REPAIR|INIT_ED_KEY_NEEDCERT)) !=
                      (INIT_ED_KEY_NO_REPAIR|INIT_ED_KEY_NEEDCERT));

  char tag[8];
  tor_snprintf(tag, sizeof(tag), "type%d", (int)cert_type);

  tor_cert_t *cert = NULL;
  char *got_tag = NULL;
  ed25519_keypair_t *keypair = tor_malloc_zero(sizeof(ed25519_keypair_t));

  if (explicit_fname) {
    secret_fname = tor_strdup(fname);
    encrypted_secret_fname = tor_strdup(fname);
  } else {
    tor_asprintf(&secret_fname, "%s_secret_key", fname);
    tor_asprintf(&encrypted_secret_fname, "%s_secret_key_encrypted", fname);
  }
  tor_asprintf(&public_fname, "%s_public_key", fname);
  tor_asprintf(&cert_fname, "%s_cert", fname);

  /* Try to read the secret key. */
  int have_secret = 0;
  int load_secret = try_to_load &&
    !offline_secret &&
    (!omit_secret || file_status(public_fname)==FN_NOENT);
  if (load_secret) {
    int rv = ed25519_seckey_read_from_file(&keypair->seckey,
                                           &got_tag, secret_fname);
    if (rv == 0) {
      have_secret = 1;
      loaded_secret_fname = secret_fname;
      tor_assert(got_tag);
    } else {
      if (errno != ENOENT && norepair) {
        tor_log(severity, LD_OR, "Unable to read %s: %s", secret_fname,
                strerror(errno));
        goto err;
      }
    }
  }

  /* Should we try for an encrypted key? */
  int have_encrypted_secret_file = 0;
  if (!have_secret && try_to_load && encrypt_key) {
    int r = read_encrypted_secret_key(&keypair->seckey,
                                      encrypted_secret_fname);
    if (r > 0) {
      have_secret = 1;
      have_encrypted_secret_file = 1;
      tor_free(got_tag); /* convince coverity we aren't leaking */
      got_tag = tor_strdup(tag);
      loaded_secret_fname = encrypted_secret_fname;
    } else if (errno != ENOENT && norepair) {
      tor_log(severity, LD_OR, "Unable to read %s: %s",
              encrypted_secret_fname, strerror(errno));
      goto err;
    }
  } else {
    if (try_to_load) {
      /* Check if it's there anyway, so we don't replace it. */
      if (file_status(encrypted_secret_fname) != FN_NOENT)
        have_encrypted_secret_file = 1;
    }
  }

  if (have_secret) {
    if (strcmp(got_tag, tag)) {
      tor_log(severity, LD_OR, "%s has wrong tag", loaded_secret_fname);
      goto err;
    }
    /* Derive the public key */
    if (ed25519_public_key_generate(&keypair->pubkey, &keypair->seckey)<0) {
      tor_log(severity, LD_OR, "%s can't produce a public key",
              loaded_secret_fname);
      goto err;
    }
  }

  /* If we do split keys here, try to read the pubkey. */
  int found_public = 0;
  if (try_to_load && (!have_secret || split)) {
    ed25519_public_key_t pubkey_tmp;
    tor_free(got_tag);
    found_public = ed25519_pubkey_read_from_file(&pubkey_tmp,
                                                 &got_tag, public_fname) == 0;
    if (!found_public && errno != ENOENT && norepair) {
      tor_log(severity, LD_OR, "Unable to read %s: %s", public_fname,
              strerror(errno));
      goto err;
    }
    if (found_public && strcmp(got_tag, tag)) {
      tor_log(severity, LD_OR, "%s has wrong tag", public_fname);
      goto err;
    }
    if (found_public) {
      if (have_secret) {
        /* If we have a secret key and we're reloading the public key,
         * the key must match! */
        if (! ed25519_pubkey_eq(&keypair->pubkey, &pubkey_tmp)) {
          tor_log(severity, LD_OR, "%s does not match %s!  If you are trying "
                  "to restore from backup, make sure you didn't mix up the "
                  "key files. If you are absolutely sure that %s is the right "
                  "key for this relay, delete %s or move it out of the way.",
                  public_fname, loaded_secret_fname,
                  loaded_secret_fname, public_fname);
          goto err;
        }
      } else {
        /* We only have the public key; better use that. */
        tor_assert(split);
        memcpy(&keypair->pubkey, &pubkey_tmp, sizeof(pubkey_tmp));
      }
    } else {
      /* We have no public key file, but we do have a secret key, make the
       * public key file! */
      if (have_secret) {
        if (ed25519_pubkey_write_to_file(&keypair->pubkey, public_fname, tag)
            < 0) {
          tor_log(severity, LD_OR, "Couldn't repair %s", public_fname);
          goto err;
        } else {
          tor_log(LOG_NOTICE, LD_OR,
                  "Found secret key but not %s. Regenerating.",
                  public_fname);
        }
      }
    }
  }

  /* If the secret key is absent and it's not allowed to be, fail. */
  if (!have_secret && found_public &&
      !(flags & INIT_ED_KEY_MISSING_SECRET_OK)) {
    if (have_encrypted_secret_file) {
      tor_log(severity, LD_OR, "We needed to load a secret key from %s, "
              "but it was encrypted. Try 'tor --keygen' instead, so you "
              "can enter the passphrase.",
              secret_fname);
    } else {
      tor_log(severity, LD_OR, "We needed to load a secret key from %s, "
              "but couldn't find it. %s", secret_fname,
              (flags & INIT_ED_KEY_SUGGEST_KEYGEN) ?
              "If you're keeping your master secret key offline, you will "
              "need to run 'tor --keygen' to generate new signing keys." :
              "Did you forget to copy it over when you copied the rest of the "
              "signing key material?");
    }
    goto err;
  }

  /* If it's absent, and we're not supposed to make a new keypair, fail. */
  if (!have_secret && !found_public && !(flags & INIT_ED_KEY_CREATE)) {
    if (split) {
      tor_log(severity, LD_OR, "No key found in %s or %s.",
              secret_fname, public_fname);
    } else {
      tor_log(severity, LD_OR, "No key found in %s.", secret_fname);
    }
    goto err;
  }

  /* If the secret key is absent, but the encrypted key would be present,
   * that's an error */
  if (!have_secret && !found_public && have_encrypted_secret_file) {
    tor_assert(!encrypt_key);
    tor_log(severity, LD_OR, "Found an encrypted secret key, "
            "but not public key file %s!", public_fname);
    goto err;
  }

  /* if it's absent, make a new keypair... */
  if (!have_secret && !found_public) {
    tor_free(keypair);
    keypair = ed_key_new(signing_key, flags, now, lifetime,
                         cert_type, &cert);
    if (!keypair) {
      tor_log(severity, LD_OR, "Couldn't create keypair");
      goto err;
    }
    created_pk = created_sk = created_cert = 1;
  }

  /* Write it to disk if we're supposed to do with a new passphrase, or if
   * we just created it. */
  if (created_sk || (have_secret && get_options()->change_key_passphrase)) {
    if (write_secret_key(&keypair->seckey,
                         encrypt_key,
                         secret_fname, tag, encrypted_secret_fname) < 0
        ||
        (split &&
         ed25519_pubkey_write_to_file(&keypair->pubkey, public_fname, tag) < 0)
        ||
        (cert &&
         crypto_write_tagged_contents_to_file(cert_fname, "ed25519v1-cert",
                                 tag, cert->encoded, cert->encoded_len) < 0)) {
      tor_log(severity, LD_OR, "Couldn't write keys or cert to file.");
      goto err;
    }
    goto done;
  }

  /* If we're not supposed to get a cert, we're done. */
  if (! (flags & INIT_ED_KEY_NEEDCERT))
    goto done;

  /* Read a cert. */
  tor_free(got_tag);
  uint8_t certbuf[256];
  ssize_t cert_body_len = crypto_read_tagged_contents_from_file(
                 cert_fname, "ed25519v1-cert",
                 &got_tag, certbuf, sizeof(certbuf));
  if (cert_body_len >= 0 && !strcmp(got_tag, tag))
    cert = tor_cert_parse(certbuf, cert_body_len);

  /* If we got it, check it to the extent we can. */
  int bad_cert = 0;

  if (! cert) {
    tor_log(severity, LD_OR, "Cert was unparseable");
    bad_cert = 1;
  } else if (!tor_memeq(cert->signed_key.pubkey, keypair->pubkey.pubkey,
                        ED25519_PUBKEY_LEN)) {
    tor_log(severity, LD_OR, "Cert was for wrong key");
    bad_cert = 1;
  } else if (signing_key &&
             tor_cert_checksig(cert, &signing_key->pubkey, now) < 0) {
    tor_log(severity, LD_OR, "Can't check certificate");
    bad_cert = 1;
  } else if (cert->cert_expired) {
    tor_log(severity, LD_OR, "Certificate is expired");
    bad_cert = 1;
  } else if (signing_key && cert->signing_key_included &&
             ! ed25519_pubkey_eq(&signing_key->pubkey, &cert->signing_key)) {
    tor_log(severity, LD_OR, "Certificate signed by unexpectd key!");
    bad_cert = 1;
  }

  if (bad_cert) {
    tor_cert_free(cert);
    cert = NULL;
  }

  /* If we got a cert, we're done. */
  if (cert)
    goto done;

  /* If we didn't get a cert, and we're not supposed to make one, fail. */
  if (!signing_key || !(flags & INIT_ED_KEY_CREATE)) {
    tor_log(severity, LD_OR, "Without signing key, can't create certificate");
    goto err;
  }

  /* We have keys but not a certificate, so make one. */
  uint32_t cert_flags = 0;
  if (flags & INIT_ED_KEY_INCLUDE_SIGNING_KEY_IN_CERT)
    cert_flags |= CERT_FLAG_INCLUDE_SIGNING_KEY;
  cert = tor_cert_create(signing_key, cert_type,
                         &keypair->pubkey,
                         now, lifetime,
                         cert_flags);

  if (! cert) {
    tor_log(severity, LD_OR, "Couldn't create certificate");
    goto err;
  }

  /* Write it to disk. */
  created_cert = 1;
  if (crypto_write_tagged_contents_to_file(cert_fname, "ed25519v1-cert",
                             tag, cert->encoded, cert->encoded_len) < 0) {
    tor_log(severity, LD_OR, "Couldn't write cert to disk.");
    goto err;
  }

 done:
  if (cert_out)
    *cert_out = cert;
  else
    tor_cert_free(cert);

  goto cleanup;

 err:
  if (keypair)
    memwipe(keypair, 0, sizeof(*keypair));
  tor_free(keypair);
  tor_cert_free(cert);
  if (cert_out)
    *cert_out = NULL;
  if (created_sk)
    unlink(secret_fname);
  if (created_pk)
    unlink(public_fname);
  if (created_cert)
    unlink(cert_fname);

 cleanup:
  tor_free(encrypted_secret_fname);
  tor_free(secret_fname);
  tor_free(public_fname);
  tor_free(cert_fname);
  tor_free(got_tag);

  return keypair;
}
Exemplo n.º 6
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;
}
Exemplo n.º 7
0
/* Return a valid hs_descriptor_t object. If no_ip is set, no introduction
 * points are added. */
static hs_descriptor_t *
hs_helper_build_hs_desc_impl(unsigned int no_ip,
                             const ed25519_keypair_t *signing_kp)
{
  int ret;
  int i;
  time_t now = approx_time();
  ed25519_keypair_t blinded_kp;
  curve25519_keypair_t auth_ephemeral_kp;
  hs_descriptor_t *descp = NULL, *desc = tor_malloc_zero(sizeof(*desc));

  desc->plaintext_data.version = HS_DESC_SUPPORTED_FORMAT_VERSION_MAX;

  /* Copy only the public key into the descriptor. */
  memcpy(&desc->plaintext_data.signing_pubkey, &signing_kp->pubkey,
         sizeof(ed25519_public_key_t));

  uint64_t current_time_period = hs_get_time_period_num(0);
  hs_build_blinded_keypair(signing_kp, NULL, 0,
                           current_time_period, &blinded_kp);
  /* Copy only the public key into the descriptor. */
  memcpy(&desc->plaintext_data.blinded_pubkey, &blinded_kp.pubkey,
         sizeof(ed25519_public_key_t));

  desc->plaintext_data.signing_key_cert =
    tor_cert_create(&blinded_kp, CERT_TYPE_SIGNING_HS_DESC,
                    &signing_kp->pubkey, now, 3600,
                    CERT_FLAG_INCLUDE_SIGNING_KEY);
  tt_assert(desc->plaintext_data.signing_key_cert);
  desc->plaintext_data.revision_counter = 42;
  desc->plaintext_data.lifetime_sec = 3 * 60 * 60;

  hs_get_subcredential(&signing_kp->pubkey, &blinded_kp.pubkey,
                    desc->subcredential);

  /* Setup superencrypted data section. */
  ret = curve25519_keypair_generate(&auth_ephemeral_kp, 0);
  tt_int_op(ret, ==, 0);
  memcpy(&desc->superencrypted_data.auth_ephemeral_pubkey,
         &auth_ephemeral_kp.pubkey,
         sizeof(curve25519_public_key_t));

  desc->superencrypted_data.clients = smartlist_new();
  for (i = 0; i < HS_DESC_AUTH_CLIENT_MULTIPLE; i++) {
    hs_desc_authorized_client_t *desc_client =
      hs_desc_build_fake_authorized_client();
    smartlist_add(desc->superencrypted_data.clients, desc_client);
  }

  /* Setup encrypted data section. */
  desc->encrypted_data.create2_ntor = 1;
  desc->encrypted_data.intro_auth_types = smartlist_new();
  desc->encrypted_data.single_onion_service = 1;
  smartlist_add(desc->encrypted_data.intro_auth_types, tor_strdup("ed25519"));
  desc->encrypted_data.intro_points = smartlist_new();
  if (!no_ip) {
    /* Add four intro points. */
    smartlist_add(desc->encrypted_data.intro_points,
              hs_helper_build_intro_point(signing_kp, now, "1.2.3.4", 0));
/* IPv6-only introduction points are not supported yet, see #23588 */
#if 0
    smartlist_add(desc->encrypted_data.intro_points,
              hs_helper_build_intro_point(signing_kp, now, "[2600::1]", 0));
#endif
    smartlist_add(desc->encrypted_data.intro_points,
              hs_helper_build_intro_point(signing_kp, now, "3.2.1.4", 1));
    smartlist_add(desc->encrypted_data.intro_points,
              hs_helper_build_intro_point(signing_kp, now, "5.6.7.8", 1));
  }

  descp = desc;
 done:
  if (descp == NULL)
    tor_free(desc);

  return descp;
}
Exemplo n.º 8
0
static void
test_routerkeys_ed_certs(void *args)
{
  (void)args;
  ed25519_keypair_t kp1, kp2;
  tor_cert_t *cert[2] = {NULL, NULL}, *nocert = NULL;
  tor_cert_t *parsed_cert[2] = {NULL, NULL};
  time_t now = 1412094534;
  uint8_t *junk = NULL;
  char *base64 = NULL;

  tt_int_op(0,OP_EQ,ed25519_keypair_generate(&kp1, 0));
  tt_int_op(0,OP_EQ,ed25519_keypair_generate(&kp2, 0));

  for (int i = 0; i <= 1; ++i) {
    uint32_t flags = i ? CERT_FLAG_INCLUDE_SIGNING_KEY : 0;

    cert[i] = tor_cert_create(&kp1, 5, &kp2.pubkey, now, 10000, flags);
    tt_assert(cert[i]);

    tt_uint_op(cert[i]->sig_bad, OP_EQ, 0);
    tt_uint_op(cert[i]->sig_ok, OP_EQ, 1);
    tt_uint_op(cert[i]->cert_expired, OP_EQ, 0);
    tt_uint_op(cert[i]->cert_valid, OP_EQ, 1);
    tt_int_op(cert[i]->cert_type, OP_EQ, 5);
    tt_mem_op(cert[i]->signed_key.pubkey, OP_EQ, &kp2.pubkey.pubkey, 32);
    tt_mem_op(cert[i]->signing_key.pubkey, OP_EQ, &kp1.pubkey.pubkey, 32);
    tt_int_op(cert[i]->signing_key_included, OP_EQ, i);

    tt_assert(cert[i]->encoded);
    tt_int_op(cert[i]->encoded_len, OP_EQ, 104 + 36 * i);
    tt_int_op(cert[i]->encoded[0], OP_EQ, 1);
    tt_int_op(cert[i]->encoded[1], OP_EQ, 5);

    parsed_cert[i] = tor_cert_parse(cert[i]->encoded, cert[i]->encoded_len);
    tt_assert(parsed_cert[i]);
    tt_int_op(cert[i]->encoded_len, OP_EQ, parsed_cert[i]->encoded_len);
    tt_mem_op(cert[i]->encoded, OP_EQ, parsed_cert[i]->encoded,
              cert[i]->encoded_len);
    tt_uint_op(parsed_cert[i]->sig_bad, OP_EQ, 0);
    tt_uint_op(parsed_cert[i]->sig_ok, OP_EQ, 0);
    tt_uint_op(parsed_cert[i]->cert_expired, OP_EQ, 0);
    tt_uint_op(parsed_cert[i]->cert_valid, OP_EQ, 0);

    /* Expired */
    tt_int_op(tor_cert_checksig(parsed_cert[i], &kp1.pubkey, now + 30000),
              OP_LT, 0);
    tt_uint_op(parsed_cert[i]->cert_expired, OP_EQ, 1);
    parsed_cert[i]->cert_expired = 0;

    /* Wrong key */
    tt_int_op(tor_cert_checksig(parsed_cert[i], &kp2.pubkey, now), OP_LT, 0);
    tt_uint_op(parsed_cert[i]->sig_bad, OP_EQ, 1);
    parsed_cert[i]->sig_bad = 0;

    /* Missing key */
    int ok = tor_cert_checksig(parsed_cert[i], NULL, now);
    tt_int_op(ok < 0, OP_EQ, i == 0);
    tt_uint_op(parsed_cert[i]->sig_bad, OP_EQ, 0);
    tt_assert(parsed_cert[i]->sig_ok == (i != 0));
    tt_assert(parsed_cert[i]->cert_valid == (i != 0));
    parsed_cert[i]->sig_bad = 0;
    parsed_cert[i]->sig_ok = 0;
    parsed_cert[i]->cert_valid = 0;

    /* Right key */
    tt_int_op(tor_cert_checksig(parsed_cert[i], &kp1.pubkey, now), OP_EQ, 0);
    tt_uint_op(parsed_cert[i]->sig_bad, OP_EQ, 0);
    tt_uint_op(parsed_cert[i]->sig_ok, OP_EQ, 1);
    tt_uint_op(parsed_cert[i]->cert_expired, OP_EQ, 0);
    tt_uint_op(parsed_cert[i]->cert_valid, OP_EQ, 1);
  }

  /* Now try some junky certs. */
  /* - Truncated */
  nocert = tor_cert_parse(cert[0]->encoded, cert[0]->encoded_len-1);
  tt_ptr_op(NULL, OP_EQ, nocert);

  /* - First byte modified */
  cert[0]->encoded[0] = 99;
  nocert = tor_cert_parse(cert[0]->encoded, cert[0]->encoded_len);
  tt_ptr_op(NULL, OP_EQ, nocert);
  cert[0]->encoded[0] = 1;

  /* - Extra byte at the end*/
  junk = tor_malloc_zero(cert[0]->encoded_len + 1);
  memcpy(junk, cert[0]->encoded, cert[0]->encoded_len);
  nocert = tor_cert_parse(junk, cert[0]->encoded_len+1);
  tt_ptr_op(NULL, OP_EQ, nocert);

  /* - Multiple signing key instances */
  tor_free(junk);
  junk = tor_malloc_zero(104 + 36 * 2);
  junk[0] = 1; /* version */
  junk[1] = 5; /* cert type */
  junk[6] = 1; /* key type */
  junk[39] = 2; /* n_extensions */
  junk[41] = 32; /* extlen */
  junk[42] = 4; /* exttype */
  junk[77] = 32; /* extlen */
  junk[78] = 4; /* exttype */
  nocert = tor_cert_parse(junk, 104 + 36 * 2);
  tt_ptr_op(NULL, OP_EQ, nocert);

 done:
  tor_cert_free(cert[0]);
  tor_cert_free(cert[1]);
  tor_cert_free(parsed_cert[0]);
  tor_cert_free(parsed_cert[1]);
  tor_cert_free(nocert);
  tor_free(junk);
  tor_free(base64);
}