Exemplo n.º 1
0
/** Check whether the ed25519-based curve25519 basepoint optimization seems to
 * be working. If so, return 0; otherwise return -1. */
static int
curve25519_basepoint_spot_check(void)
{
  static const uint8_t alicesk[32] = {
    0x77,0x07,0x6d,0x0a,0x73,0x18,0xa5,0x7d,
    0x3c,0x16,0xc1,0x72,0x51,0xb2,0x66,0x45,
    0xdf,0x4c,0x2f,0x87,0xeb,0xc0,0x99,0x2a,
    0xb1,0x77,0xfb,0xa5,0x1d,0xb9,0x2c,0x2a
  };
  static const uint8_t alicepk[32] = {
    0x85,0x20,0xf0,0x09,0x89,0x30,0xa7,0x54,
    0x74,0x8b,0x7d,0xdc,0xb4,0x3e,0xf7,0x5a,
    0x0d,0xbf,0x3a,0x0d,0x26,0x38,0x1a,0xf4,
    0xeb,0xa4,0xa9,0x8e,0xaa,0x9b,0x4e,0x6a
  };
  const int loop_max=200;
  int save_use_ed = curve25519_use_ed;
  unsigned char e1[32] = { 5 };
  unsigned char e2[32] = { 5 };
  unsigned char x[32],y[32];
  int i;
  int r=0;

  /* Check the most basic possible sanity via the test secret/public key pair
   * used in "Cryptography in NaCl - 2. Secret keys and public keys".  This
   * may catch catastrophic failures on systems where Curve25519 is expensive,
   * without requiring a ton of key generation.
   */
  curve25519_use_ed = 1;
  r |= curve25519_basepoint_impl(x, alicesk);
  if (fast_memneq(x, alicepk, 32))
    goto fail;

  /* Ok, the optimization appears to produce passable results, try a few more
   * values, maybe there's something subtle wrong.
   */
  for (i = 0; i < loop_max; ++i) {
    curve25519_use_ed = 0;
    r |= curve25519_basepoint_impl(x, e1);
    curve25519_use_ed = 1;
    r |= curve25519_basepoint_impl(y, e2);
    if (fast_memneq(x,y,32))
      goto fail;
    memcpy(e1, x, 32);
    memcpy(e2, x, 32);
  }

  goto end;
 fail:
  r = -1;
 end:
  curve25519_use_ed = save_use_ed;
  return r;
}
Exemplo n.º 2
0
/** Test the OpenSSL counter mode implementation to see whether it has the
 * counter-mode bug from OpenSSL 1.0.0. If the implementation works, then
 * we will use it for future encryption/decryption operations.
 *
 * We can't just look at the OpenSSL version, since some distributions update
 * their OpenSSL packages without changing the version number.
 **/
int
evaluate_ctr_for_aes(void)
{
  /* Result of encrypting an all-zero block with an all-zero 128-bit AES key.
   * This should be the same as encrypting an all-zero block with an all-zero
   * 128-bit AES key in counter mode, starting at position 0 of the stream.
   */
  static const unsigned char encrypt_zero[] =
    "\x66\xe9\x4b\xd4\xef\x8a\x2c\x3b\x88\x4c\xfa\x59\xca\x34\x2b\x2e";
  unsigned char zero[16];
  unsigned char output[16];
  unsigned char ivec[16];
  unsigned char ivec_tmp[16];
  unsigned int pos, i;
  AES_KEY key;
  memset(zero, 0, sizeof(zero));
  memset(ivec, 0, sizeof(ivec));
  AES_set_encrypt_key(zero, 128, &key);

  pos = 0;
  /* Encrypting a block one byte at a time should make the error manifest
   * itself for known bogus openssl versions. */
  for (i=0; i<16; ++i)
    AES_ctr128_encrypt(&zero[i], &output[i], 1, &key, ivec, ivec_tmp, &pos);

  if (fast_memneq(output, encrypt_zero, 16)) {
    /* Counter mode is buggy */
    log_err(LD_CRYPTO, "This OpenSSL has a buggy version of counter mode; "
                  "quitting tor.");
    exit(1);
  }
  return 0;
}
Exemplo n.º 3
0
/**
 * 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;
}
Exemplo n.º 4
0
/* Make sure that the commitment and reveal information in <b>commit</b>
 * match. If they match return 0, return -1 otherwise. This function MUST be
 * used everytime we receive a new reveal value. Furthermore, the commit
 * object MUST have a reveal value and the hash of the reveal value. */
STATIC int
verify_commit_and_reveal(const sr_commit_t *commit)
{
  tor_assert(commit);

  log_debug(LD_DIR, "SR: Validating commit from authority %s",
            sr_commit_get_rsa_fpr(commit));

  /* Check that the timestamps match. */
  if (commit->commit_ts != commit->reveal_ts) {
    log_warn(LD_BUG, "SR: Commit timestamp %" PRIu64 " doesn't match reveal "
                     "timestamp %" PRIu64, commit->commit_ts,
             commit->reveal_ts);
    goto invalid;
  }

  /* Verify that the hashed_reveal received in the COMMIT message, matches
   * the reveal we just received. */
  {
    /* We first hash the reveal we just received. */
    char received_hashed_reveal[sizeof(commit->hashed_reveal)];

    /* Only sha3-256 is supported. */
    if (commit->alg != SR_DIGEST_ALG) {
      goto invalid;
    }

    /* Use the invariant length since the encoded reveal variable has an
     * extra byte for the NUL terminated byte. */
    if (crypto_digest256(received_hashed_reveal, commit->encoded_reveal,
                         SR_REVEAL_BASE64_LEN, commit->alg) < 0) {
      /* Unable to digest the reveal blob, this is unlikely. */
      goto invalid;
    }

    /* Now compare that with the hashed_reveal we received in COMMIT. */
    if (fast_memneq(received_hashed_reveal, commit->hashed_reveal,
                    sizeof(received_hashed_reveal))) {
      log_warn(LD_BUG, "SR: Received reveal value from authority %s "
                       "doesn't match the commit value.",
               sr_commit_get_rsa_fpr(commit));
      goto invalid;
    }
  }

  return 0;
 invalid:
  return -1;
}
Exemplo n.º 5
0
/** Check whether the given Ed25519 implementation seems to be working.
 * If so, return 0; otherwise return -1. */
static int
ed25519_impl_spot_check(void)
{
  static const uint8_t alicesk[32] = {
    0xc5,0xaa,0x8d,0xf4,0x3f,0x9f,0x83,0x7b,
    0xed,0xb7,0x44,0x2f,0x31,0xdc,0xb7,0xb1,
    0x66,0xd3,0x85,0x35,0x07,0x6f,0x09,0x4b,
    0x85,0xce,0x3a,0x2e,0x0b,0x44,0x58,0xf7
  };
  static const uint8_t alicepk[32] = {
    0xfc,0x51,0xcd,0x8e,0x62,0x18,0xa1,0xa3,
    0x8d,0xa4,0x7e,0xd0,0x02,0x30,0xf0,0x58,
    0x08,0x16,0xed,0x13,0xba,0x33,0x03,0xac,
    0x5d,0xeb,0x91,0x15,0x48,0x90,0x80,0x25
  };
  static const uint8_t alicemsg[2] = { 0xaf, 0x82 };
  static const uint8_t alicesig[64] = {
    0x62,0x91,0xd6,0x57,0xde,0xec,0x24,0x02,
    0x48,0x27,0xe6,0x9c,0x3a,0xbe,0x01,0xa3,
    0x0c,0xe5,0x48,0xa2,0x84,0x74,0x3a,0x44,
    0x5e,0x36,0x80,0xd7,0xdb,0x5a,0xc3,0xac,
    0x18,0xff,0x9b,0x53,0x8d,0x16,0xf2,0x90,
    0xae,0x67,0xf7,0x60,0x98,0x4d,0xc6,0x59,
    0x4a,0x7c,0x15,0xe9,0x71,0x6e,0xd2,0x8d,
    0xc0,0x27,0xbe,0xce,0xea,0x1e,0xc4,0x0a
  };
  const ed25519_impl_t *impl = get_ed_impl();
  uint8_t sk[ED25519_SECKEY_LEN];
  uint8_t pk[ED25519_PUBKEY_LEN];
  uint8_t sig[ED25519_SIG_LEN];
  int r = 0;

  /* Some implementations (eg: The modified Ed25519-donna) have handy self-test
   * code that sanity-checks the internals.  If present, use that to screen out
   * catastrophic errors like massive compiler failure.
   */
  if (impl->selftest && impl->selftest() != 0)
    goto fail;

  /* Validate results versus known answer tests.  People really should be
   * running "make test" instead of relying on this, but it's better than
   * nothing.
   *
   * Test vectors taken from "EdDSA & Ed25519 - 6. Test Vectors for Ed25519
   * (TEST3)" (draft-josefsson-eddsa-ed25519-03).
   */

  /* Key expansion, public key derivation. */
  if (impl->seckey_expand(sk, alicesk) < 0)
    goto fail;
  if (impl->pubkey(pk, sk) < 0)
    goto fail;
  if (fast_memneq(pk, alicepk, ED25519_PUBKEY_LEN))
    goto fail;

  /* Signing, verification. */
  if (impl->sign(sig, alicemsg, sizeof(alicemsg), sk, pk) < 0)
    return -1;
  if (fast_memneq(sig, alicesig, ED25519_SIG_LEN))
    return -1;
  if (impl->open(sig, alicemsg, sizeof(alicemsg), pk) < 0)
    return -1;

  /* XXX/yawning: Someone that's more paranoid than I am, can write "Assume
   * ref0 is cannonical, and fuzz impl against it" if they want, but I doubt
   * that will catch anything that the known answer tests won't.
   */
  goto end;

 fail:
  r = -1;
 end:
  return r;
}