chiark / gitweb /
math/mpx-mul4-x86-sse2.S: Give `squash' an explicit destination argument.
[catacomb] / math / g-ec.c
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 "group.h"
36 #include "ec-raw.h"
37 #include "group-guts.h"
38
39 /*----- Main code ---------------------------------------------------------*/
40
41 /* --- Group operations --- */
42
43 static void gdestroygroup(group *gg) {
44   gctx_ec *g = (gctx_ec *)gg;
45   EC_DESTROY(&g->gen);
46   ec_freeinfo(&g->ei);
47   DESTROY(g);
48 }
49
50 static ec *gcreate(group *gg)
51   { ec *x = CREATE(ec); EC_CREATE(x); return (x); }
52
53 static void gcopy(group *gg, ec *d, ec *x) { EC_COPY(d, x); }
54
55 static void gburn(group *gg, ec *x) { if (x->x) (x->x)->f |= MP_BURN; }
56
57 static void gdestroy(group *gg, ec *x) { EC_DESTROY(x); DESTROY(x); }
58
59 static int gsamep(group *gg, group *hh) {
60   gctx_ec *g = (gctx_ec *)gg, *h = (gctx_ec *)hh;
61   return (ec_sameinfop(&g->ei, &h->ei));
62 }
63
64 static int geq(group *gg, ec *x, ec *y) {
65   gctx_ec *g = (gctx_ec *)gg; EC_FIX(g->ei.c, x, x); EC_FIX(g->ei.c, y, y);
66   return (EC_EQ(x, y));
67 }
68
69 static int gidentp(group *gg, ec *x) { return (EC_ATINF(x)); }
70
71 static const char *gcheck(group *gg, grand *gr)
72   { gctx_ec *g = (gctx_ec *)gg; return (ec_checkinfo(&g->ei, gr)); }
73
74 static void gmul(group *gg, ec *d, ec *x, ec *y)
75   { gctx_ec *g = (gctx_ec *)gg; EC_ADD(g->ei.c, d, x, y); }
76
77 static void gsqr(group *gg, ec *d, ec *x)
78   { gctx_ec *g = (gctx_ec *)gg; EC_DBL(g->ei.c, d, x); }
79
80 static void ginv(group *gg, ec *d, ec *x)
81   { gctx_ec *g = (gctx_ec *)gg; EC_NEG(g->ei.c, d, x); }
82
83 static void gdiv(group *gg, ec *d, ec *x, ec *y)
84   { gctx_ec *g = (gctx_ec *)gg; EC_SUB(g->ei.c, d, x, y); }
85
86 static void gexp(group *gg, ec *d, ec *x, mp *n)
87   { gctx_ec *g = (gctx_ec *)gg; ec_imul(g->ei.c, d, x, n); }
88
89 static void gmexp(group *gg, ec *d, const group_expfactor *f, size_t n) {
90   gctx_ec *g = (gctx_ec *)gg; size_t i;
91   ec_mulfactor *ff = xmalloc(n * sizeof(ec_mulfactor));
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
96 static int gread(group *gg, ec *d, const mptext_ops *ops, void *p) {
97   gctx_ec *g = (gctx_ec *)gg;
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);
117 done:
118   return (rc);
119 }
120
121 static int gwrite(group *gg, ec *x, const mptext_ops *ops, void *p) {
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);
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
129 static mp *gtoint(group *gg, mp *d, ec *x) {
130   gctx_ec *g = (gctx_ec *)gg; ec t = EC_INIT; mp *i; if (EC_ATINF(x)) i = 0;
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
135 static int gfromint(group *gg, ec *d, mp *x) {
136   gctx_ec *g = (gctx_ec *)gg; ec t = EC_INIT;
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
141 static int gtoec(group *gg, ec *d, ec *x)
142   { gctx_ec *g = (gctx_ec *)gg; EC_OUT(g->ei.c, d, x); return (0); }
143
144 static int gfromec(group *gg, ec *d, const ec *x) {
145   gctx_ec *g = (gctx_ec *)gg; ec t = EC_INIT; int rc; EC_IN(g->ei.c, &t, x);
146   rc = EC_CHECK(g->ei.c, &t); if (!rc) EC_COPY(d, &t); EC_DESTROY(&t);
147   return (rc);
148 }
149
150 static int gtobuf(group *gg, buf *b, ec *x) {
151   gctx_ec *g = (gctx_ec *)gg; ec t = EC_INIT; int rc;
152   EC_OUT(g->ei.c, &t, x); rc = buf_putec(b, &t); EC_DESTROY(&t); return (rc);
153 }
154
155 static int gfrombuf(group *gg, buf *b, ec *d) {
156   gctx_ec *g = (gctx_ec *)gg; ec t = EC_INIT; int rc;
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
162 static int gtoraw(group *gg, buf *b, ec *x) {
163   gctx_ec *g = (gctx_ec *)gg; ec t = EC_INIT; int rc;
164   EC_OUT(g->ei.c, &t, x); rc = ec_putraw(g->ei.c, b, &t);
165   EC_DESTROY(&t); return (rc);
166 }
167
168 static int gfromraw(group *gg, buf *b, ec *d) {
169   gctx_ec *g = (gctx_ec *)gg; ec t = EC_INIT; int rc;
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
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
188 static const group_ops gops = {
189   GTY_EC, "ec",
190   gdestroygroup, gcreate, gcopy, gburn, gdestroy,
191   gsamep, geq, gidentp,
192   gcheck,
193   gmul, gsqr, ginv, gdiv, gexp, gmexp,
194   gread, gwrite,
195   gtoint, gfromint, gtoec, gfromec, gtobuf, gfrombuf, gtoraw, gfromraw
196 };
197
198 group *group_ec(const ec_info *ei)
199 {
200   gctx_ec *g = CREATE(gctx_ec);
201
202   g->g.ops = &gops;
203   g->g.nbits = ei->c->f->nbits * 2;
204   g->g.noctets = ei->c->f->noctets * 2 + 1;
205   g->ei = *ei;
206   EC_CREATE(&g->id);
207   g->g.i = &g->id;
208   EC_CREATE(&g->gen);
209   g->g.g = &g->gen;
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 -------------------------------------------------*/