/* -*-c-*-
*
- * $Id: bbs-gen.c,v 1.1 1999/12/10 23:14:59 mdw Exp $
+ * $Id: bbs-gen.c,v 1.5 2000/07/01 11:20:36 mdw Exp $
*
* Generate Blum integers
*
/*----- Revision history --------------------------------------------------*
*
* $Log: bbs-gen.c,v $
+ * Revision 1.5 2000/07/01 11:20:36 mdw
+ * Remove bad type name `bbs_param'.
+ *
+ * Revision 1.4 2000/06/17 10:43:57 mdw
+ * Move GCD filter to separate file. Handle failures from pgen_jump.
+ *
+ * Revision 1.3 2000/02/12 18:21:02 mdw
+ * Overhaul of key management (again).
+ *
+ * Revision 1.2 1999/12/22 15:52:28 mdw
+ * Reworking for new prime-search system.
+ *
* Revision 1.1 1999/12/10 23:14:59 mdw
* Blum-Blum-Shub generator, and Blum-Goldwasser encryption.
*
#include <string.h>
#include "bbs.h"
-#include "fibrand.h"
#include "mp.h"
#include "mprand.h"
#include "pgen.h"
-#include "rabin.h"
+#include "strongprime.h"
/*----- Main code ---------------------------------------------------------*/
/* --- @bbs_gen@ --- *
*
- * Arguments: @bbs_params *bp@ = pointer to parameter block
- * @mp *p, *q@ = initial numbers to search from
- * @size_t n@ = number of attempts to make
- * @void (*proc)(int ev, mp *m, void *p)@ = event handler
- * @void *arg@ = argument for event handler
+ * Arguments: @bbs_priv *bp@ = pointer to parameter block
+ * @unsigned nbits@ = number of bits in the modulus
+ * @grand *r@ = pointer to random number source
+ * @unsigned n@ = number of attempts to make
+ * @pgen_proc *event@ = event handler function
+ * @void *ectx@ = argument for event handler
*
- * Returns: Zero if all went well, otherwise an event code which explains
- * the problem.
+ * Returns: If it worked OK, @PGEN_DONE@, otherwise @PGEN_ABORT@.
*
* Use: Finds two prime numbers %$p'$% and %$q'$% such that both are
* congruent to %$3 \bmod 4$%, and $(p - 1)/2$% and
* Shub pseudorandom bit generator.
*/
-int bbs_gen(bbs_params *bp, mp *p, mp *q, size_t n,
- int (*proc)(int /*ev*/, mp */*m*/, void */*p*/), void *arg)
+int bbs_gen(bbs_priv *bp, unsigned nbits, grand *r, unsigned n,
+ pgen_proc *event, void *ectx)
{
- pgen px, py;
- mp *pp;
- mp *g = MP_NEW;
- grand *gr = fibrand_create(0);
- int rcx, rcy;
- int fail = BBSEV_OK;
- size_t sz;
-
- /* --- Initialize @p@ and @q@ --- *
- *
- * Divide both by two, and make the results odd.
- */
-
- p = mp_lsr(MP_NEW, p, 1); p->v[0] |= 1;
- q = mp_lsr(MP_NEW, q, 1); q->v[0] |= 1;
-
- /* --- Set up the search for @p@ --- *
- *
- * I want a prime %$p$% such that %$(p - 1)/2$% has no small factors.
- */
-
- rcx = pgen_create(&px, p); mp_drop(p);
- rcy = pgen_muladd(&py, &px, 2, 1);
-
- if (proc && (fail = proc(BBSEV_FINDP, 0, arg)) != 0)
- goto fail_0;
-
- sz = mp_bits(py.m);
- for (;;) {
- if (rcx != PGEN_COMPOSITE && rcy != PGEN_COMPOSITE) {
- if (rcy != PGEN_PRIME) {
- rabin r;
- int i;
-
- if (proc && (fail = proc(BBSEV_TRYP, py.m, arg)) != 0)
- break;
- rabin_create(&r, py.m);
- for (i = 0; i < 5; i++) {
- g = mprand(g, sz, gr, 1);
- if ((rcy = rabin_test(&r, g)) == PGEN_COMPOSITE)
- break;
- if (proc && (fail = proc(BBSEV_PASSP, py.m, arg)) != 0)
- break;
- }
- rabin_destroy(&r);
- if (fail)
- goto fail_0;
- if (i < 5) {
- if (proc && (fail = proc(BBSEV_FAILP, py.m, arg)) != 0)
- goto fail_0;
- if (n) {
- n--;
- if (!n) {
- fail = BBSEV_FAILP;
- goto fail_0;
- }
- }
- }
- }
-
- if (rcy != PGEN_COMPOSITE)
- break;
- }
- rcx = pgen_step(&px, 2);
- rcy = pgen_step(&py, 4);
+ rabin rb;
+ pgen_safejumpctx j;
+ pgen_gcdstepctx g;
+ unsigned nb = nbits/2;
+ mp *x = MP_NEW;
+
+ /* --- Generate @p@ --- */
+
+again:
+ if ((x = strongprime_setup("p", x, &j.jq, nb, r, n, event, ectx)) == 0)
+ goto fail_x;
+ bp->p = pgen("p", MP_NEW, x, event, ectx, n, pgen_safejump, &j,
+ rabin_iters(nb), pgen_test, &rb);
+ pfilt_destroy(&j.jq);
+ if (!bp->p) {
+ if (n)
+ goto fail_p;
+ goto again;
}
- if (proc && (fail = proc(BBSEV_GOODP, py.m, arg)) != 0)
- goto fail_0;
-
- /* --- I now have a @p@ (and a %$(p - 1)/2$%) --- */
-
- pp = MP_COPY(px.m); pgen_destroy(&px);
- p = MP_COPY(py.m); pgen_destroy(&py);
+ /* --- Generate @q@ --- */
+
+ nb = nbits - nb;
+ if ((x = strongprime_setup("q", x, &g.jp, nb, r, n, event, ectx)) == 0)
+ goto fail_q;
+ if ((x->v[0] & 3) != 3)
+ x = mp_add(x, x, g.jp.m);
+ pfilt_muladd(&g.jp, &g.jp, 2, 0);
+ g.r = mp_lsr(MP_NEW, bp->p, 1);
+ g.g = MP_NEW;
+ g.max = MP_ONE;
+ bp->q = pgen("q", MP_NEW, x, event, ectx, n, pgen_gcdstep, &g,
+ rabin_iters(nb), pgen_test, &rb);
+ pfilt_destroy(&g.jp);
+ mp_drop(g.r);
+ mp_drop(g.g);
+ if (!bp->q) {
+ if (n)
+ goto fail_q;
+ mp_drop(bp->p);
+ goto again;
+ }
- /* --- Next trick is to generate @q@ --- *
- *
- * I don't care about small factors of %$(q - 1)/2$%, just that it's
- * relatively prime to %$(p - 1)/2$%.
- */
+ /* --- Compute @n@ --- */
- {
- mp *m = mp_lsl(MP_NEW, q, 1);
- m->v[0] |= 1;
- rcx = pgen_create(&px, m);
- mp_drop(m);
- }
+ bp->n = mp_mul(MP_NEW, bp->p, bp->q);
+ mp_drop(x);
+ return (PGEN_DONE);
- if (proc && (fail = proc(BBSEV_FINDQ, 0, arg)) != 0)
- goto fail_1;
-
- for (;;) {
- if (rcx != PGEN_COMPOSITE) {
- int ok;
-
- /* --- Ensure that %$(p - 1)/2$% and %$(q - 1)/2$% are coprime --- */
-
- mp_gcd(&g, 0, 0, pp, q);
- ok = MP_CMP(g, ==, MP_ONE);
-
- if (ok && rcx != PGEN_PRIME) {
- rabin r;
- int i;
-
- if (proc && (fail = proc(BBSEV_TRYQ, px.m, arg)) != 0)
- break;
- rabin_create(&r, px.m);
- for (i = 0; i < 5; i++) {
- g = mprand(g, sz, gr, 1);
- if ((rcx = rabin_test(&r, g)) == PGEN_COMPOSITE)
- break;
- if (proc && (fail = proc(BBSEV_PASSQ, px.m, arg)) != 0)
- break;
- }
- rabin_destroy(&r);
- if (fail)
- goto fail_1;
- if (i < 5) {
- if (proc && (fail = proc(BBSEV_FAILQ, px.m, arg)) != 0)
- goto fail_1;
- if (n) {
- n--;
- if (!n) {
- fail = BBSEV_FAILQ;
- goto fail_1;
- }
- }
- }
- }
-
- if (ok && rcx != PGEN_COMPOSITE)
- break;
- }
-
- q = mp_add(q, q, MP_TWO);
- rcx = pgen_step(&px, 4);
- }
+ /* --- Tidy up if things went wrong --- */
- if (proc && (fail = proc(BBSEV_GOODQ, px.m, arg)) != 0)
- goto fail_1;
-
- /* --- Done --- */
-
- mp_drop(g);
- mp_drop(q);
- mp_drop(pp);
- q = MP_COPY(px.m);
- bp->p = p;
- bp->q = q;
- pgen_destroy(&px);
- bp->n = mp_mul(MP_NEW, p, q);
- gr->ops->destroy(gr);
- return (0);
-
- /* --- Failed --- */
-
-fail_1:
- pgen_destroy(&px);
- mp_drop(p);
- mp_drop(pp);
- mp_drop(g);
- gr->ops->destroy(gr);
- return (fail);
-
-fail_0:
- if (g)
- mp_drop(g);
- pgen_destroy(&px);
- pgen_destroy(&py);
- mp_drop(q);
- gr->ops->destroy(gr);
- return (fail);
+fail_q:
+ mp_drop(bp->p);
+fail_p:
+ mp_drop(x);
+fail_x:
+ return (PGEN_ABORT);
}
/*----- That's all, folks -------------------------------------------------*/