Projective coordinates for prime curves
[u/mdw/catacomb] / ec.c
CommitLineData
b0ab12e6 1/* -*-c-*-
2 *
8823192f 3 * $Id: ec.c,v 1.4.4.2 2004/03/20 00:13:31 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 $
8823192f 33 * Revision 1.4.4.2 2004/03/20 00:13:31 mdw
34 * Projective coordinates for prime curves
35 *
dbfee00a 36 * Revision 1.4.4.1 2003/06/10 13:43:53 mdw
37 * Simple (non-projective) curves over prime fields now seem to work.
38 *
41cb1beb 39 * Revision 1.4 2003/05/15 23:25:59 mdw
40 * Make elliptic curve stuff build.
41 *
b085fd91 42 * Revision 1.3 2002/01/13 13:48:44 mdw
43 * Further progress.
44 *
41a324a7 45 * Revision 1.2 2001/05/07 17:29:44 mdw
46 * Treat projective coordinates as an internal representation. Various
47 * minor interface changes.
48 *
b0ab12e6 49 * Revision 1.1 2001/04/29 18:12:33 mdw
50 * Prototype version.
51 *
52 */
53
54/*----- Header files ------------------------------------------------------*/
55
56#include "ec.h"
b085fd91 57#include "ec-exp.h"
b0ab12e6 58
59/*----- Trivial wrappers --------------------------------------------------*/
60
61/* --- @ec_create@ --- *
62 *
63 * Arguments: @ec *p@ = pointer to an elliptic-curve point
64 *
41cb1beb 65 * Returns: The argument @p@.
b0ab12e6 66 *
67 * Use: Initializes a new point. The initial value is the additive
68 * identity (which is universal for all curves).
69 */
70
41cb1beb 71ec *ec_create(ec *p) { EC_CREATE(p); return (p); }
b0ab12e6 72
73/* --- @ec_destroy@ --- *
74 *
75 * Arguments: @ec *p@ = pointer to an elliptic-curve point
76 *
77 * Returns: ---
78 *
79 * Use: Destroys a point, making it invalid.
80 */
81
82void ec_destroy(ec *p) { EC_DESTROY(p); }
83
84/* --- @ec_atinf@ --- *
85 *
86 * Arguments: @const ec *p@ = pointer to a point
87 *
88 * Returns: Nonzero if %$p = O$% is the point at infinity, zero
89 * otherwise.
90 */
91
92int ec_atinf(const ec *p) { return (EC_ATINF(p)); }
93
94/* --- @ec_setinf@ --- *
95 *
96 * Arguments: @ec *p@ = pointer to a point
97 *
41cb1beb 98 * Returns: The argument @p@.
b0ab12e6 99 *
100 * Use: Sets the given point to be the point %$O$% at infinity.
101 */
102
41cb1beb 103ec *ec_setinf(ec *p) { EC_SETINF(p); return (p); }
b0ab12e6 104
105/* --- @ec_copy@ --- *
106 *
107 * Arguments: @ec *d@ = pointer to destination point
108 * @const ec *p@ = pointer to source point
109 *
41cb1beb 110 * Returns: The destination @d@.
b0ab12e6 111 *
112 * Use: Creates a copy of an elliptic curve point.
113 */
114
41cb1beb 115ec *ec_copy(ec *d, const ec *p) { EC_COPY(d, p); return (d); }
b0ab12e6 116
41a324a7 117/*----- Standard curve operations -----------------------------------------*/
b0ab12e6 118
8823192f 119/* --- @ec_idin@, @ec_idout@, @ec_idfix@ --- *
b0ab12e6 120 *
121 * Arguments: @ec_curve *c@ = pointer to an elliptic curve
41a324a7 122 * @ec *d@ = pointer to the destination
123 * @const ec *p@ = pointer to a source point
b0ab12e6 124 *
41a324a7 125 * Returns: The destination @d@.
b0ab12e6 126 *
41a324a7 127 * Use: An identity operation if your curve has no internal
128 * representation. (The field internal representation is still
129 * used.)
b0ab12e6 130 */
131
41a324a7 132ec *ec_idin(ec_curve *c, ec *d, const ec *p)
b0ab12e6 133{
134 if (EC_ATINF(p))
135 EC_SETINF(d);
136 else {
137 field *f = c->f;
138 d->x = F_IN(f, d->x, p->x);
139 d->y = F_IN(f, d->y, p->y);
41a324a7 140 mp_drop(d->z); d->z = 0;
141 }
142 return (d);
143}
144
145ec *ec_idout(ec_curve *c, ec *d, const ec *p)
146{
147 if (EC_ATINF(p))
148 EC_SETINF(d);
149 else {
150 field *f = c->f;
151 d->x = F_OUT(f, d->x, p->x);
152 d->y = F_OUT(f, d->y, p->y);
153 mp_drop(d->z); d->z = 0;
b0ab12e6 154 }
41a324a7 155 return (d);
b0ab12e6 156}
157
8823192f 158ec *ec_idfix(ec_curve *c, ec *d, const ec *p)
159{
160 EC_COPY(d, p);
161 return (d);
162}
163
41a324a7 164/* --- @ec_projin@, @ec_projout@ --- *
b0ab12e6 165 *
166 * Arguments: @ec_curve *c@ = pointer to an elliptic curve
41a324a7 167 * @ec *d@ = pointer to the destination
168 * @const ec *p@ = pointer to a source point
b0ab12e6 169 *
41a324a7 170 * Returns: The destination @d@.
b0ab12e6 171 *
41a324a7 172 * Use: Conversion functions if your curve operations use a
173 * projective representation.
b0ab12e6 174 */
175
41a324a7 176ec *ec_projin(ec_curve *c, ec *d, const ec *p)
177{
178 if (EC_ATINF(p))
179 EC_SETINF(d);
180 else {
181 field *f = c->f;
182 d->x = F_IN(f, d->x, p->x);
183 d->y = F_IN(f, d->y, p->y);
184 mp_drop(d->z); d->z = MP_COPY(f->one);
185 }
186 return (d);
187}
188
189ec *ec_projout(ec_curve *c, ec *d, const ec *p)
b0ab12e6 190{
191 if (EC_ATINF(p))
192 EC_SETINF(d);
193 else {
8823192f 194 mp *x, *y, *z, *zz;
b0ab12e6 195 field *f = c->f;
196 z = F_INV(f, MP_NEW, p->z);
8823192f 197 zz = F_SQR(f, MP_NEW, z);
198 z = F_MUL(f, z, zz, z);
199 x = F_MUL(f, d->x, p->x, zz);
b0ab12e6 200 y = F_MUL(f, d->y, p->y, z);
201 mp_drop(z);
8823192f 202 mp_drop(zz);
b0ab12e6 203 mp_drop(d->z);
204 d->x = F_OUT(f, x, x);
205 d->y = F_OUT(f, y, y);
206 d->z = 0;
207 }
41a324a7 208 return (d);
b0ab12e6 209}
210
8823192f 211ec *ec_projfix(ec_curve *c, ec *d, const ec *p)
212{
213 if (EC_ATINF(p))
214 EC_SETINF(d);
215 else if (d->z == c->f->one)
216 EC_COPY(d, p);
217 else {
218 mp *z, *zz;
219 field *f = c->f;
220 z = F_INV(f, MP_NEW, p->z);
221 zz = F_SQR(f, MP_NEW, z);
222 z = F_MUL(f, z, zz, z);
223 d->x = F_MUL(f, d->x, p->x, zz);
224 d->y = F_MUL(f, d->y, p->y, z);
225 mp_drop(z);
226 mp_drop(zz);
227 mp_drop(d->z);
228 d->z = MP_COPY(f->one);
229 }
230 return (d);
231}
232
b085fd91 233/* --- @ec_stdsub@ --- *
234 *
235 * Arguments: @ec_curve *c@ = pointer to an elliptic curve
236 * @ec *d@ = pointer to the destination
41cb1beb 237 * @const ec *p, *q@ = the operand points
b085fd91 238 *
239 * Returns: The destination @d@.
240 *
241 * Use: Standard point subtraction operation, in terms of negation
242 * and addition. This isn't as efficient as a ready-made
243 * subtraction operator.
244 */
245
41cb1beb 246ec *ec_stdsub(ec_curve *c, ec *d, const ec *p, const ec *q)
b085fd91 247{
248 ec t = EC_INIT;
41cb1beb 249 EC_NEG(c, &t, q);
8823192f 250 EC_FIX(c, &t, &t);
41cb1beb 251 EC_ADD(c, d, p, &t);
b085fd91 252 EC_DESTROY(&t);
253 return (d);
254}
255
41cb1beb 256/*----- Creating curves ---------------------------------------------------*/
257
258/* --- @ec_destroycurve@ --- *
259 *
260 * Arguments: @ec_curve *c@ = pointer to an ellptic curve
261 *
262 * Returns: ---
263 *
264 * Use: Destroys a description of an elliptic curve.
265 */
266
267void ec_destroycurve(ec_curve *c) { c->ops->destroy(c); }
268
41a324a7 269/*----- Real arithmetic ---------------------------------------------------*/
270
b0ab12e6 271/* --- @ec_find@ --- *
272 *
273 * Arguments: @ec_curve *c@ = pointer to an elliptic curve
274 * @ec *d@ = pointer to the destination point
275 * @mp *x@ = a possible x-coordinate
276 *
277 * Returns: Zero if OK, nonzero if there isn't a point there.
278 *
279 * Use: Finds a point on an elliptic curve with a given x-coordinate.
280 */
281
41a324a7 282ec *ec_find(ec_curve *c, ec *d, mp *x)
b0ab12e6 283{
b0ab12e6 284 x = F_IN(c->f, MP_NEW, x);
41a324a7 285 if ((d = EC_FIND(c, d, x)) != 0)
286 EC_OUT(c, d, d);
8823192f 287 MP_DROP(x);
41a324a7 288 return (d);
b0ab12e6 289}
290
dbfee00a 291/* --- @ec_neg@ --- *
292 *
293 * Arguments: @ec_curve *c@ = pointer to an elliptic curve
294 * @ec *d@ = pointer to the destination point
295 * @const ec *p@ = pointer to the operand point
296 *
297 * Returns: The destination point.
298 *
299 * Use: Computes the negation of the given point.
300 */
301
302ec *ec_neg(ec_curve *c, ec *d, const ec *p)
303{
304 EC_IN(c, d, p);
305 EC_NEG(c, d, d);
306 return (EC_OUT(c, d, d));
307}
308
b0ab12e6 309/* --- @ec_add@ --- *
310 *
311 * Arguments: @ec_curve *c@ = pointer to an elliptic curve
312 * @ec *d@ = pointer to the destination point
313 * @const ec *p, *q@ = pointers to the operand points
314 *
315 * Returns: ---
316 *
317 * Use: Adds two points on an elliptic curve.
318 */
319
41a324a7 320ec *ec_add(ec_curve *c, ec *d, const ec *p, const ec *q)
b0ab12e6 321{
322 ec pp = EC_INIT, qq = EC_INIT;
41a324a7 323 EC_IN(c, &pp, p);
324 EC_IN(c, &qq, q);
b0ab12e6 325 EC_ADD(c, d, &pp, &qq);
41a324a7 326 EC_OUT(c, d, d);
b0ab12e6 327 EC_DESTROY(&pp);
328 EC_DESTROY(&qq);
41a324a7 329 return (d);
b0ab12e6 330}
331
dbfee00a 332/* --- @ec_sub@ --- *
333 *
334 * Arguments: @ec_curve *c@ = pointer to an elliptic curve
335 * @ec *d@ = pointer to the destination point
336 * @const ec *p, *q@ = pointers to the operand points
337 *
338 * Returns: The destination @d@.
339 *
340 * Use: Subtracts one point from another on an elliptic curve.
341 */
342
343ec *ec_sub(ec_curve *c, ec *d, const ec *p, const ec *q)
344{
345 ec pp, qq;
346 EC_IN(c, &pp, p);
347 EC_IN(c, &qq, q);
348 EC_SUB(c, d, &qq, &qq);
349 EC_OUT(c, d, d);
350 EC_DESTROY(&pp);
351 EC_DESTROY(&qq);
352 return (d);
353}
354
b0ab12e6 355/* --- @ec_dbl@ --- *
356 *
357 * Arguments: @ec_curve *c@ = pointer to an elliptic curve
358 * @ec *d@ = pointer to the destination point
359 * @const ec *p@ = pointer to the operand point
360 *
361 * Returns: ---
362 *
363 * Use: Doubles a point on an elliptic curve.
364 */
365
41a324a7 366ec *ec_dbl(ec_curve *c, ec *d, const ec *p)
b0ab12e6 367{
41a324a7 368 EC_IN(c, d, p);
b0ab12e6 369 EC_DBL(c, d, d);
41a324a7 370 return (EC_OUT(c, d, d));
b0ab12e6 371}
372
8823192f 373/* --- @ec_check@ --- *
374 *
375 * Arguments: @ec_curve *c@ = pointer to an elliptic curve
376 * @const ec *p@ = pointer to the point
377 *
378 * Returns: Zero if OK, nonzero if this is an invalid point.
379 *
380 * Use: Checks that a point is actually on an elliptic curve.
381 */
382
383int ec_check(ec_curve *c, const ec *p)
384{
385 ec t = EC_INIT;
386 int rc;
387
388 if (EC_ATINF(p))
389 return (0);
390 EC_IN(c, &t, p);
391 rc = EC_CHECK(c, &t);
392 EC_DESTROY(&t);
393 return (rc);
394}
395
b085fd91 396/* --- @ec_imul@, @ec_mul@ --- *
b0ab12e6 397 *
398 * Arguments: @ec_curve *c@ = pointer to an elliptic curve
399 * @ec *d@ = pointer to the destination point
400 * @const ec *p@ = pointer to the generator point
401 * @mp *n@ = integer multiplier
402 *
b085fd91 403 * Returns: The destination @d@.
b0ab12e6 404 *
b085fd91 405 * Use: Multiplies a point by a scalar, returning %$n p$%. The
406 * @imul@ variant uses internal representations for argument
407 * and result.
b0ab12e6 408 */
409
b085fd91 410ec *ec_imul(ec_curve *c, ec *d, const ec *p, mp *n)
b0ab12e6 411{
b085fd91 412 ec t = EC_INIT;
b0ab12e6 413
b085fd91 414 EC_COPY(&t, p);
415 if (t.x && (n->f & MP_BURN))
416 t.x->f |= MP_BURN;
417 MP_SHRINK(n);
b0ab12e6 418 EC_SETINF(d);
b085fd91 419 if (MP_LEN(n) == 0)
420 ;
8823192f 421 else {
422 if (n->f & MP_NEG)
423 EC_NEG(c, &t, &t);
424 if (MP_LEN(n) < EXP_THRESH)
425 EXP_SIMPLE(*d, t, n);
426 else
427 EXP_WINDOW(*d, t, n);
428 }
dbfee00a 429 EC_DESTROY(&t);
b085fd91 430 return (d);
431}
b0ab12e6 432
b085fd91 433ec *ec_mul(ec_curve *c, ec *d, const ec *p, mp *n)
434{
435 EC_IN(c, d, p);
436 ec_imul(c, d, d, n);
41a324a7 437 return (EC_OUT(c, d, d));
b0ab12e6 438}
439
440/*----- That's all, folks -------------------------------------------------*/