chiark / gitweb /
math/mpx-mul4-amd64-sse2.S: Always collect iteration count as 32 bits.
[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 "ec-raw.h"
36 #include "group-guts.h"
37
38 /*----- Main code ---------------------------------------------------------*/
39
40 /* --- Group operations --- */
41
42 static 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
49 static ec *gcreate(group *gg)
50   { ec *x = CREATE(ec); EC_CREATE(x); return (x); }
51
52 static void gcopy(group *gg, ec *d, ec *x) { EC_COPY(d, x); }
53
54 static void gburn(group *gg, ec *x) { if (x->x) (x->x)->f |= MP_BURN; }
55
56 static void gdestroy(group *gg, ec *x) { EC_DESTROY(x); DESTROY(x); }
57
58 static 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
63 static 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
68 static int gidentp(group *gg, ec *x) { return (EC_ATINF(x)); }
69
70 static const char *gcheck(group *gg, grand *gr)
71   { gctx_ec *g = (gctx_ec *)gg; return (ec_checkinfo(&g->ei, gr)); }
72
73 static 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
76 static void gsqr(group *gg, ec *d, ec *x)
77   { gctx_ec *g = (gctx_ec *)gg; EC_DBL(g->ei.c, d, x); }
78
79 static void ginv(group *gg, ec *d, ec *x)
80   { gctx_ec *g = (gctx_ec *)gg; EC_NEG(g->ei.c, d, x); }
81
82 static 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
85 static 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
88 static 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
95 static 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);
116 done:
117   return (rc);
118 }
119
120 static 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
128 static 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
134 static 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
140 static 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
143 static 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
149 static 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
154 static 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
161 static 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
167 static 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
187 static 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
197 group *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 -------------------------------------------------*/