Пример #1
0
/** Validate every signature among those in <b>checkable</b>, which contains
 * exactly <b>n_checkable</b> elements.  If <b>okay_out</b> is non-NULL, set
 * the i'th element of <b>okay_out</b> to 1 if the i'th element of
 * <b>checkable</b> is valid, and to 0 otherwise.  Return 0 if every signature
 * was valid. Otherwise return -N, where N is the number of invalid
 * signatures.
 */
int
ed25519_checksig_batch(int *okay_out,
                       const ed25519_checkable_t *checkable,
                       int n_checkable)
{
  int res, i;

  res = 0;
  for (i = 0; i < n_checkable; ++i) {
    const ed25519_checkable_t *ch = &checkable[i];
    int r = ed25519_checksig(&ch->signature, ch->msg, ch->len, ch->pubkey);
    if (r < 0)
      --res;
    if (okay_out)
      okay_out[i] = (r == 0);
  }

#if 0
  /* This is how we'd do it if we were using ed25519_donna.  I'll keep this
   * code around here in case we ever do that. */
  const uint8_t **ms;
  size_t *lens;
  const uint8_t **pks;
  const uint8_t **sigs;
  int *oks;

  ms = tor_malloc(sizeof(uint8_t*)*n_checkable);
  lens = tor_malloc(sizeof(size_t)*n_checkable);
  pks = tor_malloc(sizeof(uint8_t*)*n_checkable);
  sigs = tor_malloc(sizeof(uint8_t*)*n_checkable);
  oks = okay_out ? okay_out : tor_malloc(sizeof(int)*n_checkable);

  for (i = 0; i < n_checkable; ++i) {
    ms[i] = checkable[i].msg;
    lens[i] = checkable[i].len;
    pks[i] = checkable[i].pubkey->pubkey;
    sigs[i] = checkable[i].signature.sig;
    oks[i] = 0;
  }

  ed25519_sign_open_batch_donna_fb(ms, lens, pks, sigs, n_checkable, oks);

  res = 0;
  for (i = 0; i < n_checkable; ++i) {
    /* XXX/yawning: Propagate to okay_out? */
    if (!oks[i])
      --res;
  }

  tor_free(ms);
  tor_free(lens);
  tor_free(pks);
  if (! okay_out)
    tor_free(oks);
#endif

  return res;
}
Пример #2
0
static void
bench_ed25519_impl(void)
{
  uint64_t start, end;
  const int iters = 1<<12;
  int i;
  const uint8_t msg[] = "but leaving, could not tell what they had heard";
  ed25519_signature_t sig;
  ed25519_keypair_t kp;
  curve25519_keypair_t curve_kp;
  ed25519_public_key_t pubkey_tmp;

  ed25519_secret_key_generate(&kp.seckey, 0);
  start = perftime();
  for (i = 0; i < iters; ++i) {
    ed25519_public_key_generate(&kp.pubkey, &kp.seckey);
  }
  end = perftime();
  printf("Generate public key: %.2f usec\n",
         MICROCOUNT(start, end, iters));

  start = perftime();
  for (i = 0; i < iters; ++i) {
    ed25519_sign(&sig, msg, sizeof(msg), &kp);
  }
  end = perftime();
  printf("Sign a short message: %.2f usec\n",
         MICROCOUNT(start, end, iters));

  start = perftime();
  for (i = 0; i < iters; ++i) {
    ed25519_checksig(&sig, msg, sizeof(msg), &kp.pubkey);
  }
  end = perftime();
  printf("Verify signature: %.2f usec\n",
         MICROCOUNT(start, end, iters));

  curve25519_keypair_generate(&curve_kp, 0);
  start = perftime();
  for (i = 0; i < iters; ++i) {
    ed25519_public_key_from_curve25519_public_key(&pubkey_tmp,
                                                  &curve_kp.pubkey, 1);
  }
  end = perftime();
  printf("Convert public point from curve25519: %.2f usec\n",
         MICROCOUNT(start, end, iters));

  curve25519_keypair_generate(&curve_kp, 0);
  start = perftime();
  for (i = 0; i < iters; ++i) {
    ed25519_public_blind(&pubkey_tmp, &kp.pubkey, msg);
  }
  end = perftime();
  printf("Blind a public key: %.2f usec\n",
         MICROCOUNT(start, end, iters));
}
Пример #3
0
static void
test_crypto_ed25519_fuzz_donna(void *arg)
{
  const unsigned iters = 1024;
  uint8_t msg[1024];
  unsigned i;
  (void)arg;

  tt_uint_op(iters, OP_EQ, sizeof(msg));
  crypto_rand((char*) msg, sizeof(msg));

  /* Fuzz Ed25519-donna vs ref10, alternating the implementation used to
   * generate keys/sign per iteration.
   */
  for (i = 0; i < iters; ++i) {
    const int use_donna = i & 1;
    uint8_t blinding[32];
    curve25519_keypair_t ckp;
    ed25519_keypair_t kp, kp_blind, kp_curve25519;
    ed25519_public_key_t pk, pk_blind, pk_curve25519;
    ed25519_signature_t sig, sig_blind;
    int bit = 0;

    crypto_rand((char*) blinding, sizeof(blinding));

    /* Impl. A:
     *  1. Generate a keypair.
     *  2. Blinded the keypair.
     *  3. Sign a message (unblinded).
     *  4. Sign a message (blinded).
     *  5. Generate a curve25519 keypair, and convert it to Ed25519.
     */
    ed25519_set_impl_params(use_donna);
    tt_int_op(0, OP_EQ, ed25519_keypair_generate(&kp, i&1));
    tt_int_op(0, OP_EQ, ed25519_keypair_blind(&kp_blind, &kp, blinding));
    tt_int_op(0, OP_EQ, ed25519_sign(&sig, msg, i, &kp));
    tt_int_op(0, OP_EQ, ed25519_sign(&sig_blind, msg, i, &kp_blind));

    tt_int_op(0, OP_EQ, curve25519_keypair_generate(&ckp, i&1));
    tt_int_op(0, OP_EQ, ed25519_keypair_from_curve25519_keypair(
            &kp_curve25519, &bit, &ckp));

    /* Impl. B:
     *  1. Validate the public key by rederiving it.
     *  2. Validate the blinded public key by rederiving it.
     *  3. Validate the unblinded signature (and test a invalid signature).
     *  4. Validate the blinded signature.
     *  5. Validate the public key (from Curve25519) by rederiving it.
     */
    ed25519_set_impl_params(!use_donna);
    tt_int_op(0, OP_EQ, ed25519_public_key_generate(&pk, &kp.seckey));
    tt_mem_op(pk.pubkey, OP_EQ, kp.pubkey.pubkey, 32);

    tt_int_op(0, OP_EQ, ed25519_public_blind(&pk_blind, &kp.pubkey, blinding));
    tt_mem_op(pk_blind.pubkey, OP_EQ, kp_blind.pubkey.pubkey, 32);

    tt_int_op(0, OP_EQ, ed25519_checksig(&sig, msg, i, &pk));
    sig.sig[0] ^= 15;
    tt_int_op(-1, OP_EQ, ed25519_checksig(&sig, msg, sizeof(msg), &pk));

    tt_int_op(0, OP_EQ, ed25519_checksig(&sig_blind, msg, i, &pk_blind));

    tt_int_op(0, OP_EQ, ed25519_public_key_from_curve25519_public_key(
            &pk_curve25519, &ckp.pubkey, bit));
    tt_mem_op(pk_curve25519.pubkey, OP_EQ, kp_curve25519.pubkey.pubkey, 32);
  }

 done:
  ;
}
Пример #4
0
/** Validate every signature among those in <b>checkable</b>, which contains
 * exactly <b>n_checkable</b> elements.  If <b>okay_out</b> is non-NULL, set
 * the i'th element of <b>okay_out</b> to 1 if the i'th element of
 * <b>checkable</b> is valid, and to 0 otherwise.  Return 0 if every signature
 * was valid. Otherwise return -N, where N is the number of invalid
 * signatures.
 */
int
ed25519_checksig_batch(int *okay_out,
                       const ed25519_checkable_t *checkable,
                       int n_checkable)
{
  int i, res;
  const ed25519_impl_t *impl = get_ed_impl();

  if (impl->open_batch == NULL) {
    /* No batch verification implementation available, fake it by checking the
     * each signature individually.
     */
    res = 0;
    for (i = 0; i < n_checkable; ++i) {
      const ed25519_checkable_t *ch = &checkable[i];
      int r = ed25519_checksig(&ch->signature, ch->msg, ch->len, ch->pubkey);
      if (r < 0)
        --res;
      if (okay_out)
        okay_out[i] = (r == 0);
    }
  } else {
    /* ed25519-donna style batch verification available.
     *
     * Theoretically, this should only be called if n_checkable >= 3, since
     * that's the threshold where the batch verification actually kicks in,
     * but the only difference is a few mallocs/frees.
     */
    const uint8_t **ms;
    size_t *lens;
    const uint8_t **pks;
    const uint8_t **sigs;
    int *oks;
    int all_ok;

    ms = tor_malloc(sizeof(uint8_t*)*n_checkable);
    lens = tor_malloc(sizeof(size_t)*n_checkable);
    pks = tor_malloc(sizeof(uint8_t*)*n_checkable);
    sigs = tor_malloc(sizeof(uint8_t*)*n_checkable);
    oks = okay_out ? okay_out : tor_malloc(sizeof(int)*n_checkable);

    for (i = 0; i < n_checkable; ++i) {
      ms[i] = checkable[i].msg;
      lens[i] = checkable[i].len;
      pks[i] = checkable[i].pubkey->pubkey;
      sigs[i] = checkable[i].signature.sig;
      oks[i] = 0;
    }

    res = 0;
    all_ok = impl->open_batch(ms, lens, pks, sigs, n_checkable, oks);
    for (i = 0; i < n_checkable; ++i) {
      if (!oks[i])
        --res;
    }
    /* XXX: For now sanity check oks with the return value.  Once we have
     * more confidence in the code, if `all_ok == 0` we can skip iterating
     * over oks since all the signatures were found to be valid.
     */
    tor_assert(((res == 0) && !all_ok) || ((res < 0) && all_ok));

    tor_free(ms);
    tor_free(lens);
    tor_free(pks);
    tor_free(sigs);
    if (! okay_out)
      tor_free(oks);
  }

  return res;
}