diff options
Diffstat (limited to 'cipher/ecc.c')
-rw-r--r-- | cipher/ecc.c | 107 |
1 files changed, 88 insertions, 19 deletions
diff --git a/cipher/ecc.c b/cipher/ecc.c index e0be2d4f..6a60785f 100644 --- a/cipher/ecc.c +++ b/cipher/ecc.c @@ -117,7 +117,25 @@ nist_generate_key (ECC_secret_key *sk, elliptic_curve_t *E, mpi_ec_t ctx, point_init (&Q); /* Generate a secret. */ - if (ctx->dialect == ECC_DIALECT_ED25519) + /* + * FIXME. It should be something like this: + * + * When the co-factor of the curve is not 1, we guarantee that + * scalar value k is multiple of its co-factor to avoid sub-group + * attack. Also, we make sure that the most significant bit of k + * is 1. + * + * It works for now as we only have two curves which have co-factor!=1; + * Ed25519 and Curve25519. + * Note that we need some a way to get number of bits of the curve to + * set MSB of k. Currently, E.nbits is not precise for this purpuse. + * We also need a way to get co-factor of a curve. + * + * Currently, we distinguish the two curves by ECC_DIALECT_ED25519 + * and MPI_EC_MONTGOMERY, which works, but is not that correct. + */ + if (ctx->dialect == ECC_DIALECT_ED25519 + || E->model == MPI_EC_MONTGOMERY) { char *rndbuf; @@ -156,7 +174,7 @@ nist_generate_key (ECC_secret_key *sk, elliptic_curve_t *E, mpi_ec_t ctx, * possibilities without any loss of security. Note that we don't * do that for Ed25519 so that we do not violate the special * construction of the secret key. */ - if (E->dialect == ECC_DIALECT_ED25519) + if (E->dialect == ECC_DIALECT_ED25519 || E->model == MPI_EC_MONTGOMERY) point_set (&sk->Q, &Q); else { @@ -227,12 +245,8 @@ static void test_keys (ECC_secret_key *sk, unsigned int nbits) { ECC_public_key pk; - gcry_mpi_t test = mpi_new (nbits); + gcry_mpi_t test; mpi_point_struct R_; - gcry_mpi_t c = mpi_new (nbits); - gcry_mpi_t out = mpi_new (nbits); - gcry_mpi_t r = mpi_new (nbits); - gcry_mpi_t s = mpi_new (nbits); if (DBG_CIPHER) log_debug ("Testing key.\n"); @@ -243,27 +257,82 @@ test_keys (ECC_secret_key *sk, unsigned int nbits) point_init (&pk.Q); point_set (&pk.Q, &sk->Q); - _gcry_mpi_randomize (test, nbits, GCRY_WEAK_RANDOM); + if (sk->E.model == MPI_EC_MONTGOMERY) + /* It's ECDH only. */ + /* FIXME: see the FIXME comment of nist_generate_key. + * Here, we generate ephemeral key, same handling is needed for secret. + */ + { + char *rndbuf; + gcry_mpi_t x0, x1; + mpi_ec_t ec; + + test = mpi_new (256); + rndbuf = _gcry_random_bytes (32, GCRY_WEAK_RANDOM); + rndbuf[0] &= 0x7f; /* Clear bit 255. */ + rndbuf[0] |= 0x40; /* Set bit 254. */ + rndbuf[31] &= 0xf8; /* Clear bits 2..0 so that d mod 8 == 0 */ + _gcry_mpi_set_buffer (test, rndbuf, 32, 0); + xfree (rndbuf); + + ec = _gcry_mpi_ec_p_internal_new (pk.E.model, pk.E.dialect, 0, + pk.E.p, pk.E.a, pk.E.b); + x0 = mpi_new (0); + x1 = mpi_new (0); - if (_gcry_ecc_ecdsa_sign (test, sk, r, s, 0, 0) ) - log_fatal ("ECDSA operation: sign failed\n"); + /* R_ = kQ <=> R_ = kdG */ + _gcry_mpi_ec_mul_point (&R_, test, &pk.Q, ec); + if (_gcry_mpi_ec_get_affine (x0, NULL, &R_, ec)) + log_fatal ("ecdh: Failed to get affine coordinates for kQ\n"); - if (_gcry_ecc_ecdsa_verify (test, &pk, r, s)) - { - log_fatal ("ECDSA operation: sign, verify failed\n"); + /* R_ = kG */ + _gcry_mpi_ec_mul_point (&R_, test, &pk.E.G, ec); + /* R_ = dkG */ + _gcry_mpi_ec_mul_point (&R_, sk->d, &R_, ec); + + if (_gcry_mpi_ec_get_affine (x1, NULL, &R_, ec)) + log_fatal ("ecdh: Failed to get affine coordinates for dkG\n"); + + if (mpi_cmp (x0, x1)) + { + log_fatal ("ECDH test failed.\n"); + } + + mpi_free (x0); + mpi_free (x1); + _gcry_mpi_ec_free (ec); } + else + { + gcry_mpi_t c = mpi_new (nbits); + gcry_mpi_t out = mpi_new (nbits); + gcry_mpi_t r = mpi_new (nbits); + gcry_mpi_t s = mpi_new (nbits); - if (DBG_CIPHER) - log_debug ("ECDSA operation: sign, verify ok.\n"); + test = mpi_new (nbits); + _gcry_mpi_randomize (test, nbits, GCRY_WEAK_RANDOM); + + if (_gcry_ecc_ecdsa_sign (test, sk, r, s, 0, 0) ) + log_fatal ("ECDSA operation: sign failed\n"); + + if (_gcry_ecc_ecdsa_verify (test, &pk, r, s)) + { + log_fatal ("ECDSA operation: sign, verify failed\n"); + } + + if (DBG_CIPHER) + log_debug ("ECDSA operation: sign, verify ok.\n"); + + mpi_free (s); + mpi_free (r); + mpi_free (out); + mpi_free (c); + } point_free (&pk.Q); _gcry_ecc_curve_free (&pk.E); point_free (&R_); - mpi_free (s); - mpi_free (r); - mpi_free (out); - mpi_free (c); mpi_free (test); } |