diff options
author | Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> | 2013-07-31 17:20:58 +0400 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2013-07-31 17:47:15 +0200 |
commit | 10dfa41b43a906031bc674ea41cd3073701011f3 (patch) | |
tree | cbc2b6be94439759fca3bd24a204b8e5882821db /cipher/ecc.c | |
parent | 43320961a8751ee28dc95cdb0ae01ea8a7ff7f91 (diff) | |
download | libgcrypt-10dfa41b43a906031bc674ea41cd3073701011f3.tar.gz |
Correct checks for ecc secret key
* cipher/ecc.c (check_secret_key): replace wrong comparison of Q and
sk->Q points with correct one.
--
Currently check_secret_keys compares pointers to coordinates of Q
(calculated) and sk->Q (provided) points. Instead it should convert them
to affine representations and use mpi_cmp to compare coordinates.
This has an implication that keys that were (erroneously) verified as
valid could now become invalid.
Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
Diffstat (limited to 'cipher/ecc.c')
-rw-r--r-- | cipher/ecc.c | 40 |
1 files changed, 37 insertions, 3 deletions
diff --git a/cipher/ecc.c b/cipher/ecc.c index 071879df..375eeafa 100644 --- a/cipher/ecc.c +++ b/cipher/ecc.c @@ -675,6 +675,7 @@ check_secret_key (ECC_secret_key * sk) int rc = 1; mpi_point_struct Q; gcry_mpi_t y_2, y2; + gcry_mpi_t x1, x2; mpi_ec_t ctx = NULL; point_init (&Q); @@ -684,6 +685,8 @@ check_secret_key (ECC_secret_key * sk) /* G in E(F_p) */ y_2 = gen_y_2 (sk->E.G.x, &sk->E); /* y^2=x^3+a*x+b */ y2 = mpi_alloc (0); + x1 = mpi_alloc (0); + x2 = mpi_alloc (0); mpi_mulm (y2, sk->E.G.y, sk->E.G.y, sk->E.p); /* y^2=y*y */ if (mpi_cmp (y_2, y2)) { @@ -717,17 +720,48 @@ check_secret_key (ECC_secret_key * sk) } /* pubkey = [d]G over E */ _gcry_mpi_ec_mul_point (&Q, sk->d, &sk->E.G, ctx); - if ((Q.x == sk->Q.x) && (Q.y == sk->Q.y) && (Q.z == sk->Q.z)) + + if (_gcry_mpi_ec_get_affine (x1, y_2, &Q, ctx)) { if (DBG_CIPHER) - log_debug - ("Bad check: There is NO correspondence between 'd' and 'Q'!\n"); + log_debug ("Bad check: Q can not be a Point at Infinity!\n"); goto leave; } + + /* Fast path for loaded secret keys - sk->Q is already in affine coordinates */ + if (!mpi_cmp_ui (sk->Q.z, 1)) + { + if (mpi_cmp (x1, sk->Q.x) || mpi_cmp (y_2, sk->Q.y)) + { + if (DBG_CIPHER) + log_debug + ("Bad check: There is NO correspondence between 'd' and 'Q'!\n"); + goto leave; + } + } + else + { + if (_gcry_mpi_ec_get_affine (x2, y2, &sk->Q, ctx)) + { + if (DBG_CIPHER) + log_debug ("Bad check: Q can not be a Point at Infinity!\n"); + goto leave; + } + + if (mpi_cmp (x1, x2) || mpi_cmp (y_2, y2)) + { + if (DBG_CIPHER) + log_debug + ("Bad check: There is NO correspondence between 'd' and 'Q'!\n"); + goto leave; + } + } rc = 0; /* Okay. */ leave: _gcry_mpi_ec_free (ctx); + mpi_free (x2); + mpi_free (x1); mpi_free (y2); mpi_free (y_2); point_free (&Q); |