1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
2 *
3 * LibTomCrypt is a library that provides various cryptographic
4 * algorithms in a highly modular and flexible manner.
5 *
6 * The library is free for all purposes without any express
7 * guarantee it works.
8 */
9
10 /* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
11 *
12 * All curves taken from NIST recommendation paper of July 1999
13 * Available at http://csrc.nist.gov/cryptval/dss.htm
14 */
15 #include "tomcrypt.h"
16
17 /**
18 @file ltc_ecc_projective_add_point.c
19 ECC Crypto, Tom St Denis
20 */
21
22 #if defined(LTC_MECC) && (!defined(LTC_MECC_ACCEL) || defined(LTM_DESC))
23
24 /**
25 Add two ECC points
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
32 */
ltc_ecc_projective_add_point(ecc_point * P,ecc_point * Q,ecc_point * R,void * modulus,void * mp)33 int ltc_ecc_projective_add_point(ecc_point *P, ecc_point *Q, ecc_point *R, void *modulus, void *mp)
34 {
35 void *t1, *t2, *x, *y, *z;
36 int err;
37
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);
43
44 if ((err = mp_init_multi(&t1, &t2, &x, &y, &z, NULL)) != CRYPT_OK) {
45 return err;
46 }
47
48 /* should we dbl instead? */
49 if ((err = mp_sub(modulus, Q->y, t1)) != CRYPT_OK) { goto done; }
50
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);
56 }
57
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; }
61
62 /* if Z is one then these are no-operations */
63 if (Q->z != NULL) {
64 /* T1 = Z' * Z' */
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; }
67 /* X = X * T1 */
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; }
70 /* T1 = Z' * T1 */
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; }
73 /* Y = Y * T1 */
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; }
76 }
77
78 /* T1 = Z*Z */
79 if ((err = mp_sqr(z, t1)) != CRYPT_OK) { goto done; }
80 if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; }
81 /* T2 = X' * T1 */
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; }
84 /* T1 = Z * T1 */
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; }
87 /* T1 = Y' * T1 */
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; }
90
91 /* Y = Y - T1 */
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; }
95 }
96 /* T1 = 2T1 */
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; }
100 }
101 /* T1 = Y + T1 */
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; }
105 }
106 /* X = X - T2 */
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; }
110 }
111 /* T2 = 2T2 */
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; }
115 }
116 /* T2 = X + T2 */
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; }
120 }
121
122 /* if Z' != 1 */
123 if (Q->z != NULL) {
124 /* Z = Z * Z' */
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; }
127 }
128
129 /* Z = Z * X */
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; }
132
133 /* T1 = T1 * X */
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; }
136 /* X = X * X */
137 if ((err = mp_sqr(x, x)) != CRYPT_OK) { goto done; }
138 if ((err = mp_montgomery_reduce(x, modulus, mp)) != CRYPT_OK) { goto done; }
139 /* T2 = T2 * x */
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; }
142 /* T1 = T1 * X */
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; }
145
146 /* X = Y*Y */
147 if ((err = mp_sqr(y, x)) != CRYPT_OK) { goto done; }
148 if ((err = mp_montgomery_reduce(x, modulus, mp)) != CRYPT_OK) { goto done; }
149 /* X = X - T2 */
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; }
153 }
154
155 /* T2 = T2 - X */
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; }
159 }
160 /* T2 = T2 - X */
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; }
164 }
165 /* T2 = T2 * Y */
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; }
168 /* Y = T2 - T1 */
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; }
172 }
173 /* Y = Y/2 */
174 if (mp_isodd(y)) {
175 if ((err = mp_add(y, modulus, y)) != CRYPT_OK) { goto done; }
176 }
177 if ((err = mp_div_2(y, y)) != CRYPT_OK) { goto done; }
178
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; }
182
183 err = CRYPT_OK;
184 done:
185 mp_clear_multi(t1, t2, x, y, z, NULL);
186 return err;
187 }
188
189 #endif
190
191 /* ref: $Format:%D$ */
192 /* git commit: $Format:%H$ */
193 /* commit time: $Format:%ai$ */
194
195