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 ------------------------------------------------------*/
37 #include "group-guts.h"
39 /*----- Main code ---------------------------------------------------------*/
41 /* --- Group operations --- */
43 static void gdestroygroup(group
*gg
) {
44 gctx_ec
*g
= (gctx_ec
*)gg
;
50 static ec
*gcreate(group
*gg
)
51 { ec
*x
= CREATE(ec
); EC_CREATE(x
); return (x
); }
53 static void gcopy(group
*gg
, ec
*d
, ec
*x
) { EC_COPY(d
, x
); }
55 static void gburn(group
*gg
, ec
*x
) { if (x
->x
) (x
->x
)->f
|= MP_BURN
; }
57 static void gdestroy(group
*gg
, ec
*x
) { EC_DESTROY(x
); DESTROY(x
); }
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
));
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
);
69 static int gidentp(group
*gg
, ec
*x
) { return (EC_ATINF(x
)); }
71 static const char *gcheck(group
*gg
, grand
*gr
)
72 { gctx_ec
*g
= (gctx_ec
*)gg
; return (ec_checkinfo(&g
->ei
, gr
)); }
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
); }
77 static void gsqr(group
*gg
, ec
*d
, ec
*x
)
78 { gctx_ec
*g
= (gctx_ec
*)gg
; EC_DBL(g
->ei
.c
, d
, x
); }
80 static void ginv(group
*gg
, ec
*d
, ec
*x
)
81 { gctx_ec
*g
= (gctx_ec
*)gg
; EC_NEG(g
->ei
.c
, d
, x
); }
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
); }
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
); }
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
);
96 static int gread(group
*gg
, ec
*d
, const mptext_ops
*ops
, void *p
) {
97 gctx_ec
*g
= (gctx_ec
*)gg
;
103 if (tolower(ch
) == 'i') {
104 if (tolower(ops
->get(p
)) != 'n' || tolower(ops
->get(p
)) != 'f')
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;
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
);
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
);
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);
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); }
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
);
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
);
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
);
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
);
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
);
175 /* --- @group_ec@ --- *
177 * Arguments: @const ec_info *ei@ = elliptic curve parameters
179 * Returns: A pointer to the group.
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.
188 static const group_ops gops
= {
190 gdestroygroup
, gcreate
, gcopy
, gburn
, gdestroy
,
191 gsamep
, geq
, gidentp
,
193 gmul
, gsqr
, ginv
, gdiv
, gexp
, gmexp
,
195 gtoint
, gfromint
, gtoec
, gfromec
, gtobuf
, gfrombuf
, gtoraw
, gfromraw
198 group
*group_ec(const ec_info
*ei
)
200 gctx_ec
*g
= CREATE(gctx_ec
);
203 g
->g
.nbits
= ei
->c
->f
->nbits
* 2;
204 g
->g
.noctets
= ei
->c
->f
->noctets
* 2 + 1;
210 EC_IN(g
->ei
.c
, &g
->gen
, &ei
->g
);
216 /*----- That's all, folks -------------------------------------------------*/