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