math/mpreduce.h: Missing include files.
[u/mdw/catacomb] / math / g-ec.c
CommitLineData
34e4f738 1/* -*-c-*-
2 *
34e4f738 3 * Abstraction for elliptic curve groups
4 *
5 * (c) 2004 Straylight/Edgeware
6 */
7
45c0fd36 8/*----- Licensing notice --------------------------------------------------*
34e4f738 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.
45c0fd36 16 *
34e4f738 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.
45c0fd36 21 *
34e4f738 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
34e4f738 28/*----- Header files ------------------------------------------------------*/
29
30#include <ctype.h>
31
32#include <mLib/sub.h>
33
34#define ge ec
35#include "group.h"
0f3faccd 36#include "ec-raw.h"
f94b972d 37#include "group-guts.h"
34e4f738 38
39/*----- Main code ---------------------------------------------------------*/
40
41/* --- Group operations --- */
42
43static void gdestroygroup(group *gg) {
f94b972d 44 gctx_ec *g = (gctx_ec *)gg;
34e4f738 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) {
f94b972d 60 gctx_ec *g = (gctx_ec *)gg, *h = (gctx_ec *)hh;
34e4f738 61 return (ec_sameinfop(&g->ei, &h->ei));
62}
63
64static int geq(group *gg, ec *x, ec *y) {
f94b972d 65 gctx_ec *g = (gctx_ec *)gg; EC_FIX(g->ei.c, x, x); EC_FIX(g->ei.c, y, y);
34e4f738 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)
f94b972d 72 { gctx_ec *g = (gctx_ec *)gg; return (ec_checkinfo(&g->ei, gr)); }
34e4f738 73
74static void gmul(group *gg, ec *d, ec *x, ec *y)
f94b972d 75 { gctx_ec *g = (gctx_ec *)gg; EC_ADD(g->ei.c, d, x, y); }
34e4f738 76
77static void gsqr(group *gg, ec *d, ec *x)
f94b972d 78 { gctx_ec *g = (gctx_ec *)gg; EC_DBL(g->ei.c, d, x); }
34e4f738 79
80static void ginv(group *gg, ec *d, ec *x)
f94b972d 81 { gctx_ec *g = (gctx_ec *)gg; EC_NEG(g->ei.c, d, x); }
34e4f738 82
83static void gdiv(group *gg, ec *d, ec *x, ec *y)
f94b972d 84 { gctx_ec *g = (gctx_ec *)gg; EC_SUB(g->ei.c, d, x, y); }
34e4f738 85
86static void gexp(group *gg, ec *d, ec *x, mp *n)
f94b972d 87 { gctx_ec *g = (gctx_ec *)gg; ec_imul(g->ei.c, d, x, n); }
34e4f738 88
89static void gmexp(group *gg, ec *d, const group_expfactor *f, size_t n) {
f94b972d 90 gctx_ec *g = (gctx_ec *)gg; size_t i;
45c0fd36 91 ec_mulfactor *ff = xmalloc(n * sizeof(ec_mulfactor));
34e4f738 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) {
f94b972d 97 gctx_ec *g = (gctx_ec *)gg;
34e4f738 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) {
f94b972d 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);
34e4f738 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) {
f94b972d 130 gctx_ec *g = (gctx_ec *)gg; ec t = EC_INIT; mp *i; if (EC_ATINF(x)) i = 0;
34e4f738 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) {
f94b972d 136 gctx_ec *g = (gctx_ec *)gg; ec t = EC_INIT;
34e4f738 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)
f94b972d 142 { gctx_ec *g = (gctx_ec *)gg; EC_OUT(g->ei.c, d, x); return (0); }
34e4f738 143
5c3f75ec 144static int gfromec(group *gg, ec *d, const ec *x) {
f94b972d 145 gctx_ec *g = (gctx_ec *)gg; ec t = EC_INIT; int rc; EC_IN(g->ei.c, &t, x);
34e4f738 146 rc = EC_CHECK(g->ei.c, &t); if (!rc) EC_COPY(d, &t); EC_DESTROY(&t);
147 return (rc);
148}
45c0fd36 149
34e4f738 150static int gtobuf(group *gg, buf *b, ec *x) {
f94b972d 151 gctx_ec *g = (gctx_ec *)gg; ec t = EC_INIT; int rc;
34e4f738 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) {
f94b972d 156 gctx_ec *g = (gctx_ec *)gg; ec t = EC_INIT; int rc;
34e4f738 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
0f3faccd 162static int gtoraw(group *gg, buf *b, ec *x) {
f94b972d 163 gctx_ec *g = (gctx_ec *)gg; ec t = EC_INIT; int rc;
0f3faccd 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) {
f94b972d 169 gctx_ec *g = (gctx_ec *)gg; ec t = EC_INIT; int rc;
0f3faccd 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
34e4f738 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 = {
f94b972d 189 GTY_EC, "ec",
34e4f738 190 gdestroygroup, gcreate, gcopy, gburn, gdestroy,
191 gsamep, geq, gidentp,
192 gcheck,
193 gmul, gsqr, ginv, gdiv, gexp, gmexp,
194 gread, gwrite,
0f3faccd 195 gtoint, gfromint, gtoec, gfromec, gtobuf, gfrombuf, gtoraw, gfromraw
34e4f738 196};
197
198group *group_ec(const ec_info *ei)
199{
f94b972d 200 gctx_ec *g = CREATE(gctx_ec);
34e4f738 201
202 g->g.ops = &gops;
203 g->g.nbits = ei->c->f->nbits * 2;
0f3faccd 204 g->g.noctets = ei->c->f->noctets * 2 + 1;
34e4f738 205 g->ei = *ei;
206 EC_CREATE(&g->id);
207 g->g.i = &g->id;
208 EC_CREATE(&g->gen);
02d7884d 209 g->g.g = &g->gen;
34e4f738 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 -------------------------------------------------*/