diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2011-05-16 22:20:17 +0200 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2011-05-20 12:31:22 +0200 |
commit | 78b9114c2c025090262e5b365fc199ce2f88334b (patch) | |
tree | 36e81a209054f87f404a5a768ef3253f614e2f02 /lib/nettle/ltc_ecc_projective_add_point.c | |
parent | f90470a7b4c672a916c4513cecf4b9a6bce0eb67 (diff) | |
download | gnutls-78b9114c2c025090262e5b365fc199ce2f88334b.tar.gz |
Initial ecc support. Adds support for anonymous ECDH ciphersuites.
Diffstat (limited to 'lib/nettle/ltc_ecc_projective_add_point.c')
-rw-r--r-- | lib/nettle/ltc_ecc_projective_add_point.c | 195 |
1 files changed, 195 insertions, 0 deletions
diff --git a/lib/nettle/ltc_ecc_projective_add_point.c b/lib/nettle/ltc_ecc_projective_add_point.c new file mode 100644 index 0000000000..2b008367c6 --- /dev/null +++ b/lib/nettle/ltc_ecc_projective_add_point.c @@ -0,0 +1,195 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b + * + * All curves taken from NIST recommendation paper of July 1999 + * Available at http://csrc.nist.gov/cryptval/dss.htm + */ +#include "ecc.h" + +/** + @file ltc_ecc_projective_add_point.c + ECC Crypto, Tom St Denis +*/ + +#if defined(LTC_MECC) && (!defined(LTC_MECC_ACCEL) || defined(LTM_LTC_DESC)) + +/** + Add two ECC points + @param P The point to add + @param Q The point to add + @param R [out] The destination of the double + @param modulus The modulus of the field the ECC curve is in + @param mp The "b" value from montgomery_setup() + @return 0 on success +*/ +int ltc_ecc_projective_add_point(ecc_point *P, ecc_point *Q, ecc_point *R, mpz_t modulus) +{ + mpz_t t1, t2, x, y, z; + int err; + + assert(P != NULL); + assert(Q != NULL); + assert(R != NULL); + assert(modulus != NULL); + + if ((err = mp_init_multi(&t1, &t2, &x, &y, &z, NULL)) != 0) { + return err; + } + + /* should we dbl instead? */ + mpz_sub(t1, modulus, Q->y); + + if ( (mpz_cmp(P->x, Q->x) == 0) && + (Q->z != NULL && mpz_cmp(P->z, Q->z) == 0) && + (mpz_cmp(P->y, Q->y) == 0 || mpz_cmp(P->y, t1) == 0)) { + mp_clear_multi(&t1, &t2, &x, &y, &z, NULL); + return ltc_ecc_projective_dbl_point(P, R, modulus); + } + + mpz_set(x, P->x); + mpz_set(y, P->y); + mpz_set(z, P->z); + + /* if Z is one then these are no-operations */ + if (mpz_cmp_ui(Q->z, 1) != 0) { + /* T1 = Z' * Z' */ + mpz_mul(t1, Q->z, Q->z); + mpz_mod(t1, t1, modulus); + /* X = X * T1 */ + mpz_mul(x, x, t1); + mpz_mod(x, x, modulus); + /* T1 = Z' * T1 */ + mpz_mul(t1, t1, Q->z); + mpz_mod(t1, t1, modulus); + /* Y = Y * T1 */ + mpz_mul(y, y, t1); + mpz_mod(y, y, modulus); + } + + /* T1 = Z*Z */ + mpz_mul(t1, z, z); + mpz_mod(t1, t1, modulus); + /* T2 = X' * T1 */ + mpz_mul(t2, t1, Q->x); + mpz_mod(t2, t2, modulus); + /* T1 = Z * T1 */ + mpz_mul(t1, t1, z); + mpz_mod(t1, t1, modulus); + /* T1 = Y' * T1 */ + mpz_mul(t1, t1, Q->y); + mpz_mod(t1, t1, modulus); + + /* Y = Y - T1 */ + mpz_sub(y, y, t1); + if (mpz_cmp_ui(y, 0) < 0) { + mpz_add(y, y, modulus); + } + /* T1 = 2T1 */ + mpz_add(t1, t1, t1); + if (mpz_cmp(t1, modulus) >= 0) { + mpz_sub(t1, t1, modulus); + } + /* T1 = Y + T1 */ + mpz_add(t1, t1, y); + if (mpz_cmp(t1, modulus) >= 0) { + mpz_sub(t1, t1, modulus); + } + /* X = X - T2 */ + mpz_sub(x, x, t2); + if (mpz_cmp_ui(x, 0) < 0) { + mpz_add(x, x, modulus); + } + /* T2 = 2T2 */ + mpz_add(t2, t2, t2); + if (mpz_cmp(t2, modulus) >= 0) { + mpz_sub(t2, t2, modulus); + } + /* T2 = X + T2 */ + mpz_add(t2, t2, x); + if (mpz_cmp(t2, modulus) >= 0) { + mpz_sub(t2, t2, modulus); + } + + /* if Z' != 1 */ + if (mpz_cmp_ui(Q->z, 1) != 0) { + /* Z = Z * Z' */ + mpz_mul(z, z, Q->z); + mpz_mod(z, z, modulus); + } + + /* Z = Z * X */ + mpz_mul(z, z, x); + mpz_mod(z, z, modulus); + + /* T1 = T1 * X */ + mpz_mul(t1, t1, x); + mpz_mod(t1, t1, modulus); + /* X = X * X */ + mpz_mul(x, x, x); + mpz_mod(x, x, modulus); + /* T2 = T2 * x */ + mpz_mul(t2, t2, x); + mpz_mod(t2, t2, modulus); + /* T1 = T1 * X */ + mpz_mul(t1, t1, x); + mpz_mod(t1, t1, modulus); + + /* X = Y*Y */ + mpz_mul(x, y, y); + mpz_mod(x, x, modulus); + /* X = X - T2 */ + mpz_sub(x, x, t2); + if (mpz_cmp_ui(x, 0) < 0) { + mpz_add(x, x, modulus); + } + + /* T2 = T2 - X */ + mpz_sub(t2, t2, x); + if (mpz_cmp_ui(t2, 0) < 0) { + mpz_add(t2, t2, modulus); + } + /* T2 = T2 - X */ + mpz_sub(t2, t2, x); + if (mpz_cmp_ui(t2, 0) < 0) { + mpz_add(t2, t2, modulus); + } + /* T2 = T2 * Y */ + mpz_mul(t2, t2, y); + mpz_mod(t2, t2, modulus); + /* Y = T2 - T1 */ + mpz_sub(y, t2, t1); + if (mpz_cmp_ui(y, 0) < 0) { + mpz_add(y, y, modulus); + } + /* Y = Y/2 */ + if (mp_isodd(y)) { + mpz_add(y, y, modulus); + } + mpz_divexact_ui(y, y, 2); + + mpz_set(R->x, x); + mpz_set(R->y, y); + mpz_set(R->z, z); + + err = 0; + + mp_clear_multi(&t1, &t2, &x, &y, &z, NULL); + return err; +} + +#endif + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ltc_ecc_projective_add_point.c,v $ */ +/* $Revision: 1.16 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ + |