RSApriv* rsafill(mpint *n, mpint *e, mpint *d, mpint *p, mpint *q) { mpint *c2, *kq, *kp, *x; RSApriv *rsa; // make sure we're not being hoodwinked if(!probably_prime(p, 10) || !probably_prime(q, 10)){ werrstr("rsafill: p or q not prime"); return nil; } x = mpnew(0); mpmul(p, q, x); if(mpcmp(n, x) != 0){ werrstr("rsafill: n != p*q"); mpfree(x); return nil; } c2 = mpnew(0); mpsub(p, mpone, c2); mpsub(q, mpone, x); mpmul(c2, x, x); mpmul(e, d, c2); mpmod(c2, x, x); if(mpcmp(x, mpone) != 0){ werrstr("rsafill: e*d != 1 mod (p-1)*(q-1)"); mpfree(x); mpfree(c2); return nil; } // compute chinese remainder coefficient mpinvert(p, q, c2); // for crt a**k mod p == (a**(k mod p-1)) mod p kq = mpnew(0); kp = mpnew(0); mpsub(p, mpone, x); mpmod(d, x, kp); mpsub(q, mpone, x); mpmod(d, x, kq); rsa = rsaprivalloc(); rsa->pub.ek = mpcopy(e); rsa->pub.n = mpcopy(n); rsa->dk = mpcopy(d); rsa->kp = kp; rsa->kq = kq; rsa->p = mpcopy(p); rsa->q = mpcopy(q); rsa->c2 = c2; mpfree(x); return rsa; }
DSApriv* dsagen(DSApub *opub) { DSApub *pub; DSApriv *priv; mpint *exp; mpint *g; mpint *r; int bits; priv = dsaprivalloc(); pub = &priv->pub; if(opub != nil){ pub->p = mpcopy(opub->p); pub->q = mpcopy(opub->q); } else { pub->p = mpnew(0); pub->q = mpnew(0); DSAprimes(pub->q, pub->p, nil); } bits = Dbits*pub->p->top; pub->alpha = mpnew(0); pub->key = mpnew(0); priv->secret = mpnew(0); // find a generator alpha of the multiplicative // group Z*p, i.e., of order n = p-1. We use the // fact that q divides p-1 to reduce the exponent. exp = mpnew(0); g = mpnew(0); r = mpnew(0); mpsub(pub->p, mpone, exp); mpdiv(exp, pub->q, exp, r); if(mpcmp(r, mpzero) != 0) sysfatal("dsagen foul up"); while(1){ mprand(bits, genrandom, g); mpmod(g, pub->p, g); mpexp(g, exp, pub->p, pub->alpha); if(mpcmp(pub->alpha, mpone) != 0) break; } mpfree(g); mpfree(exp); // create the secret key mprand(bits, genrandom, priv->secret); mpmod(priv->secret, pub->p, priv->secret); mpexp(pub->alpha, priv->secret, pub->p, pub->key); return priv; }
DSApub* dsaprivtopub(DSApriv *priv) { DSApub *pub; pub = dsapuballoc(); pub->p = mpcopy(priv->pub.p); pub->q = mpcopy(priv->pub.q); pub->alpha = mpcopy(priv->pub.alpha); pub->key = mpcopy(priv->pub.key); return pub; }
/* * needs workspace of (8*size+2) words */ int mppmilrab_w(const mpbarrett* p, randomGeneratorContext* rc, int t, mpw* wksp) { /* * Miller-Rabin probabilistic primality test, with modification * * For more information, see: * "Handbook of Applied Cryptography" * Chapter 4.24 * * Modification to the standard algorithm: * The first value of a is not obtained randomly, but set to two */ /* this routine uses (size*3) storage, and calls mpbpowmod, which needs (size*4+2) */ /* (size) for a, (size) for r, (size) for n-1 */ register size_t size = p->size; register mpw* ndata = wksp; register mpw* rdata = ndata+size; register mpw* adata = rdata+size; int s; mpcopy(size, ndata, p->modl); mpsubw(size, ndata, 1); mpcopy(size, rdata, ndata); s = mprshiftlsz(size, rdata); /* we've split p-1 into (2^s)*r */ /* should do an assert that s != 0 */ /* do at least one test, with a = 2 */ if (t == 0) t++; if (!mppmilrabtwo_w(p, s, rdata, ndata, wksp+3*size)) return 0; while (t-- > 0) { /* generate a random 'a' into b->data */ mpbrnd_w(p, rc, adata, wksp); if (!mppmilraba_w(p, adata, s, rdata, ndata, wksp+3*size)) return 0; } return 1; }
void mpbcopy(mpbarrett* b, const mpbarrett* copy) { register size_t size = copy->size; if (size) { if (b->modl) { if (b->size != size) b->modl = (mpw*) realloc(b->modl, (2*size+1) * sizeof(mpw)); } else b->modl = (mpw*) malloc((2*size+1) * sizeof(mpw)); if (b->modl) { b->size = size; b->mu = b->modl+copy->size; mpcopy(2*size+1, b->modl, copy->modl); } else { b->size = 0; b->mu = (mpw*) 0; } } else if (b->modl) { free(b->modl); b->size = 0; b->modl = b->mu = (mpw*) 0; } }
/* * mpbsubone * copies (b-1) into result */ void mpbsubone(const mpbarrett* b, mpw* result) { register size_t size = b->size; mpcopy(size, result, b->modl); mpsubw(size, result, 1); }
void ecmul(ECdomain *dom, ECpoint *a, mpint *k, ECpoint *s) { ECpoint ns, na; mpint *l; if(a->inf || mpcmp(k, mpzero) == 0){ s->inf = 1; return; } ns.inf = 1; ns.x = mpnew(0); ns.y = mpnew(0); na.x = mpnew(0); na.y = mpnew(0); ecassign(dom, a, &na); l = mpcopy(k); l->sign = 1; while(mpcmp(l, mpzero) != 0){ if(l->p[0] & 1) ecadd(dom, &na, &ns, &ns); ecadd(dom, &na, &na, &na); mpright(l, 1, l); } if(k->sign < 0){ ns.y->sign = -1; mpmod(ns.y, dom->p, ns.y); } ecassign(dom, &ns, s); mpfree(ns.x); mpfree(ns.y); mpfree(na.x); mpfree(na.y); }
/* * mpbset */ void mpbset(mpbarrett* b, size_t size, const mpw *data) { if (size > 0) { if (b->modl) { if (b->size != size) b->modl = (mpw*) realloc(b->modl, (2*size+1) * sizeof(mpw)); } else b->modl = (mpw*) malloc((2*size+1) * sizeof(mpw)); if (b->modl) { mpw* temp = (mpw*) malloc((6*size+4) * sizeof(mpw)); b->size = size; b->mu = b->modl+size; mpcopy(size, b->modl, data); mpbmu_w(b, temp); free(temp); } else { b->size = 0; b->mu = (mpw*) 0; } } }
int dldp_pgonMakeSafe(dldp_p* dp, randomGeneratorContext* rgc, size_t pbits) { /* * Generate parameters with a safe prime; i.e. p = 2q+1, where q is prime */ register size_t psize = MP_BITS_TO_WORDS(pbits + MP_WBITS - 1); register mpw* temp = (mpw*) malloc((8*psize+2) * sizeof(mpw)); if (temp) { /* generate safe p */ mpprndsafe_w(&dp->p, rgc, pbits, mpptrials(pbits), temp); /* set n */ mpbsubone(&dp->p, temp); mpbset(&dp->n, psize, temp); /* set q */ mpcopy(psize, temp, dp->p.modl); mpdivtwo(psize, temp); mpbset(&dp->q, psize, temp); /* set r = 2 */ mpnsetw(&dp->r, 2); dldp_pgonGenerator_w(dp, rgc, temp); free(temp); return 0; } return -1; }
int dldp_pgoqMakeSafe(dldp_p* dp, randomGeneratorContext* rgc, size_t bits) { /* * Generate parameters with a safe prime; p = 2q+1 i.e. r=2 * */ register size_t size = MP_BITS_TO_WORDS(bits + MP_WBITS - 1); register mpw* temp = (mpw*) malloc((8*size+2) * sizeof(mpw)); if (temp) { /* generate p */ mpprndsafe_w(&dp->p, rgc, bits, mpptrials(bits), temp); /* set q */ mpcopy(size, temp, dp->p.modl); mpdivtwo(size, temp); mpbset(&dp->q, size, temp); /* set r = 2 */ mpnsetw(&dp->r, 2); /* clear n */ mpbzero(&dp->n); dldp_pgoqGenerator_w(dp, rgc, temp); free(temp); return 0; } return -1; }
/* * mpbneg * computes the negative (modulo b) of x, where x must contain a value between 0 and b-1 */ void mpbneg(const mpbarrett* b, const mpw* data, mpw* result) { register size_t size = b->size; mpcopy(size, result, data); mpneg(size, result); mpadd(size, result, b->modl); }
void mpprndsafe_w(mpbarrett* p, randomGeneratorContext* rc, size_t bits, int t, mpw* wksp) { /* * Initialize with a probable safe prime of 'size' words, with probability factor t * * A safe prime p has the property that p = 2q+1, where q is also prime * Use for ElGamal type schemes, where a generator of order (p-1) is required */ size_t size = MP_BITS_TO_WORDS(bits + MP_WBITS - 1); mpbinit(p, size); if (p->modl != (mpw*) 0) { mpbarrett q; mpbzero(&q); mpbinit(&q, size); while (1) { /* * Generate a random appropriate candidate prime, and test * it with small prime divisor test BEFORE computing mu */ mpprndbits(p, bits, 2, (mpnumber*) 0, (mpnumber*) 0, rc, wksp); mpcopy(size, q.modl, p->modl); mpdivtwo(size, q.modl); /* do a small prime product trial division on q */ if (!mppsppdiv_w(&q, wksp)) continue; /* do a small prime product trial division on p */ if (!mppsppdiv_w(p, wksp)) continue; /* candidate prime has passed small prime division test for p and q */ mpbmu_w(&q, wksp); if (!mppmilrab_w(&q, rc, t, wksp)) continue; mpbmu_w(p, wksp); if (!mppmilrab_w(p, rc, t, wksp)) continue; mpbfree(&q); return; } } }
/* setup crt info, returns a newly created structure */ CRTpre* crtpre(int n, mpint **m) { CRTpre *crt; int i, j; mpint *u; crt = malloc(sizeof(CRTpre)+sizeof(mpint)*3*n); if(crt == nil) sysfatal("crtpre: %r"); crt->m = crt->a; crt->c = crt->a+n; crt->p = crt->c+n; crt->n = n; /* make a copy of the moduli */ for(i = 0; i < n; i++) crt->m[i] = mpcopy(m[i]); /* precompute the products */ u = mpcopy(mpone); for(i = 0; i < n; i++){ mpmul(u, m[i], u); crt->p[i] = mpcopy(u); } /* precompute the coefficients */ for(i = 1; i < n; i++){ crt->c[i] = mpcopy(mpone); for(j = 0; j < i; j++){ mpinvert(m[j], m[i], u); mpmul(u, crt->c[i], u); mpmod(u, m[i], crt->c[i]); } } mpfree(u); return crt; }
static int binput(Fmt *f, Const *c) { mpint *n, *x; int rc, i, j, k; mpdigit p, q; n = mpcopy(c->n); x = mpcopy(c->x); j = mpsignif(n); k = mpsignif(x); i = j > k ? j : k; if(x->sign == -1){ mptrunc(n, ++i, n); mptrunc(x, i, x); }else if(k >= j) i++; if(n->sign == -1) return fmtstrcpy(f, "(invalid)"); if(i == 0) i = 1; j = (i + 31) / (sizeof(mpdigit) * 8); i = (i + sizeof(mpdigit) * 8 - 1) % (sizeof(mpdigit) * 8) + 1; rc = fmtstrcpy(f, "'b"); while(--j >= 0){ p = j >= n->top ? 0 : n->p[j]; q = j >= x->top ? 0 : x->p[j]; while(--i >= 0){ k = (mpdigit)1<<i; rc += fmtstrcpy(f, (q & k) != 0 ? ((p & k) != 0 ? "z" : "x") : ((p & k) != 0 ? "1" : "0")); } i = sizeof(mpdigit) * 8; } mpfree(n); mpfree(x); return rc; }
static int mpleg(mpint *a, mpint *b) { int r, k; mpint *m, *n, *t; r = 1; m = mpcopy(a); n = mpcopy(b); for(;;){ if(mpcmp(m, n) > 0) mpmod(m, n, m); if(mpcmp(m, mpzero) == 0){ r = 0; break; } if(mpcmp(m, mpone) == 0) break; k = mplowbits0(m); if(k > 0){ if(k & 1) switch(n->p[0] & 15){ case 3: case 5: case 11: case 13: r = -r; } mpright(m, k, m); } if((n->p[0] & 3) == 3 && (m->p[0] & 3) == 3) r = -r; t = m; m = n; n = t; } mpfree(m); mpfree(n); return r; }
/* * mpbmod_w * computes the barrett modular reduction of a number x, which has twice the size of b * needs workspace of (2*size+2) words */ void mpbmod_w(const mpbarrett* b, const mpw* data, mpw* result, mpw* wksp) { register mpw rc; register size_t sp = 2; register const mpw* src = data+b->size+1; register mpw* dst = wksp+b->size+1; rc = mpsetmul(sp, dst, b->mu, *(--src)); *(--dst) = rc; while (sp <= b->size) { sp++; if ((rc = *(--src))) { rc = mpaddmul(sp, dst, b->mu, rc); *(--dst) = rc; } else *(--dst) = 0; } if ((rc = *(--src))) { rc = mpaddmul(sp, dst, b->mu, rc); *(--dst) = rc; } else *(--dst) = 0; sp = b->size; rc = 0; dst = wksp+b->size+1; src = dst; *dst = mpsetmul(sp, dst+1, b->modl, *(--src)); while (sp > 0) mpaddmul(sp--, dst, b->modl+(rc++), *(--src)); mpsetx(b->size+1, wksp, b->size*2, data); mpsub(b->size+1, wksp, wksp+b->size+1); while (mpgex(b->size+1, wksp, b->size, b->modl)) mpsubx(b->size+1, wksp, b->size, b->modl); mpcopy(b->size, result, wksp+1); }
/* * mpbrnd_w * generates a random number in the range 1 < r < b-1 * need workspace of (size) words */ void mpbrnd_w(const mpbarrett* b, randomGeneratorContext* rc, mpw* result, mpw* wksp) { size_t msz = mpmszcnt(b->size, b->modl); mpcopy(b->size, wksp, b->modl); mpsubw(b->size, wksp, 1); do { rc->rng->next(rc->param, (byte*) result, MP_WORDS_TO_BYTES(b->size)); result[0] &= (MP_ALLMASK >> msz); while (mpge(b->size, result, wksp)) mpsub(b->size, result, wksp); } while (mpleone(b->size, result)); }
/* * mpbmu_w * computes the Barrett 'mu' coefficient * needs workspace of (6*size+4) words */ void mpbmu_w(mpbarrett* b, mpw* wksp) { register size_t size = b->size; register size_t shift; register mpw* divmod = wksp; register mpw* dividend = divmod+(size*2+2); register mpw* workspace = dividend+(size*2+1); /* normalize modulus before division */ shift = mpnorm(size, b->modl); /* make the dividend, initialize first word to 1 (shifted); the rest is zero */ *dividend = ((mpw) MP_LSBMASK << shift); mpzero(size*2, dividend+1); mpndivmod(divmod, size*2+1, dividend, size, b->modl, workspace); mpcopy(size+1, b->mu, divmod+1); /* de-normalize */ mprshift(size, b->modl, shift); }
/* * Read an ascii label in from FILE f, * in the same format as that put out by display(), * and fill in lp. */ int getasciilabel(FILE *f, struct disklabel *lp) { char **cpp, *cp; const char *errstr; struct partition *pp; char *mp, *tp, *s, line[BUFSIZ]; char **omountpoints = NULL; int lineno = 0, errors = 0; u_int32_t v, fsize; u_int64_t lv; unsigned int part; lp->d_version = 1; lp->d_bbsize = BBSIZE; /* XXX */ lp->d_sbsize = SBSIZE; /* XXX */ if (!(omountpoints = calloc(MAXPARTITIONS, sizeof(char *)))) errx(4, "out of memory"); mpcopy(omountpoints, mountpoints); for (part = 0; part < MAXPARTITIONS; part++) { free(mountpoints[part]); mountpoints[part] = NULL; } while (fgets(line, sizeof(line), f)) { lineno++; mp = NULL; if ((cp = strpbrk(line, "\r\n"))) *cp = '\0'; if ((cp = strpbrk(line, "#"))) { *cp = '\0'; mp = skip(cp+1); if (mp && *mp != '/') mp = NULL; } cp = skip(line); if (cp == NULL) continue; tp = strchr(cp, ':'); if (tp == NULL) { warnx("line %d: syntax error", lineno); errors++; continue; } *tp++ = '\0', tp = skip(tp); if (!strcmp(cp, "type")) { if (tp == NULL) tp = "unknown"; else if (strcasecmp(tp, "IDE") == 0) tp = "ESDI"; cpp = dktypenames; for (; cpp < &dktypenames[DKMAXTYPES]; cpp++) if ((s = *cpp) && !strcasecmp(s, tp)) { lp->d_type = cpp - dktypenames; goto next; } v = GETNUM(lp->d_type, tp, 0, &errstr); if (errstr || v >= DKMAXTYPES) warnx("line %d: warning, unknown disk type: %s", lineno, tp); lp->d_type = v; continue; } if (!strcmp(cp, "flags")) { for (v = 0; (cp = tp) && *cp != '\0';) { tp = word(cp); if (!strcmp(cp, "badsect")) v |= D_BADSECT; else if (!strcmp(cp, "vendor")) v |= D_VENDOR; else { warnx("line %d: bad flag: %s", lineno, cp); errors++; } } lp->d_flags = v; continue; } if (!strcmp(cp, "drivedata")) { int i; for (i = 0; (cp = tp) && *cp != '\0' && i < NDDATA;) { v = GETNUM(lp->d_drivedata[i], cp, 0, &errstr); if (errstr) warnx("line %d: bad drivedata %s", lineno, cp); lp->d_drivedata[i++] = v; tp = word(cp); } continue; } if (sscanf(cp, "%d partitions", &v) == 1) { if (v == 0 || v > MAXPARTITIONS) { warnx("line %d: bad # of partitions", lineno); lp->d_npartitions = MAXPARTITIONS; errors++; } else lp->d_npartitions = v; continue; } if (tp == NULL) tp = ""; if (!strcmp(cp, "disk")) { strncpy(lp->d_typename, tp, sizeof (lp->d_typename)); continue; } if (!strcmp(cp, "label")) { strncpy(lp->d_packname, tp, sizeof (lp->d_packname)); continue; } if (!strcmp(cp, "duid")) { if (duid_parse(lp, tp) != 0) { warnx("line %d: bad %s: %s", lineno, cp, tp); errors++; } continue; } if (!strcmp(cp, "bytes/sector")) { v = GETNUM(lp->d_secsize, tp, 1, &errstr); if (errstr || (v % 512) != 0) { warnx("line %d: bad %s: %s", lineno, cp, tp); errors++; } else lp->d_secsize = v; continue; } if (!strcmp(cp, "sectors/track")) { v = GETNUM(lp->d_nsectors, tp, 1, &errstr); if (errstr) { warnx("line %d: bad %s: %s", lineno, cp, tp); errors++; } else lp->d_nsectors = v; continue; } if (!strcmp(cp, "sectors/cylinder")) { v = GETNUM(lp->d_secpercyl, tp, 1, &errstr); if (errstr) { warnx("line %d: bad %s: %s", lineno, cp, tp); errors++; } else lp->d_secpercyl = v; continue; } if (!strcmp(cp, "tracks/cylinder")) { v = GETNUM(lp->d_ntracks, tp, 1, &errstr); if (errstr) { warnx("line %d: bad %s: %s", lineno, cp, tp); errors++; } else lp->d_ntracks = v; continue; } if (!strcmp(cp, "cylinders")) { v = GETNUM(lp->d_ncylinders, tp, 1, &errstr); if (errstr) { warnx("line %d: bad %s: %s", lineno, cp, tp); errors++; } else lp->d_ncylinders = v; continue; } /* Ignore fields that are no longer in the disklabel. */ if (!strcmp(cp, "rpm") || !strcmp(cp, "interleave") || !strcmp(cp, "trackskew") || !strcmp(cp, "cylinderskew") || !strcmp(cp, "headswitch") || !strcmp(cp, "track-to-track seek")) continue; /* Ignore fields that are forcibly set when label is read. */ if (!strcmp(cp, "total sectors") || !strcmp(cp, "boundstart") || !strcmp(cp, "boundend")) continue; if ('a' <= *cp && *cp <= 'z' && cp[1] == '\0') { unsigned int part = *cp - 'a'; if (part >= lp->d_npartitions) { if (part >= MAXPARTITIONS) { warnx("line %d: bad partition name: %s", lineno, cp); errors++; continue; } else { lp->d_npartitions = part + 1; } } pp = &lp->d_partitions[part]; #define NXTNUM(n, field, errstr) { \ if (tp == NULL) { \ warnx("line %d: too few fields", lineno); \ errors++; \ break; \ } else \ cp = tp, tp = word(cp), (n) = GETNUM(field, cp, 0, errstr); \ } NXTNUM(lv, lv, &errstr); if (errstr) { warnx("line %d: bad partition size: %s", lineno, cp); errors++; } else { DL_SETPSIZE(pp, lv); } NXTNUM(lv, lv, &errstr); if (errstr) { warnx("line %d: bad partition offset: %s", lineno, cp); errors++; } else { DL_SETPOFFSET(pp, lv); } if (tp == NULL) { pp->p_fstype = FS_UNUSED; goto gottype; } cp = tp, tp = word(cp); cpp = fstypenames; for (; cpp < &fstypenames[FSMAXTYPES]; cpp++) if ((s = *cpp) && !strcasecmp(s, cp)) { pp->p_fstype = cpp - fstypenames; goto gottype; } if (isdigit((unsigned char)*cp)) v = GETNUM(pp->p_fstype, cp, 0, &errstr); else v = FSMAXTYPES; if (errstr || v >= FSMAXTYPES) { warnx("line %d: warning, unknown filesystem type: %s", lineno, cp); v = FS_UNUSED; } pp->p_fstype = v; gottype: switch (pp->p_fstype) { case FS_UNUSED: /* XXX */ if (tp == NULL) /* ok to skip fsize/bsize */ break; NXTNUM(fsize, fsize, &errstr); if (fsize == 0) break; NXTNUM(v, v, &errstr); pp->p_fragblock = DISKLABELV1_FFS_FRAGBLOCK(fsize, v / fsize); break; case FS_BSDFFS: NXTNUM(fsize, fsize, &errstr); if (fsize == 0) break; NXTNUM(v, v, &errstr); pp->p_fragblock = DISKLABELV1_FFS_FRAGBLOCK(fsize, v / fsize); NXTNUM(pp->p_cpg, pp->p_cpg, &errstr); break; default: break; } if (mp) mountpoints[part] = strdup(mp); continue; } warnx("line %d: unknown field: %s", lineno, cp); errors++; next: ; } errors += checklabel(lp); if (errors > 0) mpcopy(mountpoints, omountpoints); mpfree(omountpoints); return (errors > 0); }
/* * needs workspace of (8*size+2) words */ void mpprndconone_w(mpbarrett* p, randomGeneratorContext* rc, size_t bits, int t, const mpbarrett* q, const mpnumber* f, mpnumber* r, int cofactor, mpw* wksp) { /* * Generate a prime p with n bits such that p mod q = 1, and p = qr+1 where r = 2s * * Conditions: q > 2 and size(q) < size(p) and size(f) <= size(p) * * Conditions: r must be chosen so that r is even, otherwise p will be even! * * if cofactor == 0, then s will be chosen randomly * if cofactor == 1, then make sure that q does not divide r, i.e.: * q cannot be equal to r, since r is even, and q > 2; hence if q <= r make sure that GCD(q,r) == 1 * if cofactor == 2, then make sure that s is prime * * Optional input f: if f is not null, then search p so that GCD(p-1,f) = 1 */ mpbinit(p, MP_BITS_TO_WORDS(bits + MP_WBITS - 1)); if (p->modl != (mpw*) 0) { size_t sbits = bits - mpbits(q->size, q->modl) - 1; mpbarrett s; mpbzero(&s); mpbinit(&s, MP_BITS_TO_WORDS(sbits + MP_WBITS - 1)); while (1) { mpprndbits(&s, sbits, 0, (mpnumber*) 0, (mpnumber*) 0, rc, wksp); if (cofactor == 1) { mpsetlsb(s.size, s.modl); /* if (q <= s) check if GCD(q,s) != 1 */ if (mplex(q->size, q->modl, s.size, s.modl)) { /* we can find adequate storage for computing the gcd in s->wksp */ mpsetx(s.size, wksp, q->size, q->modl); mpgcd_w(s.size, s.modl, wksp, wksp+s.size, wksp+2*s.size); if (!mpisone(s.size, wksp+s.size)) continue; } } else if (cofactor == 2) { mpsetlsb(s.size, s.modl); } if (cofactor == 2) { /* do a small prime product trial division test on r */ if (!mppsppdiv_w(&s, wksp)) continue; } /* multiply q*s */ mpmul(wksp, s.size, s.modl, q->size, q->modl); /* s.size + q.size may be greater than p.size by 1, but the product will fit exactly into p */ mpsetx(p->size, p->modl, s.size+q->size, wksp); /* multiply by two and add 1 */ mpmultwo(p->size, p->modl); mpaddw(p->size, p->modl, 1); /* test if the product actually contains enough bits */ if (mpbits(p->size, p->modl) < bits) continue; /* do a small prime product trial division test on p */ if (!mppsppdiv_w(p, wksp)) continue; /* if we have an f, do the congruence test */ if (f != (mpnumber*) 0) { mpcopy(p->size, wksp, p->modl); mpsubw(p->size, wksp, 1); mpsetx(p->size, wksp, f->size, f->data); mpgcd_w(p->size, wksp, wksp+p->size, wksp+2*p->size, wksp+3*p->size); if (!mpisone(p->size, wksp+2*p->size)) continue; } /* if cofactor is two, test if s is prime */ if (cofactor == 2) { mpbmu_w(&s, wksp); if (!mppmilrab_w(&s, rc, mpptrials(sbits), wksp)) continue; } /* candidate has passed so far, now we do the probabilistic test on p */ mpbmu_w(p, wksp); if (!mppmilrab_w(p, rc, t, wksp)) continue; mpnset(r, s.size, s.modl); mpmultwo(r->size, r->data); mpbfree(&s); return; } } }
/* * implements IEEE P1363 A.15.6 * * f, min, max are optional */ int mpprndr_w(mpbarrett* p, randomGeneratorContext* rc, size_t bits, int t, const mpnumber* min, const mpnumber* max, const mpnumber* f, mpw* wksp) { /* * Generate a prime into p with the requested number of bits * * Conditions: size(f) <= size(p) * * Optional input min: if min is not null, then search p so that min <= p * Optional input max: if max is not null, then search p so that p <= max * Optional input f: if f is not null, then search p so that GCD(p-1,f) = 1 */ size_t size = MP_BITS_TO_WORDS(bits + MP_WBITS - 1); /* if min has more bits than what was requested for p, bail out */ if (min && (mpbits(min->size, min->data) > bits)) return -1; /* if max has a different number of bits than what was requested for p, bail out */ if (max && (mpbits(max->size, max->data) != bits)) return -1; /* if min is not less than max, bail out */ if (min && max && mpgex(min->size, min->data, max->size, max->data)) return -1; mpbinit(p, size); if (p->modl) { while (1) { /* * Generate a random appropriate candidate prime, and test * it with small prime divisor test BEFORE computing mu */ mpprndbits(p, bits, 1, min, max, rc, wksp); /* do a small prime product trial division test on p */ if (!mppsppdiv_w(p, wksp)) continue; /* if we have an f, do the congruence test */ if (f != (mpnumber*) 0) { mpcopy(size, wksp, p->modl); mpsubw(size, wksp, 1); mpsetx(size, wksp+size, f->size, f->data); mpgcd_w(size, wksp, wksp+size, wksp+2*size, wksp+3*size); if (!mpisone(size, wksp+2*size)) continue; } /* candidate has passed so far, now we do the probabilistic test */ mpbmu_w(p, wksp); if (mppmilrab_w(p, rc, t, wksp)) return 0; } } return -1; }
// extended binary gcd // // For a anv b it solves, v = gcd(a,b) and finds x and y s.t. // ax + by = v // // Handbook of Applied Cryptography, Menezes et al, 1997, pg 608. void mpextendedgcd(mpint *a, mpint *b, mpint *v, mpint *x, mpint *y) { mpint *u, *A, *B, *C, *D; int g; if(a->top == 0){ mpassign(b, v); mpassign(mpone, y); mpassign(mpzero, x); return; } if(b->top == 0){ mpassign(a, v); mpassign(mpone, x); mpassign(mpzero, y); return; } g = 0; a = mpcopy(a); b = mpcopy(b); while(iseven(a) && iseven(b)){ mpright(a, 1, a); mpright(b, 1, b); g++; } u = mpcopy(a); mpassign(b, v); A = mpcopy(mpone); B = mpcopy(mpzero); C = mpcopy(mpzero); D = mpcopy(mpone); for(;;) { // print("%B %B %B %B %B %B\n", u, v, A, B, C, D); while(iseven(u)){ mpright(u, 1, u); if(!iseven(A) || !iseven(B)) { mpadd(A, b, A); mpsub(B, a, B); } mpright(A, 1, A); mpright(B, 1, B); } // print("%B %B %B %B %B %B\n", u, v, A, B, C, D); while(iseven(v)){ mpright(v, 1, v); if(!iseven(C) || !iseven(D)) { mpadd(C, b, C); mpsub(D, a, D); } mpright(C, 1, C); mpright(D, 1, D); } // print("%B %B %B %B %B %B\n", u, v, A, B, C, D); if(mpcmp(u, v) >= 0){ mpsub(u, v, u); mpsub(A, C, A); mpsub(B, D, B); } else { mpsub(v, u, v); mpsub(C, A, C); mpsub(D, B, D); } if(u->top == 0) break; } mpassign(C, x); mpassign(D, y); mpleft(v, g, v); mpfree(A); mpfree(B); mpfree(C); mpfree(D); mpfree(u); mpfree(a); mpfree(b); }
int dsasign(const mpbarrett* p, const mpbarrett* q, const mpnumber* g, randomGeneratorContext* rgc, const mpnumber* hm, const mpnumber* x, mpnumber* r, mpnumber* s) { register size_t psize = p->size; register size_t qsize = q->size; register mpw* ptemp; register mpw* qtemp; register mpw* pwksp; register mpw* qwksp; register int rc = -1; ptemp = (mpw*) malloc((5*psize+2)*sizeof(mpw)); if (ptemp == (mpw*) 0) return rc; qtemp = (mpw*) malloc((9*qsize+6)*sizeof(mpw)); if (qtemp == (mpw*) 0) { free(ptemp); return rc; } pwksp = ptemp+psize; qwksp = qtemp+3*qsize; /* allocate r */ mpnfree(r); mpnsize(r, qsize); /* get a random k, invertible modulo q; store k @ qtemp, inv(k) @ qtemp+qsize */ mpbrndinv_w(q, rgc, qtemp, qtemp+qsize, qwksp); /* g^k mod p */ mpbpowmod_w(p, g->size, g->data, qsize, qtemp, ptemp, pwksp); /* (g^k mod p) mod q - simple modulo */ mpmod(qtemp+2*qsize, psize, ptemp, qsize, q->modl, pwksp); mpcopy(qsize, r->data, qtemp+psize+qsize); /* allocate s */ mpnfree(s); mpnsize(s, qsize); /* x*r mod q */ mpbmulmod_w(q, x->size, x->data, r->size, r->data, qtemp, qwksp); /* add h(m) mod q */ mpbaddmod_w(q, qsize, qtemp, hm->size, hm->data, qtemp+2*qsize, qwksp); /* multiply inv(k) mod q */ mpbmulmod_w(q, qsize, qtemp+qsize, qsize, qtemp+2*qsize, s->data, qwksp); rc = 0; free(qtemp); free(ptemp); return rc; }
void mpexp(mpint *b, mpint *e, mpint *m, mpint *res) { mpint *t[2]; int tofree; mpdigit d, bit; int i, j; t[0] = mpcopy(b); t[1] = res; tofree = 0; if(res == b){ b = mpcopy(b); tofree |= Freeb; } if(res == e){ e = mpcopy(e); tofree |= Freee; } if(res == m){ m = mpcopy(m); tofree |= Freem; } // skip first bit i = e->top-1; d = e->p[i]; for(bit = mpdighi; (bit & d) == 0; bit >>= 1) ; bit >>= 1; j = 0; for(;;){ for(; bit != 0; bit >>= 1){ mpmul(t[j], t[j], t[j^1]); if(bit & d) mpmul(t[j^1], b, t[j]); else j ^= 1; if(m != nil && t[j]->top > m->top){ mpmod(t[j], m, t[j^1]); j ^= 1; } } if(--i < 0) break; bit = mpdighi; d = e->p[i]; } if(m != nil){ mpmod(t[j], m, t[j^1]); j ^= 1; } if(t[j] == res){ mpfree(t[j^1]); } else { mpassign(t[j], res); mpfree(t[j]); } if(tofree){ if(tofree & Freeb) mpfree(b); if(tofree & Freee) mpfree(e); if(tofree & Freem) mpfree(m); } }
void mpeuclid(mpint *a, mpint *b, mpint *d, mpint *x, mpint *y) { mpint *tmp, *x0, *x1, *x2, *y0, *y1, *y2, *q, *r; if(a->sign<0 || b->sign<0) sysfatal("mpeuclid: negative arg"); if(mpcmp(a, b) < 0){ tmp = a; a = b; b = tmp; tmp = x; x = y; y = tmp; } if(b->top == 0){ mpassign(a, d); mpassign(mpone, x); mpassign(mpzero, y); return; } a = mpcopy(a); b = mpcopy(b); x0 = mpnew(0); x1 = mpcopy(mpzero); x2 = mpcopy(mpone); y0 = mpnew(0); y1 = mpcopy(mpone); y2 = mpcopy(mpzero); q = mpnew(0); r = mpnew(0); while(b->top != 0 && b->sign > 0){ // q = a/b // r = a mod b mpdiv(a, b, q, r); // x0 = x2 - qx1 mpmul(q, x1, x0); mpsub(x2, x0, x0); // y0 = y2 - qy1 mpmul(q, y1, y0); mpsub(y2, y0, y0); // rotate values tmp = a; a = b; b = r; r = tmp; tmp = x2; x2 = x1; x1 = x0; x0 = tmp; tmp = y2; y2 = y1; y1 = y0; y0 = tmp; } mpassign(a, d); mpassign(x2, x); mpassign(y2, y); mpfree(x0); mpfree(x1); mpfree(x2); mpfree(y0); mpfree(y1); mpfree(y2); mpfree(q); mpfree(r); mpfree(a); mpfree(b); }