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