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