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