summaryrefslogtreecommitdiff
path: root/lib/nettle
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2011-11-05 21:22:17 +0100
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2011-11-05 21:28:58 +0100
commit124dfe0de2321a4c4a3383c8866f6a1dbd45d635 (patch)
tree4dcc5b51189b0311d77fadcac8785562383e6092 /lib/nettle
parent5b541a346638429712f8a9db8ced61f1b5ffcec4 (diff)
downloadgnutls-124dfe0de2321a4c4a3383c8866f6a1dbd45d635.tar.gz
Verify that received ECDH public key lies on the curve.
Diffstat (limited to 'lib/nettle')
-rw-r--r--lib/nettle/Makefile.am2
-rw-r--r--lib/nettle/ecc.h8
-rw-r--r--lib/nettle/ecc_free.c2
-rw-r--r--lib/nettle/ecc_make_key.c16
-rw-r--r--lib/nettle/ecc_projective_check_point.c106
-rw-r--r--lib/nettle/ecc_projective_dbl_point.c207
-rw-r--r--lib/nettle/ecc_sign_hash.c2
-rw-r--r--lib/nettle/pk.c38
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);