/* -*-c-*-
*
- * $Id: bbs-gen.c,v 1.1 1999/12/10 23:14:59 mdw Exp $
+ * $Id: bbs-gen.c,v 1.2 1999/12/22 15:52:28 mdw Exp $
*
* Generate Blum integers
*
/*----- Revision history --------------------------------------------------*
*
* $Log: bbs-gen.c,v $
+ * 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"
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct gcdctx {
+ mp *q;
+ mp *r;
+ pfilt p;
+} gcdctx;
+
+/*----- Custom stepper ----------------------------------------------------*/
+
+static int gcdstep(int rq, pgen_event *ev, void *p)
+{
+ gcdctx *g = p;
+ int rc = PGEN_ABORT;
+ mp *z = MP_NEW;
+
+ switch (rq) {
+ case PGEN_BEGIN: {
+ mp *p = ev->m = mp_split(ev->m);
+ p->v[0] |= 3;
+ g->q = mp_lsr(MP_NEW, p, 1);
+ rc = pfilt_create(&g->p, p);
+ } break;
+ case PGEN_TRY:
+ g->q = mp_add(g->q, g->q, MP_FOUR);
+ rc = pfilt_step(&g->p, 4);
+ break;
+ case PGEN_DONE:
+ pfilt_destroy(&g->p);
+ mp_drop(g->q);
+ return (PGEN_DONE);
+ }
+ for (;;) {
+ if (rc != PGEN_FAIL) {
+ mp_gcd(&z, 0, 0, g->r, g->q);
+ if (MP_CMP(z, !=, MP_ONE))
+ rc = PGEN_FAIL;
+ }
+ if (rc != PGEN_FAIL)
+ break;
+ g->q = mp_add(g->q, g->q, MP_FOUR);
+ rc = pfilt_step(&g->p, 4);
+ }
+
+ mp_drop(z);
+ mp_drop(ev->m);
+ ev->m = MP_COPY(g->p.m);
+ return (rc);
+}
/*----- Main code ---------------------------------------------------------*/
/* --- @bbs_gen@ --- *
*
- * Arguments: @bbs_params *bp@ = pointer to parameter block
+ * Arguments: @bbs_param *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
+ * @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_param *bp, mp *p, mp *q, size_t 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 r;
+ pgen_safestepctx c;
+ gcdctx g;
- if (proc && (fail = proc(BBSEV_GOODP, py.m, arg)) != 0)
- goto fail_0;
+ /* --- Generate @p@ --- */
- /* --- I now have a @p@ (and a %$(p - 1)/2$%) --- */
+ if ((bp->p = pgen("p", MP_NEW, p, event, ectx, n, pgen_safestep, &c,
+ rabin_iters(mp_bits(p)), pgen_test, &r)) == 0)
+ goto fail_p;
- pp = MP_COPY(px.m); pgen_destroy(&px);
- p = MP_COPY(py.m); pgen_destroy(&py);
+ /* --- Generate @q@ --- */
- /* --- 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$%.
- */
+ g.r = mp_lsr(MP_NEW, bp->p, 1);
+ if ((bp->q = pgen("q", MP_NEW, q, event, ectx, n, gcdstep, &g,
+ rabin_iters(mp_bits(q)), pgen_test, &r)) == 0)
+ goto fail_q;
- {
- mp *m = mp_lsl(MP_NEW, q, 1);
- m->v[0] |= 1;
- rcx = pgen_create(&px, m);
- mp_drop(m);
- }
+ /* --- Compute @n@ --- */
- if (proc && (fail = proc(BBSEV_FINDQ, 0, arg)) != 0)
- goto fail_1;
+ bp->n = mp_mul(MP_NEW, bp->p, bp->q);
+ mp_drop(g.r);
+ return (PGEN_DONE);
- 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(g.r);
+ mp_drop(bp->p);
+fail_p:
+ return (PGEN_ABORT);
}
/*----- That's all, folks -------------------------------------------------*/