diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2011-11-05 21:22:17 +0100 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2011-11-05 21:28:58 +0100 |
commit | 124dfe0de2321a4c4a3383c8866f6a1dbd45d635 (patch) | |
tree | 4dcc5b51189b0311d77fadcac8785562383e6092 /lib/nettle | |
parent | 5b541a346638429712f8a9db8ced61f1b5ffcec4 (diff) | |
download | gnutls-124dfe0de2321a4c4a3383c8866f6a1dbd45d635.tar.gz |
Verify that received ECDH public key lies on the curve.
Diffstat (limited to 'lib/nettle')
-rw-r--r-- | lib/nettle/Makefile.am | 2 | ||||
-rw-r--r-- | lib/nettle/ecc.h | 8 | ||||
-rw-r--r-- | lib/nettle/ecc_free.c | 2 | ||||
-rw-r--r-- | lib/nettle/ecc_make_key.c | 16 | ||||
-rw-r--r-- | lib/nettle/ecc_projective_check_point.c | 106 | ||||
-rw-r--r-- | lib/nettle/ecc_projective_dbl_point.c | 207 | ||||
-rw-r--r-- | lib/nettle/ecc_sign_hash.c | 2 | ||||
-rw-r--r-- | lib/nettle/pk.c | 38 |
8 files changed, 148 insertions, 233 deletions
diff --git a/lib/nettle/Makefile.am b/lib/nettle/Makefile.am index 86afffc4f9..24552dc943 100644 --- a/lib/nettle/Makefile.am +++ b/lib/nettle/Makefile.am @@ -36,5 +36,5 @@ noinst_LTLIBRARIES = libcrypto.la libcrypto_la_SOURCES = pk.c mpi.c mac.c cipher.c rnd.c init.c egd.c egd.h \ multi.c ecc_free.c ecc.h ecc_make_key.c ecc_shared_secret.c \ ecc_map.c ecc_mulmod.c ecc_points.c ecc_projective_dbl_point_3.c \ - ecc_projective_add_point.c ecc_projective_dbl_point.c \ + ecc_projective_add_point.c ecc_projective_check_point.c \ ecc_sign_hash.c ecc_verify_hash.c gnettle.h diff --git a/lib/nettle/ecc.h b/lib/nettle/ecc.h index ea2b837488..d5a5fa013e 100644 --- a/lib/nettle/ecc.h +++ b/lib/nettle/ecc.h @@ -69,6 +69,7 @@ typedef struct { mpz_t prime; mpz_t order; mpz_t A; + mpz_t B; mpz_t Gx; mpz_t Gy; @@ -79,12 +80,11 @@ typedef struct { mpz_t k; } ecc_key; -int ecc_test(void); void ecc_sizes(int *low, int *high); int ecc_get_size(ecc_key *key); int ecc_make_key(void *random_ctx, nettle_random_func random, ecc_key *key, const ecc_set_type *dp); -int ecc_make_key_ex(void *random_ctx, nettle_random_func random, ecc_key *key, mpz_t prime, mpz_t order, mpz_t A, mpz_t Gx, mpz_t Gy); +int ecc_make_key_ex(void *random_ctx, nettle_random_func random, ecc_key *key, mpz_t prime, mpz_t order, mpz_t A, mpz_t B, mpz_t Gx, mpz_t Gy); void ecc_free(ecc_key *key); int ecc_shared_secret(ecc_key *private_key, ecc_key *public_key, @@ -115,6 +115,10 @@ int ecc_mulmod(mpz_t k, ecc_point *G, ecc_point *R, mpz_t a, mpz_t modulus, int /* map P to affine from projective */ int ecc_map(ecc_point *P, mpz_t modulus); +/* check whether a point lies on the curve */ +int ecc_projective_check_point (ecc_point * P, mpz_t b, mpz_t modulus); + /* helper functions */ int mp_init_multi(mpz_t *a, ...); void mp_clear_multi(mpz_t *a, ...); + diff --git a/lib/nettle/ecc_free.c b/lib/nettle/ecc_free.c index ab04d033db..d5708ddb5e 100644 --- a/lib/nettle/ecc_free.c +++ b/lib/nettle/ecc_free.c @@ -37,7 +37,7 @@ void ecc_free (ecc_key * key) { mp_clear_multi (&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, - &key->prime, &key->order, &key->Gx, &key->Gy, &key->A, NULL); + &key->prime, &key->order, &key->Gx, &key->Gy, &key->A, &key->B, NULL); } /* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_free.c,v $ */ diff --git a/lib/nettle/ecc_make_key.c b/lib/nettle/ecc_make_key.c index 3476276d97..4972eabb30 100644 --- a/lib/nettle/ecc_make_key.c +++ b/lib/nettle/ecc_make_key.c @@ -43,7 +43,7 @@ int ecc_make_key_ex (void *random_ctx, nettle_random_func random, ecc_key * key, - mpz_t prime, mpz_t order, mpz_t A, mpz_t Gx, mpz_t Gy) + mpz_t prime, mpz_t order, mpz_t A, mpz_t B, mpz_t Gx, mpz_t Gy) { int err; ecc_point *base; @@ -67,7 +67,7 @@ ecc_make_key_ex (void *random_ctx, nettle_random_func random, ecc_key * key, /* setup the key variables */ if ((err = mp_init_multi (&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, - &key->prime, &key->order, &key->A, &key->Gx, &key->Gy, + &key->prime, &key->order, &key->A, &key->B, &key->Gx, &key->Gy, NULL)) != 0) { goto ERR_BUF; @@ -85,6 +85,7 @@ ecc_make_key_ex (void *random_ctx, nettle_random_func random, ecc_key * key, mpz_set (key->Gx, Gx); mpz_set (key->Gy, Gy); mpz_set (key->A, A); + mpz_set (key->B, B); mpz_set (base->x, key->Gx); mpz_set (base->y, key->Gy); @@ -111,7 +112,7 @@ ecc_make_key_ex (void *random_ctx, nettle_random_func random, ecc_key * key, goto cleanup; errkey: mp_clear_multi (&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, - &key->order, &key->prime, &key->Gx, &key->Gy, &key->A, + &key->order, &key->prime, &key->Gx, &key->Gy, &key->A, &key->B, NULL); cleanup: ecc_del_point (base); @@ -124,11 +125,11 @@ int ecc_make_key (void *random_ctx, nettle_random_func random, ecc_key * key, const ecc_set_type * dp) { - mpz_t prime, order, Gx, Gy, A; + mpz_t prime, order, Gx, Gy, A, B; int err; /* setup the key variables */ - if ((err = mp_init_multi (&prime, &order, &A, &Gx, &Gy, NULL)) != 0) + if ((err = mp_init_multi (&prime, &order, &A, &B, &Gx, &Gy, NULL)) != 0) { goto cleanup; } @@ -139,10 +140,11 @@ ecc_make_key (void *random_ctx, nettle_random_func random, ecc_key * key, mpz_set_str (Gx, (char *) dp->Gx, 16); mpz_set_str (Gy, (char *) dp->Gy, 16); mpz_set_str (A, (char *) dp->A, 16); + mpz_set_str (B, (char *) dp->B, 16); - err = ecc_make_key_ex (random_ctx, random, key, prime, order, A, Gx, Gy); + err = ecc_make_key_ex (random_ctx, random, key, prime, order, A, B, Gx, Gy); - mp_clear_multi (&prime, &order, &A, &Gx, &Gy, NULL); + mp_clear_multi (&prime, &order, &A, &B, &Gx, &Gy, NULL); cleanup: return err; } diff --git a/lib/nettle/ecc_projective_check_point.c b/lib/nettle/ecc_projective_check_point.c new file mode 100644 index 0000000000..42abeea18b --- /dev/null +++ b/lib/nettle/ecc_projective_check_point.c @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2011 Free Software Foundation, Inc. + * + * This file is part of GNUTLS. + * + * The GNUTLS library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 3 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/> + * + */ + +#include "ecc.h" +#include <gnutls_errors.h> + +#ifdef ECC_SECP_CURVES_ONLY + +/* + @file ecc_projective_check_point.c +*/ + +/* + Checks whether a point lies on the curve y^2 = x^3 - 3x + b + @param P The point to check + @param modulus The modulus of the field the ECC curve is in + @param b The "B" value of the curve + @return 0 on success +*/ +int ecc_projective_check_point (ecc_point * P, mpz_t b, mpz_t modulus) +{ + mpz_t t1, t2, t3; + int err; + + if (P == NULL || b == NULL || modulus == NULL) + return -1; + + if ((err = mp_init_multi (&t1, &t2, &t3, NULL)) != 0) + { + return err; + } + + if (mpz_cmp_ui (P->z, 1) != 0) + { + gnutls_assert (); + return -1; + } + + /* t1 = Z * Z */ + mpz_mul (t1, P->y, P->y); + mpz_mod (t1, t1, modulus); /* t1 = y^2 */ + + mpz_mul (t2, P->x, P->x); + mpz_mod (t2, t2, modulus); + + mpz_mul (t2, P->x, t2); + mpz_mod (t2, t2, modulus); /* t2 = x^3 */ + + mpz_add (t3, P->x, P->x); + if (mpz_cmp (t3, modulus) >= 0) + { + mpz_sub (t3, t3, modulus); + } + + mpz_add (t3, t3, P->x); /* t3 = 3x */ + if (mpz_cmp (t3, modulus) >= 0) + { + mpz_sub (t3, t3, modulus); + } + + mpz_sub (t1, t1, t2); /* t1 = y^2 - x^3 */ + if (mpz_cmp_ui (t1, 0) < 0) + { + mpz_add (t1, t1, modulus); + } + + mpz_add (t1, t1, t3); /* t1 = y^2 - x^3 + 3x */ + if (mpz_cmp (t1, modulus) >= 0) + { + mpz_sub (t1, t1, modulus); + } + + mpz_sub (t1, t1, b); /* t1 = y^2 - x^3 + 3x - b */ + if (mpz_cmp_ui (t1, 0) < 0) + { + mpz_add (t1, t1, modulus); + } + + if (mpz_cmp_ui (t1, 0) != 0) + { + return -1; + } + else + { + return 0; + } +} + +#endif diff --git a/lib/nettle/ecc_projective_dbl_point.c b/lib/nettle/ecc_projective_dbl_point.c deleted file mode 100644 index 2df4e52769..0000000000 --- a/lib/nettle/ecc_projective_dbl_point.c +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright (C) 2011 Free Software Foundation, Inc. - * - * Author: Nikos Mavrogiannopoulos - * - * This file is part of GNUTLS. - * - * The GNUTLS library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 3 of - * the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/> - * - */ - -/* Implements ECC point doubling over Z/pZ for curve y^2 = x^3 + ax + b - */ -#include "ecc.h" - -#ifndef ECC_SECP_CURVES_ONLY - -/* - Double an ECC point - @param P The point to double - @param R [out] The destination of the double - @param a The "a" value from curve - @param modulus The modulus of the field the ECC curve is in - @return 0 on success -*/ -int -ecc_projective_dbl_point (ecc_point * P, ecc_point * R, mpz_t a, - mpz_t modulus) -{ - mpz_t t1, m, s; - int err; - - if (P == NULL || R == NULL || modulus == NULL) - return -1; - - /* - algorithm used: - if (Y == 0) - return POINT_AT_INFINITY - S = 4*X*Y^2 - M = 3*X^2 + a*Z^4 - X' = M^2 - 2*S - Y' = M*(S - X') - 8*Y^4 - Z' = 2*Y*Z - return (X', Y', Z') - */ - - if (mpz_cmp_ui(P->y, 0) == 0) - { - /* point at infinity - * under jacobian coordinates - */ - mpz_set(R->x, 1); - mpz_set(R->y, 1); - mpz_set(R->z, 0); - - return 0; - } - - if ((err = mp_init_multi (&t1, &m, &s, NULL)) != 0) - { - return err; - } - - if (P != R) - { - mpz_set (R->x, P->x); - mpz_set (R->y, P->y); - mpz_set (R->z, P->z); - } - - - /* m = Z * Z */ - mpz_mul (m, R->z, R->z); - mpz_mod (m, m, modulus); - - /* Calculate Z and get rid of it */ - /* Z = Y * Z */ - mpz_mul (R->z, R->y, R->z); - mpz_mod (R->z, R->z, modulus); - /* Z = 2Z */ - mpz_add (R->z, R->z, R->z); - if (mpz_cmp (R->z, modulus) >= 0) - { - mpz_sub (R->z, R->z, modulus); - } - - /* continue with M and S calculations */ - - /* m = m * m = z^4 */ - mpz_mul (m, m, m); - mpz_mod (m, m, modulus); - - /* m = a * m = a*z^4 */ - mpz_mul (m, a, m); - mpz_mod (m, m, modulus); - - /* Y = 2y */ - mpz_add (R->y, R->y, R->y); - if (mpz_cmp (R->y, modulus) >= 0) - { - mpz_sub (R->y, R->y, modulus); - } - - /* Y = Y * Y = 4y^2 */ - mpz_mul (R->y, R->y, R->y); - mpz_mod (R->y, R->y, modulus); - - /* s = X*Y = 4xy^2 */ - mpz_mul (s, R->x, R->y); - mpz_mod (s, s, modulus); - - /* X = x^2 */ - mpz_mul (R->x, R->x, R->x); - mpz_mod (R->x, R->x, modulus); - - /* t1 = 2X = 2x^2 */ - mpz_add (t1, R->x, R->x); - if (mpz_cmp (t1, modulus) >= 0) - { - mpz_sub (t1, t1, modulus); - } - - /* t1 = t1+X = 3X = 3x^2 */ - mpz_add (t1, t1, R->x); - if (mpz_cmp (t1, modulus) >= 0) - { - mpz_sub (t1, t1, modulus); - } - - /* m = t1+m = 3x^2 + a*z^4 */ - mpz_add (m, m, t1); - if (mpz_cmp (m, modulus) >= 0) - { - mpz_sub (m, m, modulus); - } - - /* - X' = M^2 - 2*S - Y' = M*(S - X') - 8*Y^4 - */ - - /* Y = Y*Y = 16y^4 */ - mpz_mul (R->y, R->y, R->y); - mpz_mod (R->y, R->y, modulus); - - /* Y = 8y^4 */ - if (mpz_odd_p (R->y)) - { - mpz_add (R->y, R->y, modulus); - } - mpz_divexact_ui (R->y, R->y, 2); - - /* X = m^2 */ - mpz_mul (R->x, m, m); - mpz_mod (R->x, R->x, modulus); - - /* X = X - s = m^2 - s */ - mpz_sub (R->x, R->x, s); - if (mpz_cmp_ui (R->x, 0) < 0) - { - mpz_add (R->x, R->x, modulus); - } - - /* X = X - s = m^2 - 2s */ - mpz_sub (R->x, R->x, s); - if (mpz_cmp_ui (R->x, 0) < 0) - { - mpz_add (R->x, R->x, modulus); - } - - /* t1 = s - X */ - mpz_sub (t1, s, R->x); - if (mpz_cmp_ui (t1, 0) < 0) - { - mpz_add (t1, t1, modulus); - } - - /* t1 = M * t1 = M * (s-X) */ - mpz_mul (t1, m, t1); - mpz_mod (t1, t1, modulus); - - /* Y = t1 - Y = (M * (s-X)) - 8y^4 */ - mpz_sub (R->y, t1, R->y); - if (mpz_cmp_ui (R->y, 0) < 0) - { - mpz_add (R->y, R->y, modulus); - } - - err = 0; - - mp_clear_multi (&t1, &m, &s, NULL); - return err; -} - -#endif diff --git a/lib/nettle/ecc_sign_hash.c b/lib/nettle/ecc_sign_hash.c index ab7f94309d..04c3f1d0c8 100644 --- a/lib/nettle/ecc_sign_hash.c +++ b/lib/nettle/ecc_sign_hash.c @@ -72,7 +72,7 @@ ecc_sign_hash (const unsigned char *in, unsigned long inlen, { if ((err = ecc_make_key_ex (random_ctx, random, &pubkey, key->prime, - key->order, key->A, key->Gx, key->Gy)) != 0) + key->order, key->A, key->B, key->Gx, key->Gy)) != 0) { goto errnokey; } diff --git a/lib/nettle/pk.c b/lib/nettle/pk.c index 794a2c99be..826c27b064 100644 --- a/lib/nettle/pk.c +++ b/lib/nettle/pk.c @@ -89,11 +89,12 @@ _ecc_params_to_privkey(const gnutls_pk_params_st * pk_params, memcpy(&priv->prime, pk_params->params[0], sizeof(mpz_t)); memcpy(&priv->order, pk_params->params[1], sizeof(mpz_t)); memcpy(&priv->A, pk_params->params[2], sizeof(mpz_t)); - memcpy(&priv->Gx, pk_params->params[3], sizeof(mpz_t)); - memcpy(&priv->Gy, pk_params->params[4], sizeof(mpz_t)); - memcpy(&priv->pubkey.x, pk_params->params[5], sizeof(mpz_t)); - memcpy(&priv->pubkey.y, pk_params->params[6], sizeof(mpz_t)); - memcpy(&priv->k, pk_params->params[7], sizeof(mpz_t)); + memcpy(&priv->B, pk_params->params[3], sizeof(mpz_t)); + memcpy(&priv->Gx, pk_params->params[4], sizeof(mpz_t)); + memcpy(&priv->Gy, pk_params->params[5], sizeof(mpz_t)); + memcpy(&priv->pubkey.x, pk_params->params[6], sizeof(mpz_t)); + memcpy(&priv->pubkey.y, pk_params->params[7], sizeof(mpz_t)); + memcpy(&priv->k, pk_params->params[8], sizeof(mpz_t)); mpz_init_set_ui(priv->pubkey.z, 1); } @@ -110,10 +111,11 @@ _ecc_params_to_pubkey(const gnutls_pk_params_st * pk_params, memcpy(&pub->prime, pk_params->params[0], sizeof(mpz_t)); memcpy(&pub->order, pk_params->params[1], sizeof(mpz_t)); memcpy(&pub->A, pk_params->params[2], sizeof(mpz_t)); - memcpy(&pub->Gx, pk_params->params[3], sizeof(mpz_t)); - memcpy(&pub->Gy, pk_params->params[4], sizeof(mpz_t)); - memcpy(&pub->pubkey.x, pk_params->params[5], sizeof(mpz_t)); - memcpy(&pub->pubkey.y, pk_params->params[6], sizeof(mpz_t)); + memcpy(&pub->B, pk_params->params[3], sizeof(mpz_t)); + memcpy(&pub->Gx, pk_params->params[4], sizeof(mpz_t)); + memcpy(&pub->Gy, pk_params->params[5], sizeof(mpz_t)); + memcpy(&pub->pubkey.x, pk_params->params[6], sizeof(mpz_t)); + memcpy(&pub->pubkey.y, pk_params->params[7], sizeof(mpz_t)); mpz_init_set_ui(pub->pubkey.z, 1); } @@ -138,6 +140,12 @@ static int _wrap_nettle_pk_derive(gnutls_pk_algorithm_t algo, gnutls_datum_t * o _ecc_params_to_pubkey(pub, &ecc_pub); _ecc_params_to_privkey(priv, &ecc_priv); + + if (ecc_projective_check_point(&ecc_pub.pubkey, pub->params[3], pub->params[0]) != 0) + { + ret = gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + goto ecc_cleanup; + } sz = ECC_BUF_SIZE; out->data = gnutls_malloc(sz); @@ -792,6 +800,7 @@ rsa_fail: tls_ecc_set.Gx = st->Gx; tls_ecc_set.Gy = st->Gy; tls_ecc_set.A = st->A; + tls_ecc_set.B = st->B; ret = ecc_make_key(NULL, rnd_func, &key, &tls_ecc_set); if (ret != 0) @@ -813,11 +822,12 @@ rsa_fail: mpz_set(TOMPZ(params->params[0]), key.prime); mpz_set(TOMPZ(params->params[1]), key.order); mpz_set(TOMPZ(params->params[2]), key.A); - mpz_set(TOMPZ(params->params[3]), key.Gx); - mpz_set(TOMPZ(params->params[4]), key.Gy); - mpz_set(TOMPZ(params->params[5]), key.pubkey.x); - mpz_set(TOMPZ(params->params[6]), key.pubkey.y); - mpz_set(TOMPZ(params->params[7]), key.k); + mpz_set(TOMPZ(params->params[3]), key.B); + mpz_set(TOMPZ(params->params[4]), key.Gx); + mpz_set(TOMPZ(params->params[5]), key.Gy); + mpz_set(TOMPZ(params->params[6]), key.pubkey.x); + mpz_set(TOMPZ(params->params[7]), key.pubkey.y); + mpz_set(TOMPZ(params->params[8]), key.k); ecc_fail: ecc_free(&key); |