Fix bug dividing small things by large ones.
[u/mdw/catacomb] / ec.c
CommitLineData
b0ab12e6 1/* -*-c-*-
2 *
41cb1beb 3 * $Id: ec.c,v 1.4 2003/05/15 23:25:59 mdw Exp $
b0ab12e6 4 *
5 * Elliptic curve definitions
6 *
7 * (c) 2001 Straylight/Edgeware
8 */
9
10/*----- Licensing notice --------------------------------------------------*
11 *
12 * This file is part of Catacomb.
13 *
14 * Catacomb is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU Library General Public License as
16 * published by the Free Software Foundation; either version 2 of the
17 * License, or (at your option) any later version.
18 *
19 * Catacomb is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU Library General Public License for more details.
23 *
24 * You should have received a copy of the GNU Library General Public
25 * License along with Catacomb; if not, write to the Free
26 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
27 * MA 02111-1307, USA.
28 */
29
30/*----- Revision history --------------------------------------------------*
31 *
32 * $Log: ec.c,v $
41cb1beb 33 * Revision 1.4 2003/05/15 23:25:59 mdw
34 * Make elliptic curve stuff build.
35 *
b085fd91 36 * Revision 1.3 2002/01/13 13:48:44 mdw
37 * Further progress.
38 *
41a324a7 39 * Revision 1.2 2001/05/07 17:29:44 mdw
40 * Treat projective coordinates as an internal representation. Various
41 * minor interface changes.
42 *
b0ab12e6 43 * Revision 1.1 2001/04/29 18:12:33 mdw
44 * Prototype version.
45 *
46 */
47
48/*----- Header files ------------------------------------------------------*/
49
50#include "ec.h"
b085fd91 51#include "ec-exp.h"
b0ab12e6 52
53/*----- Trivial wrappers --------------------------------------------------*/
54
55/* --- @ec_create@ --- *
56 *
57 * Arguments: @ec *p@ = pointer to an elliptic-curve point
58 *
41cb1beb 59 * Returns: The argument @p@.
b0ab12e6 60 *
61 * Use: Initializes a new point. The initial value is the additive
62 * identity (which is universal for all curves).
63 */
64
41cb1beb 65ec *ec_create(ec *p) { EC_CREATE(p); return (p); }
b0ab12e6 66
67/* --- @ec_destroy@ --- *
68 *
69 * Arguments: @ec *p@ = pointer to an elliptic-curve point
70 *
71 * Returns: ---
72 *
73 * Use: Destroys a point, making it invalid.
74 */
75
76void ec_destroy(ec *p) { EC_DESTROY(p); }
77
78/* --- @ec_atinf@ --- *
79 *
80 * Arguments: @const ec *p@ = pointer to a point
81 *
82 * Returns: Nonzero if %$p = O$% is the point at infinity, zero
83 * otherwise.
84 */
85
86int ec_atinf(const ec *p) { return (EC_ATINF(p)); }
87
88/* --- @ec_setinf@ --- *
89 *
90 * Arguments: @ec *p@ = pointer to a point
91 *
41cb1beb 92 * Returns: The argument @p@.
b0ab12e6 93 *
94 * Use: Sets the given point to be the point %$O$% at infinity.
95 */
96
41cb1beb 97ec *ec_setinf(ec *p) { EC_SETINF(p); return (p); }
b0ab12e6 98
99/* --- @ec_copy@ --- *
100 *
101 * Arguments: @ec *d@ = pointer to destination point
102 * @const ec *p@ = pointer to source point
103 *
41cb1beb 104 * Returns: The destination @d@.
b0ab12e6 105 *
106 * Use: Creates a copy of an elliptic curve point.
107 */
108
41cb1beb 109ec *ec_copy(ec *d, const ec *p) { EC_COPY(d, p); return (d); }
b0ab12e6 110
41a324a7 111/*----- Standard curve operations -----------------------------------------*/
b0ab12e6 112
41a324a7 113/* --- @ec_idin@, @ec_idout@ --- *
b0ab12e6 114 *
115 * Arguments: @ec_curve *c@ = pointer to an elliptic curve
41a324a7 116 * @ec *d@ = pointer to the destination
117 * @const ec *p@ = pointer to a source point
b0ab12e6 118 *
41a324a7 119 * Returns: The destination @d@.
b0ab12e6 120 *
41a324a7 121 * Use: An identity operation if your curve has no internal
122 * representation. (The field internal representation is still
123 * used.)
b0ab12e6 124 */
125
41a324a7 126ec *ec_idin(ec_curve *c, ec *d, const ec *p)
b0ab12e6 127{
128 if (EC_ATINF(p))
129 EC_SETINF(d);
130 else {
131 field *f = c->f;
132 d->x = F_IN(f, d->x, p->x);
133 d->y = F_IN(f, d->y, p->y);
41a324a7 134 mp_drop(d->z); d->z = 0;
135 }
136 return (d);
137}
138
139ec *ec_idout(ec_curve *c, ec *d, const ec *p)
140{
141 if (EC_ATINF(p))
142 EC_SETINF(d);
143 else {
144 field *f = c->f;
145 d->x = F_OUT(f, d->x, p->x);
146 d->y = F_OUT(f, d->y, p->y);
147 mp_drop(d->z); d->z = 0;
b0ab12e6 148 }
41a324a7 149 return (d);
b0ab12e6 150}
151
41a324a7 152/* --- @ec_projin@, @ec_projout@ --- *
b0ab12e6 153 *
154 * Arguments: @ec_curve *c@ = pointer to an elliptic curve
41a324a7 155 * @ec *d@ = pointer to the destination
156 * @const ec *p@ = pointer to a source point
b0ab12e6 157 *
41a324a7 158 * Returns: The destination @d@.
b0ab12e6 159 *
41a324a7 160 * Use: Conversion functions if your curve operations use a
161 * projective representation.
b0ab12e6 162 */
163
41a324a7 164ec *ec_projin(ec_curve *c, ec *d, const ec *p)
165{
166 if (EC_ATINF(p))
167 EC_SETINF(d);
168 else {
169 field *f = c->f;
170 d->x = F_IN(f, d->x, p->x);
171 d->y = F_IN(f, d->y, p->y);
172 mp_drop(d->z); d->z = MP_COPY(f->one);
173 }
174 return (d);
175}
176
177ec *ec_projout(ec_curve *c, ec *d, const ec *p)
b0ab12e6 178{
179 if (EC_ATINF(p))
180 EC_SETINF(d);
181 else {
182 mp *x, *y, *z;
183 field *f = c->f;
184 z = F_INV(f, MP_NEW, p->z);
185 x = F_MUL(f, d->x, p->x, z);
186 y = F_MUL(f, d->y, p->y, z);
187 mp_drop(z);
188 mp_drop(d->z);
189 d->x = F_OUT(f, x, x);
190 d->y = F_OUT(f, y, y);
191 d->z = 0;
192 }
41a324a7 193 return (d);
b0ab12e6 194}
195
b085fd91 196/* --- @ec_stdsub@ --- *
197 *
198 * Arguments: @ec_curve *c@ = pointer to an elliptic curve
199 * @ec *d@ = pointer to the destination
41cb1beb 200 * @const ec *p, *q@ = the operand points
b085fd91 201 *
202 * Returns: The destination @d@.
203 *
204 * Use: Standard point subtraction operation, in terms of negation
205 * and addition. This isn't as efficient as a ready-made
206 * subtraction operator.
207 */
208
41cb1beb 209ec *ec_stdsub(ec_curve *c, ec *d, const ec *p, const ec *q)
b085fd91 210{
211 ec t = EC_INIT;
41cb1beb 212 EC_NEG(c, &t, q);
213 EC_ADD(c, d, p, &t);
b085fd91 214 EC_DESTROY(&t);
215 return (d);
216}
217
41cb1beb 218/*----- Creating curves ---------------------------------------------------*/
219
220/* --- @ec_destroycurve@ --- *
221 *
222 * Arguments: @ec_curve *c@ = pointer to an ellptic curve
223 *
224 * Returns: ---
225 *
226 * Use: Destroys a description of an elliptic curve.
227 */
228
229void ec_destroycurve(ec_curve *c) { c->ops->destroy(c); }
230
41a324a7 231/*----- Real arithmetic ---------------------------------------------------*/
232
b0ab12e6 233/* --- @ec_find@ --- *
234 *
235 * Arguments: @ec_curve *c@ = pointer to an elliptic curve
236 * @ec *d@ = pointer to the destination point
237 * @mp *x@ = a possible x-coordinate
238 *
239 * Returns: Zero if OK, nonzero if there isn't a point there.
240 *
241 * Use: Finds a point on an elliptic curve with a given x-coordinate.
242 */
243
41a324a7 244ec *ec_find(ec_curve *c, ec *d, mp *x)
b0ab12e6 245{
b0ab12e6 246 x = F_IN(c->f, MP_NEW, x);
41a324a7 247 if ((d = EC_FIND(c, d, x)) != 0)
248 EC_OUT(c, d, d);
b0ab12e6 249 mp_drop(x);
41a324a7 250 return (d);
b0ab12e6 251}
252
253/* --- @ec_add@ --- *
254 *
255 * Arguments: @ec_curve *c@ = pointer to an elliptic curve
256 * @ec *d@ = pointer to the destination point
257 * @const ec *p, *q@ = pointers to the operand points
258 *
259 * Returns: ---
260 *
261 * Use: Adds two points on an elliptic curve.
262 */
263
41a324a7 264ec *ec_add(ec_curve *c, ec *d, const ec *p, const ec *q)
b0ab12e6 265{
266 ec pp = EC_INIT, qq = EC_INIT;
41a324a7 267 EC_IN(c, &pp, p);
268 EC_IN(c, &qq, q);
b0ab12e6 269 EC_ADD(c, d, &pp, &qq);
41a324a7 270 EC_OUT(c, d, d);
b0ab12e6 271 EC_DESTROY(&pp);
272 EC_DESTROY(&qq);
41a324a7 273 return (d);
b0ab12e6 274}
275
276/* --- @ec_dbl@ --- *
277 *
278 * Arguments: @ec_curve *c@ = pointer to an elliptic curve
279 * @ec *d@ = pointer to the destination point
280 * @const ec *p@ = pointer to the operand point
281 *
282 * Returns: ---
283 *
284 * Use: Doubles a point on an elliptic curve.
285 */
286
41a324a7 287ec *ec_dbl(ec_curve *c, ec *d, const ec *p)
b0ab12e6 288{
41a324a7 289 EC_IN(c, d, p);
b0ab12e6 290 EC_DBL(c, d, d);
41a324a7 291 return (EC_OUT(c, d, d));
b0ab12e6 292}
293
b085fd91 294/* --- @ec_imul@, @ec_mul@ --- *
b0ab12e6 295 *
296 * Arguments: @ec_curve *c@ = pointer to an elliptic curve
297 * @ec *d@ = pointer to the destination point
298 * @const ec *p@ = pointer to the generator point
299 * @mp *n@ = integer multiplier
300 *
b085fd91 301 * Returns: The destination @d@.
b0ab12e6 302 *
b085fd91 303 * Use: Multiplies a point by a scalar, returning %$n p$%. The
304 * @imul@ variant uses internal representations for argument
305 * and result.
b0ab12e6 306 */
307
b085fd91 308ec *ec_imul(ec_curve *c, ec *d, const ec *p, mp *n)
b0ab12e6 309{
b085fd91 310 ec t = EC_INIT;
b0ab12e6 311
b085fd91 312 EC_COPY(&t, p);
313 if (t.x && (n->f & MP_BURN))
314 t.x->f |= MP_BURN;
315 MP_SHRINK(n);
b0ab12e6 316 EC_SETINF(d);
b085fd91 317 if (MP_LEN(n) == 0)
318 ;
319 else if (MP_LEN(n) < EXP_THRESH)
41cb1beb 320 EXP_SIMPLE(*d, t, n);
b085fd91 321 else
41cb1beb 322 EXP_WINDOW(*d, t, n);
b085fd91 323 return (d);
324}
b0ab12e6 325
b085fd91 326ec *ec_mul(ec_curve *c, ec *d, const ec *p, mp *n)
327{
328 EC_IN(c, d, p);
329 ec_imul(c, d, d, n);
41a324a7 330 return (EC_OUT(c, d, d));
b0ab12e6 331}
332
333/*----- That's all, folks -------------------------------------------------*/