Make tables of standard encryption schemes etc.
[u/mdw/catacomb] / g-ec.c
CommitLineData
34e4f738 1/* -*-c-*-
2 *
0f3faccd 3 * $Id: g-ec.c,v 1.3 2004/04/04 19:04:11 mdw Exp $
34e4f738 4 *
5 * Abstraction for elliptic curve groups
6 *
7 * (c) 2004 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: g-ec.c,v $
0f3faccd 33 * Revision 1.3 2004/04/04 19:04:11 mdw
34 * Raw I/O of elliptic curve points and group elements.
35 *
02d7884d 36 * Revision 1.2 2004/04/03 03:32:05 mdw
37 * General robustification.
38 *
34e4f738 39 * Revision 1.1 2004/04/01 12:50:09 mdw
40 * Add cyclic group abstraction, with test code. Separate off exponentation
41 * functions for better static linking. Fix a buttload of bugs on the way.
42 * Generally ensure that negative exponents do inversion correctly. Add
43 * table of standard prime-field subgroups. (Binary field subgroups are
44 * currently unimplemented but easy to add if anyone ever finds a good one.)
45 *
46 */
47
48/*----- Header files ------------------------------------------------------*/
49
50#include <ctype.h>
51
52#include <mLib/sub.h>
53
54#define ge ec
55#include "group.h"
0f3faccd 56#include "ec-raw.h"
34e4f738 57
58/*----- Data structures ---------------------------------------------------*/
59
60typedef struct gctx {
61 group g;
62 ec id, gen;
63 ec_info ei;
64} gctx;
65
66/*----- Main code ---------------------------------------------------------*/
67
68/* --- Group operations --- */
69
70static void gdestroygroup(group *gg) {
71 gctx *g = (gctx *)gg;
72 EC_DESTROY(&g->gen);
73 ec_freeinfo(&g->ei);
74 DESTROY(g);
75}
76
77static ec *gcreate(group *gg)
78 { ec *x = CREATE(ec); EC_CREATE(x); return (x); }
79
80static void gcopy(group *gg, ec *d, ec *x) { EC_COPY(d, x); }
81
82static void gburn(group *gg, ec *x) { if (x->x) (x->x)->f |= MP_BURN; }
83
84static void gdestroy(group *gg, ec *x) { EC_DESTROY(x); DESTROY(x); }
85
86static int gsamep(group *gg, group *hh) {
87 gctx *g = (gctx *)gg, *h = (gctx *)hh;
88 return (ec_sameinfop(&g->ei, &h->ei));
89}
90
91static int geq(group *gg, ec *x, ec *y) {
92 gctx *g = (gctx *)gg; EC_FIX(g->ei.c, x, x); EC_FIX(g->ei.c, y, y);
93 return (EC_EQ(x, y));
94}
95
96static int gidentp(group *gg, ec *x) { return (EC_ATINF(x)); }
97
98static const char *gcheck(group *gg, grand *gr)
99 { gctx *g = (gctx *)gg; return (ec_checkinfo(&g->ei, gr)); }
100
101static void gmul(group *gg, ec *d, ec *x, ec *y)
102 { gctx *g = (gctx *)gg; EC_ADD(g->ei.c, d, x, y); }
103
104static void gsqr(group *gg, ec *d, ec *x)
105 { gctx *g = (gctx *)gg; EC_DBL(g->ei.c, d, x); }
106
107static void ginv(group *gg, ec *d, ec *x)
108 { gctx *g = (gctx *)gg; EC_NEG(g->ei.c, d, x); }
109
110static void gdiv(group *gg, ec *d, ec *x, ec *y)
111 { gctx *g = (gctx *)gg; EC_SUB(g->ei.c, d, x, y); }
112
113static void gexp(group *gg, ec *d, ec *x, mp *n)
114 { gctx *g = (gctx *)gg; ec_imul(g->ei.c, d, x, n); }
115
116static void gmexp(group *gg, ec *d, const group_expfactor *f, size_t n) {
117 gctx *g = (gctx *)gg; size_t i;
118 ec_mulfactor *ff = xmalloc(n * sizeof(ec_mulfactor));
119 for (i = 0; i < n; i++) { ff[i].base = *f[i].base; ff[i].exp = f[i].exp; }
120 ec_immul(g->ei.c, d, ff, n); xfree(ff);
121}
122
123static int gread(group *gg, ec *d, const mptext_ops *ops, void *p) {
124 gctx *g = (gctx *)gg;
125 ec t = EC_INIT;
126 int rc = -1;
127 int ch;
128
129 ch = ops->get(p);
130 if (tolower(ch) == 'i') {
131 if (tolower(ops->get(p)) != 'n' || tolower(ops->get(p)) != 'f')
132 return (-1);
133 EC_SETINF(d);
134 return (0);
135 }
136 ops->unget(ch, p);
137 if ((t.x = mp_read(MP_NEW, 0, ops, p)) == 0) goto done;
138 do ch = ops->get(p); while (ch == ',' || isspace(ch)); ops->unget(ch, p);
139 if ((t.y = mp_read(MP_NEW, 0, ops, p)) == 0) goto done;
140 EC_IN(g->ei.c, &t, &t);
141 if (EC_CHECK(g->ei.c, &t)) goto done;
142 EC_COPY(d, &t); rc = 0;
143 EC_DESTROY(&t);
144done:
145 return (rc);
146}
147
148static int gwrite(group *gg, ec *x, const mptext_ops *ops, void *p) {
149 gctx *g = (gctx *)gg; int rc = -1; ec t = EC_INIT; EC_OUT(g->ei.c, &t, x);
150 if (EC_ATINF(&t)) rc = ops->put("inf", 3, p);
151 else if (!ops->put("0x", 2, p) && !mp_write(t.x, 16, ops, p) &&
152 !ops->put(", 0x", 4, p) && !mp_write(t.y, 16, ops, p)) rc = 0;
153 EC_DESTROY(&t); return (rc);
154}
155
156static mp *gtoint(group *gg, mp *d, ec *x) {
157 gctx *g = (gctx *)gg; ec t = EC_INIT; mp *i; if (EC_ATINF(x)) i = 0;
158 else { EC_OUT(g->ei.c, &t, x); i = MP_COPY(t.x); EC_DESTROY(&t); }
159 mp_drop(d); return (i);
160}
161
162static int gfromint(group *gg, ec *d, mp *x) {
163 gctx *g = (gctx *)gg; ec t = EC_INIT;
164 if (!ec_find(g->ei.c, &t, x)) return (-1);
165 EC_IN(g->ei.c, d, &t); EC_DESTROY(&t); return (0);
166}
167
168static int gtoec(group *gg, ec *d, ec *x)
169 { gctx *g = (gctx *)gg; EC_OUT(g->ei.c, d, x); return (0); }
170
171static int gfromec(group *gg, ec *d, ec *x) {
172 gctx *g = (gctx *)gg; ec t = EC_INIT; int rc; EC_IN(g->ei.c, &t, x);
173 rc = EC_CHECK(g->ei.c, &t); if (!rc) EC_COPY(d, &t); EC_DESTROY(&t);
174 return (rc);
175}
176
177static int gtobuf(group *gg, buf *b, ec *x) {
178 gctx *g = (gctx *)gg; ec t = EC_INIT; int rc;
179 EC_OUT(g->ei.c, &t, x); rc = buf_putec(b, &t); EC_DESTROY(&t); return (rc);
180}
181
182static int gfrombuf(group *gg, buf *b, ec *d) {
183 gctx *g = (gctx *)gg; ec t = EC_INIT; int rc;
184 if (buf_getec(b, &t)) return (-1);
185 EC_IN(g->ei.c, &t, &t); rc = EC_CHECK(g->ei.c, &t);
186 if (!rc) EC_COPY(d, &t); EC_DESTROY(&t); return (rc);
187}
188
0f3faccd 189static int gtoraw(group *gg, buf *b, ec *x) {
190 gctx *g = (gctx *)gg; ec t = EC_INIT; int rc;
191 EC_OUT(g->ei.c, &t, x); rc = ec_putraw(g->ei.c, b, &t);
192 EC_DESTROY(&t); return (rc);
193}
194
195static int gfromraw(group *gg, buf *b, ec *d) {
196 gctx *g = (gctx *)gg; ec t = EC_INIT; int rc;
197 if (ec_getraw(g->ei.c, b, &t)) return (-1);
198 EC_IN(g->ei.c, &t, &t); rc = EC_CHECK(g->ei.c, &t);
199 if (!rc) EC_COPY(d, &t); EC_DESTROY(&t); return (rc);
200}
201
34e4f738 202/* --- @group_ec@ --- *
203 *
204 * Arguments: @const ec_info *ei@ = elliptic curve parameters
205 *
206 * Returns: A pointer to the group.
207 *
208 * Use: Constructs an abstract group interface for an elliptic curve
209 * group. Group elements are @ec@ structures. The contents of
210 * the @ec_info@ structure becomes the property of the @group@
211 * object; you can (and should) free the structure itself, but
212 * calling @ec_freeinfo@ on it is not allowed.
213 */
214
215static const group_ops gops = {
216 GTY_EC,
217 gdestroygroup, gcreate, gcopy, gburn, gdestroy,
218 gsamep, geq, gidentp,
219 gcheck,
220 gmul, gsqr, ginv, gdiv, gexp, gmexp,
221 gread, gwrite,
0f3faccd 222 gtoint, gfromint, gtoec, gfromec, gtobuf, gfrombuf, gtoraw, gfromraw
34e4f738 223};
224
225group *group_ec(const ec_info *ei)
226{
227 gctx *g = CREATE(gctx);
228
229 g->g.ops = &gops;
230 g->g.nbits = ei->c->f->nbits * 2;
0f3faccd 231 g->g.noctets = ei->c->f->noctets * 2 + 1;
34e4f738 232 g->ei = *ei;
233 EC_CREATE(&g->id);
234 g->g.i = &g->id;
235 EC_CREATE(&g->gen);
02d7884d 236 g->g.g = &g->gen;
34e4f738 237 EC_IN(g->ei.c, &g->gen, &ei->g);
238 g->g.r = ei->r;
239 g->g.h = ei->h;
240 return (&g->g);
241}
242
243/*----- That's all, folks -------------------------------------------------*/