/**
 * Helper: implements keypin_check and keypin_check_and_add.
 */
static int
keypin_check_and_add_impl(const uint8_t *rsa_id_digest,
                          const uint8_t *ed25519_id_key,
                          const int do_not_add,
                          const int replace)
{
  keypin_ent_t search, *ent;
  memset(&search, 0, sizeof(search));
  memcpy(search.rsa_id, rsa_id_digest, sizeof(search.rsa_id));
  memcpy(search.ed25519_key, ed25519_id_key, sizeof(search.ed25519_key));

  /* Search by RSA key digest first */
  ent = HT_FIND(rsamap, &the_rsa_map, &search);
  if (ent) {
    tor_assert(fast_memeq(ent->rsa_id, rsa_id_digest, sizeof(ent->rsa_id)));
    if (tor_memeq(ent->ed25519_key, ed25519_id_key,sizeof(ent->ed25519_key))) {
      return KEYPIN_FOUND; /* Match on both keys. Great. */
    } else {
      if (!replace)
        return KEYPIN_MISMATCH; /* Found RSA with different Ed key */
    }
  }

  /* See if we know a different RSA key for this ed key */
  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. */
  if (do_not_add)
    return KEYPIN_NOT_FOUND;

  ent = tor_memdup(&search, sizeof(search));
  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;
}
Exemple #2
0
int
should_make_new_ed_keys(const or_options_t *options, const time_t now)
{
  if (!master_identity_key ||
      !master_signing_key ||
      !current_auth_key ||
      !link_cert_cert ||
      EXPIRES_SOON(signing_key_cert, options->TestingSigningKeySlop) ||
      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;
}
Exemple #3
0
static void
bench_dh(void)
{
  const int iters = 1<<10;
  int i;
  uint64_t start, end;

  reset_perftime();
  start = perftime();
  for (i = 0; i < iters; ++i) {
    char dh_pubkey_a[DH_BYTES], dh_pubkey_b[DH_BYTES];
    char secret_a[DH_BYTES], secret_b[DH_BYTES];
    ssize_t slen_a, slen_b;
    crypto_dh_t *dh_a = crypto_dh_new(DH_TYPE_TLS);
    crypto_dh_t *dh_b = crypto_dh_new(DH_TYPE_TLS);
    crypto_dh_generate_public(dh_a);
    crypto_dh_generate_public(dh_b);
    crypto_dh_get_public(dh_a, dh_pubkey_a, sizeof(dh_pubkey_a));
    crypto_dh_get_public(dh_b, dh_pubkey_b, sizeof(dh_pubkey_b));
    slen_a = crypto_dh_compute_secret(LOG_NOTICE,
                                      dh_a, dh_pubkey_b, sizeof(dh_pubkey_b),
                                      secret_a, sizeof(secret_a));
    slen_b = crypto_dh_compute_secret(LOG_NOTICE,
                                      dh_b, dh_pubkey_a, sizeof(dh_pubkey_a),
                                      secret_b, sizeof(secret_b));
    tor_assert(slen_a == slen_b);
    tor_assert(fast_memeq(secret_a, secret_b, slen_a));
    crypto_dh_free(dh_a);
    crypto_dh_free(dh_b);
  }
  end = perftime();
  printf("Complete DH handshakes (1024 bit, public and private ops):\n"
         "      %f millisec each.\n", NANOCOUNT(start, end, iters)/1e6);
}
Exemple #4
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;
}
Exemple #5
0
static routerstatus_t *
mock_router_get_status_by_digest(networkstatus_t *c, const char *d)
{
  (void) c;
  ++mock_rgsbd_called;

  if (fast_memeq(d, "\x5d\x76", 2)) {
    memcpy(mock_rgsbd_val_a->descriptor_digest, d, 32);
    return mock_rgsbd_val_a;
  } else if (fast_memeq(d, "\x20\xd1", 2)) {
    memcpy(mock_rgsbd_val_b->descriptor_digest, d, 32);
    return mock_rgsbd_val_b;
  } else {
    return NULL;
  }
}
Exemple #6
0
/**
 * Given a curve25519 keypair in <b>inp</b>, generate a corresponding
 * ed25519 keypair in <b>out</b>, and set <b>signbit_out</b> to the
 * sign bit of the X coordinate of the ed25519 key.
 *
 * NOTE THAT IT IS PROBABLY NOT SAFE TO USE THE GENERATED KEY FOR ANYTHING
 * OUTSIDE OF WHAT'S PRESENTED IN PROPOSAL 228.  In particular, it's probably
 * not a great idea to use it to sign attacker-supplied anything.
 */
int
ed25519_keypair_from_curve25519_keypair(ed25519_keypair_t *out,
                                        int *signbit_out,
                                        const curve25519_keypair_t *inp)
{
  const char string[] = "Derive high part of ed25519 key from curve25519 key";
  ed25519_public_key_t pubkey_check;
  SHA512_CTX ctx;
  uint8_t sha512_output[64];

  memcpy(out->seckey.seckey, inp->seckey.secret_key, 32);
  SHA512_Init(&ctx);
  SHA512_Update(&ctx, out->seckey.seckey, 32);
  SHA512_Update(&ctx, string, sizeof(string));
  SHA512_Final(sha512_output, &ctx);
  memcpy(out->seckey.seckey + 32, sha512_output, 32);

  ed25519_public_key_generate(&out->pubkey, &out->seckey);

  *signbit_out = out->pubkey.pubkey[31] >> 7;

  ed25519_public_key_from_curve25519_public_key(&pubkey_check, &inp->pubkey,
                                                *signbit_out);

  tor_assert(fast_memeq(pubkey_check.pubkey, out->pubkey.pubkey, 32));

  memwipe(&pubkey_check, 0, sizeof(pubkey_check));
  memwipe(&ctx, 0, sizeof(ctx));
  memwipe(sha512_output, 0, sizeof(sha512_output));

  return 0;
}
Exemple #7
0
static void
test_crypto_curve25519_persist(void *arg)
{
  curve25519_keypair_t keypair, keypair2;
  char *fname = tor_strdup(get_fname("curve25519_keypair"));
  char *tag = NULL;
  char *content = NULL;
  const char *cp;
  struct stat st;
  size_t taglen;

  (void)arg;

  tt_int_op(0,==,curve25519_keypair_generate(&keypair, 0));

  tt_int_op(0,==,curve25519_keypair_write_to_file(&keypair, fname, "testing"));
  tt_int_op(0,==,curve25519_keypair_read_from_file(&keypair2, &tag, fname));
  tt_str_op(tag,==,"testing");
  tor_free(tag);

  test_memeq(keypair.pubkey.public_key,
             keypair2.pubkey.public_key,
             CURVE25519_PUBKEY_LEN);
  test_memeq(keypair.seckey.secret_key,
             keypair2.seckey.secret_key,
             CURVE25519_SECKEY_LEN);

  content = read_file_to_str(fname, RFTS_BIN, &st);
  tt_assert(content);
  taglen = strlen("== c25519v1: testing ==");
  tt_int_op(st.st_size, ==, 32+CURVE25519_PUBKEY_LEN+CURVE25519_SECKEY_LEN);
  tt_assert(fast_memeq(content, "== c25519v1: testing ==", taglen));
  tt_assert(tor_mem_is_zero(content+taglen, 32-taglen));
  cp = content + 32;
  test_memeq(keypair.seckey.secret_key,
             cp,
             CURVE25519_SECKEY_LEN);
  cp += CURVE25519_SECKEY_LEN;
  test_memeq(keypair.pubkey.public_key,
             cp,
             CURVE25519_SECKEY_LEN);

  tor_free(fname);
  fname = tor_strdup(get_fname("bogus_keypair"));

  tt_int_op(-1, ==, curve25519_keypair_read_from_file(&keypair2, &tag, fname));
  tor_free(tag);

  content[69] ^= 0xff;
  tt_int_op(0, ==, write_bytes_to_file(fname, content, (size_t)st.st_size, 1));
  tt_int_op(-1, ==, curve25519_keypair_read_from_file(&keypair2, &tag, fname));

 done:
  tor_free(fname);
  tor_free(content);
  tor_free(tag);
}
Exemple #8
0
/* We just received a commit from the vote of authority with
 * <b>identity_digest</b>. Return 1 if this commit is authorititative that
 * is, it belongs to the authority that voted it. Else return 0 if not. */
STATIC int
commit_is_authoritative(const sr_commit_t *commit,
                        const char *voter_key)
{
  tor_assert(commit);
  tor_assert(voter_key);

  return fast_memeq(commit->rsa_identity, voter_key,
                    sizeof(commit->rsa_identity));
}
Exemple #9
0
/** Try to tell whether the <b>in_len</b>-byte string in <b>in</b> is likely
 * to be compressed or not.  If it is, return the likeliest compression method.
 * Otherwise, return UNKNOWN_METHOD.
 */
compress_method_t
detect_compression_method(const char *in, size_t in_len)
{
  if (in_len > 2 && fast_memeq(in, "\x1f\x8b", 2)) {
    return GZIP_METHOD;
  } else if (in_len > 2 && (in[0] & 0x0f) == 8 &&
             (ntohs(get_uint16(in)) % 31) == 0) {
    return ZLIB_METHOD;
  } else {
    return UNKNOWN_METHOD;
  }
}
Exemple #10
0
/**
 * Given an ed25519 keypair in <b>inp</b>, generate a corresponding
 * ed25519 keypair in <b>out</b>, blinded by the corresponding 32-byte input
 * in 'param'.
 *
 * Tor uses key blinding for the "next-generation" hidden services design:
 * service descriptors are encrypted with a key derived from the service's
 * long-term public key, and then signed with (and stored at a position
 * indexed by) a short-term key derived by blinding the long-term keys.
 */
int
ed25519_keypair_blind(ed25519_keypair_t *out,
                      const ed25519_keypair_t *inp,
                      const uint8_t *param)
{
  ed25519_public_key_t pubkey_check;

  get_ed_impl()->blind_secret_key(out->seckey.seckey,
                                  inp->seckey.seckey, param);

  ed25519_public_blind(&pubkey_check, &inp->pubkey, param);
  ed25519_public_key_generate(&out->pubkey, &out->seckey);

  tor_assert(fast_memeq(pubkey_check.pubkey, out->pubkey.pubkey, 32));

  memwipe(&pubkey_check, 0, sizeof(pubkey_check));

  return 0;
}
Exemple #11
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;
}
Exemple #12
0
static void
bench_ecdh_impl(int nid, const char *name)
{
  const int iters = 1<<10;
  int i;
  uint64_t start, end;

  reset_perftime();
  start = perftime();
  for (i = 0; i < iters; ++i) {
    char secret_a[DH_BYTES], secret_b[DH_BYTES];
    ssize_t slen_a, slen_b;
    EC_KEY *dh_a = EC_KEY_new_by_curve_name(nid);
    EC_KEY *dh_b = EC_KEY_new_by_curve_name(nid);
    if (!dh_a || !dh_b) {
      puts("Skipping.  (No implementation?)");
      return;
    }

    EC_KEY_generate_key(dh_a);
    EC_KEY_generate_key(dh_b);
    slen_a = ECDH_compute_key(secret_a, DH_BYTES,
                              EC_KEY_get0_public_key(dh_b), dh_a,
                              NULL);
    slen_b = ECDH_compute_key(secret_b, DH_BYTES,
                              EC_KEY_get0_public_key(dh_a), dh_b,
                              NULL);

    tor_assert(slen_a == slen_b);
    tor_assert(fast_memeq(secret_a, secret_b, slen_a));
    EC_KEY_free(dh_a);
    EC_KEY_free(dh_b);
  }
  end = perftime();
  printf("Complete ECDH %s handshakes (2 public and 2 private ops):\n"
         "      %f millisec each.\n", name, NANOCOUNT(start, end, iters)/1e6);
}
Exemple #13
0
static bool
chunk_eq(const chunk_t *a, const chunk_t *b)
{
  return a->len == b->len && fast_memeq(a->buf, b->buf, a->len);
}