1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
3 * LibTomCrypt is a library that provides various cryptographic
4 * algorithms in a highly modular and flexible manner.
6 * The library is free for all purposes without any express
10 /* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
12 * All curves taken from NIST recommendation paper of July 1999
13 * Available at http://csrc.nist.gov/cryptval/dss.htm
18 @file ltc_ecc_projective_add_point.c
19 ECC Crypto, Tom St Denis
22 #if defined(LTC_MECC) && (!defined(LTC_MECC_ACCEL) || defined(LTM_DESC))
26 @param P The point to add
27 @param Q The point to add
28 @param R [out] The destination of the double
29 @param modulus The modulus of the field the ECC curve is in
30 @param mp The "b" value from montgomery_setup()
31 @return CRYPT_OK on success
33 int ltc_ecc_projective_add_point(ecc_point *P, ecc_point *Q, ecc_point *R, void *modulus, void *mp)
35 void *t1, *t2, *x, *y, *z;
38 LTC_ARGCHK(P != NULL);
39 LTC_ARGCHK(Q != NULL);
40 LTC_ARGCHK(R != NULL);
41 LTC_ARGCHK(modulus != NULL);
42 LTC_ARGCHK(mp != NULL);
44 if ((err = mp_init_multi(&t1, &t2, &x, &y, &z, NULL)) != CRYPT_OK) {
48 /* should we dbl instead? */
49 if ((err = mp_sub(modulus, Q->y, t1)) != CRYPT_OK) { goto done; }
51 if ( (mp_cmp(P->x, Q->x) == LTC_MP_EQ) &&
52 (Q->z != NULL && mp_cmp(P->z, Q->z) == LTC_MP_EQ) &&
53 (mp_cmp(P->y, Q->y) == LTC_MP_EQ || mp_cmp(P->y, t1) == LTC_MP_EQ)) {
54 mp_clear_multi(t1, t2, x, y, z, NULL);
55 return ltc_ecc_projective_dbl_point(P, R, modulus, mp);
58 if ((err = mp_copy(P->x, x)) != CRYPT_OK) { goto done; }
59 if ((err = mp_copy(P->y, y)) != CRYPT_OK) { goto done; }
60 if ((err = mp_copy(P->z, z)) != CRYPT_OK) { goto done; }
62 /* if Z is one then these are no-operations */
65 if ((err = mp_sqr(Q->z, t1)) != CRYPT_OK) { goto done; }
66 if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; }
68 if ((err = mp_mul(t1, x, x)) != CRYPT_OK) { goto done; }
69 if ((err = mp_montgomery_reduce(x, modulus, mp)) != CRYPT_OK) { goto done; }
71 if ((err = mp_mul(Q->z, t1, t1)) != CRYPT_OK) { goto done; }
72 if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; }
74 if ((err = mp_mul(t1, y, y)) != CRYPT_OK) { goto done; }
75 if ((err = mp_montgomery_reduce(y, modulus, mp)) != CRYPT_OK) { goto done; }
79 if ((err = mp_sqr(z, t1)) != CRYPT_OK) { goto done; }
80 if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; }
82 if ((err = mp_mul(Q->x, t1, t2)) != CRYPT_OK) { goto done; }
83 if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK) { goto done; }
85 if ((err = mp_mul(z, t1, t1)) != CRYPT_OK) { goto done; }
86 if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; }
88 if ((err = mp_mul(Q->y, t1, t1)) != CRYPT_OK) { goto done; }
89 if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; }
92 if ((err = mp_sub(y, t1, y)) != CRYPT_OK) { goto done; }
93 if (mp_cmp_d(y, 0) == LTC_MP_LT) {
94 if ((err = mp_add(y, modulus, y)) != CRYPT_OK) { goto done; }
97 if ((err = mp_add(t1, t1, t1)) != CRYPT_OK) { goto done; }
98 if (mp_cmp(t1, modulus) != LTC_MP_LT) {
99 if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; }
102 if ((err = mp_add(t1, y, t1)) != CRYPT_OK) { goto done; }
103 if (mp_cmp(t1, modulus) != LTC_MP_LT) {
104 if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; }
107 if ((err = mp_sub(x, t2, x)) != CRYPT_OK) { goto done; }
108 if (mp_cmp_d(x, 0) == LTC_MP_LT) {
109 if ((err = mp_add(x, modulus, x)) != CRYPT_OK) { goto done; }
112 if ((err = mp_add(t2, t2, t2)) != CRYPT_OK) { goto done; }
113 if (mp_cmp(t2, modulus) != LTC_MP_LT) {
114 if ((err = mp_sub(t2, modulus, t2)) != CRYPT_OK) { goto done; }
117 if ((err = mp_add(t2, x, t2)) != CRYPT_OK) { goto done; }
118 if (mp_cmp(t2, modulus) != LTC_MP_LT) {
119 if ((err = mp_sub(t2, modulus, t2)) != CRYPT_OK) { goto done; }
125 if ((err = mp_mul(z, Q->z, z)) != CRYPT_OK) { goto done; }
126 if ((err = mp_montgomery_reduce(z, modulus, mp)) != CRYPT_OK) { goto done; }
130 if ((err = mp_mul(z, x, z)) != CRYPT_OK) { goto done; }
131 if ((err = mp_montgomery_reduce(z, modulus, mp)) != CRYPT_OK) { goto done; }
134 if ((err = mp_mul(t1, x, t1)) != CRYPT_OK) { goto done; }
135 if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; }
137 if ((err = mp_sqr(x, x)) != CRYPT_OK) { goto done; }
138 if ((err = mp_montgomery_reduce(x, modulus, mp)) != CRYPT_OK) { goto done; }
140 if ((err = mp_mul(t2, x, t2)) != CRYPT_OK) { goto done; }
141 if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK) { goto done; }
143 if ((err = mp_mul(t1, x, t1)) != CRYPT_OK) { goto done; }
144 if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; }
147 if ((err = mp_sqr(y, x)) != CRYPT_OK) { goto done; }
148 if ((err = mp_montgomery_reduce(x, modulus, mp)) != CRYPT_OK) { goto done; }
150 if ((err = mp_sub(x, t2, x)) != CRYPT_OK) { goto done; }
151 if (mp_cmp_d(x, 0) == LTC_MP_LT) {
152 if ((err = mp_add(x, modulus, x)) != CRYPT_OK) { goto done; }
156 if ((err = mp_sub(t2, x, t2)) != CRYPT_OK) { goto done; }
157 if (mp_cmp_d(t2, 0) == LTC_MP_LT) {
158 if ((err = mp_add(t2, modulus, t2)) != CRYPT_OK) { goto done; }
161 if ((err = mp_sub(t2, x, t2)) != CRYPT_OK) { goto done; }
162 if (mp_cmp_d(t2, 0) == LTC_MP_LT) {
163 if ((err = mp_add(t2, modulus, t2)) != CRYPT_OK) { goto done; }
166 if ((err = mp_mul(t2, y, t2)) != CRYPT_OK) { goto done; }
167 if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK) { goto done; }
169 if ((err = mp_sub(t2, t1, y)) != CRYPT_OK) { goto done; }
170 if (mp_cmp_d(y, 0) == LTC_MP_LT) {
171 if ((err = mp_add(y, modulus, y)) != CRYPT_OK) { goto done; }
175 if ((err = mp_add(y, modulus, y)) != CRYPT_OK) { goto done; }
177 if ((err = mp_div_2(y, y)) != CRYPT_OK) { goto done; }
179 if ((err = mp_copy(x, R->x)) != CRYPT_OK) { goto done; }
180 if ((err = mp_copy(y, R->y)) != CRYPT_OK) { goto done; }
181 if ((err = mp_copy(z, R->z)) != CRYPT_OK) { goto done; }
185 mp_clear_multi(t1, t2, x, y, z, NULL);
191 /* ref: $Format:%D$ */
192 /* git commit: $Format:%H$ */
193 /* commit time: $Format:%ai$ */