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