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