3 * $Id: g-ec.c,v 1.5 2004/04/17 09:58:37 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 /*----- Header files ------------------------------------------------------*/
40 /*----- Data structures ---------------------------------------------------*/
48 /*----- Main code ---------------------------------------------------------*/
50 /* --- Group operations --- */
52 static void gdestroygroup(group
*gg
) {
59 static ec
*gcreate(group
*gg
)
60 { ec
*x
= CREATE(ec
); EC_CREATE(x
); return (x
); }
62 static void gcopy(group
*gg
, ec
*d
, ec
*x
) { EC_COPY(d
, x
); }
64 static void gburn(group
*gg
, ec
*x
) { if (x
->x
) (x
->x
)->f
|= MP_BURN
; }
66 static void gdestroy(group
*gg
, ec
*x
) { EC_DESTROY(x
); DESTROY(x
); }
68 static int gsamep(group
*gg
, group
*hh
) {
69 gctx
*g
= (gctx
*)gg
, *h
= (gctx
*)hh
;
70 return (ec_sameinfop(&g
->ei
, &h
->ei
));
73 static int geq(group
*gg
, ec
*x
, ec
*y
) {
74 gctx
*g
= (gctx
*)gg
; EC_FIX(g
->ei
.c
, x
, x
); EC_FIX(g
->ei
.c
, y
, y
);
78 static int gidentp(group
*gg
, ec
*x
) { return (EC_ATINF(x
)); }
80 static const char *gcheck(group
*gg
, grand
*gr
)
81 { gctx
*g
= (gctx
*)gg
; return (ec_checkinfo(&g
->ei
, gr
)); }
83 static void gmul(group
*gg
, ec
*d
, ec
*x
, ec
*y
)
84 { gctx
*g
= (gctx
*)gg
; EC_ADD(g
->ei
.c
, d
, x
, y
); }
86 static void gsqr(group
*gg
, ec
*d
, ec
*x
)
87 { gctx
*g
= (gctx
*)gg
; EC_DBL(g
->ei
.c
, d
, x
); }
89 static void ginv(group
*gg
, ec
*d
, ec
*x
)
90 { gctx
*g
= (gctx
*)gg
; EC_NEG(g
->ei
.c
, d
, x
); }
92 static void gdiv(group
*gg
, ec
*d
, ec
*x
, ec
*y
)
93 { gctx
*g
= (gctx
*)gg
; EC_SUB(g
->ei
.c
, d
, x
, y
); }
95 static void gexp(group
*gg
, ec
*d
, ec
*x
, mp
*n
)
96 { gctx
*g
= (gctx
*)gg
; ec_imul(g
->ei
.c
, d
, x
, n
); }
98 static void gmexp(group
*gg
, ec
*d
, const group_expfactor
*f
, size_t n
) {
99 gctx
*g
= (gctx
*)gg
; size_t i
;
100 ec_mulfactor
*ff
= xmalloc(n
* sizeof(ec_mulfactor
));
101 for (i
= 0; i
< n
; i
++) { ff
[i
].base
= *f
[i
].base
; ff
[i
].exp
= f
[i
].exp
; }
102 ec_immul(g
->ei
.c
, d
, ff
, n
); xfree(ff
);
105 static int gread(group
*gg
, ec
*d
, const mptext_ops
*ops
, void *p
) {
106 gctx
*g
= (gctx
*)gg
;
112 if (tolower(ch
) == 'i') {
113 if (tolower(ops
->get(p
)) != 'n' || tolower(ops
->get(p
)) != 'f')
119 if ((t
.x
= mp_read(MP_NEW
, 0, ops
, p
)) == 0) goto done
;
120 do ch
= ops
->get(p
); while (ch
== ',' || isspace(ch
)); ops
->unget(ch
, p
);
121 if ((t
.y
= mp_read(MP_NEW
, 0, ops
, p
)) == 0) goto done
;
122 EC_IN(g
->ei
.c
, &t
, &t
);
123 if (EC_CHECK(g
->ei
.c
, &t
)) goto done
;
124 EC_COPY(d
, &t
); rc
= 0;
130 static int gwrite(group
*gg
, ec
*x
, const mptext_ops
*ops
, void *p
) {
131 gctx
*g
= (gctx
*)gg
; int rc
= -1; ec t
= EC_INIT
; EC_OUT(g
->ei
.c
, &t
, x
);
132 if (EC_ATINF(&t
)) rc
= ops
->put("inf", 3, p
);
133 else if (!ops
->put("0x", 2, p
) && !mp_write(t
.x
, 16, ops
, p
) &&
134 !ops
->put(", 0x", 4, p
) && !mp_write(t
.y
, 16, ops
, p
)) rc
= 0;
135 EC_DESTROY(&t
); return (rc
);
138 static mp
*gtoint(group
*gg
, mp
*d
, ec
*x
) {
139 gctx
*g
= (gctx
*)gg
; ec t
= EC_INIT
; mp
*i
; if (EC_ATINF(x
)) i
= 0;
140 else { EC_OUT(g
->ei
.c
, &t
, x
); i
= MP_COPY(t
.x
); EC_DESTROY(&t
); }
141 mp_drop(d
); return (i
);
144 static int gfromint(group
*gg
, ec
*d
, mp
*x
) {
145 gctx
*g
= (gctx
*)gg
; ec t
= EC_INIT
;
146 if (!ec_find(g
->ei
.c
, &t
, x
)) return (-1);
147 EC_IN(g
->ei
.c
, d
, &t
); EC_DESTROY(&t
); return (0);
150 static int gtoec(group
*gg
, ec
*d
, ec
*x
)
151 { gctx
*g
= (gctx
*)gg
; EC_OUT(g
->ei
.c
, d
, x
); return (0); }
153 static int gfromec(group
*gg
, ec
*d
, const ec
*x
) {
154 gctx
*g
= (gctx
*)gg
; ec t
= EC_INIT
; int rc
; EC_IN(g
->ei
.c
, &t
, x
);
155 rc
= EC_CHECK(g
->ei
.c
, &t
); if (!rc
) EC_COPY(d
, &t
); EC_DESTROY(&t
);
159 static int gtobuf(group
*gg
, buf
*b
, ec
*x
) {
160 gctx
*g
= (gctx
*)gg
; ec t
= EC_INIT
; int rc
;
161 EC_OUT(g
->ei
.c
, &t
, x
); rc
= buf_putec(b
, &t
); EC_DESTROY(&t
); return (rc
);
164 static int gfrombuf(group
*gg
, buf
*b
, ec
*d
) {
165 gctx
*g
= (gctx
*)gg
; ec t
= EC_INIT
; int rc
;
166 if (buf_getec(b
, &t
)) return (-1);
167 EC_IN(g
->ei
.c
, &t
, &t
); rc
= EC_CHECK(g
->ei
.c
, &t
);
168 if (!rc
) EC_COPY(d
, &t
); EC_DESTROY(&t
); return (rc
);
171 static int gtoraw(group
*gg
, buf
*b
, ec
*x
) {
172 gctx
*g
= (gctx
*)gg
; ec t
= EC_INIT
; int rc
;
173 EC_OUT(g
->ei
.c
, &t
, x
); rc
= ec_putraw(g
->ei
.c
, b
, &t
);
174 EC_DESTROY(&t
); return (rc
);
177 static int gfromraw(group
*gg
, buf
*b
, ec
*d
) {
178 gctx
*g
= (gctx
*)gg
; ec t
= EC_INIT
; int rc
;
179 if (ec_getraw(g
->ei
.c
, b
, &t
)) return (-1);
180 EC_IN(g
->ei
.c
, &t
, &t
); rc
= EC_CHECK(g
->ei
.c
, &t
);
181 if (!rc
) EC_COPY(d
, &t
); EC_DESTROY(&t
); return (rc
);
184 /* --- @group_ec@ --- *
186 * Arguments: @const ec_info *ei@ = elliptic curve parameters
188 * Returns: A pointer to the group.
190 * Use: Constructs an abstract group interface for an elliptic curve
191 * group. Group elements are @ec@ structures. The contents of
192 * the @ec_info@ structure becomes the property of the @group@
193 * object; you can (and should) free the structure itself, but
194 * calling @ec_freeinfo@ on it is not allowed.
197 static const group_ops gops
= {
199 gdestroygroup
, gcreate
, gcopy
, gburn
, gdestroy
,
200 gsamep
, geq
, gidentp
,
202 gmul
, gsqr
, ginv
, gdiv
, gexp
, gmexp
,
204 gtoint
, gfromint
, gtoec
, gfromec
, gtobuf
, gfrombuf
, gtoraw
, gfromraw
207 group
*group_ec(const ec_info
*ei
)
209 gctx
*g
= CREATE(gctx
);
212 g
->g
.nbits
= ei
->c
->f
->nbits
* 2;
213 g
->g
.noctets
= ei
->c
->f
->noctets
* 2 + 1;
219 EC_IN(g
->ei
.c
, &g
->gen
, &ei
->g
);
225 /*----- That's all, folks -------------------------------------------------*/