--- /dev/null
+/* -*-c-*-
+ *
+ * $Id: group.h,v 1.1 2004/04/01 12:50:09 mdw Exp $
+ *
+ * General cyclic group abstraction
+ *
+ * (c) 2004 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of Catacomb.
+ *
+ * Catacomb is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * Catacomb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with Catacomb; if not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+/*----- Revision history --------------------------------------------------*
+ *
+ * $Log: group.h,v $
+ * Revision 1.1 2004/04/01 12:50:09 mdw
+ * Add cyclic group abstraction, with test code. Separate off exponentation
+ * functions for better static linking. Fix a buttload of bugs on the way.
+ * Generally ensure that negative exponents do inversion correctly. Add
+ * table of standard prime-field subgroups. (Binary field subgroups are
+ * currently unimplemented but easy to add if anyone ever finds a good one.)
+ *
+ */
+
+#ifndef CATACOMB_GROUP_H
+#define CATACOMB_GROUP_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/dstr.h>
+
+#ifndef CATACOMB_BUF_H
+# include "buf.h"
+#endif
+
+#ifndef CATACOMB_DH_H
+# include "ec.h"
+#endif
+
+#ifndef CATACOMB_GRAND_H
+# include "grand.h"
+#endif
+
+#ifndef CATACOMB_MP_H
+# include "mp.h"
+#endif
+
+#ifndef CATACOMB_QDPARSE_H
+# include "qdparse.h"
+#endif
+
+/*----- Data structures ---------------------------------------------------*/
+
+#ifndef ge
+ typedef struct ge ge; /* Group element (abstract type) */
+#endif
+
+typedef struct group {
+ const struct group_ops *ops; /* Operations table */
+ size_t nbits; /* Size of an element in bits */
+ size_t noctets; /* Size of an element in octets */
+ ge *i; /* Identity element */
+ ge *g; /* Generator element */
+ mp *r; /* Order of the generator */
+ mp *h; /* Cofactor */
+} group;
+
+typedef struct group_expfactor {
+ ge *base; /* The base */
+ mp *exp; /* The exponent */
+} group_expfactor;
+
+typedef struct group_ops {
+ unsigned ty; /* Type of this group */
+
+ /* --- Memory management --- */
+
+ void (*destroygroup)(group */*g*/);
+ ge *(*create)(group */*g*/);
+ void (*copy)(group */*g*/, ge */*d*/, ge */*x*/);
+ void (*burn)(group */*g*/, ge */*x*/);
+ void (*destroy)(group */*g*/, ge */*e*/);
+
+ /* --- Comparisons --- */
+
+ int (*samep)(group */*g*/, group */*h*/);
+ int (*eq)(group */*g*/, ge */*x*/, ge */*y*/);
+ int (*identp)(group */*g*/, ge */*x*/);
+
+ /* --- Other stuff --- */
+
+ const char *(*check)(group */*g*/, grand */*gr*/);
+
+ /* --- Arithmetic --- */
+
+ void (*mul)(group */*g*/, ge */*d*/, ge */*x*/, ge */*y*/);
+ void (*sqr)(group */*g*/, ge */*d*/, ge */*x*/);
+ void (*inv)(group */*g*/, ge */*d*/, ge */*x*/);
+ void (*div)(group */*g*/, ge */*d*/, ge */*x*/, ge */*y*/);
+ void (*exp)(group */*g*/, ge */*d*/, ge */*x*/, mp */*n*/);
+ void (*mexp)(group */*g*/, ge */*d*/,
+ const group_expfactor */*f*/, size_t /*n*/);
+
+ /* --- Debugging --- */
+
+ int (*read)(group */*g*/, ge */*d*/,
+ const mptext_ops */*ops*/, void */*p*/);
+ int (*write)(group */*g*/, ge */*x*/,
+ const mptext_ops */*ops*/, void */*p*/);
+
+ /* --- Conversions --- */
+
+ mp *(*toint)(group */*g*/, mp */*d*/, ge */*x*/);
+ int (*fromint)(group */*g*/, ge */*d*/, mp */*x*/);
+ int (*toec)(group */*g*/, ec */*d*/, ge */*x*/);
+ int (*fromec)(group */*g*/, ge */*d*/, ec */*p*/);
+ int (*tobuf)(group */*h*/, buf */*b*/, ge */*x*/);
+ int (*frombuf)(group */*h*/, buf */*b*/, ge */*d*/);
+
+} group_ops;
+
+enum {
+ GTY_PRIME, /* Prime field subgroup */
+ GTY_BINARY, /* Binary feld subgroup */
+ GTY_EC /* Elliptic curve group */
+};
+
+#define G_DESTROYGROUP(g) (g)->ops->destroygroup((g))
+#define G_CREATE(g) (g)->ops->create((g))
+#define G_COPY(g, d, x) (g)->ops->copy((g), (d), (x))
+#define G_BURN(g, x) (g)->ops->burn((g), (x))
+#define G_DESTROY(g, x) (g)->ops->destroy((g), (x))
+
+#define G_SAMEP(g, h) (g)->ops->samep((g), (h))
+#define G_EQ(g, x, y) (g)->ops->eq((g), (x), (y))
+#define G_IDENTP(g, x) (g)->ops->identp((g), (x))
+
+#define G_CHECK(g, gr) (g)->ops->check((g), (gr))
+
+#define G_MUL(g, d, x, y) (g)->ops->mul((g), (d), (x), (y))
+#define G_SQR(g, d, x) (g)->ops->sqr((g), (d), (x))
+#define G_INV(g, d, x) (g)->ops->inv((g), (d), (x))
+#define G_DIV(g, d, x, y) (g)->ops->div((g), (d), (x), (y))
+#define G_EXP(g, d, x, n) (g)->ops->exp((g), (d), (x), (n))
+#define G_MEXP(g, d, f, n) (g)->ops->mexp((g), (d), (f), (n))
+
+#define G_READ(g, d, o, p) (g)->ops->read((g), (d), (o), (p))
+#define G_WRITE(g, x, o, p) (g)->ops->write((g), (x), (o), (p))
+
+#define G_TOINT(g, d, x) (g)->ops->toint((g), (d), (x))
+#define G_FROMINT(g, d, x) (g)->ops->fromint((g), (d), (x))
+#define G_TOEC(g, d, x) (g)->ops->toec((g), (d), (x))
+#define G_FROMEC(g, d, p) (g)->ops->fromec((g), (d), (p))
+#define G_TOBUF(g, b, x) (g)->ops->tobuf((g), (b), (x))
+#define G_FROMBUF(g, b, d) (g)->ops->frombuf((g), (b), (d))
+
+/*----- Handy functions ---------------------------------------------------*/
+
+/* --- @group_check@ --- *
+ *
+ * Arguments: @group *g@ = an abstract group
+ * @ge *x@ = a group element
+ *
+ * Returns: Zero on success, nonzero for failure.
+ *
+ * Use: Checks that @x@ is a valid group element. This may take a
+ * while, since it checks that %$x^h \ne 1$%.
+ */
+
+extern int group_check(group */*g*/, ge */*x*/);
+
+/* --- @group_samep@ --- *
+ *
+ * Arguments: @group *g, *h@ = two abstract groups
+ *
+ * Returns: Nonzero if the groups are in fact identical (not just
+ * isomorphic).
+ *
+ * Use: Checks to see whether two groups are actually the same. This
+ * function does the full check: the group operatrion @samep@
+ * just does the group-specific details.
+ */
+
+extern int group_samep(group */*g*/, group */*h*/);
+
+/*----- Textual I/O on group elements -------------------------------------*/
+
+extern int group_readstring(group */*g*/, ge */*d*/,
+ const char */*p*/, char **/*end*/);
+extern int group_writestring(group */*g*/, ge */*d*/,
+ char */*p*/, size_t /*sz*/);
+
+extern int group_readfile(group */*g*/, ge */*d*/, FILE */*fp*/);
+extern int group_writefile(group */*g*/, ge */*x*/, FILE */*fp*/);
+
+extern int group_readdstr(group */*g*/, ge */*d*/,
+ dstr */*dd*/, size_t */*off*/);
+extern int group_writedstr(group */*g*/, ge */*x*/, dstr */*d*/);
+
+/*----- Standard implementations ------------------------------------------*/
+
+/* --- @group_stdidentp@ --- *
+ *
+ * Arguments: @group *g@ = abstract group
+ * @ge *x@ = group element
+ *
+ * Returns: Nonzero if %$x$% is the group identity.
+ */
+
+extern int group_stdidentp(group */*g*/, ge */*x*/);
+
+/* --- @group_stdcheck@ --- *
+ *
+ * Arguments: @group *g@ = abstract group
+ * @grand *gr@ = random number source.
+ *
+ * Returns: Null on success, or a pointer to an error message.
+ */
+
+extern const char *group_stdcheck(group */*g*/, grand */*gr*/);
+
+/* --- @group_stdsqr@ --- *
+ *
+ * Arguments: @group *g@ = abstract group
+ * @ge *d@ = destination pointer
+ * @ge *x@ = group element
+ *
+ * Returns: ---
+ *
+ * Use: Computes %$d = x^2$% as %$d = x x$%.
+ */
+
+extern void group_stdsqr(group */*g*/, ge */*d*/, ge */*x*/);
+
+/* --- @group_stddiv@ --- *
+ *
+ * Arguments: @group *g@ = abstract group
+ * @ge *d@ = destination pointer
+ * @ge *x@ = dividend
+ * @ge *y@ = divisor
+ *
+ * Returns: ---
+ *
+ * Use: Computes %$d = x/y$% as %$d = x y^{-1}$%.
+ */
+
+extern void group_stddiv(group */*g*/, ge */*d*/, ge */*x*/, ge */*y*/);
+
+/* --- @group_stdexp@ --- *
+ *
+ * Arguments: @group *g@ = abstract group
+ * @ge *d@ = destination pointer
+ * @ge *x@ = base element
+ * @mp *n@ = exponent
+ *
+ * Returns: ---
+ *
+ * Use: Computes %$d = x^n$% efficiently.
+ */
+
+extern void group_stdexp(group */*g*/, ge */*d*/, ge */*x*/, mp */*n*/);
+
+/* --- @group_stdmexp@ --- *
+ *
+ * Arguments: @group *g@ = abstract group
+ * @ge *d@ = destination pointer
+ * @const group_expfactor *f@ = vector of factors
+ * @size_t n@ = number of factors
+ *
+ * Returns: ---
+ *
+ * Use: Computes %$d = g_0^{x_0} g_1^{x_1} \ldots$% efficiently.
+ */
+
+extern void group_stdmexp(group */*g*/, ge */*d*/,
+ const group_expfactor */*f*/, size_t /*n*/);
+
+/* --- @group_stdtoec@ --- *
+ *
+ * Arguments: @group *g@ = abstract group
+ * @ec *d@ = destination point
+ * @ge *x@ = group element
+ *
+ * Returns: @-1@, indicating failure.
+ *
+ * Use: Fails to convert a group element to an elliptic curve point.
+ */
+
+extern int group_stdtoec(group */*g*/, ec */*d*/, ge */*x*/);
+
+/* --- @group_stdfromec@ --- *
+ *
+ * Arguments: @group *g@ = abstract group
+ * @ge *d@ = destination pointer
+ * @ec *p@ = elliptic curve point
+ *
+ * Returns: Zero for success, @-1@ on failure.
+ *
+ * Use: Converts %$p$% to a group element by converting its %$x$%-
+ * coordinate.
+ */
+
+extern int group_stdfromec(group */*g*/, ge */*d*/, ec */*p*/);
+
+/*----- Prime field subgroups ---------------------------------------------*/
+
+typedef struct gprime_param {
+ mp *p, *q; /* Prime numbers %$p$% and %$q$% */
+ mp *g; /* Generates order-%$q$% subgroup */
+} gprime_param;
+
+/* --- @group_prime@ --- *
+ *
+ * Arguments: @const gprime_param *gp@ = group parameters
+ *
+ * Returns: A pointer to the group.
+ *
+ * Use: Constructs an abstract group interface for a subgroup of a
+ * prime field. Group elements are @mp *@ pointers.
+ */
+
+group *group_prime(const gprime_param */*gp*/);
+
+/*----- Elliptic curve groups ---------------------------------------------*/
+
+/* --- @group_ec@ --- *
+ *
+ * Arguments: @const ec_info *ei@ = elliptic curve parameters
+ *
+ * Returns: A pointer to the group.
+ *
+ * Use: Constructs an abstract group interface for an elliptic curve
+ * group. Group elements are @ec@ structures. The contents of
+ * the @ec_info@ structure becomes the property of the @group@
+ * object; you can (and should) free the structure itself, but
+ * calling @ec_freeinfo@ on it is not allowed.
+ */
+
+group *group_ec(const ec_info */*ei*/);
+
+/*----- General group initialization --------------------------------------*/
+
+/* --- @group_parse@ --- *
+ *
+ * Arguments: @qd_parse *qd@ = quick-and-dirty parser
+ *
+ * Returns: Group pointer, or null for failure.
+ *
+ * Use: Parses a group description and returns the group. This has
+ * the form `TYPE { SPEC }' where TYPE is `prime' or `ec', and
+ * SPEC is the appropriate kind of group specification of the
+ * given type.
+ */
+
+extern group *group_parse(qd_parse */*qd*/);
+
+/* --- @group_fromstring@ --- *
+ *
+ * Arguments: @const char *p@ = pointer to string to read
+ * @group **gg@ = where to put the group pointer
+ *
+ * Returns: Null if OK, or an error string.
+ *
+ * Use: Parses a group spec from a string, and returns the group.
+ */
+
+extern const char *group_fromstring(const char */*p*/, group **/*gg*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif