math/mpreduce.h: Missing include files.
[u/mdw/catacomb] / math / g-ec.c
... / ...
CommitLineData
1/* -*-c-*-
2 *
3 * Abstraction for elliptic curve groups
4 *
5 * (c) 2004 Straylight/Edgeware
6 */
7
8/*----- Licensing notice --------------------------------------------------*
9 *
10 * This file is part of Catacomb.
11 *
12 * Catacomb is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU Library General Public License as
14 * published by the Free Software Foundation; either version 2 of the
15 * License, or (at your option) any later version.
16 *
17 * Catacomb is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU Library General Public License for more details.
21 *
22 * You should have received a copy of the GNU Library General Public
23 * License along with Catacomb; if not, write to the Free
24 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
25 * MA 02111-1307, USA.
26 */
27
28/*----- Header files ------------------------------------------------------*/
29
30#include <ctype.h>
31
32#include <mLib/sub.h>
33
34#define ge ec
35#include "group.h"
36#include "ec-raw.h"
37#include "group-guts.h"
38
39/*----- Main code ---------------------------------------------------------*/
40
41/* --- Group operations --- */
42
43static void gdestroygroup(group *gg) {
44 gctx_ec *g = (gctx_ec *)gg;
45 EC_DESTROY(&g->gen);
46 ec_freeinfo(&g->ei);
47 DESTROY(g);
48}
49
50static ec *gcreate(group *gg)
51 { ec *x = CREATE(ec); EC_CREATE(x); return (x); }
52
53static void gcopy(group *gg, ec *d, ec *x) { EC_COPY(d, x); }
54
55static void gburn(group *gg, ec *x) { if (x->x) (x->x)->f |= MP_BURN; }
56
57static void gdestroy(group *gg, ec *x) { EC_DESTROY(x); DESTROY(x); }
58
59static int gsamep(group *gg, group *hh) {
60 gctx_ec *g = (gctx_ec *)gg, *h = (gctx_ec *)hh;
61 return (ec_sameinfop(&g->ei, &h->ei));
62}
63
64static int geq(group *gg, ec *x, ec *y) {
65 gctx_ec *g = (gctx_ec *)gg; EC_FIX(g->ei.c, x, x); EC_FIX(g->ei.c, y, y);
66 return (EC_EQ(x, y));
67}
68
69static int gidentp(group *gg, ec *x) { return (EC_ATINF(x)); }
70
71static const char *gcheck(group *gg, grand *gr)
72 { gctx_ec *g = (gctx_ec *)gg; return (ec_checkinfo(&g->ei, gr)); }
73
74static void gmul(group *gg, ec *d, ec *x, ec *y)
75 { gctx_ec *g = (gctx_ec *)gg; EC_ADD(g->ei.c, d, x, y); }
76
77static void gsqr(group *gg, ec *d, ec *x)
78 { gctx_ec *g = (gctx_ec *)gg; EC_DBL(g->ei.c, d, x); }
79
80static void ginv(group *gg, ec *d, ec *x)
81 { gctx_ec *g = (gctx_ec *)gg; EC_NEG(g->ei.c, d, x); }
82
83static void gdiv(group *gg, ec *d, ec *x, ec *y)
84 { gctx_ec *g = (gctx_ec *)gg; EC_SUB(g->ei.c, d, x, y); }
85
86static void gexp(group *gg, ec *d, ec *x, mp *n)
87 { gctx_ec *g = (gctx_ec *)gg; ec_imul(g->ei.c, d, x, n); }
88
89static void gmexp(group *gg, ec *d, const group_expfactor *f, size_t n) {
90 gctx_ec *g = (gctx_ec *)gg; size_t i;
91 ec_mulfactor *ff = xmalloc(n * sizeof(ec_mulfactor));
92 for (i = 0; i < n; i++) { ff[i].base = *f[i].base; ff[i].exp = f[i].exp; }
93 ec_immul(g->ei.c, d, ff, n); xfree(ff);
94}
95
96static int gread(group *gg, ec *d, const mptext_ops *ops, void *p) {
97 gctx_ec *g = (gctx_ec *)gg;
98 ec t = EC_INIT;
99 int rc = -1;
100 int ch;
101
102 ch = ops->get(p);
103 if (tolower(ch) == 'i') {
104 if (tolower(ops->get(p)) != 'n' || tolower(ops->get(p)) != 'f')
105 return (-1);
106 EC_SETINF(d);
107 return (0);
108 }
109 ops->unget(ch, p);
110 if ((t.x = mp_read(MP_NEW, 0, ops, p)) == 0) goto done;
111 do ch = ops->get(p); while (ch == ',' || isspace(ch)); ops->unget(ch, p);
112 if ((t.y = mp_read(MP_NEW, 0, ops, p)) == 0) goto done;
113 EC_IN(g->ei.c, &t, &t);
114 if (EC_CHECK(g->ei.c, &t)) goto done;
115 EC_COPY(d, &t); rc = 0;
116 EC_DESTROY(&t);
117done:
118 return (rc);
119}
120
121static int gwrite(group *gg, ec *x, const mptext_ops *ops, void *p) {
122 gctx_ec *g = (gctx_ec *)gg; int rc = -1; ec t = EC_INIT;
123 EC_OUT(g->ei.c, &t, x); if (EC_ATINF(&t)) rc = ops->put("inf", 3, p);
124 else if (!ops->put("0x", 2, p) && !mp_write(t.x, 16, ops, p) &&
125 !ops->put(", 0x", 4, p) && !mp_write(t.y, 16, ops, p)) rc = 0;
126 EC_DESTROY(&t); return (rc);
127}
128
129static mp *gtoint(group *gg, mp *d, ec *x) {
130 gctx_ec *g = (gctx_ec *)gg; ec t = EC_INIT; mp *i; if (EC_ATINF(x)) i = 0;
131 else { EC_OUT(g->ei.c, &t, x); i = MP_COPY(t.x); EC_DESTROY(&t); }
132 mp_drop(d); return (i);
133}
134
135static int gfromint(group *gg, ec *d, mp *x) {
136 gctx_ec *g = (gctx_ec *)gg; ec t = EC_INIT;
137 if (!ec_find(g->ei.c, &t, x)) return (-1);
138 EC_IN(g->ei.c, d, &t); EC_DESTROY(&t); return (0);
139}
140
141static int gtoec(group *gg, ec *d, ec *x)
142 { gctx_ec *g = (gctx_ec *)gg; EC_OUT(g->ei.c, d, x); return (0); }
143
144static int gfromec(group *gg, ec *d, const ec *x) {
145 gctx_ec *g = (gctx_ec *)gg; ec t = EC_INIT; int rc; EC_IN(g->ei.c, &t, x);
146 rc = EC_CHECK(g->ei.c, &t); if (!rc) EC_COPY(d, &t); EC_DESTROY(&t);
147 return (rc);
148}
149
150static int gtobuf(group *gg, buf *b, ec *x) {
151 gctx_ec *g = (gctx_ec *)gg; ec t = EC_INIT; int rc;
152 EC_OUT(g->ei.c, &t, x); rc = buf_putec(b, &t); EC_DESTROY(&t); return (rc);
153}
154
155static int gfrombuf(group *gg, buf *b, ec *d) {
156 gctx_ec *g = (gctx_ec *)gg; ec t = EC_INIT; int rc;
157 if (buf_getec(b, &t)) return (-1);
158 EC_IN(g->ei.c, &t, &t); rc = EC_CHECK(g->ei.c, &t);
159 if (!rc) EC_COPY(d, &t); EC_DESTROY(&t); return (rc);
160}
161
162static int gtoraw(group *gg, buf *b, ec *x) {
163 gctx_ec *g = (gctx_ec *)gg; ec t = EC_INIT; int rc;
164 EC_OUT(g->ei.c, &t, x); rc = ec_putraw(g->ei.c, b, &t);
165 EC_DESTROY(&t); return (rc);
166}
167
168static int gfromraw(group *gg, buf *b, ec *d) {
169 gctx_ec *g = (gctx_ec *)gg; ec t = EC_INIT; int rc;
170 if (ec_getraw(g->ei.c, b, &t)) return (-1);
171 EC_IN(g->ei.c, &t, &t); rc = EC_CHECK(g->ei.c, &t);
172 if (!rc) EC_COPY(d, &t); EC_DESTROY(&t); return (rc);
173}
174
175/* --- @group_ec@ --- *
176 *
177 * Arguments: @const ec_info *ei@ = elliptic curve parameters
178 *
179 * Returns: A pointer to the group.
180 *
181 * Use: Constructs an abstract group interface for an elliptic curve
182 * group. Group elements are @ec@ structures. The contents of
183 * the @ec_info@ structure becomes the property of the @group@
184 * object; you can (and should) free the structure itself, but
185 * calling @ec_freeinfo@ on it is not allowed.
186 */
187
188static const group_ops gops = {
189 GTY_EC, "ec",
190 gdestroygroup, gcreate, gcopy, gburn, gdestroy,
191 gsamep, geq, gidentp,
192 gcheck,
193 gmul, gsqr, ginv, gdiv, gexp, gmexp,
194 gread, gwrite,
195 gtoint, gfromint, gtoec, gfromec, gtobuf, gfrombuf, gtoraw, gfromraw
196};
197
198group *group_ec(const ec_info *ei)
199{
200 gctx_ec *g = CREATE(gctx_ec);
201
202 g->g.ops = &gops;
203 g->g.nbits = ei->c->f->nbits * 2;
204 g->g.noctets = ei->c->f->noctets * 2 + 1;
205 g->ei = *ei;
206 EC_CREATE(&g->id);
207 g->g.i = &g->id;
208 EC_CREATE(&g->gen);
209 g->g.g = &g->gen;
210 EC_IN(g->ei.c, &g->gen, &ei->g);
211 g->g.r = ei->r;
212 g->g.h = ei->h;
213 return (&g->g);
214}
215
216/*----- That's all, folks -------------------------------------------------*/