Merge branch '2.5.x'
[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
0f3faccd 35#include "ec-raw.h"
f94b972d 36#include "group-guts.h"
34e4f738 37
38/*----- Main code ---------------------------------------------------------*/
39
40/* --- Group operations --- */
41
42static void gdestroygroup(group *gg) {
f94b972d 43 gctx_ec *g = (gctx_ec *)gg;
34e4f738 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) {
f94b972d 59 gctx_ec *g = (gctx_ec *)gg, *h = (gctx_ec *)hh;
34e4f738 60 return (ec_sameinfop(&g->ei, &h->ei));
61}
62
63static int geq(group *gg, ec *x, ec *y) {
f94b972d 64 gctx_ec *g = (gctx_ec *)gg; EC_FIX(g->ei.c, x, x); EC_FIX(g->ei.c, y, y);
34e4f738 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)
f94b972d 71 { gctx_ec *g = (gctx_ec *)gg; return (ec_checkinfo(&g->ei, gr)); }
34e4f738 72
73static void gmul(group *gg, ec *d, ec *x, ec *y)
f94b972d 74 { gctx_ec *g = (gctx_ec *)gg; EC_ADD(g->ei.c, d, x, y); }
34e4f738 75
76static void gsqr(group *gg, ec *d, ec *x)
f94b972d 77 { gctx_ec *g = (gctx_ec *)gg; EC_DBL(g->ei.c, d, x); }
34e4f738 78
79static void ginv(group *gg, ec *d, ec *x)
f94b972d 80 { gctx_ec *g = (gctx_ec *)gg; EC_NEG(g->ei.c, d, x); }
34e4f738 81
82static void gdiv(group *gg, ec *d, ec *x, ec *y)
f94b972d 83 { gctx_ec *g = (gctx_ec *)gg; EC_SUB(g->ei.c, d, x, y); }
34e4f738 84
85static void gexp(group *gg, ec *d, ec *x, mp *n)
f94b972d 86 { gctx_ec *g = (gctx_ec *)gg; ec_imul(g->ei.c, d, x, n); }
34e4f738 87
88static void gmexp(group *gg, ec *d, const group_expfactor *f, size_t n) {
f94b972d 89 gctx_ec *g = (gctx_ec *)gg; size_t i;
45c0fd36 90 ec_mulfactor *ff = xmalloc(n * sizeof(ec_mulfactor));
34e4f738 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) {
f94b972d 96 gctx_ec *g = (gctx_ec *)gg;
34e4f738 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) {
f94b972d 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);
34e4f738 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) {
f94b972d 129 gctx_ec *g = (gctx_ec *)gg; ec t = EC_INIT; mp *i; if (EC_ATINF(x)) i = 0;
34e4f738 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) {
f94b972d 135 gctx_ec *g = (gctx_ec *)gg; ec t = EC_INIT;
34e4f738 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)
f94b972d 141 { gctx_ec *g = (gctx_ec *)gg; EC_OUT(g->ei.c, d, x); return (0); }
34e4f738 142
5c3f75ec 143static int gfromec(group *gg, ec *d, const ec *x) {
f94b972d 144 gctx_ec *g = (gctx_ec *)gg; ec t = EC_INIT; int rc; EC_IN(g->ei.c, &t, x);
34e4f738 145 rc = EC_CHECK(g->ei.c, &t); if (!rc) EC_COPY(d, &t); EC_DESTROY(&t);
146 return (rc);
147}
45c0fd36 148
34e4f738 149static int gtobuf(group *gg, buf *b, ec *x) {
f94b972d 150 gctx_ec *g = (gctx_ec *)gg; ec t = EC_INIT; int rc;
34e4f738 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) {
f94b972d 155 gctx_ec *g = (gctx_ec *)gg; ec t = EC_INIT; int rc;
34e4f738 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
0f3faccd 161static int gtoraw(group *gg, buf *b, ec *x) {
f94b972d 162 gctx_ec *g = (gctx_ec *)gg; ec t = EC_INIT; int rc;
0f3faccd 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) {
f94b972d 168 gctx_ec *g = (gctx_ec *)gg; ec t = EC_INIT; int rc;
0f3faccd 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
34e4f738 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 = {
f94b972d 188 GTY_EC, "ec",
34e4f738 189 gdestroygroup, gcreate, gcopy, gburn, gdestroy,
190 gsamep, geq, gidentp,
191 gcheck,
192 gmul, gsqr, ginv, gdiv, gexp, gmexp,
193 gread, gwrite,
0f3faccd 194 gtoint, gfromint, gtoec, gfromec, gtobuf, gfrombuf, gtoraw, gfromraw
34e4f738 195};
196
197group *group_ec(const ec_info *ei)
198{
f94b972d 199 gctx_ec *g = CREATE(gctx_ec);
34e4f738 200
201 g->g.ops = &gops;
202 g->g.nbits = ei->c->f->nbits * 2;
0f3faccd 203 g->g.noctets = ei->c->f->noctets * 2 + 1;
34e4f738 204 g->ei = *ei;
205 EC_CREATE(&g->id);
206 g->g.i = &g->id;
207 EC_CREATE(&g->gen);
02d7884d 208 g->g.g = &g->gen;
34e4f738 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 -------------------------------------------------*/