2 * Copyright (C) 2011-2012 Free Software Foundation, Inc.
4 * This file is part of GNUTLS.
6 * The GNUTLS library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public License
8 * as published by the Free Software Foundation; either version 3 of
9 * the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>
21 /* Based on public domain code of LibTomCrypt by Tom St Denis.
22 * Adapted to gmp and nettle by Nikos Mavrogiannopoulos.
28 @file ecc_projective_add_point.c
29 ECC Crypto, Tom St Denis
34 @param P The point to add
35 @param Q The point to add
36 @param R [out] The destination of the double
37 @param a Curve's a value
38 @param modulus The modulus of the field the ECC curve is in
42 ecc_projective_add_point (ecc_point
* P
, ecc_point
* Q
, ecc_point
* R
,
43 mpz_t a
, mpz_t modulus
)
45 mpz_t t1
, t2
, x
, y
, z
;
48 if (P
== NULL
|| Q
== NULL
|| R
== NULL
|| modulus
== NULL
)
51 if ((err
= mp_init_multi (&t1
, &t2
, &x
, &y
, &z
, NULL
)) != 0)
56 /* Check if P == Q and do doubling in that case
57 * If Q == -P then P+Q=point at infinity
59 if ((mpz_cmp (P
->x
, Q
->x
) == 0) &&
60 (mpz_cmp (P
->z
, Q
->z
) == 0))
62 /* x and z coordinates match. Check if P->y = Q->y, or P->y = -Q->y
64 if (mpz_cmp (P
->y
, Q
->y
) == 0)
66 mp_clear_multi (&t1
, &t2
, &x
, &y
, &z
, NULL
);
67 return ecc_projective_dbl_point (P
, R
, a
, modulus
);
70 mpz_sub (t1
, modulus
, Q
->y
);
71 if (mpz_cmp (P
->y
, t1
) == 0)
73 mp_clear_multi (&t1
, &t2
, &x
, &y
, &z
, NULL
);
86 /* if Z is one then these are no-operations */
87 if (mpz_cmp_ui (Q
->z
, 1) != 0)
90 mpz_mul (t1
, Q
->z
, Q
->z
);
91 mpz_mod (t1
, t1
, modulus
);
94 mpz_mod (x
, x
, modulus
);
96 mpz_mul (t1
, t1
, Q
->z
);
97 mpz_mod (t1
, t1
, modulus
);
100 mpz_mod (y
, y
, modulus
);
105 mpz_mod (t1
, t1
, modulus
);
107 mpz_mul (t2
, t1
, Q
->x
);
108 mpz_mod (t2
, t2
, modulus
);
111 mpz_mod (t1
, t1
, modulus
);
113 mpz_mul (t1
, t1
, Q
->y
);
114 mpz_mod (t1
, t1
, modulus
);
118 if (mpz_cmp_ui (y
, 0) < 0)
120 mpz_add (y
, y
, modulus
);
123 mpz_add (t1
, t1
, t1
);
124 if (mpz_cmp (t1
, modulus
) >= 0)
126 mpz_sub (t1
, t1
, modulus
);
130 if (mpz_cmp (t1
, modulus
) >= 0)
132 mpz_sub (t1
, t1
, modulus
);
136 if (mpz_cmp_ui (x
, 0) < 0)
138 mpz_add (x
, x
, modulus
);
141 mpz_add (t2
, t2
, t2
);
142 if (mpz_cmp (t2
, modulus
) >= 0)
144 mpz_sub (t2
, t2
, modulus
);
148 if (mpz_cmp (t2
, modulus
) >= 0)
150 mpz_sub (t2
, t2
, modulus
);
154 if (mpz_cmp_ui (Q
->z
, 1) != 0)
157 mpz_mul (z
, z
, Q
->z
);
158 mpz_mod (z
, z
, modulus
);
163 mpz_mod (z
, z
, modulus
);
167 mpz_mod (t1
, t1
, modulus
);
170 mpz_mod (x
, x
, modulus
);
173 mpz_mod (t2
, t2
, modulus
);
176 mpz_mod (t1
, t1
, modulus
);
180 mpz_mod (x
, x
, modulus
);
183 if (mpz_cmp_ui (x
, 0) < 0)
185 mpz_add (x
, x
, modulus
);
190 if (mpz_cmp_ui (t2
, 0) < 0)
192 mpz_add (t2
, t2
, modulus
);
196 if (mpz_cmp_ui (t2
, 0) < 0)
198 mpz_add (t2
, t2
, modulus
);
202 mpz_mod (t2
, t2
, modulus
);
205 if (mpz_cmp_ui (y
, 0) < 0)
207 mpz_add (y
, y
, modulus
);
212 mpz_add (y
, y
, modulus
);
214 mpz_divexact_ui (y
, y
, 2);
222 mp_clear_multi (&t1
, &t2
, &x
, &y
, &z
, NULL
);
226 /* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_projective_add_point.c,v $ */
227 /* $Revision: 1.16 $ */
228 /* $Date: 2007/05/12 14:32:35 $ */