3 * Abstraction for elliptic curve groups
5 * (c) 2004 Straylight/Edgeware
8 /*----- Licensing notice --------------------------------------------------*
10 * This file is part of Catacomb.
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.
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.
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,
28 /*----- Header files ------------------------------------------------------*/
36 #include "group-guts.h"
38 /*----- Main code ---------------------------------------------------------*/
40 /* --- Group operations --- */
42 static void gdestroygroup(group
*gg
) {
43 gctx_ec
*g
= (gctx_ec
*)gg
;
49 static ec
*gcreate(group
*gg
)
50 { ec
*x
= CREATE(ec
); EC_CREATE(x
); return (x
); }
52 static void gcopy(group
*gg
, ec
*d
, ec
*x
) { EC_COPY(d
, x
); }
54 static void gburn(group
*gg
, ec
*x
) { if (x
->x
) (x
->x
)->f
|= MP_BURN
; }
56 static void gdestroy(group
*gg
, ec
*x
) { EC_DESTROY(x
); DESTROY(x
); }
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
));
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
);
68 static int gidentp(group
*gg
, ec
*x
) { return (EC_ATINF(x
)); }
70 static const char *gcheck(group
*gg
, grand
*gr
)
71 { gctx_ec
*g
= (gctx_ec
*)gg
; return (ec_checkinfo(&g
->ei
, gr
)); }
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
); }
76 static void gsqr(group
*gg
, ec
*d
, ec
*x
)
77 { gctx_ec
*g
= (gctx_ec
*)gg
; EC_DBL(g
->ei
.c
, d
, x
); }
79 static void ginv(group
*gg
, ec
*d
, ec
*x
)
80 { gctx_ec
*g
= (gctx_ec
*)gg
; EC_NEG(g
->ei
.c
, d
, x
); }
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
); }
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
); }
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
);
95 static int gread(group
*gg
, ec
*d
, const mptext_ops
*ops
, void *p
) {
96 gctx_ec
*g
= (gctx_ec
*)gg
;
102 if (tolower(ch
) == 'i') {
103 if (tolower(ops
->get(p
)) != 'n' || tolower(ops
->get(p
)) != 'f')
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;
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
);
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
);
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);
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); }
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
);
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
);
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
);
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
);
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
);
174 /* --- @group_ec@ --- *
176 * Arguments: @const ec_info *ei@ = elliptic curve parameters
178 * Returns: A pointer to the group.
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.
187 static const group_ops gops
= {
189 gdestroygroup
, gcreate
, gcopy
, gburn
, gdestroy
,
190 gsamep
, geq
, gidentp
,
192 gmul
, gsqr
, ginv
, gdiv
, gexp
, gmexp
,
194 gtoint
, gfromint
, gtoec
, gfromec
, gtobuf
, gfrombuf
, gtoraw
, gfromraw
197 group
*group_ec(const ec_info
*ei
)
199 gctx_ec
*g
= CREATE(gctx_ec
);
202 g
->g
.nbits
= ei
->c
->f
->nbits
* 2;
203 g
->g
.noctets
= ei
->c
->f
->noctets
* 2 + 1;
209 EC_IN(g
->ei
.c
, &g
->gen
, &ei
->g
);
215 /*----- That's all, folks -------------------------------------------------*/