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