X-Git-Url: https://git.distorted.org.uk/u/mdw/catacomb/blobdiff_plain/ba6e6b64033b1f9de49feccb5c9cd438354481f7..0f00dc4c8eb47e67bc0f148c2dd109f73a451e0a:/pub/dh-kcdsa.c diff --git a/pub/dh-kcdsa.c b/pub/dh-kcdsa.c new file mode 100644 index 0000000..e773309 --- /dev/null +++ b/pub/dh-kcdsa.c @@ -0,0 +1,123 @@ +/* -*-c-*- + * + * Generate KCDSA prime groups + * + * (c) 2006 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. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include + +#include "dh.h" +#include "mprand.h" +#include "pgen.h" +#include "prim.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @dh_kcdsagen@ --- * + * + * Arguments: @dh_param *dp@ = pointer to output parameter block + * @unsigned ql@ = size of small factor of %$(p - 1)/2$% + * @unsigned pl@ = size of %$p$% in bits + * @unsigned flags@ = other generation flags + * @unsigned steps@ = number of steps to go + * @grand *r@ = random number source + * @pgen_proc *ev@ = event handler function + * @void *ec@ = context for the event handler + * + * Returns: @PGEN_DONE@ if it worked, @PGEN_ABORT@ if it failed. + * + * Use: Generates a KCDSA prime group. That is, it chooses a prime + * %$p$%, such that $%p = 2 q v + 1$%, for primes %$q$% and + * %$v$%. The actual group of interest is the subgroup of order + * %$q$%. + */ + +int dh_kcdsagen(dh_param *dp, unsigned ql, unsigned pl, + unsigned flags, unsigned steps, grand *r, + pgen_proc *ev, void *ec) +{ + pgen_filterctx pf; + pgen_simulprime sp[2]; + pgen_simulctx ss; + prim_ctx pc; + rabin rb; + int rc = PGEN_ABORT; + int i; + mp *x; + + /* --- First trick: find %$q$% --- */ + + pf.step = 2; + x = mprand(MP_NEW, pl - ql, r, 1); + x = pgen("v", x, x, ev, ec, + steps, pgen_filter, &pf, + rabin_iters(pl - ql), pgen_test, &rb); + if (!x) + goto fail_0; + + /* --- Second trick: find %$p$% and %$v$% --- */ + + x = mp_lsl(x, x, 1); + sp[0].add = MP_ZERO; sp[0].mul = MP_ONE; sp[0].f = 0; + sp[1].add = MP_ONE; sp[1].mul = x; sp[1].f = PGENF_KEEP; + ss.step = MP_TWO; ss.v = sp; ss.n = N(sp); + x = mprand(MP_NEW, ql, r, 1); + dp->q = pgen("p", MP_NEW, x, ev, ec, + steps, pgen_simulstep, &ss, + rabin_iters(ql), pgen_simultest, &ss); + mp_drop(sp[0].mul); + if (!dp->q) + goto fail_1; + dp->p = sp[1].u.x; + + /* --- Third trick: find a generator --- */ + + mpmont_create(&pc.mm, dp->p); + mp_div(&x, 0, dp->p, dp->q); + i = 0; + pc.exp = x; + pc.n = 0; + dp->g = pgen("g", MP_NEW, MP_NEW, ev, ec, + 0, prim_step, &i, 1, prim_test, &pc); + mpmont_destroy(&pc.mm); + if (!dp->g) + goto fail_2; + + rc = PGEN_DONE; + goto done; + + /* --- Tidying up and going home --- */ + +fail_2: + mp_drop(dp->p); +fail_1: +fail_0: +done: + mp_drop(x); + return (rc); +} + +/*----- That's all, folks -------------------------------------------------*/