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 ------------------------------------------------------*/
39 #include "group-guts.h"
41 /*----- Main code ---------------------------------------------------------*/
43 /* --- Group operations --- */
45 static void gdestroygroup(group
*gg
) {
46 gctx_ec
*g
= (gctx_ec
*)gg
;
52 static ec
*gcreate(group
*gg
)
53 { ec
*x
= CREATE(ec
); EC_CREATE(x
); return (x
); }
55 static void gcopy(group
*gg
, ec
*d
, ec
*x
) { EC_COPY(d
, x
); }
57 static void gburn(group
*gg
, ec
*x
) { if (x
->x
) (x
->x
)->f
|= MP_BURN
; }
59 static void gdestroy(group
*gg
, ec
*x
) { EC_DESTROY(x
); DESTROY(x
); }
61 static int gsamep(group
*gg
, group
*hh
) {
62 gctx_ec
*g
= (gctx_ec
*)gg
, *h
= (gctx_ec
*)hh
;
63 return (ec_sameinfop(&g
->ei
, &h
->ei
));
66 static int geq(group
*gg
, ec
*x
, ec
*y
) {
67 gctx_ec
*g
= (gctx_ec
*)gg
; EC_FIX(g
->ei
.c
, x
, x
); EC_FIX(g
->ei
.c
, y
, y
);
71 static int gidentp(group
*gg
, ec
*x
) { return (EC_ATINF(x
)); }
73 static const char *gcheck(group
*gg
, grand
*gr
)
74 { gctx_ec
*g
= (gctx_ec
*)gg
; return (ec_checkinfo(&g
->ei
, gr
)); }
76 static void gmul(group
*gg
, ec
*d
, ec
*x
, ec
*y
)
77 { gctx_ec
*g
= (gctx_ec
*)gg
; EC_ADD(g
->ei
.c
, d
, x
, y
); }
79 static void gsqr(group
*gg
, ec
*d
, ec
*x
)
80 { gctx_ec
*g
= (gctx_ec
*)gg
; EC_DBL(g
->ei
.c
, d
, x
); }
82 static void ginv(group
*gg
, ec
*d
, ec
*x
)
83 { gctx_ec
*g
= (gctx_ec
*)gg
; EC_NEG(g
->ei
.c
, d
, x
); }
85 static void gdiv(group
*gg
, ec
*d
, ec
*x
, ec
*y
)
86 { gctx_ec
*g
= (gctx_ec
*)gg
; EC_SUB(g
->ei
.c
, d
, x
, y
); }
88 static void gexp(group
*gg
, ec
*d
, ec
*x
, mp
*n
)
89 { gctx_ec
*g
= (gctx_ec
*)gg
; ec_imul(g
->ei
.c
, d
, x
, n
); }
91 static void gmexp(group
*gg
, ec
*d
, const group_expfactor
*f
, size_t n
) {
92 gctx_ec
*g
= (gctx_ec
*)gg
; size_t i
;
93 ec_mulfactor
*ff
= xmalloc(n
* sizeof(ec_mulfactor
));
94 for (i
= 0; i
< n
; i
++) { ff
[i
].base
= *f
[i
].base
; ff
[i
].exp
= f
[i
].exp
; }
95 ec_immul(g
->ei
.c
, d
, ff
, n
); xfree(ff
);
98 static int gread(group
*gg
, ec
*d
, const mptext_ops
*ops
, void *p
) {
99 gctx_ec
*g
= (gctx_ec
*)gg
;
105 if (tolower(ch
) == 'i') {
106 if (tolower(ops
->get(p
)) != 'n' || tolower(ops
->get(p
)) != 'f')
112 if ((t
.x
= mp_read(MP_NEW
, 0, ops
, p
)) == 0) goto done
;
113 do ch
= ops
->get(p
); while (ch
== ',' || isspace(ch
)); ops
->unget(ch
, p
);
114 if ((t
.y
= mp_read(MP_NEW
, 0, ops
, p
)) == 0) goto done
;
115 EC_IN(g
->ei
.c
, &t
, &t
);
116 if (EC_CHECK(g
->ei
.c
, &t
)) goto done
;
117 EC_COPY(d
, &t
); rc
= 0;
123 static int gwrite(group
*gg
, ec
*x
, const mptext_ops
*ops
, void *p
) {
124 gctx_ec
*g
= (gctx_ec
*)gg
; int rc
= -1; ec t
= EC_INIT
;
125 EC_OUT(g
->ei
.c
, &t
, x
); if (EC_ATINF(&t
)) rc
= ops
->put("inf", 3, p
);
126 else if (!ops
->put("0x", 2, p
) && !mp_write(t
.x
, 16, ops
, p
) &&
127 !ops
->put(", 0x", 4, p
) && !mp_write(t
.y
, 16, ops
, p
)) rc
= 0;
128 EC_DESTROY(&t
); return (rc
);
131 static mp
*gtoint(group
*gg
, mp
*d
, ec
*x
) {
132 gctx_ec
*g
= (gctx_ec
*)gg
; ec t
= EC_INIT
; mp
*i
; if (EC_ATINF(x
)) i
= 0;
133 else { EC_OUT(g
->ei
.c
, &t
, x
); i
= MP_COPY(t
.x
); EC_DESTROY(&t
); }
134 mp_drop(d
); return (i
);
137 static int gfromint(group
*gg
, ec
*d
, mp
*x
) {
138 gctx_ec
*g
= (gctx_ec
*)gg
; ec t
= EC_INIT
;
139 if (!ec_find(g
->ei
.c
, &t
, x
)) return (-1);
140 EC_IN(g
->ei
.c
, d
, &t
); EC_DESTROY(&t
); return (0);
143 static int gtoec(group
*gg
, ec
*d
, ec
*x
)
144 { gctx_ec
*g
= (gctx_ec
*)gg
; EC_OUT(g
->ei
.c
, d
, x
); return (0); }
146 static int gfromec(group
*gg
, ec
*d
, const ec
*x
) {
147 gctx_ec
*g
= (gctx_ec
*)gg
; ec t
= EC_INIT
; int rc
; EC_IN(g
->ei
.c
, &t
, x
);
148 rc
= EC_CHECK(g
->ei
.c
, &t
); if (!rc
) EC_COPY(d
, &t
); EC_DESTROY(&t
);
152 static int gtobuf(group
*gg
, buf
*b
, ec
*x
) {
153 gctx_ec
*g
= (gctx_ec
*)gg
; ec t
= EC_INIT
; int rc
;
154 EC_OUT(g
->ei
.c
, &t
, x
); rc
= buf_putec(b
, &t
); EC_DESTROY(&t
); return (rc
);
157 static int gfrombuf(group
*gg
, buf
*b
, ec
*d
) {
158 gctx_ec
*g
= (gctx_ec
*)gg
; ec t
= EC_INIT
; int rc
;
159 if (buf_getec(b
, &t
)) return (-1);
160 EC_IN(g
->ei
.c
, &t
, &t
); rc
= EC_CHECK(g
->ei
.c
, &t
);
161 if (!rc
) EC_COPY(d
, &t
); EC_DESTROY(&t
); return (rc
);
164 static int gtoraw(group
*gg
, buf
*b
, ec
*x
) {
165 gctx_ec
*g
= (gctx_ec
*)gg
; ec t
= EC_INIT
; int rc
;
166 EC_OUT(g
->ei
.c
, &t
, x
); rc
= ec_putraw(g
->ei
.c
, b
, &t
);
167 EC_DESTROY(&t
); return (rc
);
170 static int gfromraw(group
*gg
, buf
*b
, ec
*d
) {
171 gctx_ec
*g
= (gctx_ec
*)gg
; ec t
= EC_INIT
; int rc
;
172 if (ec_getraw(g
->ei
.c
, b
, &t
)) return (-1);
173 EC_IN(g
->ei
.c
, &t
, &t
); rc
= EC_CHECK(g
->ei
.c
, &t
);
174 if (!rc
) EC_COPY(d
, &t
); EC_DESTROY(&t
); return (rc
);
177 /* --- @group_ec@ --- *
179 * Arguments: @const ec_info *ei@ = elliptic curve parameters
181 * Returns: A pointer to the group.
183 * Use: Constructs an abstract group interface for an elliptic curve
184 * group. Group elements are @ec@ structures. The contents of
185 * the @ec_info@ structure becomes the property of the @group@
186 * object; you can (and should) free the structure itself, but
187 * calling @ec_freeinfo@ on it is not allowed.
190 static const group_ops gops
= {
192 gdestroygroup
, gcreate
, gcopy
, gburn
, gdestroy
,
193 gsamep
, geq
, gidentp
,
195 gmul
, gsqr
, ginv
, gdiv
, gexp
, gmexp
,
197 gtoint
, gfromint
, gtoec
, gfromec
, gtobuf
, gfrombuf
, gtoraw
, gfromraw
200 group
*group_ec(const ec_info
*ei
)
202 gctx_ec
*g
= CREATE(gctx_ec
);
205 g
->g
.nbits
= ei
->c
->f
->nbits
* 2;
206 g
->g
.noctets
= ei
->c
->f
->noctets
* 2 + 1;
212 EC_IN(g
->ei
.c
, &g
->gen
, &ei
->g
);
218 /*----- That's all, folks -------------------------------------------------*/