3 * $Id: g-ec.c,v 1.2 2004/04/03 03:32:05 mdw Exp $
5 * Abstraction for elliptic curve groups
7 * (c) 2004 Straylight/Edgeware
10 /*----- Licensing notice --------------------------------------------------*
12 * This file is part of Catacomb.
14 * Catacomb is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU Library General Public License as
16 * published by the Free Software Foundation; either version 2 of the
17 * License, or (at your option) any later version.
19 * Catacomb is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU Library General Public License for more details.
24 * You should have received a copy of the GNU Library General Public
25 * License along with Catacomb; if not, write to the Free
26 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
30 /*----- Revision history --------------------------------------------------*
33 * Revision 1.2 2004/04/03 03:32:05 mdw
34 * General robustification.
36 * Revision 1.1 2004/04/01 12:50:09 mdw
37 * Add cyclic group abstraction, with test code. Separate off exponentation
38 * functions for better static linking. Fix a buttload of bugs on the way.
39 * Generally ensure that negative exponents do inversion correctly. Add
40 * table of standard prime-field subgroups. (Binary field subgroups are
41 * currently unimplemented but easy to add if anyone ever finds a good one.)
45 /*----- Header files ------------------------------------------------------*/
54 /*----- Data structures ---------------------------------------------------*/
62 /*----- Main code ---------------------------------------------------------*/
64 /* --- Group operations --- */
66 static void gdestroygroup(group
*gg
) {
73 static ec
*gcreate(group
*gg
)
74 { ec
*x
= CREATE(ec
); EC_CREATE(x
); return (x
); }
76 static void gcopy(group
*gg
, ec
*d
, ec
*x
) { EC_COPY(d
, x
); }
78 static void gburn(group
*gg
, ec
*x
) { if (x
->x
) (x
->x
)->f
|= MP_BURN
; }
80 static void gdestroy(group
*gg
, ec
*x
) { EC_DESTROY(x
); DESTROY(x
); }
82 static int gsamep(group
*gg
, group
*hh
) {
83 gctx
*g
= (gctx
*)gg
, *h
= (gctx
*)hh
;
84 return (ec_sameinfop(&g
->ei
, &h
->ei
));
87 static int geq(group
*gg
, ec
*x
, ec
*y
) {
88 gctx
*g
= (gctx
*)gg
; EC_FIX(g
->ei
.c
, x
, x
); EC_FIX(g
->ei
.c
, y
, y
);
92 static int gidentp(group
*gg
, ec
*x
) { return (EC_ATINF(x
)); }
94 static const char *gcheck(group
*gg
, grand
*gr
)
95 { gctx
*g
= (gctx
*)gg
; return (ec_checkinfo(&g
->ei
, gr
)); }
97 static void gmul(group
*gg
, ec
*d
, ec
*x
, ec
*y
)
98 { gctx
*g
= (gctx
*)gg
; EC_ADD(g
->ei
.c
, d
, x
, y
); }
100 static void gsqr(group
*gg
, ec
*d
, ec
*x
)
101 { gctx
*g
= (gctx
*)gg
; EC_DBL(g
->ei
.c
, d
, x
); }
103 static void ginv(group
*gg
, ec
*d
, ec
*x
)
104 { gctx
*g
= (gctx
*)gg
; EC_NEG(g
->ei
.c
, d
, x
); }
106 static void gdiv(group
*gg
, ec
*d
, ec
*x
, ec
*y
)
107 { gctx
*g
= (gctx
*)gg
; EC_SUB(g
->ei
.c
, d
, x
, y
); }
109 static void gexp(group
*gg
, ec
*d
, ec
*x
, mp
*n
)
110 { gctx
*g
= (gctx
*)gg
; ec_imul(g
->ei
.c
, d
, x
, n
); }
112 static void gmexp(group
*gg
, ec
*d
, const group_expfactor
*f
, size_t n
) {
113 gctx
*g
= (gctx
*)gg
; size_t i
;
114 ec_mulfactor
*ff
= xmalloc(n
* sizeof(ec_mulfactor
));
115 for (i
= 0; i
< n
; i
++) { ff
[i
].base
= *f
[i
].base
; ff
[i
].exp
= f
[i
].exp
; }
116 ec_immul(g
->ei
.c
, d
, ff
, n
); xfree(ff
);
119 static int gread(group
*gg
, ec
*d
, const mptext_ops
*ops
, void *p
) {
120 gctx
*g
= (gctx
*)gg
;
126 if (tolower(ch
) == 'i') {
127 if (tolower(ops
->get(p
)) != 'n' || tolower(ops
->get(p
)) != 'f')
133 if ((t
.x
= mp_read(MP_NEW
, 0, ops
, p
)) == 0) goto done
;
134 do ch
= ops
->get(p
); while (ch
== ',' || isspace(ch
)); ops
->unget(ch
, p
);
135 if ((t
.y
= mp_read(MP_NEW
, 0, ops
, p
)) == 0) goto done
;
136 EC_IN(g
->ei
.c
, &t
, &t
);
137 if (EC_CHECK(g
->ei
.c
, &t
)) goto done
;
138 EC_COPY(d
, &t
); rc
= 0;
144 static int gwrite(group
*gg
, ec
*x
, const mptext_ops
*ops
, void *p
) {
145 gctx
*g
= (gctx
*)gg
; int rc
= -1; ec t
= EC_INIT
; EC_OUT(g
->ei
.c
, &t
, x
);
146 if (EC_ATINF(&t
)) rc
= ops
->put("inf", 3, p
);
147 else if (!ops
->put("0x", 2, p
) && !mp_write(t
.x
, 16, ops
, p
) &&
148 !ops
->put(", 0x", 4, p
) && !mp_write(t
.y
, 16, ops
, p
)) rc
= 0;
149 EC_DESTROY(&t
); return (rc
);
152 static mp
*gtoint(group
*gg
, mp
*d
, ec
*x
) {
153 gctx
*g
= (gctx
*)gg
; ec t
= EC_INIT
; mp
*i
; if (EC_ATINF(x
)) i
= 0;
154 else { EC_OUT(g
->ei
.c
, &t
, x
); i
= MP_COPY(t
.x
); EC_DESTROY(&t
); }
155 mp_drop(d
); return (i
);
158 static int gfromint(group
*gg
, ec
*d
, mp
*x
) {
159 gctx
*g
= (gctx
*)gg
; ec t
= EC_INIT
;
160 if (!ec_find(g
->ei
.c
, &t
, x
)) return (-1);
161 EC_IN(g
->ei
.c
, d
, &t
); EC_DESTROY(&t
); return (0);
164 static int gtoec(group
*gg
, ec
*d
, ec
*x
)
165 { gctx
*g
= (gctx
*)gg
; EC_OUT(g
->ei
.c
, d
, x
); return (0); }
167 static int gfromec(group
*gg
, ec
*d
, ec
*x
) {
168 gctx
*g
= (gctx
*)gg
; ec t
= EC_INIT
; int rc
; EC_IN(g
->ei
.c
, &t
, x
);
169 rc
= EC_CHECK(g
->ei
.c
, &t
); if (!rc
) EC_COPY(d
, &t
); EC_DESTROY(&t
);
173 static int gtobuf(group
*gg
, buf
*b
, ec
*x
) {
174 gctx
*g
= (gctx
*)gg
; ec t
= EC_INIT
; int rc
;
175 EC_OUT(g
->ei
.c
, &t
, x
); rc
= buf_putec(b
, &t
); EC_DESTROY(&t
); return (rc
);
178 static int gfrombuf(group
*gg
, buf
*b
, ec
*d
) {
179 gctx
*g
= (gctx
*)gg
; ec t
= EC_INIT
; int rc
;
180 if (buf_getec(b
, &t
)) return (-1);
181 EC_IN(g
->ei
.c
, &t
, &t
); rc
= EC_CHECK(g
->ei
.c
, &t
);
182 if (!rc
) EC_COPY(d
, &t
); EC_DESTROY(&t
); return (rc
);
185 /* --- @group_ec@ --- *
187 * Arguments: @const ec_info *ei@ = elliptic curve parameters
189 * Returns: A pointer to the group.
191 * Use: Constructs an abstract group interface for an elliptic curve
192 * group. Group elements are @ec@ structures. The contents of
193 * the @ec_info@ structure becomes the property of the @group@
194 * object; you can (and should) free the structure itself, but
195 * calling @ec_freeinfo@ on it is not allowed.
198 static const group_ops gops
= {
200 gdestroygroup
, gcreate
, gcopy
, gburn
, gdestroy
,
201 gsamep
, geq
, gidentp
,
203 gmul
, gsqr
, ginv
, gdiv
, gexp
, gmexp
,
205 gtoint
, gfromint
, gtoec
, gfromec
, gtobuf
, gfrombuf
208 group
*group_ec(const ec_info
*ei
)
210 gctx
*g
= CREATE(gctx
);
213 g
->g
.nbits
= ei
->c
->f
->nbits
* 2;
214 g
->g
.noctets
= ei
->c
->f
->noctets
* 2;
220 EC_IN(g
->ei
.c
, &g
->gen
, &ei
->g
);
226 /*----- That's all, folks -------------------------------------------------*/