must be even and bn must be odd */ pgpAssert((bnLSWord(step) & 1) == 0); pgpAssert((bnLSWord(bn) & 1) == 1); bnBegin(&a, bn->mgr, isSecure); bnBegin(&e, bn->mgr, isSecure); for (;;) { if (sieveBuildBig(sieve, SIEVE, bn, step, 0) < 0) goto failed; p = prev = 0; if (sieve[0] & 1 || (p = sieveSearch(sieve, SIEVE, p)) != 0) { do { /* * Adjust bn to have the right value, * adding (p-prev) * 2*step. */ pgpAssert(p >= prev); /* Compute delta into a */ if (bnMulQ(&a, step, p-prev) < 0) goto failed; if (bnAdd(bn, &a) < 0) goto failed; prev = p; retval = primeTest(bn, &e, &a, f, arg); if (retval <= 0) goto done; /* Success! */ modexps += retval; if (f && (retval = f(arg, '.')) < 0) goto done; /* And try again */ p = sieveSearch(sieve, SIEVE, p); } while (p); } /* Ran out of sieve space - increase bn and keep trying. */ #if SIEVE*8 == 65536 /* Corner case that will never actually happen */ if (!prev) { if (bnAdd(bn, step) < 0) goto failed; p = 65535; } else { p = (unsigned)(SIEVE*8 - prev); } #else p = SIEVE*8 - prev; #endif if (bnMulQ(&a, step, p) < 0 || bnAdd(bn, &a) < 0) goto failed; if (f && (retval = f(arg, '/')) < 0) goto done; } /* for (;;) */ failed: retval = -1; done: bnEnd(&e); bnEnd(&a); #ifdef MSDOS bniMemFree(sieve, SIEVE); #else bniMemWipe(sieve, sizeof(sieve)); #endif return retval < 0 ? retval : modexps + CONFIRMTESTS; } ize="12" subscript="false" superscript="false" underline="false"/> >5) #define PPC_MFTB(d) PPC_TYPE31(371,d,12,8) #define PPC_MFTBU(d) PPC_TYPE31(371,d,13,8) #define PPC_MTCRF(mask,s) PPC_TYPE31(144,s,0,(mask)&0xff) #define PPC_MTSPR(s,spr) PPC_TYPE31(467,s,(spr)&31,(spr)>>5) #define PPC_MULHW(d,a,b) PPC_TYPE31(75,d,a,b) #define PPC_MULHW_(d,a,b) PPC_TYPE31(75,d,a,b)|PPC_RC #define PPC_MULHWU(d,a,b) PPC_TYPE31(11,d,a,b) #define PPC_MULHWU_(d,a,b) PPC_TYPE31(11,d,a,b)|PPC_RC #define PPC_MULLW(d,a,b) PPC_TYPE31(235,d,a,b) #define PPC_MULLW_(d,a,b) PPC_TYPE31(235,d,a,b)|PPC_RC #define PPC_MULLWO(d,a,b) PPC_TYPE31(235,d,a,b)|PPC_OE #define PPC_MULLWO_(d,a,b) PPC_TYPE31(235,d,a,b)|PPC_OE|PPC_RC #define PPC_NAND(a,s,b) PPC_TYPE31(476,s,a,b) #define PPC_NAND_(a,s,b) PPC_TYPE31(476,s,a,b)|PPC_RC #define PPC_NEG(d,a) PPC_TYPE31(104,d,a,b) #define PPC_NEG_(d,a) PPC_TYPE31(104,d,a,b)|PPC_RC #define PPC_NEGO(d,a) PPC_TYPE31(104,d,a,b)|PPC_OE #define PPC_NEGO_(d,a) PPC_TYPE31(104,d,a,b)|PPC_OE|PPC_RC #define PPC_NOR(a,s,b) PPC_TYPE31(124,s,a,b) #define PPC_NOR_(a,s,b) PPC_TYPE31(124,s,a,b)|PPC_RC #define PPC_OR(a,s,b) PPC_TYPE31(444,s,a,b) #define PPC_OR_(a,s,b) PPC_TYPE31(444,s,a,b)|PPC_RC #define PPC_ORC(a,s,b) PPC_TYPE31(412,s,a,b) #define PPC_ORC_(a,s,b) PPC_TYPE31(412,s,a,b)|PPC_RC #define PPC_SLW(a,s,b) PPC_TYPE31(24,s,a,b) #define PPC_SLW_(a,s,b) PPC_TYPE31(24,s,a,b)|PPC_RC #define PPC_SRAW(a,s,b) PPC_TYPE31(792,s,a,b) #define PPC_SRAW_(a,s,b) PPC_TYPE31(792,s,a,b)|PPC_RC #define PPC_SRAWI(a,s,sh) PPC_TYPE31(824,s,a,sh) #define PPC_SRAWI_(a,s,sh) PPC_TYPE31(824,s,a,sh)|PPC_RC #define PPC_SRW(a,s,b) PPC_TYPE31(536,s,a,b) #define PPC_SRW_(a,s,b) PPC_TYPE31(536,s,a,b)|PPC_RC #define PPC_STBUX(s,a,b) PPC_TYPE31(247,s,a,b) #define PPC_STBX(s,a,b) PPC_TYPE31(215,s,a,b) #define PPC_STHBRX(s,a,b) PPC_TYPE31(918,s,a,b) #define PPC_STHUX(s,a,b) PPC_TYPE31(439,s,a,b) #define PPC_STHX(s,a,b) PPC_TYPE31(407,s,a,b) #define PPC_STSWI(s,a,nb) PPC_TYPE31(725,s,a,nb) #define PPC_STSWX(s,a,b) PPC_TYPE31(661,s,a,b) #define PPC_STWBRX(s,a,b) PPC_TYPE31(662,s,a,b) #define PPC_STWCX_(s,a,b) PPC_TYPE31(150,s,a,b)|PPC_RC #define PPC_STWUX(s,a,b) PPC_TYPE31(183,s,a,b) #define PPC_STWX(s,a,b) PPC_TYPE31(151,s,a,b) #define PPC_SUBF(d,a,b) PPC_TYPE31(40,d,a,b) #define PPC_SUBF_(d,a,b) PPC_TYPE31(40,d,a,b)|PPC_RC #define PPC_SUBFO(d,a,b) PPC_TYPE31(40,d,a,b)|PPC_OE #define PPC_SUBFO_(d,a,b) PPC_TYPE31(40,d,a,b)|PPC_OE|PPC_RC #define PPC_SUB(d,b,a) PPC_SUBF(d,a,b) #define PPC_SUB_(d,b,a) PPC_SUBF_(d,a,b) #define PPC_SUBO(d,b,a) PPC_SUBFO(d,a,b) #define PPC_SUBO_(d,b,a) PPC_SUBFO_(d,a,b) #define PPC_SUBFC(d,a,b) PPC_TYPE31(8,d,a,b) #define PPC_SUBFC_(d,a,b) PPC_TYPE31(8,d,a,b)|PPC_RC #define PPC_SUBFCO(d,a,b) PPC_TYPE31(8,d,a,b)|PPC_OE #define PPC_SUBFCO_(d,a,b) PPC_TYPE31(8,d,a,b)|PPC_OE|PPC_RC #define PPC_SUBFE(d,a,b) PPC_TYPE31(136,d,a,b) #define PPC_SUBFE_(d,a,b) PPC_TYPE31(136,d,a,b)|PPC_RC #define PPC_SUBFEO(d,a,b) PPC_TYPE31(136,d,a,b)|PPC_OE #define PPC_SUBFEO_(d,a,b) PPC_TYPE31(136,d,a,b)|PPC_OE|PPC_RC #define PPC_SUBFME(d,a) PPC_TYPE31(232,d,a,0) #define PPC_SUBFME_(d,a) PPC_TYPE31(232,d,a,0)|PPC_RC #define PPC_SUBFMEO(d,a) PPC_TYPE31(232,d,a,0)|PPC_OE #define PPC_SUBFMEO_(d,a) PPC_TYPE31(232,d,a,0)|PPC_OE|PPC_RC #define PPC_SUBFZE(d,a) PPC_TYPE31(200,d,a,0) #define PPC_SUBFZE_(d,a) PPC_TYPE31(200,d,a,0)|PPC_RC #define PPC_SUBFZEO(d,a) PPC_TYPE31(200,d,a,0)|PPC_OE #define PPC_SUBFZEO_(d,a) PPC_TYPE31(200,d,a,0)|PPC_OE|PPC_RC #define PPC_SYNC() PPC_TYPE31(598,0,0,0) #define PPC_TW(to,a,b) PPC_TYPE31(4,to,a,b) #define PPC_XOR(a,s,b) PPC_TYPE31(316,s,a,b) /* Immediate-operand instructions. Take a 16-bit immediate operand */ #define PPC_IMM(major,d,a,imm) \ PPC_MAJOR(major)|PPC_DEST(d)|PPC_SRCA(a)|((imm)&0xffff) /* Trap word immediate */ #define PPV_TWI(to,a,simm) PPC_IMM(3,to,a,simm) /* Integer arithmetic */ #define PPC_MULLI(d,a,simm) PPC_IMM(7,d,a,simm) #define PPC_SUBFIC(s,a,simm) PPC_IMM(8,s,a,simm) #define PPC_CMPLI(cr,a,uimm) PPC_IMM(10,(cr)<<2,a,uimm) #define PPC_CMPI(cr,a,simm) PPC_IMM(11,(cr)<<2,a,simm) #define PPC_ADDIC(d,a,simm) PPC_IMM(12,d,a,simm) #define PPC_ADDIC_(d,a,simm) PPC_IMM(13,d,a,simm) #define PPC_ADDI(d,a,simm) PPC_IMM(14,d,a,simm) #define PPC_ADDIS(d,a,simm) PPC_IMM(15,d,a,simm) /* Conditional branch (dest is 16 bits, +/- 2^15 bytes) */ #define PPC_BC(bo,bi,dest) PPC_IMM(16,bo,bi,((dest)<<2)&0xfffc) #define PPC_BCA(bo,bi,dest) PPC_BC(bo,bi,dest)|PPC_AA #define PPC_BCL(bo,bi,dest) PPC_BC(bo,bi,dest)|PPC_LK #define PPC_BCLA(bo,bi,dest) PPC_BC(bo,bi,dest)|PPC_AA|PPC_LK /* Logical operations */ #define PPC_ORI(a,s,uimm) PPC_IMM(24,s,a,uimm) #define PPC_ORIS(a,s,uimm) PPC_IMM(25,s,a,uimm) #define PPC_XORI(a,s,uimm) PPC_IMM(26,s,a,uimm) #define PPC_XORIS(a,s,uimm) PPC_IMM(27,s,a,uimm) #define PPC_ANDI_(a,s,uimm) PPC_IMM(28,s,a,uimm) #define PPC_ANDIS(a,s,uimm) PPC_IMM(29,s,a,uimm) /* Load/store */ #define PPC_LWZ(d,a,simm) PPC_IMM(32,d,a,simm) #define PPC_LWZU(d,a,simm) PPC_IMM(33,d,a,simm) #define PPC_LBZ(d,a,simm) PPC_IMM(34,d,a,simm) #define PPC_LBZU(d,a,simm) PPC_IMM(35,d,a,simm) #define PPC_STW(s,a,simm) PPC_IMM(36,s,a,simm) #define PPC_STWU(s,a,simm) PPC_IMM(37,s,a,simm) #define PPC_STB(s,a,simm) PPC_IMM(38,s,a,simm) #define PPC_STBU(s,a,simm) PPC_IMM(39,s,a,simm) #define PPC_LHZ(d,a,simm) PPC_IMM(40,d,a,simm) #define PPC_LHZU(d,a,simm) PPC_IMM(41,d,a,simm) #define PPC_LHA(d,a,simm) PPC_IMM(42,d,a,simm) #define PPC_STH(s,a,simm) PPC_IMM(44,s,a,simm) #define PPC_STHU(s,a,simm) PPC_IMM(45,s,a,simm) #define PPC_LHAU(d,a,simm) PPC_IMM(43,d,a,simm) #define PPC_LMW(d,a,simm) PPC_IMM(46,d,a,simm) #define PPC_STMW(s,a,simm) PPC_IMM(47,s,a,simm) /* Major number = 19 - condition register operations. d, a and b are CR bits*/ #define PPC_TYPE19(minor,d,a,b) \ PPC_MAJOR(19)|PPC_DEST(d)|PPC_SRCA(a)|PPC_SRCB(b)|PPC_MINOR(minor) #define PPC_MCRF(d,s) PPC_TYPE19(0,(d)<<2,(s)<<2,0) #define PPC_CRNOR(d,a,b) PPC_TYPE19(33,d,a,b) #define PPC_CRANDC(d,a,b) PPC_TYPE19(129,d,a,b) #define PPC_CRXOR(d,a,b) PPC_TYPE19(193,d,a,b) #define PPC_CRNAND(d,a,b) PPC_TYPE19(225,d,a,b) #define PPC_CRAND(d,a,b) PPC_TYPE19(257,d,a,b) #define PPC_CREQV(d,a,b) PPC_TYPE19(289,d,a,b) #define PPC_CRORC(d,a,b) PPC_TYPE19(417,d,a,b) #define PPC_CROR(d,a,b) PPC_TYPE19(449,d,a,b) /* Indirect conditional branch */ #define PPC_BCLR(bo,bi) PPC_TYPE19(16,bo,bi,0) #define PPC_BCLRL(bo,bi) PPC_TYPE19(16,bo,bi,0)|PPC_LK #define PPC_BCCTR(bo,bi) PPC_TYPE19(528,bo,bi,0) #define PPC_BCCTRL(bo,bi) PPC_TYPE19(528,bo,bi,0)|PPC_LK #define PPC_BLR() PPC_BCLR(20,31) #define PPC_BCTR() PPC_BCCTR(20,31) /* Other */ #define PPC_RLWIMI(a,s,sh,mb,me) \ PPC_MAJOR(20)|PPC_DEST(s)|PPC_SRCA(A)|PPC_SRCB(sh)|(mb)<<6|(me)<<1 #define PPC_RLWIMI_(a,s,sh,mb,me) PPC_RLWIMI(a,s,sh,mb,me)|PPC_RC #define PPC_RLWINM(a,s,sh,mb,me) \ PPC_MAJOR(21)|PPC_DEST(s)|PPC_SRCA(A)|PPC_SRCB(sh)|(mb)<<6|(me)<<1 #define PPC_RLWINM_(a,s,sh,mb,me) PPC_RLWINM(a,s,sh,mb,me)|PPC_RC #define PPC_RLWNM(a,s,b,mb,me) \ PPC_MAJOR(23)|PPC_DEST(s)|PPC_SRCA(A)|PPC_SRCB(b)|(mb)<<6|(me)<<1 #define PPC_RLWNM_(a,s,b,mb,me) PPC_RLWNM(a,s,b,mb,me)|PPC_RC #define PPC_SC() PPC_MAJOR(17)|2 /* Major number = 63 Floating-point operations (not implemented for now) */ /* Simplified Mnemonics */ /* Fabricate immediate subtract out of add negative */ #define PPC_SUBI(d,a,simm) PPC_ADDI(d,a,-(simm)) #define PPC_SUBIS(d,a,simm) PPC_ADDIS(d,a,-(simm)) #define PPC_SUBIC(d,a,simm) PPC_ADDIC(d,a,-(simm)) #define PPC_SUBIC_(d,a,simm) PPC_ADDIC_(d,a,-(simm)) /* Fabricate subtract out of subtract from */ #define PPC_SUBC(d,b,a) PPC_SUBFC(d,a,b) #define PPC_SUBC_(d,b,a) PPC_SUBFC_(d,a,b) #define PPC_SUBCO(d,b,a) PPC_SUBFCO(d,a,b) #define PPC_SUBCO_(d,b,a) PPC_SUBFCO_(d,a,b) /* Messy compare bits omitted */ /* Shift and rotate omitted */ /* Branch coding omitted */ #define PPC_CRSET(d) PPC_CREQV(d,d,d) #define PPC_CRCLR(d) PPC_CRXOR(d,d,d) #define PPC_CRMOVE(d,s) PPC_CROR(d,s,s) #define PPC_CRNOT(d,s) PPC_CRNOR(d,s,s) /* Trap menmonics omitted */ /* Menmonics for user-accessible SPRs */ #define PPC_MFXER(d) PPC_MFSPR(d,1) #define PPC_MFLR(d) PPC_MFSPR(d,8) #define PPC_MFCTR(d) PPC_MFSPR(d,9) #define PPC_MTXER(s) PPC_MTSPR(s,1) #define PPC_MTLR(s) PPC_MTSPR(s,8) #define PPC_MTCTR(s) PPC_MTSPR(s,9) /* Recommended mnemonics */ #define PPC_NOP() PPC_ORI(0,0,0) #define PPC_LI(d,simm) PPC_ADDI(d,0,simm) #define PPC_LIS(d,simm) PPC_ADDIS(d,0,simm) #define PPC_LA(d,a,simm) PPC_ADDI(d,a,simm) #define PPC_MR(d,s) PPC_OR(d,s,s) #define PPC_NOT(d,s) PPC_NOR(d,s,s) #define PPC_MTCR(s) PPC_MTCRF(0xff,s) #endif /* Included_bnppcasm_h */ /* 45678901234567890123456789012345678901234567890123456789012345678901234567*/ 9zRzYkJSpwcm90ZWN0ZWRHSShfc3lzbGliRzYiNiNJInZHRic= LUkkY29zRzYkJSpwcm90ZWN0ZWRHSShfc3lzbGliRzYiNiMqJEkieEdGJyIiIw== = bn. leaving the result in bn. */ int bnPrimeGen(BigNum *bn, unsigned (*randnum)(void *randnum_arg, unsigned limit), void *randnum_arg, int (*f)(void *f_arg, int c), void *f_arg, unsigned exponent, ...); /* * Generate a prime of the form bn + k*step. Step must be even and * bn must be odd. */ int bnPrimeGenStrong(BigNum *bn, BigNum const *step, int (*f)(void *arg, int c), void *arg); PGP_END_C_DECLARATIONS #endif /* Included_bnprime_h */ ZpbmZpeEYnLyUnbHNwYWNlR1EvdGhpY2ttYXRoc3BhY2VGJy8lJ3JzcGFjZUdGTy8lKG1pbnNpemVHUSIxRicvJShtYXhzaXplR1EpaW5maW5pdHlGJy1GIzYnLUkjbW5HRiQ2JFEiMkYnRjktRjY2MFExJkludmlzaWJsZVRpbWVzO0YnRjlGO0Y+RkBGQkZERkZGSEZKL0ZOUSQwZW1GJy9GUUZcb0ZSRlUtRiM2JS1GLDYlUSRjb3NGJy9GMEY9RjktRjY2MFEwJkFwcGx5RnVuY3Rpb247RidGOUY7Rj5GQEZCRkRGRkZIRkpGW29GXW9GUkZVLUkobWZlbmNlZEdGJDYkLUYjNiMtRiM2Iy1JJW1zdXBHRiQ2JS1GLDYlUSJ4RidGL0YyRlovJTFzdXBlcnNjcmlwdHNoaWZ0R1EiMEYnRjlGaG5GYXA=">LCQqJi1JJGNvc0c2JCUqcHJvdGVjdGVkR0koX3N5c2xpYkc2IjYjKiRJInhHRikiIiMiIiJGLEYuRi0= The material above can be cut and pasted into a new execution group to work with any functions f and g we choose to define. We also want to look at a diagram that we will use when we generalize to a chain rule in several variables. We can think of variables as points and line segments as derivatives of the functions that connect the points. The chain rule says that the longer path is obtained by multiplying the derivatives connected to the segments. VVRNZDxRQm07dkk7SU5rQ0NnUj1JQls/VFJbRGhDZUd1cj1LRks/VU5rQ2NnVEVpQl1HdFJdRGhDaVd1c0FbRkxDZU5tQ0NnVk1JQ19PVFNfVGhDZWd1dEVrRk1HdU5tQ2NnWFVpQ2FTRHFhSWhhY1h1VUJ5dkdHR1dtcnR3VltHU2FtR3RhQnhlZUNhdU1LR09BVT1HdVZrVD5pRGVrcnRVZFQ9aUR1V0I9Q1BPVV1NVU9XVmZtVGVpSExDVGRFU1ZVV1I9Q0xRRWtRR0FfU3JlVWR3dFVpRGg9Y2VzaU47WEpHRkhvQ0M/ZlpdQ0FTVlNFdGJtclREb1o9UGdxdm9NTEBJcUVFdl09WXZdc2xMSnNETkh4V1RkT1Zka3NwbjtNV29QTldwdWtwd2l1dHNoVWFVcFhxc3dZcFV5dXBUVUBVeFNkTT1YeXlwdXRRSzpZdkVEUTxNWERgcmZcXGpmbFhtaVFdTHFqWExZQHRxcVQ9YFVzPUtCZXBTeHNzYFVodVBVVVRVWVFFYUpaQXhkXXlKcXJhUW5GZFZtSU54bHRvWXJRRVFdbVlFeFViTG1NTVlEUXVKUVJQTGpWPXRgQVhITXdRXFxKS1R4dUFMQmlPTEVXW1xcamZlT2NQU0pNUlBWYko+ckpOZT1Ba0xwclBvbGtgWnNGWk4+cGpAXmdgW2JPXTx4cnNwZ1VvXUFJcEZZaWpZZlpGdDtWZUZecl9Gb1lpXWdQZk1OeURHXkhAbmBxckVuY1xccWhmWGBiRl1V/*____________________________________________________________________________ Copyright (C) 2002 PGP Corporation All rights reserved. $Id: bnprint.c,v 1.3 2002/08/06 20:10:57 dallen Exp $ ____________________________________________________________________________*/ /* * bnprint.c - Print a bignum, for debugging purposes. * * Written by Colin Plumb. * */ #include "pgpConfig.h" #include "pgpMem.h" /* * Some compilers complain about #if FOO if FOO isn't defined, * so do the ANSI-mandated thing explicitly... */ #ifndef NO_STRING_H #define NO_STRING_H 0 #endif #ifndef HAVE_STRINGS_H #define HAVE_STRINGS_H 0 #endif #include #if !NO_STRING_H #include #elif HAVE_STRINGS_H #include #endif #include "bn.h" #include "bnprint.h" #include "bnkludge.h" int bnPrint(FILE *f, char const *prefix, BigNum const *bn, char const *suffix) { unsigned char temp[32]; /* How much to print on one line */ unsigned len; size_t i; if (prefix && fputs(prefix, f) < 0) return EOF; len = (bnBits(bn) + 7)/ 8; if (!len) { if (putc('0', f) < 0) return EOF; } else { while (len > sizeof(temp)) { len -= sizeof(temp); bnExtractBigBytes(bn, temp, len, sizeof(temp)); for (i = 0; i < sizeof(temp); i++) if (fprintf(f, "%02X", temp[i]) < 0) return EOF; if (putc('\\', f) < 0 || putc('\n', f) < 0) return EOF; if (prefix) { i = strlen(prefix); while (i--) if (putc(' ', f) < 0) return EOF; } } bnExtractBigBytes(bn, temp, 0, len); for (i = 0; i < len; i++) if (fprintf(f, "%02X", temp[i]) < 0) return EOF; } return suffix ? fputs(suffix, f) : 0; } int bnPrint10(FILE *f, char const *prefix, BigNum const *bn, char const *suffix) { BigNum pbig, pbig1; BigNum ten, zero, rem; char buf[3000]; /* up to 9000 bits */ int bufi = sizeof(buf)-1; int n; buf[bufi] = '\0'; bnBegin (&pbig, bn->mgr, bn->isSecure ); bnBegin (&pbig1, bn->mgr, bn->isSecure ); bnBegin (&rem, bn->mgr, bn->isSecure ); bnBegin (&ten, bn->mgr, bn->isSecure ); bnAddQ (&ten, 10); bnBegin (&zero, bn->mgr, bn->isSecure ); bnCopy (&pbig, bn); while (bnCmp (&pbig, &zero) != 0) { bnDivMod (&pbig1, &rem, &pbig, &ten); bnCopy (&pbig, &pbig1); n = bnLSWord (&rem); buf[--bufi] = n + '0'; } bnEnd (&pbig); bnEnd (&pbig1); bnEnd (&rem); if (prefix && fputs(prefix, f) < 0) return EOF; fputs (buf+bufi, f); pgpClearMemory (buf, sizeof(buf)); return suffix ? fputs(suffix, f) : 0; } c2R3V2JqUVRAT2Y9bVlXU2I8QXJsP0hXR2JnT2Ruc1h2S1h2YVVFa2hVb1VKS3ZUS0NvTUZlV0ZzbUVmTUNIdVlcXEVjbENTVVNmZkNZXkVzUm10QnF5amd1S2NFdnF2YndHWFlYQ3NHQklJbW13YT9FeVNmdVtzeXVjb2tWW0l3cmNWWlVUdEtHVVlCUk1TTVNSUk1DP19zW11kRVNHOmlzO3FEV0tmYl1XbGdDYWF1aj9HWUNVbz9JY09UZFVUQHdEdFNVU1liUHljSUVVanNHc19WcjtFPGFUZ1FzP3N1WWlXYHhzYExNc2VWc3FUbDxyPUxPXkVVaz1XO2hKXmByTml5SnBuO3FvS0hMTz1Wb2lMVURWOkBMa1xcdXlUbGBZS01lVWtFbmh0S0A9V3NwUkVdcEBtTj1dbk5JWXJYeHRcXFFbSFB5aHBhZVNIbU8/cG9GUFRYSWxGdVNmWXlhWXFCRVNrRG1HZVA6RG5kbVA8cWw+V1tpQG9ecXFtVnN0d209d2BMPl9ISW1idnlOb2haT2puUGNASG5gYXk7RlpHZmxkYHddd2VuQEBLUlNLRVJVU1RnYmlZRGFRWT9taD5lRW9LQ1lzd2ZfR3A7QmVDU1FhYkRJdztvR1xcd0luO1ZSV3hHW3ZGaUhpYXlsQXVVT0NdU1dJZWNbPUleZ3d0ZXZYZXdKZUZWPXNVS3hmPXg6ZUJHX3ZEQUJUY3luUWJvW0NDY1Joa2hGVVJLU1RWQXJYPUllR3ZCc1lKU0VcXEtCWnlDclxcXVBmW0FeajxbXmtBRmJYR3hqXmpQV15KRmBAUWZbeFp1aHFpeVxcSkBiUmBzYEFgYGhjVUZhVHBzbEdmRE9gV29ac15zRm9mbWBdYD5nZT9cXEhRZms/eUxudHY/W1pYYWJZZGNfbT55dltebkxHZ05PcV9vYFd4Y2JgZGQ/ZHRWXFx2SGBRR295eHJvXnBfcGhtcFplP2VUZ3NgYXBUdmg6X1pxZm9Kd2Z1RmlJWV1JWGFlcV9xWWF4eGBnV2hReXdRV3FfcXh3eWk6UWJkR3B0YGhzWWdkXm1IP2hsXnZeX3Y8b3NCSWZEYGJcXGhsZldoRl5yW1ZgT1dsWHFoTXdiOkF3bk9ld25eUWBiYWF0XUdvUmF3W1BfQWlmS0lkQFhhc25meHdhdm5qZnFyb15tbnh3R3dxWkFocl9lcmZjY2hxZk52bEdpVm9xYXdgV3hzPEh4c2hdSHZuUWdvUWF3cEdmcGZfUVlnd3h1akFpakddXnBebUZvVkl1cmlxWHdxYW9wWk5jcnlfeGdlRldqdVZxaGF5eHdpVld5ZWBtXmhfREZjXT9dZVhqQ1Z1ZlZqZD5wdU5jXUdiPGBcXFZmeTxBXFxGYF5MSVs8P1xcTnBkUGhuZG9aRmBrWz9bTD9cXFpQZkpOZlteX0BQeEBWbk1GbEVfY1hvbF9gd2RmXjxHaEZoZlNGb0dhaU5OamVeblpgcGtWa0pfdXBXcm92WnVubllRcEZfbmNXXkNRXFxE/* * $Id: bnprint.h,v 1.1.1.1 1999/08/08 19:38:15 heller Exp $ */ #ifndef Included_bnprint_h #define Included_bnprint_h #include "pgpBase.h" PGP_BEGIN_C_DECLARATIONS #include #include "pgpOpaqueStructs.h" /* Print in base 16 */ int bnPrint(FILE *f, char const *prefix, BigNum const *bn, char const *suffix); /* Print in base 10 */ int bnPrint10(FILE *f, char const *prefix, BigNum const *bn, char const *suffix); PGP_END_C_DECLARATIONS #endif /* Included_bnprint_h */ WFU/bWpfQU1jaWo7dUtASFE8UU0+TXBDTHVGWUxKcHRwZFNWUXRDaWs+dVJjUE5RSG5FbVY9QFFQWXBsXFxORERSVHVvdUxrUGxLPUFMXkhQQ1xcdVNMc1NdU25EU3RNeF91bmNkWFl4dmNZVnhlVGVdWFBUdD1FVG9Fc2BsTnJlTkd0c09xdG9dUlh5T3NocFd1SlxcUVJTYXZKcHNScXhHZG49RFVMaVFlcHdSWW1maHNqWFVxZVNLYU9KdXBXdXZqaFVQaVFlcVlCSXBPVHF5QXZpPVFLQFlbQXFFWEpAZHVybG1wbFRWSUxYWXFMZG9rXVZOQU1qaFBoeHNUUG5rUXd2cVNaeEt0QWp3dG9saVRpaU9HPXRBaXRxcXZ0cXJIPEo8PE89WG1aYFc6cUs+PGptRHFfZXdPbXNaXFxybnV4XVVvSHhQPD13ZXF5VXFSZ1VxaGV0d1VsQElxaEl4RVxcWXlocjtoVmJ0bV1gcGY/WjxfeXZ4ZGpoXnFGd3ZXW2BZZVlfeHd3b2VAYl1Xc3Bhc25QZll5W1Z5cWpmdXdXaUVpaWVOd2VQWnNXbldXaWlpeXlZd3B5YkdRdGw/XmA/d0l5cWJhW3hvXVtfX2heXkduc2JYWnVJWlphaktOakpvY0RGYlJnXz8+dj5JXT1AZGd3X0pAXFw6PlpHRlo6cjo7QjpASjpwYzpGWjs+Wj06O1JZO1o8cjpyOl5baEdaPXI6O0o6QEo6UFo6RlpAPlo9OjtiOjtqOkBbPkI6REo6XltuR1pPcjo7Wjs+Wj1qOlRbPj46Plo6Plo/R1pRQjtiOkJZPWJAO1I7Plo7SkBMcjpoSzpQSjo6bHI6bFs9SjpSOjxqOlxcXFw9OjtiOj5aOlpCPlpCPjo8SjpKPkA6SVJ4O2o7ZFY6ZEp4PVI6dl5KPlpEXlk6NDpcIlx7XH0=
<Text-field style="Heading 2" layout="Heading 2">Using 3-space to visualize composition of functions</Text-field> Next we want to visualize composition of functions. Note that the green and blue curves are the graphs of f and g respectively, using x, v, and y as described above, with the extra variable held constant. The red curve plots h. g := x -> x^2: f := v -> sin(v): h := x -> f(g(x)): x0 := 2; v0 := g(x0): y0 := f(g(x0)): IiIj del := 2: plotg := [x,g(x), y0, x=(x0-del)..(x0+del), color=blue]: plotf := [x0, v, f(v), v=(v0-del)..(v0+del), color=green]: ploth := [x, g(x), f(g(x)), x=(x0-del)..(x0+del), color=red]: spacecurve({plotg, plotf, ploth}, thickness=3, axes=boxed, labels=["x", "v", "y"]); NiktJStBWEVTTEFCRUxTRzYlUSJ4NiJRInY2IlEieTYiLSUqQVhFU1NU/*____________________________________________________________________________ Copyright (C) 2002 PGP Corporation All rights reserved. $Id: bnprime.c,v 1.5 2003/11/12 20:45:51 ajivsov Exp $ ____________________________________________________________________________*/ /* * bnprime.c - Prime generation using the bignum library and sieving. * * Written by Colin Plumb * */ #include "pgpConfig.h" #include /* We just can't live without this... */ #ifndef BNDEBUG #define BNDEBUG 0 #endif #if BNDEBUG #include #endif #include "bn.h" #include "bnimem.h" #include "bnprime.h" #include "bnsieve.h" #include "bnkludge.h" #include "pgpDebug.h" /* Size of the shuffle table */ #define SHUFFLE 256 /* Size of the sieve area */ #define SIEVE 32768u/16 /* Confirmation tests. The first one *must* be 2 */ static unsigned const confirm[] = {2, 3, 5, 7, 11, 13, 17}; #define CONFIRMTESTS (sizeof(confirm)/sizeof(*confirm)) /* * Helper function that does the slow primality test. * bn is the input bignum; a and e are temporary buffers that are * allocated by the caller to save overhead. * * Returns 0 if prime, >0 if not prime, and -1 on error (out of memory). * If not prime, returns the number of modular exponentiations performed. * Calls the given progress function with a '*' for each primality test * that is passed. * * The testing consists of strong pseudoprimality tests, to the bases given * in the confirm[] array above. (Also called Miller-Rabin, although that's * not technically correct if we're using fixed bases.) Some people worry * that this might not be enough. Number theorists may wish to generate * primality proofs, but for random inputs, this returns non-primes with * a probability which is quite negligible, which is good enough. * * It has been proved (see Carl Pomerance, "On the Distribution of * Pseudoprimes", Math. Comp. v.37 (1981) pp. 587-593) that the number of * pseudoprimes (composite numbers that pass a Fermat test to the base 2) * less than x is bounded by: * exp(ln(x)^(5/14)) <= P_2(x) ### CHECK THIS FORMULA - it looks wrong! ### * P_2(x) <= x * exp(-1/2 * ln(x) * ln(ln(ln(x))) / ln(ln(x))). * Thus, the local density of Pseudoprimes near x is at most * exp(-1/2 * ln(x) * ln(ln(ln(x))) / ln(ln(x))), and at least * exp(ln(x)^(5/14) - ln(x)). Here are some values of this function * for various k-bit numbers x = 2^k: * Bits Density <= Bit equivalent Density >= Bit equivalent * 128 3.577869e-07 21.414396 4.202213e-37 120.840190 * 192 4.175629e-10 31.157288 4.936250e-56 183.724558 * 256 5.804314e-13 40.647940 4.977813e-75 246.829095 * 384 1.578039e-18 59.136573 3.938861e-113 373.400096 * 512 5.858255e-24 77.175803 2.563353e-151 500.253110 * 768 1.489276e-34 112.370944 7.872825e-228 754.422724 * 1024 6.633188e-45 146.757062 1.882404e-304 1008.953565 * * As you can see, there's quite a bit of slop between these estimates. * In fact, the density of pseudoprimes is conjectured to be closer to the * square of that upper bound. E.g. the density of pseudoprimes of size * 256 is around 3 * 10^-27. The density of primes is very high, from * 0.005636 at 256 bits to 0.001409 at 1024 bits, i.e. more than 10^-3. * * For those people used to cryptographic levels of security where the * 56 bits of DES key space is too small because it's exhaustible with * custom hardware searching engines, note that you are not generating * 50,000,000 primes per second on each of 56,000 custom hardware chips * for several hours. The chances that another Dinosaur Killer asteroid * will land today is about 10^-11 or 2^-36, so it would be better to * spend your time worrying about *that*. Well, okay, there should be * some derating for the chance that astronomers haven't seen it yet, * but I think you get the idea. For a good feel about the probability * of various events, I have heard that a good book is by E'mile Borel, * "Les Probabilite's et la vie". (The 's are accents, not apostrophes.) * * For more on the subject, try "Finding Four Million Large Random Primes", * by Ronald Rivest, in Advancess in Cryptology: Proceedings of Crypto * '90. He used a small-divisor test, then a Fermat test to the base 2, * and then 8 iterations of a Miller-Rabin test. About 718 million random * 256-bit integers were generated, 43,741,404 passed the small divisor * test, 4,058,000 passed the Fermat test, and all 4,058,000 passed all * 8 iterations of the Miller-Rabin test, proving their primality beyond * most reasonable doubts. * * If the probability of getting a pseudoprime is some small p, then the * probability of not getting it in t trials is (1-p)^t. Remember that, * for small p, (1-p)^(1/p) ~ 1/e, the base of natural logarithms. * (This is more commonly expressed as e = lim_{x\to\infty} (1+1/x)^x.) * Thus, (1-p)^t ~ e^(-p*t) = exp(-p*t). So the odds of being able to * do this many tests without seeing a pseudoprime if you assume that * p = 10^-6 (one in a million) is one in 57.86. If you assume that * p = 2*10^-6, it's one in 3347.6. So it's implausible that the density * of pseudoprimes is much more than one millionth the density of primes. * * He also gives a theoretical argument that the chance of finding a * 256-bit non-prime which satisfies one Fermat test to the base 2 is * less than 10^-22. The small divisor test improves this number, and * if the numbers are 512 bits (as needed for a 1024-bit key) the odds * of failure shrink to about 10^-44. Thus, he concludes, for practical * purposes *one* Fermat test to the base 2 is sufficient. */ static int primeTest(BigNum const *bn, BigNum *e, BigNum *a, int (*f)(void *arg, int c), void *arg) { unsigned i, j; unsigned k, l; int err; #if BNDEBUG /* Debugging */ /* * This is debugging code to test the sieving stage. * If the sieving is wrong, it will let past numbers with * small divisors. The prime test here will still work, and * weed them out, but you'll be doing a lot more slow tests, * and presumably excluding from consideration some other numbers * which might be prime. This check just verifies that none * of the candidates have any small divisors. If this * code is enabled and never triggers, you can feel quite * confident that the sieving is doing its job. */ i = bnLSWord(bn); if (!(i % 2)) printf("bn div by 2!"); i = bnModQ(bn, 51051); /* 51051 = 3 * 7 * 11 * 13 * 17 */ if (!(i % 3)) printf("bn div by 3!"); if (!(i % 7)) printf("bn div by 7!"); if (!(i % 11)) printf("bn div by 11!"); if (!(i % 13)) printf("bn div by 13!"); if (!(i % 17)) printf("bn div by 17!"); i = bnModQ(bn, 63365); /* 63365 = 5 * 19 * 23 * 29 */ if (!(i % 5)) printf("bn div by 5!"); if (!(i % 19)) printf("bn div by 19!"); if (!(i % 23)) printf("bn div by 23!"); if (!(i % 29)) printf("bn div by 29!"); i = bnModQ(bn, 47027); /* 47027 = 31 * 37 * 41 */ if (!(i % 31)) printf("bn div by 31!"); if (!(i % 37)) printf("bn div by 37!"); if (!(i % 41)) printf("bn div by 41!"); #endif /* * Now, check that bn is prime. If it passes to the base 2, * it's prime beyond all reasonable doubt, and everything else * is just gravy, but it gives people warm fuzzies to do it. * * This starts with verifying Euler's criterion for a base of 2. * This is the fastest pseudoprimality test that I know of, * saving a modular squaring over a Fermat test, as well as * being stronger. 7/8 of the time, it's as strong as a strong * pseudoprimality test, too. (The exception being when bn == * 1 mod 8 and 2 is a quartic residue, i.e. bn is of the form * a^2 + (8*b)^2.) The precise series of tricks used here is * not documented anywhere, so here's an explanation. * Euler's criterion states that if p is prime then a^((p-1)/2) * is congruent to Jacobi(a,p), modulo p. Jacobi(a,p) is * a function which is +1 if a is a square modulo p, and -1 if * it is not. For a = 2, this is particularly simple. It's * +1 if p == +/-1 (mod 8), and -1 if m == +/-3 (mod 8). * If p == 3 mod 4, then all a strong test does is compute * 2^((p-1)/2). and see if it's +1 or -1. (Euler's criterion * says *which* it should be.) If p == 5 (mod 8), then * 2^((p-1)/2) is -1, so the initial step in a strong test, * looking at 2^((p-1)/4), is wasted - you're not going to * find a +/-1 before then if it *is* prime, and it shouldn't * have either of those values if it isn't. So don't bother. * * The remaining case is p == 1 (mod 8). In this case, we * expect 2^((p-1)/2) == 1 (mod p), so we expect that the * square root of this, 2^((p-1)/4), will be +/-1 (mod p). * Evaluating this saves us a modular squaring 1/4 of the time. * If it's -1, a strong pseudoprimality test would call p * prime as well. Only if the result is +1, indicating that * 2 is not only a quadratic residue, but a quartic one as well, * does a strong pseudoprimality test verify more things than * this test does. Good enough. * * We could back that down another step, looking at 2^((p-1)/8) * if there was a cheap way to determine if 2 were expected to * be a quartic residue or not. Dirichlet proved that 2 is * a quartic residue iff p is of the form a^2 + (8*b^2). * All primes == 1 (mod 4) can be expressed as a^2 + (2*b)^2, * but I see no cheap way to evaluate this condition. */ if (bnCopy(e, bn) < 0) return -1; (void)bnSubQ(e, 1); l = bnLSWord(e); j = 1; /* Where to start in prime array for strong prime tests */ if (l & 7) { bnRShift(e, 1); if (bnTwoExpMod(a, e, bn) < 0) return -1; if ((l & 7) == 6) { /* bn == 7 mod 8, expect +1 */ if (bnBits(a) != 1) return 1; /* Not prime */ k = 1; } else { /* bn == 3 or 5 mod 8, expect -1 == bn-1 */ if (bnAddQ(a, 1) < 0) return -1; if (bnCmp(a, bn) != 0) return 1; /* Not prime */ k = 1; if (l & 4) { /* bn == 5 mod 8, make odd for strong tests */ bnRShift(e, 1); k = 2; } } } else { /* bn == 1 mod 8, expect 2^((bn-1)/4) == +/-1 mod bn */ bnRShift(e, 2); if (bnTwoExpMod(a, e, bn) < 0) return -1; if (bnBits(a) == 1) { j = 0; /* Re-do strong prime test to base 2 */ } else { if (bnAddQ(a, 1) < 0) return -1; if (bnCmp(a, bn) != 0) return 1; /* Not prime */ } k = 2 + bnMakeOdd(e); } /* It's prime! Now go on to confirmation tests */ /* * Now, e = (bn-1)/2^k is odd. k >= 1, and has a given value * with probability 2^-k, so its expected value is 2. * j = 1 in the usual case when the previous test was as good as * a strong prime test, but 1/8 of the time, j = 0 because * the strong prime test to the base 2 needs to be re-done. */ for (i = j; i < CONFIRMTESTS; i++) { if (f && (err = f(arg, '*')) < 0) return err; (void)bnSetQ(a, confirm[i]); if (bnExpMod(a, a, e, bn) < 0) return -1; if (bnBits(a) == 1) continue; /* Passed this test */ l = k; for (;;) { if (bnAddQ(a, 1) < 0) return -1; if (bnCmp(a, bn) == 0) /* Was result bn-1? */ break; /* Prime */ if (!--l) /* Reached end, not -1? luck? */ return i+2-j; /* Failed, not prime */ /* This portion is executed, on average, once. */ (void)bnSubQ(a, 1); /* Put a back where it was. */ if (bnSquare(a, a) < 0 || bnMod(a, a, bn) < 0) return -1; if (bnBits(a) == 1) return i+2-j; /* Failed, not prime */ } /* It worked (to the base confirm[i]) */ } /* Yes, we've decided that it's prime. */ if (f && (err = f(arg, '*')) < 0) return err; return 0; /* Prime! */ } /* * Add x*y to bn, which is usually (but not always) < 65536. * Do it in a simple linear manner. */ static int bnAddMult(BigNum *bn, unsigned x, unsigned y) { unsigned long z = (unsigned long)x * y; while (z > 65535) { if (bnAddQ(bn, 65535) < 0) return -1; z -= 65535; } return bnAddQ(bn, (unsigned)z); } static int bnSubMult(BigNum *bn, unsigned x, unsigned y) { unsigned long z = (unsigned long)x * y; while (z > 65535) { if (bnSubQ(bn, 65535) < 0) return -1; z -= 65535; } return bnSubQ(bn, (unsigned)z); } /* * Modifies the bignum to return a nearby (slightly larger) number which * is a probable prime. Returns >=0 on success or -1 on failure (out of * memory). The return value is the number of unsuccessful modular * exponentiations performed. This never gives up searching. * * All other arguments are optional. They may be NULL. They are: * * unsigned (*randfunc)(unsigned limit) * For better distributed numbers, supply a non-null pointer to a * function which returns a random x, 0 <= x < limit. (It may make it * simpler to know that 0 < limit <= SHUFFLE, so you need at most a byte.) * The program generates a large window of sieve data and then does * pseudoprimality tests on the data. If a randfunc function is supplied, * the candidates which survive sieving are shuffled with a window of * size SHUFFLE before testing to increase the uniformity of the prime * selection. This isn't perfect, but it reduces the correlation between * the size of the prime-free gap before a prime and the probability * that that prime will be found by a sequential search. * * If randfunc is NULL, sequential search is used. If you want sequential * search, note that the search begins with the given number; if you're * trying to generate consecutive primes, you must increment the previous * one by two before calling this again. * * int (*f)(void *f_arg, int c), void *f_arg * The function f argument, if non-NULL, is called with progress indicator * characters for printing. A dot (.) is written every time a primality test * is failed, a star (*) every time one is passed, and a slash (/) in the * (very rare) case that the sieve was emptied without finding a prime * and is being refilled. f is also passed the void *f_arg argument for * private context storage. If f returns < 0, the test aborts and returns * that value immediately. (bn is set to the last value tested, so you * can increment bn and continue.) * * The "exponent" argument, and following unsigned numbers, are exponents * for which an inverse is desired, modulo p. For a d to exist such that * (x^e)^d == x (mod p), then d*e == 1 (mod p-1), so gcd(e,p-1) must be 1. * The prime returned is constrained to not be congruent to 1 modulo * any of the zero-terminated list of 16-bit numbers. Note that this list * should contain all the small prime factors of e. (You'll have to test * for large prime factors of e elsewhere, but the chances of needing to * generate another prime are low.) * * The list is terminated by a 0, and may be empty. */ int bnPrimeGen(BigNum *bn, unsigned (*randfunc)(void *randfunc_arg, unsigned limit), void *randfunc_arg, int (*f)(void *f_arg, int c), void *f_arg, unsigned exponent, ...) { int retval; int modexps = 0; unsigned short offsets[SHUFFLE]; unsigned i, j; unsigned p, q, prev; BigNum a, e; #ifdef MSDOS unsigned char *sieve; #else unsigned char sieve[SIEVE]; #endif #ifdef MSDOS sieve = bniMemAlloc(SIEVE); if (!sieve) return -1; #endif PGPBoolean isSecure = TRUE; bnBegin(&a, bn->mgr, isSecure); bnBegin(&e, bn->mgr, isSecure); #if 0 /* Self-test (not used for production) */ { BigNum t; static unsigned char const prime1[] = {5}; static unsigned char const prime2[] = {7}; static unsigned char const prime3[] = {11}; static unsigned char const prime4[] = {1, 1}; /* 257 */ static unsigned char const prime5[] = {0xFF, 0xF1}; /* 65521 */ static unsigned char const prime6[] = {1, 0, 1}; /* 65537 */ static unsigned char const prime7[] = {1, 0, 3}; /* 65539 */ /* A small prime: 1234567891 */ static unsigned char const prime8[] = {0x49, 0x96, 0x02, 0xD3}; /* A slightly larger prime: 12345678901234567891 */ static unsigned char const prime9[] = { 0xAB, 0x54, 0xA9, 0x8C, 0xEB, 0x1F, 0x0A, 0xD3 }; /* * No, 123456789012345678901234567891 isn't prime; it's just a * lucky, easy-to-remember conicidence. (You have to go to * ...4567907 for a prime.) */ static struct { unsigned char const *prime; unsigned size; } const primelist[] = { { prime1, sizeof(prime1) }, { prime2, sizeof(prime2) }, { prime3, sizeof(prime3) }, { prime4, sizeof(prime4) }, { prime5, sizeof(prime5) }, { prime6, sizeof(prime6) }, { prime7, sizeof(prime7) }, { prime8, sizeof(prime8) }, { prime9, sizeof(prime9) } }; bnBegin(&t); for (i = 0; i < sizeof(primelist)/sizeof(primelist[0]); i++) { bnInsertBytes(&t, primelist[i].prime, 0, primelist[i].size); bnCopy(&e, &t); (void)bnSubQ(&e, 1); bnTwoExpMod(&a, &e, &t); p = bnBits(&a); if (p != 1) { printf( "Bug: Fermat(2) %u-bit output (1 expected)\n", p); fputs("Prime = 0x", stdout); for (j = 0; j < primelist[i].size; j++) printf("%02X", primelist[i].prime[j]); putchar('\n'); } bnSetQ(&a, 3); bnExpMod(&a, &a, &e, &t); p = bnBits(&a); if (p != 1) { printf( "Bug: Fermat(3) %u-bit output (1 expected)\n", p); fputs("Prime = 0x", stdout); for (j = 0; j < primelist[i].size; j++) printf("%02X", primelist[i].prime[j]); putchar('\n'); } } bnEnd(&t); } #endif /* First, make sure that bn is odd. */ if ((bnLSWord(bn) & 1) == 0) (void)bnAddQ(bn, 1); retry: /* Then build a sieve starting at bn. */ sieveBuild(sieve, SIEVE, bn, 2, 0); /* Do the extra exponent sieving */ if (exponent) { va_list ap; unsigned t = exponent; va_start(ap, exponent); do { /* The exponent had better be odd! */ pgpAssert(t & 1); i = bnModQ(bn, t); /* Find 1-i */ if (i == 0) i = 1; else if (--i) i = t - i; /* Divide by 2, modulo the exponent */ i = (i & 1) ? i/2 + t/2 + 1 : i/2; /* Remove all following multiples from the sieve. */ sieveSingle(sieve, SIEVE, i, t); /* Get the next exponent value */ t = va_arg(ap, unsigned); } while (t); va_end(ap); } /* Fill up the offsets array with the first SHUFFLE candidates */ i = p = 0; /* Get first prime */ if (sieve[0] & 1 || (p = sieveSearch(sieve, SIEVE, p)) != 0) { offsets[i++] = p; p = sieveSearch(sieve, SIEVE, p); } /* * Okay, from this point onwards, p is always the next entry * from the sieve, that has not been added to the shuffle table, * and is 0 iff the sieve has been exhausted. * * If we want to shuffle, then fill the shuffle table until the * sieve is exhausted or the table is full. */ if (randfunc && p) { do { offsets[i++] = p; p = sieveSearch(sieve, SIEVE, p); } while (p && i < SHUFFLE); } /* Choose a random candidate for experimentation */ prev = 0; while (i) { /* Pick a random entry from the shuffle table */ j = randfunc ? randfunc(randfunc_arg, i) : 0; q = offsets[j]; /* The entry to use */ /* Replace the entry with some more data, if possible */ if (p) { offsets[j] = p; p = sieveSearch(sieve, SIEVE, p); } else { offsets[j] = offsets[--i]; offsets[i] = 0; } /* Adjust bn to have the right value */ if ((q > prev ? bnAddMult(bn, q-prev, 2) : bnSubMult(bn, prev-q, 2)) < 0) goto failed; prev = q; /* Now do the Fermat tests */ retval = primeTest(bn, &e, &a, f, f_arg); if (retval <= 0) goto done; /* Success or error */ modexps += retval; if (f && (retval = f(f_arg, '.')) < 0) goto done; } /* Ran out of sieve space - increase bn and keep trying. */ if (bnAddMult(bn, SIEVE*8-prev, 2) < 0) goto failed; if (f && (retval = f(f_arg, '/')) < 0) goto done; goto retry; failed: retval = -1; done: bnEnd(&e); bnEnd(&a); bniMemWipe(offsets, sizeof(offsets)); #ifdef MSDOS bniMemFree(sieve, SIEVE); #else bniMemWipe(sieve, sizeof(sieve)); #endif return retval < 0 ? retval : modexps + CONFIRMTESTS; } /* * Similar, but searches forward from the given starting value in steps of * "step" rather than 1. The step size must be even, and bn must be odd. * Among other possibilities, this can be used to generate "strong" * primes, where p-1 has a large prime factor. */ int bnPrimeGenStrong(BigNum *bn, BigNum const *step, int (*f)(void *arg, int c), void *arg) { int retval; unsigned p, prev; BigNum a, e; int modexps = 0; #ifdef MSDOS unsigned char *sieve; #else unsigned char sieve[SIEVE]; #endif PGPBoolean isSecure = bn->isSecure; #ifdef MSDOS sieve = bniMemAlloc(SIEVE); if (!sieve) return -1; #endif /* Step must be even and bn must be odd */ pgpAssert((bnLSWord(step) & 1) == 0); pgpAssert((bnLSWord(bn) & 1) == 1); bnBegin(&a, bn->mgr, isSecure); bnBegin(&e, bn->mgr, isSecure); for (;;) { if (sieveBuildBig(sieve, SIEVE, bn, step, 0) < 0) goto failed; p = prev = 0; if (sieve[0] & 1 || (p = sieveSearch(sieve, SIEVE, p)) != 0) { do { /* * Adjust bn to have the right value, * adding (p-prev) * 2*step. */ pgpAssert(p >= prev); /* Compute delta into a */ if (bnMulQ(&a, step, p-prev) < 0) goto failed; if (bnAdd(bn, &a) < 0) goto failed; prev = p; retval = primeTest(bn, &e, &a, f, arg); if (retval <= 0) goto done; /* Success! */ modexps += retval; if (f && (retval = f(arg, '.')) < 0) goto done; /* And try again */ p = sieveSearch(sieve, SIEVE, p); } while (p); } /* Ran out of sieve space - increase bn and keep trying. */ #if SIEVE*8 == 65536 /* Corner case that will never actually happen */ if (!prev) { if (bnAdd(bn, step) < 0) goto failed; p = 65535; } else { p = (unsigned)(SIEVE*8 - prev); } #else p = SIEVE*8 - prev; #endif if (bnMulQ(&a, step, p) < 0 || bnAdd(bn, &a) < 0) goto failed; if (f && (retval = f(arg, '/')) < 0) goto done; } /* for (;;) */ failed: retval = -1; done: bnEnd(&e); bnEnd(&a); #ifdef MSDOS bniMemFree(sieve, SIEVE); #else bniMemWipe(sieve, sizeof(sieve)); #endif return retval < 0 ? retval : modexps + CONFIRMTESTS; } iQiK04wak9hISIqJCErYFwtb3YhIzU3JSQiK0UpZTxOIyEiKiQiK3cmcDJgJiEiKiQhK2BcLW92ISM1NyUkIitIJGY9UCMhIiokIit4bXJEYyEiKiQhK2BcLW92ISM1NyUkIitLKWY+UiMhIiokIitRPVpAZCEiKiQhK2BcLW92ISM1NyUkIitOLjE3QyEiKiQiK2ddLj1lISIqJCErYFwtb3YhIzU3JSQiK1EzO0tDISIqJCIrVWpTOmYhIiokIStgXC1vdiEjNTclJCIrVDhFX0MhIiokIismbyZlOGchIiokIStgXC1vdiEjNTclJCIrVz1Pc0MhIiokIispM3RENichIiokIStgXC1vdiEjNTclJCIrWkJZI1wjISIqJCIrXiZvQkAnISIqJCErYFwtb3YhIzU3JSQiK11HYzdEISIqJCIrdj8oSEonISIqJCErYFwtb3YhIzU3JSQiK2BMbUtEISIqJCIrZ09ROWshIiokIStgXC1vdiEjNTclJCIrY1F3X0QhIiokIisvTGc7bCEiKiQhK2BcLW92ISM1NyUkIitmVidHZCMhIiokIis1NWo+bSEiKiQhK2BcLW92ISM1NyUkIitpWydIZiMhIiokIit3bllCbiEiKiQhK2BcLW92ISM1NyUkIitsYDE4RSEiKiQiKy0xNkdvISIqJCErYFwtb3YhIzU3JSQiK29lO0xFISIqJCIrKVtpTiRwISIqJCErYFwtb3YhIzU3JSQiK3JqRWBFISIqJCIrTkMjKVJxISIqJCErYFwtb3YhIzU3JSQiK3VvT3RFISIqJCIrVi8qbzkoISIqJCErYFwtb3YhIzU3JSQiK3h0WSRwIyEiKiQiKzZsd2FzISIqJCErYFwtb3YhIzU3JSQiKyEpeWM4RiEiKiQiK1IxWGp0ISIqJCErYFwtb3YhIzU3JSQiKyRRb090IyEiKiQiK0dHJUhaKCEiKiQhK2BcLW92ISM1NyUkIisnKSlvUHYjISIqJCIreUlDJGUoISIqJCErYFwtb3YhIzU3JSQiKypRcFF4IyEiKiQiKyhRXlZwKCEiKiQhK2BcLW92ISM1NyUkIisjKilwUnojISIqJCIrZHhFMXkhIiokIStgXC1vdiEjNTclJCIrJlJxUyJHISIqJCIrKT0jKio9eiEiKiQhK2BcLW92ISM1NyUkIispKjM8TUchIiokIit6WV9LISkhIiokIStgXC1vdiEjNTclJCIrLDlGYUchIiokIitKXydvOSkhIiokIStgXC1vdiEjNTclJCIrLz5QdUchIiokIitWUSxpIykhIiokIStgXC1vdiEjNTclJCIrMkNaJSpHISIqJCIrOjAoelApISIqJCErYFwtb3YhIzU3JSQiKzVIZDlIISIqJCIrW190JVwpISIqJCErYFwtb3YhIzU3JSQiKzhNbk1IISIqJCIrVCEzQmgpISIqJCErYFwtb3YhIzU3JSQiKztSeGFIISIqJCIrJiopKW9JKCkhIiokIStgXC1vdiEjNTclJCIrPlcoWyhIISIqJCIrNHkoKVwpKSEiKiQhK2BcLW92ISM1NyUkIitBXChcKkghIiokIiskeXUpcCopISIqJCErYFwtb3YhIzU3JSQiK0RhMjpJISIqJCIrPSl6MTQqISIqJCErYFwtb3YhIzU3JSQiK0dmPE5JISIqJCIrOUhINyMqISIqJCErYFwtb3YhIzU3JSQiK0prRmJJISIqJCIrcVNyTSQqISIqJCErYFwtb3YhIzU3JSQiK01wUHZJISIqJCIrJ0dWelgqISIqJCErYFwtb3YhIzU3JSQiK1B1WiY0JCEiKiQiK2owKT5lKiEiKiQhK2BcLW92ISM1NyUkIitTemQ6SiEiKiQiKytmI29xKiEiKiQhK2BcLW92ISM1NyUkIitWJXljOCQhIiokIispSHpDJCkqISIqJCErYFwtb3YhIzU3JSQiK1kqeWQ6JCEiKiQiK2MyJSplKiohIiokIStgXC1vdiEjNTclJCIrXCV6ZTwkISIqJCIrRjVpMzUhIikkIStgXC1vdiEjNTclJCIrXyp6Zj4kISIqJCIrJnlHOS0iISIpJCErYFwtb3YhIzU3JSQiK2IvMztLISIqJCIrXHRKTTUhIikkIStgXC1vdiEjNTclJCIrZTQ9T0shIiokIis+bkdaNSEiKSQhK2BcLW92ISM1NyUkIitoOUdjSyEiKiQiKyYqb0xnNSEiKSQhK2BcLW92ISM1NyUkIitrPlF3SyEiKiQiK3h5WXQ1ISIpJCErYFwtb3YhIzU3JSQiK25DWydIJCEiKiQiK20nem0zIiEiKSQhK2BcLW92ISM1NyUkIitxSGU7TCEiKiQiK2dBKCoqNCIhIikkIStgXC1vdiEjNTclJCIrdE1vT0whIiokIitnY004NiEiKSQhK2BcLW92ISM1NyUkIit3UnljTCEiKiQiK20pKnpFNiEiKSQhK2BcLW92ISM1NyUkIit6VylvUCQhIiokIit5W0xTNiEiKSQhK2BcLW92ISM1NyUkIisjKVwpc/*____________________________________________________________________________ Copyright (C) 2002 PGP Corporation All rights reserved. $Id: bnsieve.c,v 1.3 2002/08/06 20:10:57 dallen Exp $ ____________________________________________________________________________*/ /* * bnsieve.c - Trial division for prime finding. * * Written by Colin Plumb * * Finding primes: * - Sieve 1 to find the small primes for * - Sieve 2 to find the candidate large primes, then * - Pseudo-primality test. * * An important question is how much trial division by small primes * should we do? The answer is a LOT. Even a heavily optimized * Fermat test to the base 2 (the simplest pseudoprimality test) * is much more expensive than a division. * * For an prime of n k-bit words, a Fermat test to the base 2 requires n*k * modular squarings, each of which involves n*(n+1)/2 signle-word multiplies * in the squaring and n*(n+1) multiplies in the modular reduction, plus * some overhead to get into and out of Montgomery form. This is a total * of 3/2 * k * n^2 * (n+1). Equivalently, if n*k = b bits, it's * 3/2 * (b/k+1) * b^2 / k. * * A modulo operation requires n single-word divides. Let's assume that * a divide is 4 times the cost of a multiply. That's 4*n multiplies. * However, you only have to do the division once for your entire * search. It can be amortized over 10-15 primes. So it's * really more like n/3 multiplies. This is b/3k. * * Now, let's suppose you have a candidate prime t. Your options * are to a) do trial division by a prime p, then do a Fermat test, * or to do the Fermat test directly. Doing the trial division * costs b/3k multiplies, but a certain fraction of the time (1/p), it * saves you 3/2 b^3 / k^2 multiplies. Thus, it's worth it doing the * division as long as b/3k < 3/2 * (b/k+1) * b^2 / k / p. * I.e. p < 9/2 * (b/k + 1) * b = 9/2 * (b^2/k + b). * E.g. for k=16 and b=256, p < 9/2 * 17 * 256 = 19584. * Solving for k=16 and k=32 at a few interesting value of b: * * k=16, b=256: p < 19584 k=32, b=256: p < 10368 * k=16, b=384: p < 43200 k=32, b=384; p < 22464 * k=16, b=512: p < 76032 k=32, b=512: p < 39168 * k=16, b=640: p < 118080 k=32, b=640: p < 60480 * * H'm... before using the highly-optimized Fermat test, I got much larger * numbers (64K to 256K), and designed the sieve for that. Maybe it needs * to be reduced. It *is* true that the desirable sieve size increases * rapidly with increasing prime size, and it's the larger primes that are * worrisome in any case. I'll leave it as is (64K) for now while I * think about it. * * A bit of tweaking the division (we can compute a reciprocal and do * multiplies instead, turning 4*n into 4 + 2*n) would increase all the * numbers by a factor of 2 or so. * * * Bit k in a sieve corresponds to the number a + k*b. * For a given a and b, the sieve's job is to find the values of * k for which a + k*b == 0 (mod p). Multiplying by b^-1 and * isolating k, you get k == -a*b^-1 (mod p). So the values of * k which should be worked on are k = (-a*b^-1 mod p) + i * p, * for i = 0, 1, 2,... * * Note how this is still easy to use with very large b, if you need it. * It just requires computing (b mod p) and then finding the multiplicative * inverse of that. * * * How large a space to search to ensure that one will hit a prime? * The average density is known, but the primes behave oddly, and sometimes * there are large gaps. It is conjectured by shanks that the first gap * of size "delta" will occur at approximately exp(sqrt(delta)), so a delta * of 65536 is conjectured to be to contain a prime up to e^256. * Remembering the handy 2<->e conversion ratios: * ln(2) = 0.693147 log2(e) = 1.442695 * This covers up to 369 bits. Damn, not enough! Still, it'll have to do. * * Cramer's conjecture (he proved it for "most" cases) is that in the limit, * as p goes to infinity, the largest gap after a prime p tends to (ln(p))^2. * So, for a 1024-bit p, the interval to the next prime is expected to be * about 709.78^2, or 503791. We'd need to enlarge our space by a factor of * 8 to be sure. It isn't worth the hassle. * * Note that a span of this size is expected to contain 92 primes even * in the vicinity of 2^1024 (it's 369 at 256 bits and 492 at 192 bits). * So the probability of failure is pretty low. */ #include "pgpConfig.h" #include "pgpMem.h" /* * Some compilers complain about #if FOO if FOO isn't defined, * so do the ANSI-mandated thing explicitly... */ #ifndef NO_ASSERT_H #define NO_ASSERT_H 0 #endif #ifndef NO_LIMITS_H #define NO_LIMITS_H 0 #endif #ifndef NO_STRING_H #define NO_STRING_H 0 #endif #ifndef HAVE_STRINGS_H #define HAVE_STRINGS_H 0 #endif #ifndef NEED_MEMORY_H #define NEED_MEMORY_H 0 #endif #if !NO_LIMITS_H #include /* For UINT_MAX */ #endif /* If not avail, default value of 0 is safe */ #if !NO_STRING_H #include /* for memset() */ #elif HAVE_STRINGS_H #include #endif #if NEED_MEMORY_H #include #endif #include "bn.h" #include "bnsieve.h" #ifdef MSDOS #include "bnimem.h" #endif #include "bnkludge.h" #include "pgpDebug.h" /* * Each array stores potential primes as 1 bits in little-endian bytes. * Bit k in an array represents a + k*b, for some parameters a and b * of the sieve. Currently, b is hardcoded to 2. * * Various factors of 16 arise because these are all *byte* sizes, and * skipping even numbers, 16 numbers fit into a byte's worth of bitmap. */ /* * The first number in the small prime sieve. This could be raised to * 3 if you want to squeeze bytes out aggressively for a smaller SMALL * table, and doing so would let one more prime into the end of the array, * but there is no sense making it larger if you're generating small * primes up to the limit if 2^16, since it doesn't save any memory and * would require extra code to ignore 65537 in the last byte, which is * over the 16-bit limit. */ #define SMALLSTART 1 /* * Size of sieve used to find large primes, in bytes. For compatibility * with 16-bit-int systems, the largest prime that can appear in it, * SMALL * 16 + SMALLSTART - 2, must be < 65536. Since 65537 is a prime, * this is the absolute maximum table size. */ #define SMALL (65536/16) /* * Compute the multiplicative inverse of x, modulo mod, using the extended * Euclidean algorithm. The classical EEA returns two results, traditionally * named s and t, but only one (t) is needed or computed here. * It is unrolled twice to avoid some variable-swapping, and because negating * t every other round makes all the number positive and less than the * modulus, which makes fixed-length arithmetic easier. * * If gcd(x, mod) != 1, then this will return 0. */ static unsigned sieveModInvert(unsigned x, unsigned mod) { unsigned y; unsigned t0, t1; unsigned q; if (x <= 1) return x; /* 0 and 1 are self-inverse */ /* * The first round is simplified based on the * initial conditions t0 = 1 and t1 = 0. */ t1 = mod / x; y = mod % x; if (y <= 1) return y ? mod - t1 : 0; t0 = 1; do { q = x / y; x = x % y; t0 += q * t1; if (x <= 1) return x ? t0 : 0; q = y / x; y = y % x; t1 += q * t0; } while (y > 1); return y ? mod - t1 : 0; } /* * Perform a single sieving operation on an array. Clear bits "start", * "start+step", "start+2*step", etc. from the array, up to the size * limit (in BYTES) "size". All of the arguments must fit into 16 bits * for portability. * * This is the core of the sieving operation. In addition to being * called from the sieving functions, it is useful to call directly if, * say, you want to exclude primes congruent to 1 mod 3, or whatever. * (Although in that case, it would be better to change the sieving to * use a step size of 6 and start == 5 (mod 6).) * * Originally, this was inlined in the code below (with various checks * turned off where they could be inferred from the environment), but it * turns out that all the sieving is so fast that it makes a negligible * speed difference and smaller, cleaner code was preferred. * * Rather than increment a bit index through the array and clear * the corresponding bit, this code takes advantage of the fact that * every eighth increment must use the same bit position in a byte. * I.e. start + k*step == start + (k+8)*step (mod 8). Thus, a bitmask * can be computed only eight times and used for all multiples. Thus, the * outer loop is over (k mod 8) while the inner loop is over (k div 8). * * The only further trickiness is that this code is designed to accept * start, step, and size up to 65535 on 16-bit machines. On such a * machine, the computation "start+step" can overflow, so we need to * insert an extra check for that situation. */ void sieveSingle(unsigned char *array, unsigned size, unsigned start, unsigned step) { unsigned bit; unsigned char mask; unsigned i; #if UINT_MAX < 0x1ffff /* Unsigned is small; add checks for wrap */ for (bit = 0; bit < 8; bit++) { i = start/8; if (i >= size) break; mask = ~(1 << (start & 7)); do { array[i] &= mask; i += step; } while (i >= step && i < size); start += step; if (start < step) /* Overflow test */ break; } #else /* Unsigned has the range - no overflow possible */ for (bit = 0; bit < 8; bit++) { i = start/8; if (i >= size) break; mask = ~(1 << (start & 7)); do { array[i] &= mask; i += step; } while (i < size); start += step; } #endif } /* * Returns the index of the next bit set in the given array. The search * begins after the specified bit, so if you care about bit 0, you need * to check it explicitly yourself. This returns 0 if no bits are found. * * Note that the size is in bytes, and that it takes and returns BIT * positions. If the array represents odd numbers only, as usual, the * returned values must be doubled to turn them into offsets from the * initial number. */ unsigned sieveSearch(unsigned char const *array, unsigned size, unsigned start) { unsigned i; /* Loop index */ unsigned char t; /* Temp */ if (!++start) return 0; i = start/8; if (i >= size) return 0; /* Done! */ /* Deal with odd-bit beginnings => search the first byte */ if (start & 7) { t = array[i++] >> (start & 7); if (t) { if (!(t & 15)) { t >>= 4; start += 4; } if (!(t & 3)) { t >>= 2; start += 2; } if (!(t & 1)) start += 1; return start; } else if (i == size) { return 0; /* Done */ } } /* Now the main search loop */ do { if ((t = array[i]) != 0) { start = 8*i; if (!(t & 15)) { t >>= 4; start += 4; } if (!(t & 3)) { t >>= 2; start += 2; } if (!(t & 1)) start += 1; return start; } } while (++i < size); /* Failed */ return 0; } /* * Build a table of small primes for sieving larger primes with. This * could be cached between calls to sieveBuild, but it's so fast that * it's really not worth it. This code takes a few milliseconds to run. */ static void sieveSmall(unsigned char *array, unsigned size) { unsigned i; /* Loop index */ unsigned p; /* The current prime */ /* Initialize to all 1s */ pgpFillMemory(array, size, 0xFF); #if SMALLSTART == 1 /* Mark 1 as NOT prime */ array[0] = 0xfe; i = 1; /* Index of first prime */ #else i = 0; /* Index of first prime */ #endif /* * Okay, now sieve via the primes up to 256, obtained from the * table itself. We know the maximum possible table size is * 65536, and sieveSingle() can cope with out-of-range inputs * safely, and the time required is trivial, so it isn't adaptive * based on the array size. * * Convert each bit position into a prime, compute a starting * sieve position (the square of the prime), and remove multiples * from the table, using sieveSingle(). I used to have that * code in line here, but the speed difference was so small it * wasn't worth it. If a compiler really wants to waste memory, * it can inline it. */ do { p = 2 * i + SMALLSTART; if (p > 256) break; /* Start at square of p */ sieveSingle(array, size, (p*p-SMALLSTART)/2, p); /* And find the next prime */ i = sieveSearch(array, 16, i); } while (i); } /* * This is the primary sieving function. It fills in the array with * a sieve (multiples of small primes removed) beginning at bn and * proceeding in steps of "step". * * It generates a small array to get the primes to sieve by. It's * generated on the fly - sieveSmall is fast enough to make that * perfectly acceptable. * * The caller should take the array, walk it with sieveSearch, and * apply a stronger primality test to the numbers that are returned. * * If the "dbl" flag non-zero (at least 1), this also sieves 2*bn+1, in * steps of 2*step. If dbl is 2 or more, this also sieve 4*bn+3, * in steps of 4*step, and so on for arbitrarily high values of "dbl". * This is convenient for finding primes such that (p-1)/2 is also prime. * This is particularly efficient because sieveSingle is controlled by the * parameter s = -n/step (mod p). (In fact, we find t = -1/step (mod p) * and multiply that by n (mod p).) If you have -n/step (mod p), then * finding -(2*n+1)/(2*step) (mod p), which is -n/step - 1/(2*step) (mod p), * reduces to finding -1/(2*step) (mod p), or t/2 (mod p), and adding that * to s = -n/step (mod p). Dividing by 2 modulo an odd p is easy - * if even, divide directly. Otherwise, add p (which produces an even * sum), and divide by 2. Very simple. And this produces s' and t' * for step' = 2*step. It can be repeated for step'' = 4*step and so on. * * Note that some of the math is complicated by the fact that 2*p might * not fit into an unsigned, so rather than if (odd(x)) x = (x+p)/2, * we do if (odd(x)) x = x/2 + p/2 + 1; * * TODO: Do the double-sieving by sieving the larger number, and then * just subtract one from the remainder to get the other parameter. * (bn-1)/2 is divisible by an odd p iff bn-1 is divisible, which is * true iff bn == 1 mod p. This requires using a step size of 4. */ int sieveBuild(unsigned char *array, unsigned size, BigNum const *bn, unsigned step, unsigned dbl) { unsigned i, j; /* Loop index */ unsigned p; /* Current small prime */ unsigned s; /* Where to start operations in the big sieve */ unsigned t; /* Step modulo p, the current prime */ #ifdef MSDOS /* Use dynamic allocation rather than on the stack */ unsigned char *small; #else unsigned char small[SMALL]; #endif pgpAssert(array); #ifdef MSDOS small = bniMemAlloc(SMALL); /* Which allocator? Not secure. */ if (!small) return -1; /* Failed */ #endif /* * An odd step is a special case, since we must sieve by 2, * which isn't in the small prime array and has a few other * special properties. These are: * - Since the numbers are stored in binary, we don't need to * use bnModQ to find the remainder. * - If step is odd, then t = step % 2 is 1, which allows * the elimination of a lot of math. Inverting and negating * t don't change it, and multiplying s by 1 is a no-op, * so t isn't actually mentioned. * - Since this is the first sieving, instead of calling * sieveSingle, we can just use memset to fill the array * with 0x55 or 0xAA. Since a 1 bit means possible prime * (i.e. NOT divisible by 2), and the least significant bit * is first, if bn % 2 == 0, we use 0xAA (bit 0 = bn is NOT * prime), while if bn % 2 == 1, use 0x55. * (If step is even, bn must be odd, so fill the array with 0xFF.) * - Any doublings need not be considered, since 2*bn+1 is odd, and * 2*step is even, so none of these numbers are divisible by 2. */ if (step & 1) { s = bnLSWord(bn) & 1; memset(array, 0xAA >> s, size); } else { /* Initialize the array to all 1's */ memset(array, 255, size); pgpAssert(bnLSWord(bn) & 1); } /* * This could be cached between calls to sieveBuild, but * it's really not worth it; sieveSmall is *very* fast. * sieveSmall returns a sieve of odd primes. */ sieveSmall(small, SMALL); /* * Okay, now sieve via the primes up to ssize*16+SMALLSTART-1, * obtained from the small table. */ i = (small[0] & 1) ? 0 : sieveSearch(small, SMALL, 0); do { p = 2 * i + SMALLSTART; /* * Modulo is usually very expensive, but step is usually * small, so this conditional is worth it. */ t = (step < p) ? step : step % p; if (!t) { /* * Instead of pgpAssert failing, returning all zero * bits is the "correct" thing to do, but I think * that the caller should take care of that * themselves before starting. */ pgpAssert(bnModQ(bn, p) != 0); continue; } /* * Get inverse of step mod p. 0 < t < p, and p is prime, * so it has an inverse and sieveModInvert can't return 0. */ t = sieveModInvert(t, p); pgpAssert(t); /* Negate t, so now t == -1/step (mod p) */ t = p - t; /* Now get the bignum modulo the prime. */ s = bnModQ(bn, p); /* Multiply by t, the negative inverse of step size */ #if UINT_MAX/0xffff < 0xffff s = (unsigned)(((unsigned long)s * t) % p); #else s = (s * t) % p; #endif /* s is now the starting bit position, so sieve */ sieveSingle(array, size, s, p); /* Now do the double sieves as desired. */ for (j = 0; j < dbl; j++) { /* Halve t modulo p */ #if UINT_MAX < 0x1ffff t = (t & 1) ? p/2 + t/2 + 1 : t/2; /* Add t to s, modulo p with overflow checks. */ s += t; if (s >= p || s < t) s -= p; #else if (t & 1) t += p; t /= 2; /* Add t to s, modulo p */ s += t; if (s >= p) s -= p; #endif sieveSingle(array, size, s, p); } /* And find the next prime */ } while ((i = sieveSearch(small, SMALL, i)) != 0); #ifdef MSDOS bniMemFree(small, SMALL); #endif return 0; /* Success */ } /* * Similar to the above, but use "step" (which must be even) as a step * size rather than a fixed value of 2. If "step" has any small divisors * other than 2, this will blow up. * * Returns -1 on out of memory (MSDOS only, actually), and -2 * if step is found to be non-prime. */ int sieveBuildBig(unsigned char *array, unsigned size, BigNum const *bn, BigNum const *step, unsigned dbl) { unsigned i, j; /* Loop index */ unsigned p; /* Current small prime */ unsigned s; /* Where to start operations in the big sieve */ unsigned t; /* step modulo p, the current prime */ #ifdef MSDOS /* Use dynamic allocation rather than on the stack */ unsigned char *small; #else unsigned char small[SMALL]; #endif pgpAssert(array); #ifdef MSDOS small = bniMemAlloc(SMALL); /* Which allocator? Not secure. */ if (!small) return -1; /* Failed */ #endif /* * An odd step is a special case, since we must sieve by 2, * which isn't in the small prime array and has a few other * special properties. These are: * - Since the numbers are stored in binary, we don't need to * use bnModQ to find the remainder. * - If step is odd, then t = step % 2 is 1, which allows * the elimination of a lot of math. Inverting and negating * t don't change it, and multiplying s by 1 is a no-op, * so t isn't actually mentioned. * - Since this is the first sieving, instead of calling * sieveSingle, we can just use memset to fill the array * with 0x55 or 0xAA. Since a 1 bit means possible prime * (i.e. NOT divisible by 2), and the least significant bit * is first, if bn % 2 == 0, we use 0xAA (bit 0 = bn is NOT * prime), while if bn % 2 == 1, use 0x55. * (If step is even, bn must be odd, so fill the array with 0xFF.) * - Any doublings need not be considered, since 2*bn+1 is odd, and * 2*step is even, so none of these numbers are divisible by 2. */ if (bnLSWord(step) & 1) { s = bnLSWord(bn) & 1; memset(array, 0xAA >> s, size); } else { /* Initialize the array to all 1's */ memset(array, 255, size); pgpAssert(bnLSWord(bn) & 1); } /* * This could be cached between calls to sieveBuild, but * it's really not worth it; sieveSmall is *very* fast. * sieveSmall returns a sieve of the odd primes. */ sieveSmall(small, SMALL); /* * Okay, now sieve via the primes up to ssize*16+SMALLSTART-1, * obtained from the small table. */ i = (small[0] & 1) ? 0 : sieveSearch(small, SMALL, 0); do { p = 2 * i + SMALLSTART; t = bnModQ(step, p); if (!t) { pgpAssert(bnModQ(bn, p) != 0); continue; } /* Get negative inverse of step */ t = sieveModInvert(bnModQ(step, p), p); pgpAssert(t); t = p-t; /* Okay, we have a prime - get the remainder */ s = bnModQ(bn, p); /* Now multiply s by the negative inverse of step (mod p) */ #if UINT_MAX < 0xffff * 0xffff s = (unsigned)(((unsigned long)s * t) % p); #else s = (s * t) % p; #endif /* We now have the starting bit pos */ sieveSingle(array, size, s, p); /* Now do the double sieves as desired. */ for (j = 0; j < dbl; j++) { /* Halve t modulo p */ #if UINT_MAX < 0x1ffff t = (t & 1) ? p/2 + t/2 + 1 : t/2; /* Add t to s, modulo p with overflow checks. */ s += t; if (s >= p || s < t) s -= p; #else if (t & 1) t += p; t /= 2; /* Add t to s, modulo p */ s += t; if (s >= p) s -= p; #endif sieveSingle(array, size, s, p); } /* And find the next prime */ } while ((i = sieveSearch(small, SMALL, i)) != 0); #ifdef MSDOS bniMemFree(small, SMALL); #endif return 0; /* Success */ } SIqJCErYFwtb3YhIzU3JSQiKz81Yng9ISIqJCIrTHk+RE4hIiokIStgXC1vdiEjNTclJCIrdE89Zj4hIiokIitsMVNRUSEiKiQhK2BcLW92ISM1NyUkIitFaiIzLyMhIiokIit3NyRcOyUhIiokIStgXC1vdiEjNTclJCIreipbQzcjISIqJCIrbycqeS9YISIqJCErYFwtb3YhIzU3JSQiK0s7My9BISIqJCIrVGUoeiZbISIqJCErYFwtb3YhIzU3JSQiKyZHOWRHIyEiKiQiKyR6KltDXyEiKiQhK2BcLW92ISM1NyUkIitRcE1uQiEiKiQiK0Q6TC9jISIqJCErYFwtb3YhIzU3JSQiKyJmeipbQyEiKiQiK1A1XSgqZiEiKiQhK2BcLW92ISM1NyUkIitXQWhJRCEiKiQiK0gkKSpSUychIiokIStgXC1vdiEjNTclJCIrKCpbQzdFISIqJCIrLU0jUSNvISIqJCErYFwtb3YhIzU3JSQiK112KFFwIyEiKiQiK2FpKHBEKCEiKiQhK2BcLW92ISM1NyUkIisuLV52RiEiKiQiKygpb1gueCEiKiQhK2BcLW92ISM1NyUkIitjRzlkRyEiKiQiKytgRWoiKSEiKiQhK2BcLW92ISM1NyUkIis0YnhRSCEiKiQiKyNcLGtqKSEiKiQhK2BcLW92ISM1NyUkIitpIjMvLSQhIiokIitsYSdHNyohIiokIStgXC1vdiEjNTclJCIrOjMvLUohIiokIis9c2xBJyohIiokIStgXC1vdiEjNTclJCIrb01uJD0kISIqJCIrdndkODUhIikkIStgXC1vdiEjNTclJCIrQGhJbEshIiokIisxQ0FtNSEiKSQhK2BcLW92ISM1NyUkIit1KFFwTSQhIiokIis7Kio+PzYhIikkIStgXC1vdiEjNTclJCIrRjlkR00hIiokIisuLV52NiEiKSQhK2BcLW92ISM1NyUkIishMy8tXiQhIiokIitvSzpLNyEiKSQhK2BcLW92ISM1NyUkIitMbiQ9ZiQhIiokIis3IkgsSCIhIikkIStgXC1vdiEjNTclJCIrJ1FwTW4kISIqJCIrTHhWXDghIikkIStgXC1vdiEjNTclJCIrUj81YlAhIiokIitLInorVCIhIikkIStgXC1vdiEjNTclJCIrI3BNbiRRISIqJCIrNUwwczkhIikkIStgXC1vdiEjNTclJCIrWHRPPVIhIiokIitsLU9OOiEiKSQhK2BcLW92ISM1NyUkIispKioqKioqKlIhIiokIispKioqKioqZiIhIikkIStgXC1vdiEjNS1JJ0NPTE9VUkc2JCUqcHJvdGVjdGVkR0koX3N5c2xpYkc2IjYmSSRSR0JHNiIkIiIhIiIhJCIiISIiISQiKisrKysiISIpLUknQ1VSVkVTRzYkJSpwcm90ZWN0ZWRHSShfc3lzbGliRzYiNiQ3VDclJCIiIyIiISQiIiMiIiEkIitvVShINCohIzU3JSQiIiMiIiEkIitgRWoiMyMhIiokIityI2ZMcykhIzU3JSQiIiMiIiEkIisxYEVqQCEiKiQiK1RdayZIKSEjNTclJCIiIyIiISQiK2Z6KltDIyEiKiQiK08tbzd5ISM1NyUkIiIjIiIhJCIrNzFgRUIhIiokIisnXCJveHMhIzU3JSQiIiMiIiEkIitsSzszQyEiKiQiKzc/QCVwJyEjNTclJCIiIyIiISQiKz1meipbIyEiKiQiKy15Om1nISM1NyUkIiIjIiIhJCIrciZHOWQjISIqJCIrRz1xKFImISM1NyUkIiIjIiIhJCIrQzcxYEUhIiokIitLaEgkcCUhIzU3JSQiIiMiIiEkIit4UXBNRiEiKiQiKyI+S3cmUiEjNTclJCIiIyIiISQiK0lsSztHISIqJCIrbyc0Yz4kISM1NyUkIiIjIiIhJCIrJD1meipHISIqJCIrdlBJN0MhIzU3JSQiIiMiIiEkIitPPWZ6SCEiKiQiKyJbSkhoIiEjNTclJCIiIyIiISQiKypbQzcxJCEiKiQiK2t2O0chKSEjNjclJCIiIyIiISQiK1VyJkc5JCEiKiQhK3QhKVtrNyEjNzclJCIiIyIiISQiKyZ6KltDSyEiKiQhKzBJQSFHKSEjNjclJCIiIyIiISQiK1tDNzFMISIqJCErTVwpeWoiISM1NyUkIiIjIiIhJCIrLF52KFEkISIqJCErVipRb1YjISM1NyUkIiIjIiIhJCIrYXhRcE0hIiokIStTSmM+SyEjNTclJCIiIyIiISQiKzIvLV5OISIqJCErTlclMylSISM1NyUkIiIjIiIhJCIrZ0lsS08hIiokIStbRGg6WiEjNTclJCIiIyIiISQiKzhkRzlQISIqJCErJnl0Kj1hISM1NyUkIiIjIiIhJCIrbSQ9ZnokISIqJCErRE9DJzMnISM1NyUkIiIjIiIhJCIrPjVieFEhIiokIStEeihIcichIzU3JSQiIiMiIiEkIitzTz1mUiEiKiQhKzpEKyZIKCEjNTclJCIiIyIiISQiK/* * $Id: bnprint.h,v 1.1.1.1 1999/08/08 19:38:15 heller Exp $ */ #ifndef Included_bnprint_h #define Included_bnprint_h #include "pgpBase.h" PGP_BEGIN_C_DECLARATIONS #include #include "pgpOpaqueStructs.h" /* Print in base 16 */ int bnPrint(FILE *f, char const *prefix, BigNum const *bn, char const *suffix); /* Print in base 10 */ int bnPrint10(FILE *f, char const *prefix, BigNum const *bn, char const *suffix); PGP_END_C_DECLARATIONS #endif /* Included_bnprint_h */ SQiIiMiIiEkIitoIjMvLSYhIiokIStzJ2YkSCYqISM1NyUkIiIjIiIhJCIrOTMvLV4hIiokIStFUFRdIyohIzU3JSQiIiMiIiEkIituTW4kPSYhIiokIStsI2UpNCopISM1NyUkIiIjIiIhJCIrP2hJbF8hIiokIStfOScqNCYpISM1NyUkIiIjIiIhJCIrdChRcE0mISIqJCEreW1RYCEpISM1NyUkIiIjIiIhJCIrRTlkR2EhIiokISs7WzxWdiEjNTclJCIiIyIiISQiK3pTPzViISIqJCErdVJzIylwISM1NyUkIiIjIiIhJCIrS24kPWYmISIqJCEram93dmohIzU3JSQiIiMiIiEkIismUXBNbiYhIiokIStLZk1FZCEjNTclJCIiIyIiISQiK1E/NWJkISIqJCErWmt5UV0hIzU3JSQiIiMiIiEkIisicE1uJGUhIiokISsnb253SiUhIzU3JSQiIiMiIiEkIitXdE89ZiEiKiQhK09Dem5OISM1NyUkIiIjIiIhJCIrKCoqKioqKipmISIqJCErNl06JXojISM1LUknQ09MT1VSRzYkJSpwcm90ZWN0ZWRHSShfc3lzbGliRzYiNiZJJFJHQkc2IiQiIiEiIiEkIiorKysrIiEiKSQiIiEiIiEtSSdDVVJWRVNHNiQlKnByb3RlY3RlZEdJKF9zeXNsaWJHNiI2JDdUNyUkIiIhIiIhJCIiISIiISQiIiEiIiE3JSQiKzFgRWoiKSEjNiQiK1krKlFtJyEjNyQiK0QyJVFtJyEjNzclJCIraElsSzshIzUkIis9Z2JsRSEjNiQiK3UuQ2xFISM2NyUkIisjZnoqW0MhIzUkIitVNV0oKmYhIzYkIismPTFSKmYhIzY3JSQiK0JoSWxLISM1JCIrM0NBbTUhIzUkIittTD9rNSEjNTclJCIrYUVqIjMlISM1JCIrN0QoZm0iISM1JCIrKHl3I2U7ISM1NyUkIismPWZ6KlshIzUkIis9LysqUiMhIzUkIis/YDB3QiEjNTclJCIrO2RHOWQhIzUkIitDaElsSyEjNSQiK3MqKWUySyEjNTclJCIrWkFoSWwhIzUkIitLJyopW0UlISM1JCIrdCNvbjglISM1NyUkIit5KFFwTSghIzUkIitUNHYoUiYhIzUkIitcMlZSXiEjNTclJCIrNGBFaiIpISM1JCIrXisqUW0nISM1JCIrJm86Oj0nISM1NyUkIitTPWZ6KikhIzUkIitocElqISkhIzUkIitdS188cyEjNTclJCIrciQ9ZnoqISM1JCIrdDsrJ2YqISM1JCIrMz5pKj0pISM1NyUkIishXEM3MSIhIiokIis9dT5FNiEiKiQiK2RDJHktKiEjNTclJCIrVnImRzkiISIqJCIrXEM3MTghIiokIitUJ3k8bCohIzU3JSQiKyd6KltDNyEiKiQiK2hfUCpcIiEiKiQiKycqZl11KiohIzU3JSQiK1xDNzE4ISIqJCIrX2UmZnEiISIqJCIrIlspejMqKiEjNTclJCIrLV52KFEiISIqJCIrQlUnZSM+ISIqJCIrbClHaVAqISM1NyUkIitieFFwOSEiKiQiK3YuNWZAISIqJCIrYS8kKT0kKSEjNTclJCIrMy8tXjohIiokIisxVm0wQyEiKiQiK0xhdjduISM1NyUkIitoSWxLOyEiKiQiKz1nYmxFISIqJCIrVDJnI2UlISM1NyUkIis5ZEc5PCEiKiQiKzRieFFIISIqJCIreV9IOT8hIzU3JSQiK24kPWZ6IiEiKiQiKyJ5QWBBJCEiKiQhK29FQmokKSEjNjclJCIrPzVieD0hIiokIitMeT5ETiEiKiQhK1MwbVVQISM1NyUkIit0Tz1mPiEiKiQiK2wxU1FRISIqJCErOy90PGshIzU3JSQiK0VqIjMvIyEiKiQiK3c3JFw7JSEiKiQhKzhmXVEmKSEjNTclJCIreipbQzcjISIqJCIrbycqeS9YISIqJCErSmFHJnkqISM1NyUkIitLOzMvQSEiKiQiK1RlKHomWyEiKiQhKydRNFUqKSohIzU3JSQiKyZHOWRHIyEiKiQiKyR6KltDXyEiKiQhK1EsPDwoKSEjNTclJCIrUXBNbkIhIiokIitEOkwvYyEiKiQhK09NLHppISM1NyUkIisiZnoqW0MhIiokIitQNV0oKmYhIiokIStKMDk9RyEjNTclJCIrV0FoSUQhIiokIitIJCkqUlMnISIqJCIrS00+MDchIzU3JSQiKygqW0M3RSEiKiQiKy1NI1EjbyEiKiQiK2o9JG85JiEjNTclJCIrXXYoUXAjISIqJCIrYWkocEQoISIqJCIrOyFHLUYpISM1NyUkIisuLV52RiEiKiQiKygpb1gueCEiKiQiK1lfI3ApKSohIzU3JSQiK2NHOWRHISIqJCIrK2BFaiIpISIqJCIrJlw9Yl8qISM1NyUkIis0YnhRSCEiKiQiKyNcLGtqKSEiKiQiKzxpNCM0KCEjNTclJCIraSIzLy0kISIqJCIrbGEnRzcqISIqJCIrP3VZdEghIzU3JSQiKzozLy1KISIqJCIrPXNsQScqISIqJCEra1QhZic+ISM1NyUkIitvTW4kPSQhIiokIit2d2Q4NSEiKSQhKywqM2ZfJyEjNTclJCIrQGhJbEshIiokIisxQ0FtNSEiKSQhKyg+OSZcJSohIzU3JSQiK3UoUXBNJCEiKiQiKzsqKj4/NiEiKSQhK1QkKnAoeSohIzU3JSQiK0Y5ZEdNISIqJCIrLi1edjYhIikkISsjeTc7RCghIzU3JSQiKyEzLy1eJCEiKiQiK29LOks3ISIpJCErRDQqUlUjISM1NyUkIitMbiQ9ZiQhIiokIis3IkgsSCIhIikkIisuNCVwRyQhIzU3JSQiKydRcE1uJCEiKiQiK0x4Vlw4ISIpJCIrZ3BFLyEpISM1NyUkIitSPzViUCEiKiQiK0sieitUIiEiKSQiKy1bUSQqKiohIzU3JSQiKyNwTW4kUSEiKiQiKzVMMHM5ISIpJCIrMT04WSQpISM1NyUkIitYdE89UiEiKiQiK2wtT046ISIpJCIrJ3oyKnBNISM1NyUkIispKioqKioqKlIhIiokIispKioqKioqZiIhIikkISs4SS56RyEjNS1JJ0NPTE9VUkc2JCUqcHJvdGVjdGVkR0koX3N5c2xpYkc2IjYmSSRSR0JHNiIkIiorKysrIiEiKSQiIiEiIiEkIiIhIiIhLUkqVEhJQ0tORVNTRzYiNiMiIiQtSStBWEVTTEFCRUxTRzYkJSpwcm90ZWN0ZWRHSShfc3lzbGliRzYiNiVRIng2IlEidjYiUSJ5NiItSSpBWEVTU1RZTEVHNiQlKnByb3RlY3RlZEdJKF9zeXNsaWJHNiI2I0kkQk9YRzYkJSpwcm90ZWN0ZWRHSShfc3lzbGliRzYiLUkrUFJPSkVDVElPTkc2IjYlJCEjISoiIiEkIiMhKiIiISIiIg== 16-bit step size */ int sieveBuildBig(unsigned char *array, unsigned size, BigNum const *bn, BigNum const *step, unsigned dbl); /* Return the next bit set in the sieve (or 0 on failure) */ unsigned sieveSearch(unsigned char const *array, unsigned size, unsigned start); PGP_END_C_DECLARATIONS #endif /* Included_bnsieve_h */ ;, "v", "y"]); NigtSSdDVVJWRVNHNiQlKnByb3RlY3RlZEdJKF9zeXNsaWJHNiI2JDdUNyUkIiIhIiIhJCIiISIiISQiK1spNFpUKSEjNTclJCIrYEVqIjMlISM2JCIrLXkpKSp6JyEjOSQiK1spNFpUKSEjNTclJCIrMWBFaiIpISM2JCIrVC0iKlJhISM4JCIrWyk0WlQpISM1NyUkIisneipbQzchIzUkIisyKHBmJD0hIzckIitbKTRaVCkhIzU3JSQiK2hJbEs7ISM1JCIrIj5HPk4lISM3JCIrWyk0WlQpISM1NyUkIitFaiIzLyMhIzUkIitZKGYpKlwpISM3JCIrWyk0WlQpISM1NyUkIisiZnoqW0MhIzUkIitrZHhvOSEjNiQiK1spNFpUKSEjNTclJCIrY0c5ZEchIzUkIis4Ok9LQiEjNiQiK1spNFpUKSEjNTclJCIrQGhJbEshIzUkIitdRGEiWyQhIzYkIitbKTRaVCkhIzU3JSQiKydRcE1uJCEjNSQiKysjPXImXCEjNiQiK1spNFpUKSEjNTclJCIrXkVqIjMlISM1JCIrI3ooKSkqeichIzYkIitbKTRaVCkhIzU3JSQiKztmeipbJSEjNSQiK10xbF0hKiEjNiQiK1spNFpUKSEjNTclJCIrIj1meipbISM1JCIrNTEtdjYhIzUkIitbKTRaVCkhIzU3JSQiK1lDNzFgISM1JCIrW2AkUlwiISM1JCIrWyk0WlQpISM1NyUkIis2ZEc5ZCEjNSQiKzUjKillJz0hIzUkIitbKTRaVCkhIzU3JSQiK3cqW0M3JyEjNSQiK0hAJ1xIIyEjNSQiK1spNFpUKSEjNTclJCIrVEFoSWwhIzUkIitSU0ImeSMhIzUkIitbKTRaVCkhIzU3JSQiKzFieFFwISM1JCIrclt5U0whIzUkIitbKTRaVCkhIzU3JSQiK3IoUXBNKCEjNSQiK2ZYcGxSISM1JCIrWyk0WlQpISM1NyUkIitPPzVieCEjNSQiK05JL2tZISM1JCIrWyk0WlQpISM1NyUkIissYEVqIikhIzUkIitKLSIqUmEhIzUkIitbKTRaVCkhIzU3JSQiK20mRzlkKSEjNSQiKyIzd3RIJyEjNSQiK1spNFpUKSEjNTclJCIrSj1meiopISM1JCIrPTBfU3MhIzUkIitbKTRaVCkhIzU3JSQiKyc0YnhRKiEjNSQiK3RNVXQjKSEjNSQiK1spNFpUKSEjNTclJCIraCQ9ZnoqISM1JCIrels7KyUqISM1JCIrWyk0WlQpISM1NyUkIitqIjMvLSIhIiokIitvQ1tpNSEiKiQiK1spNFpUKSEjNTclJCIrIVxDNzEiISIqJCIrIkdbXj4iISIqJCIrWyk0WlQpISM1NyUkIis8My8tNiEiKiQiKz0+VVE4ISIqJCIrWyk0WlQpISM1NyUkIitXciZHOSIhIiokIit2OHIjXCIhIiokIitbKTRaVCkhIzU3JSQiK3JNbiQ9IiEiKiQiK1ZZVWU7ISIqJCIrWyk0WlQpISM1NyUkIispeipbQzchIiokIis7KHBmJD0hIiokIitbKTRaVCkhIzU3JSQiK0RoSWw3ISIqJCIrKGVhZC0jISIqJCIrWyk0WlQpISM1NyUkIitfQzcxOCEiKiQiK11zPUdBISIqJCIrWyk0WlQpISM1NyUkIit6KFFwTSIhIiokIispcHZPVyMhIiokIitbKTRaVCkhIzU3JSQiKzFedihRIiEiKiQiK0R6aXNFISIqJCIrWyk0WlQpISM1NyUkIitMOWRHOSEiKiQiK0E+WDpIISIqJCIrWyk0WlQpISM1NyUkIitneFFwOSEiKiQiKyZvYkQ8JCEiKiQiK1spNFpUKSEjNTclJCIrKDMvLV4iISIqJCIrMHNNV00hIiokIitbKTRaVCkhIzU3JSQiKzkvLV46ISIqJCIreFdCSlAhIiokIitbKTRaVCkhIzU3JSQiK1RuJD1mIiEiKiQiKyRcRE8uJSEiKiQiK1spNFpUKSEjNTclJCIrb0lsSzshIiokIitaI0c+TiUhIiokIitbKTRaVCkhIzU3JSQiKyZScE1uIiEiKiQiK0wyYidvJSEiKiQiK1spNFpUKSEjNTclJCIrQWRHOTwhIiokIitWNCF6LiYhIiokIitbKTRaVCkhIzU3JSQiK1w/NWI8ISIqJCIrcW9RMWEhIiokIitbKTRaVCkhIzU3JSQiK3ckPWZ6IiEiKiQiKzRsVCN6JiEiKiQiK1spNFpUKSEjNTclJCIrLlp0Tz0hIiokIitfeVInPichIiokIitbKTRaVCkhIz/* * $Id: bnprime.h,v 1.4 2003/11/12 20:45:51 ajivsov Exp $ */ #ifndef Included_bnprime_h #define Included_bnprime_h #include "pgpBase.h" PGP_BEGIN_C_DECLARATIONS #include "pgpBigNumOpaqueStructs.h" /* Generate a prime >= bn. leaving the result in bn. */ int bnPrimeGen(BigNum *bn, unsigned (*randnum)(void *randnum_arg, unsigned limit), void *randnum_arg, int (*f)(void *f_arg, int c), void *f_arg, unsigned exponent, ...); /* * Generate a prime of the form bn + k*step. Step must be even and * bn must be odd. */ int bnPrimeGenStrong(BigNum *bn, BigNum const *step, int (*f)(void *arg, int c), void *arg); PGP_END_C_DECLARATIONS #endif /* Included_bnprime_h */ M1NyUkIiIiIiIhJCIrVEFoSWwhIzUkIitzYj93ZyEjNTclJCIiIiIiISQiKzFieFFwISM1JCIrXCRIX1InISM1NyUkIiIiIiIhJCIrcihRcE0oISM1JCIrRy5nLm4hIzU3JSQiIiIiIiEkIitPPzVieCEjNSQiK1dbITMrKCEjNTclJCIiIiIiISQiKyxgRWoiKSEjNSQiK0p5TSdHKCEjNTclJCIiIiIiISQiK20mRzlkKSEjNSQiK1tPdmZ2ISM1NyUkIiIiIiIhJCIrSj1meiopISM1JCIrcm9jP3khIzU3JSQiIiIiIiEkIisnNGJ4USohIzUkIithSU5vISkhIzU3JSQiIiIiIiEkIitoJD1meiohIzUkIitbJSpwLSQpISM1NyUkIiIiIiIhJCIraiIzLy0iISIqJCIrJ3A6S18pISM1NyUkIiIiIiIhJCIrIVxDNzEiISIqJCIrc1dgSCgpISM1NyUkIiIiIiIhJCIrPDMvLTYhIiokIistQEpAKikhIzU3JSQiIiIiIiEkIitXciZHOSIhIiokIitNIkgjKTQqISM1NyUkIiIiIiIhJCIrck1uJD0iISIqJCIrcjMqKmYjKiEjNTclJCIiIiIiISQiKyl6KltDNyEiKiQiK2V5SzElKiEjNTclJCIiIiIiISQiK0RoSWw3ISIqJCIrUGoqcGAqISM1NyUkIiIiIiIhJCIrX0M3MTghIiokIitbJ3k8bCohIzU3JSQiIiIiIiEkIit6KFFwTSIhIiokIisjZiRbXSgqISM1NyUkIiIiIiIhJCIrMV52KFEiISIqJCIrYW4lSCQpKiEjNTclJCIiIiIiISQiK0w5ZEc5ISIqJCIrcTIuKiopKiEjNTclJCIiIiIiISQiK2d4UXA5ISIqJCIraWJpWyoqISM1NyUkIiIiIiIhJCIrKDMvLV4iISIqJCIrPSZbOykqKiEjNTclJCIiIiIiISQiKzkvLV46ISIqJCIrSVkvKSoqKiEjNTclJCIiIiIiISQiK1RuJD1mIiEiKiQiKyhlJ3koKioqISM1NyUkIiIiIiIhJCIrb0lsSzshIiokIis8WygzKSoqISM1NyUkIiIiIiIhJCIrJlJwTW4iISIqJCIrJFxQdCUqKiEjNTclJCIiIiIiISQiK0FkRzk8ISIqJCIreS9CKCopKiEjNTclJCIiIiIiISQiK1w/NWI8ISIqJCIrUHNqSSkqISM1NyUkIiIiIiIhJCIrdyQ9ZnoiISIqJCIrKnBvd3UqISM1NyUkIiIiIiIhJCIrLlp0Tz0hIiokIittSVlbJyohIzU3JSQiIiIiIiEkIitJNWJ4PSEiKiQiKyFmJj1MJiohIzU3JSQiIiIiIiEkIitkdE89PiEiKiQiKyRIRz9TKiEjNTclJCIiIiIiISQiKyVvJD1mPiEiKiQiK10nNF9EKiEjNTclJCIiIiIiISQiKzYrKys/ISIqJCIrQVUoSDQqISM1LUknQ09MT1VSRzYkJSpwcm90ZWN0ZWRHSShfc3lzbGliRzYiNiZJJFJHQkc2IiQiIiEiIiEkIiorKysrIiEiKSQiIiEiIiEtSSdDVVJWRVNHNiQlKnByb3RlY3RlZEdJKF9zeXNsaWJHNiI2JDdUNyUkIiIhIiIhJCIiISIiISQiIiEiIiE3JSQiK2BFaiIzJSEjNiQiKy15KSkqeichIzkkIisneigpKSp6JyEjOTclJCIrMWBFaiIpISM2JCIrVC0iKlJhISM4JCIrdCo0KlJhISM4NyUkIisneipbQzchIzUkIisyKHBmJD0hIzckIit2J29mJD0hIzc3JSQiK2hJbEs7ISM1JCIrIj5HPk4lISM3JCIrYVciPk4lISM3NyUkIitFaiIzLyMhIzUkIitZKGYpKlwpISM3JCIrKFJkKCpcKSEjNzclJCIrImZ6KltDISM1JCIra2R4bzkhIzYkIithSHNvOSEjNjclJCIrY0c5ZEchIzUkIis4Ok9LQiEjNiQiK2IrOktCISM2NyUkIitAaElsSyEjNSQiK11EYSJbJCEjNiQiK2IjUjNbJCEjNjclJCIrJ1FwTW4kISM1JCIrKyM9ciZcISM2JCIrZyMpM2JcISM2NyUkIiteRWoiMyUhIzUkIisjeigpKSp6JyEjNiQiK0goW1l6JyEjNjclJCIrO2Z6KlslISM1JCIrXTFsXSEqISM2JCIrPSUqSFEhKiEjNjclJCIrIj1meipbISM1JCIrNTEtdjYhIzUkIis1Jz1CPCIhIzU3JSQiK1lDNzFgISM1JCIrW2AkUlwiISM1JCIrKFwlUSlbIiEjNTclJCIrNmRHOWQhIzUkIis1IyopZSc9ISM1JCIrKDMiM2I9ISM1NyUkIit3KltDNychIzUkIitIQCdcSCMhIzUkIitUKHBbRiMhIzU3JSQiK1RBaElsISM1JCIrUlNCJnkjISM1JCIrckRPXEYhIzU3JSQiKzFieFFwISM1JCIrclt5U0whIzUkIitUdSkqeUshIzU3JSQiK3IoUXBNKCEjNSQiK2ZYcGxSISM1JCIrbkpjaVEhIzU3JSQiK08/NWJ4ISM1JCIrTkkva1khIzUkIitjYngnXCUhIzU3JSQiKyxgRWoiKSEjNSQiK0otIipSYSEjNSQiK0otYnZeISM1NyUkIittJkc5ZCkhIzUkIisiM3d0SCchIzUkIit5cksqKWUhIzU3JSQiK0o9ZnoqKSEjNSQiKz0wX1NzISM1JCIraGdEQ20hIzU3JSQiKyc0YnhRKiEjNSQiK3RNVXQjKSEjNSQiKz09Tmh0ISM1NyUkIitoJD1meiohIzUkIit6WzsrJSohIzUkIitaI3ljMikhIzU3JSQiK2oiMy8tIiEiKiQiK29DW2k1ISIqJCIrRFNtTigpISM1NyUkIishXEM3MSIhIiokIisiR1tePiIhIiokIiteMXEtJCohIzU3JSQiKzwzLy02ISIqJCIrPT5VUTghIiokIisiUkI3dCohIzU3JSQiK1dyJkc5IiEiKiQiK3Y4ciNcIiEiKiQiKyk9SCZwKiohIzU3JS/*____________________________________________________________________________ Copyright (C) 2002 PGP Corporation All rights reserved. $Id: bnsieve.c,v 1.3 2002/08/06 20:10:57 dallen Exp $ ____________________________________________________________________________*/ /* * bnsieve.c - Trial division for prime finding. * * Written by Colin Plumb * * Finding primes: * - Sieve 1 to find the small primes for * - Sieve 2 to find the candidate large primes, then * - Pseudo-primality test. * * An important question is how much trial division by small primes * should we do? The answer is a LOT. Even a heavily optimized * Fermat test to the base 2 (the simplest pseudoprimality test) * is much more expensive than a division. * * For an prime of n k-bit words, a Fermat test to the base 2 requires n*k * modular squarings, each of which involves n*(n+1)/2 signle-word multiplies * in the squaring and n*(n+1) multiplies in the modular reduction, plus * some overhead to get into and out of Montgomery form. This is a total * of 3/2 * k * n^2 * (n+1). Equivalently, if n*k = b bits, it's * 3/2 * (b/k+1) * b^2 / k. * * A modulo operation requires n single-word divides. Let's assume that * a divide is 4 times the cost of a multiply. That's 4*n multiplies. * However, you only have to do the division once for your entire * search. It can be amortized over 10-15 primes. So it's * really more like n/3 multiplies. This is b/3k. * * Now, let's suppose you have a candidate prime t. Your options * are to a) do trial division by a prime p, then do a Fermat test, * or to do the Fermat test directly. Doing the trial division * costs b/3k multiplies, but a certain fraction of the time (1/p), it * saves you 3/2 b^3 / k^2 multiplies. Thus, it's worth it doing the * division as long as b/3k < 3/2 * (b/k+1) * b^2 / k / p. * I.e. p < 9/2 * (b/k + 1) * b = 9/2 * (b^2/k + b). * E.g. for k=16 and b=256, p < 9/2 * 17 * 256 = 19584. * Solving for k=16 and k=32 at a few interesting value of b: * * k=16, b=256: p < 19584 k=32, b=256: p < 10368 * k=16, b=384: p < 43200 k=32, b=384; p < 22464 * k=16, b=512: p < 76032 k=32, b=512: p < 39168 * k=16, b=640: p < 118080 k=32, b=640: p < 60480 * * H'm... before using the highly-optimized Fermat test, I got much larger * numbers (64K to 256K), and designed the sieve for that. Maybe it needs * to be reduced. It *is* true that the desirable sieve size increases * rapidly with increasing prime size, and it's the larger primes that are * worrisome in any case. I'll leave it as is (64K) for now while I * think about it. * * A bit of tweaking the division (we can compute a reciprocal and do * multiplies instead, turning 4*n into 4 + 2*n) would increase all the * numbers by a factor of 2 or so. * * * Bit k in a sieve corresponds to the number a + k*b. * For a given a and b, the sieve's job is to find the values of * k for which a + k*b == 0 (mod p). Multiplying by b^-1 and * isolating k, you get k == -a*b^-1 (mod p). So the values of * k which should be worked on are k = (-a*b^-1 mod p) + i * p, * for i = 0, 1, 2,... * * Note how this is still easy to use with very large b, if you need it. * It just requires computing (b mod p) and then finding the multiplicative * inverse of that. * * * How large a space to search to ensure that one will hit a prime? * The average density is known, but the primes behave oddly, and sometimes * there are large gaps. It is conjectured by shanks that the first gap * of size "delta" will occur at approximately exp(sqrt(delta)), so a delta * of 65536 is conjectured to be to contain a prime up to e^256. * Remembering the handy 2<->e conversion ratios: * ln(2) = 0.693147 log2(e) = 1.442695 * This covers up to 369 bits. Damn, not enough! Still, it'll have to do. * * Cramer's conjecture (he proved it for "most" cases) is that in the limit, * as p goes to infinity, the largest gap after a prime p tends to (ln(p))^2. * So, for a 1024-bit p, the interval to the next prime is expected to be * about 709.78^2, or 503791. We'd need to enlarge our space by a factor of * 8 to be sure. It isn't worth the hassle. * * Note that a span of this size is expected to contain 92 primes even * in the vicinity of 2^1024 (it's 369 at 256 bits and 492 at 192 bits). * So the probability of failure is pretty low. */ #include "pgpConfig.h" #include "pgpMem.h" /* * Some compilers complain about #if FOO if FOO isn't defined, * so do the ANSI-mandated thing explicitly... */ #ifndef NO_ASSERT_H #define NO_ASSERT_H 0 #endif #ifndef NO_LIMITS_H #define NO_LIMITS_H 0 #endif #ifndef NO_STRING_H #define NO_STRING_H 0 #endif #ifndef HAVE_STRINGS_H #define HAVE_STRINGS_H 0 #endif #ifndef NEED_MEMORY_H #define NEED_MEMORY_H 0 #endif #if !NO_LIMITS_H #include /* For UINT_MAX */ #endif /* If not avail, default value of 0 is safe */ #if !NO_STRING_H #include /* for memset() */ #elif HAVE_STRINGS_H #include #endif #if NEED_MEMORY_H #include #endif #include "bn.h" #include "bnsieve.h" #ifdef MSDOS #include "bnimem.h" #endif #include "bnkludge.h" #include "pgpDebug.h" /* * Each array stores potential primes as 1 bits in little-endian bytes. * Bit k in an array represents a + k*b, for some parameters a and b * of the sieve. Currently, b is hardcoded to 2. * * Various factors of 16 arise because these are all *byte* sizes, and * skipping even numbers, 16 numbers fit into a byte's worth of bitmap. */ /* * The first number in the small prime sieve. This could be raised to * 3 if you want to squeeze bytes out aggressively for a smaller SMALL * table, and doing so would let one more prime into the end of the array, * but there is no sense making it larger if you're generating small * primes up to the limit if 2^16, since it doesn't save any memory and * would require extra code to ignore 65537 in the last byte, which is * over the 16-bit limit. */ #define SMALLSTART 1 /* * Size of sieve used to find large primes, in bytes. For compatibility * with 16-bit-int systems, the largest prime that can appear in it, * SMALL * 16 + SMALLSTART - 2, must be < 65536. Since 65537 is a prime, * this is the absolute maximum table size. */ #define SMALL (65536/16) /* * Compute the multiplicative inverse of x, modulo mod, using the extended * Euclidean algorithm. The classical EEA returns two results, traditionally * named s and t, but only one (t) is needed or computed here. * It is unrolled twice to avoid some variable-swapping, and because negating * t every other round makes all the number positive and less than the * modulus, which makes fixed-length arithmetic easier. * * If gcd(x, mod) != 1, then this will return 0. */ static unsigned sieveModInvert(unsigned x, unsigned mod) { unsigned y; unsigned t0, t1; unsigned q; if (x <= 1) return x; /* 0 and 1 are self-inverse */ /* * The first round is simplified based on the * initial conditions t0 = 1 and t1 = 0. */ t1 = mod / x; y = mod % x; if (y <= 1) return y ? mod - t1 : 0; t0 = 1; do { q = x / y; x = x % y; t0 += q * t1; if (x <= 1) return x ? t0 : 0; q = y / x; y = y % x; t1 += q * t0; } while (y > 1); return y ? mod - t1 : 0; } /* * Perform a single sieving operation on an array. Clear bits "start", * "start+step", "start+2*step", etc. from the array, up to the size * limit (in BYTES) "size". All of the arguments must fit into 16 bits * for portability. * * This is the core of the sieving operation. In addition to being * called from the sieving functions, it is useful to call directly if, * say, you want to exclude primes congruent to 1 mod 3, or whatever. * (Although in that case, it would be better to change the sieving to * use a step size of 6 and start == 5 (mod 6).) * * Originally, this was inlined in the code below (with various checks * turned off where they could be inferred from the environment), but it * turns out that all the sieving is so fast that it makes a negligible * speed difference and smaller, cleaner code was preferred. * * Rather than increment a bit index through the array and clear * the corresponding bit, this code takes advantage of the fact that * every eighth increment must use the same bit position in a byte. * I.e. start + k*step == start + (k+8)*step (mod 8). Thus, a bitmask * can be computed only eight times and used for all multiples. Thus, the * outer loop is over (k mod 8) while the inner loop is over (k div 8). * * The only further trickiness is that this code is designed to accept * start, step, and size up to 65535 on 16-bit machines. On such a * machine, the computation "start+step" can overflow, so we need to * insert an extra check for that situation. */ void sieveSingle(unsigned char *array, unsigned size, unsigned start, unsigned step) { unsigned bit; unsigned char mask; unsigned i; #if UINT_MAX < 0x1ffff /* Unsigned is small; add checks for wrap */ for (bit = 0; bit < 8; bit++) { i = start/8; if (i >= size) break; mask = ~(1 << (start & 7)); do { array[i] &= mask; i += step; } while (i >= step && i < size); start += step; if (start < step) /* Overflow test */ break; } #else /* Unsigned has the range - no overflow possible */ for (bit = 0; bit < 8; bit++) { i = start/8; if (i >= size) break; mask = ~(1 << (start & 7)); do { array[i] &= mask; i += step; } while (i < size); start += step; } #endif } /* * Returns the index of the next bit set in the given array. The search * begins after the specified bit, so if you care about bit 0, you need * to check it explicitly yourself. This returns 0 if no bits are found. * * Note that the size is in bytes, and that it takes and returns BIT * positions. If the array represents odd numbers only, as usual, the * returned values must be doubled to turn them into offsets from the * initial number. */ unsigned sieveSearch(unsigned char const *array, unsigned size, unsigned start) { unsigned i; /* Loop index */ unsigned char t; /* Temp */ if (!++start) return 0; i = start/8; if (i >= size) return 0; /* Done! */ /* Deal with odd-bit beginnings => search the first byte */ if (start & 7) { t = array[i++] >> (start & 7); if (t) { if (!(t & 15)) { t >>= 4; start += 4; } if (!(t & 3)) { t >>= 2; start += 2; } if (!(t & 1)) start += 1; return start; } else if (i == size) { return 0; /* Done */ } } /* Now the main search loop */ do { if ((t = array[i]) != 0) { start = 8*i; if (!(t & 15)) { t >>= 4; start += 4; } if (!(t & 3)) { t >>= 2; start += 2; } if (!(t & 1)) start += 1; return start; } } while (++i < size); /* Failed */ return 0; } /* * Build a table of small primes for sieving larger primes with. This * could be cached between calls to sieveBuild, but it's so fast that * it's really not worth it. This code takes a few milliseconds to run. */ static void sieveSmall(unsigned char *array, unsigned size) { unsigned i; /* Loop index */ unsigned p; /* The current prime */ /* Initialize to all 1s */ pgpFillMemory(array, size, 0xFF); #if SMALLSTART == 1 /* Mark 1 as NOT prime */ array[0] = 0xfe; i = 1; /* Index of first prime */ #else i = 0; /* Index of first prime */ #endif /* * Okay, now sieve via the primes up to 256, obtained from the * table itself. We know the maximum possible table size is * 65536, and sieveSingle() can cope with out-of-range inputs * safely, and the time required is trivial, so it isn't adaptive * based on the array size. * * Convert each bit position into a prime, compute a starting * sieve position (the square of the prime), and remove multiples * from the table, using sieveSingle(). I used to have that * code in line here, but the speed difference was so small it * wasn't worth it. If a compiler really wants to waste memory, * it can inline it. */ do { p = 2 * i + SMALLSTART; if (p > 256) break; /* Start at square of p */ sieveSingle(array, size, (p*p-SMALLSTART)/2, p); /* And find the next prime */ i = sieveSearch(array, 16, i); } while (i); } /* * This is the primary sieving function. It fills in the array with * a sieve (multiples of small primes removed) beginning at bn and * proceeding in steps of "step". * * It generates a small array to get the primes to sieve by. It's * generated on the fly - sieveSmall is fast enough to make that * perfectly acceptable. * * The caller should take the array, walk it with sieveSearch, and * apply a stronger primality test to the numbers that are returned. * * If the "dbl" flag non-zero (at least 1), this also sieves 2*bn+1, in * steps of 2*step. If dbl is 2 or more, this also sieve 4*bn+3, * in steps of 4*step, and so on for arbitrarily high values of "dbl". * This is convenient for finding primes such that (p-1)/2 is also prime. * This is particularly efficient because sieveSingle is controlled by the * parameter s = -n/step (mod p). (In fact, we find t = -1/step (mod p) * and multiply that by n (mod p).) If you have -n/step (mod p), then * finding -(2*n+1)/(2*step) (mod p), which is -n/step - 1/(2*step) (mod p), * reduces to finding -1/(2*step) (mod p), or t/2 (mod p), and adding that * to s = -n/step (mod p). Dividing by 2 modulo an odd p is easy - * if even, divide directly. Otherwise, add p (which produces an even * sum), and divide by 2. Very simple. And this produces s' and t' * for step' = 2*step. It can be repeated for step'' = 4*step and so on. * * Note that some of the math is complicated by the fact that 2*p might * not fit into an unsigned, so rather than if (odd(x)) x = (x+p)/2, * we do if (odd(x)) x = x/2 + p/2 + 1; * * TODO: Do the double-sieving by sieving the larger number, and then * just subtract one from the remainder to get the other parameter. * (bn-1)/2 is divisible by an odd p iff bn-1 is divisible, which is * true iff bn == 1 mod p. This requires using a step size of 4. */ int sieveBuild(unsigned char *array, unsigned size, BigNum const *bn, unsigned step, unsigned dbl) { unsigned i, j; /* Loop index */ unsigned p; /* Current small prime */ unsigned s; /* Where to start operations in the big sieve */ unsigned t; /* Step modulo p, the current prime */ #ifdef MSDOS /* Use dynamic allocation rather than on the stack */ unsigned char *small; #else unsigned char small[SMALL]; #endif pgpAssert(array); #ifdef MSDOS small = bniMemAlloc(SMALL); /* Which allocator? Not secure. */ if (!small) return -1; /* Failed */ #endif /* * An odd step is a special case, since we must sieve by 2, * which isn't in the small prime array and has a few other * special properties. These are: * - Since the numbers are stored in binary, we don't need to * use bnModQ to find the remainder. * - If step is odd, then t = step % 2 is 1, which allows * the elimination of a lot of math. Inverting and negating * t don't change it, and multiplying s by 1 is a no-op, * so t isn't actually mentioned. * - Since this is the first sieving, instead of calling * sieveSingle, we can just use memset to fill the array * with 0x55 or 0xAA. Since a 1 bit means possible prime * (i.e. NOT divisible by 2), and the least significant bit * is first, if bn % 2 == 0, we use 0xAA (bit 0 = bn is NOT * prime), while if bn % 2 == 1, use 0x55. * (If step is even, bn must be odd, so fill the array with 0xFF.) * - Any doublings need not be considered, since 2*bn+1 is odd, and * 2*step is even, so none of these numbers are divisible by 2. */ if (step & 1) { s = bnLSWord(bn) & 1; memset(array, 0xAA >> s, size); } else { /* Initialize the array to all 1's */ memset(array, 255, size); pgpAssert(bnLSWord(bn) & 1); } /* * This could be cached between calls to sieveBuild, but * it's really not worth it; sieveSmall is *very* fast. * sieveSmall returns a sieve of odd primes. */ sieveSmall(small, SMALL); /* * Okay, now sieve via the primes up to ssize*16+SMALLSTART-1, * obtained from the small table. */ i = (small[0] & 1) ? 0 : sieveSearch(small, SMALL, 0); do { p = 2 * i + SMALLSTART; /* * Modulo is usually very expensive, but step is usually * small, so this conditional is worth it. */ t = (step < p) ? step : step % p; if (!t) { /* * Instead of pgpAssert failing, returning all zero * bits is the "correct" thing to do, but I think * that the caller should take care of that * themselves before starting. */ pgpAssert(bnModQ(bn, p) != 0); continue; } /* * Get inverse of step mod p. 0 < t < p, and p is prime, * so it has an inverse and sieveModInvert can't return 0. */ t = sieveModInvert(t, p); pgpAssert(t); /* Negate t, so now t == -1/step (mod p) */ t = p - t; /* Now get the bignum modulo the prime. */ s = bnModQ(bn, p); /* Multiply by t, the negative inverse of step size */ #if UINT_MAX/0xffff < 0xffff s = (unsigned)(((unsigned long)s * t) % p); #else s = (s * t) % p; #endif /* s is now the starting bit position, so sieve */ sieveSingle(array, size, s, p); /* Now do the double sieves as desired. */ for (j = 0; j < dbl; j++) { /* Halve t modulo p */ #if UINT_MAX < 0x1ffff t = (t & 1) ? p/2 + t/2 + 1 : t/2; /* Add t to s, modulo p with overflow checks. */ s += t; if (s >= p || s < t) s -= p; #else if (t & 1) t += p; t /= 2; /* Add t to s, modulo p */ s += t; if (s >= p) s -= p; #endif sieveSingle(array, size, s, p); } /* And find the next prime */ } while ((i = sieveSearch(small, SMALL, i)) != 0); #ifdef MSDOS bniMemFree(small, SMALL); #endif return 0; /* Success */ } /* * Similar to the above, but use "step" (which must be even) as a step * size rather than a fixed value of 2. If "step" has any small divisors * other than 2, this will blow up. * * Returns -1 on out of memory (MSDOS only, actually), and -2 * if step is found to be non-prime. */ int sieveBuildBig(unsigned char *array, unsigned size, BigNum const *bn, BigNum const *step, unsigned dbl) { unsigned i, j; /* Loop index */ unsigned p; /* Current small prime */ unsigned s; /* Where to start operations in the big sieve */ unsigned t; /* step modulo p, the current prime */ #ifdef MSDOS /* Use dynamic allocation rather than on the stack */ unsigned char *small; #else unsigned char small[SMALL]; #endif pgpAssert(array); #ifdef MSDOS small = bniMemAlloc(SMALL); /* Which allocator? Not secure. */ if (!small) return -1; /* Failed */ #endif /* * An odd step is a special case, since we must sieve by 2, * which isn't in the small prime array and has a few other * special properties. These are: * - Since the numbers are stored in binary, we don't need to * use bnModQ to find the remainder. * - If step is odd, then t = step % 2 is 1, which allows * the elimination of a lot of math. Inverting and negating * t don't change it, and multiplying s by 1 is a no-op, * so t isn't actually mentioned. * - Since this is the first sieving, instead of calling * sieveSingle, we can just use memset to fill the array * with 0x55 or 0xAA. Since a 1 bit means possible prime * (i.e. NOT divisible by 2), and the least significant bit * is first, if bn % 2 == 0, we use 0xAA (bit 0 = bn is NOT * prime), while if bn % 2 == 1, use 0x55. * (If step is even, bn must be odd, so fill the array with 0xFF.) * - Any doublings need not be considered, since 2*bn+1 is odd, and * 2*step is even, so none of these numbers are divisible by 2. */ if (bnLSWord(step) & 1) { s = bnLSWord(bn) & 1; memset(array, 0xAA >> s, size); } else { /* Initialize the array to all 1's */ memset(array, 255, size); pgpAssert(bnLSWord(bn) & 1); } /* * This could be cached between calls to sieveBuild, but * it's really not worth it; sieveSmall is *very* fast. * sieveSmall returns a sieve of the odd primes. */ sieveSmall(small, SMALL); /* * Okay, now sieve via the primes up to ssize*16+SMALLSTART-1, * obtained from the small table. */ i = (small[0] & 1) ? 0 : sieveSearch(small, SMALL, 0); do { p = 2 * i + SMALLSTART; t = bnModQ(step, p); if (!t) { pgpAssert(bnModQ(bn, p) != 0); continue; } /* Get negative inverse of step */ t = sieveModInvert(bnModQ(step, p), p); pgpAssert(t); t = p-t; /* Okay, we have a prime - get the remainder */ s = bnModQ(bn, p); /* Now multiply s by the negative inverse of step (mod p) */ #if UINT_MAX < 0xffff * 0xffff s = (unsigned)(((unsigned long)s * t) % p); #else s = (s * t) % p; #endif /* We now have the starting bit pos */ sieveSingle(array, size, s, p); /* Now do the double sieves as desired. */ for (j = 0; j < dbl; j++) { /* Halve t modulo p */ #if UINT_MAX < 0x1ffff t = (t & 1) ? p/2 + t/2 + 1 : t/2; /* Add t to s, modulo p with overflow checks. */ s += t; if (s >= p || s < t) s -= p; #else if (t & 1) t += p; t /= 2; /* Add t to s, modulo p */ s += t; if (s >= p) s -= p; #endif sieveSingle(array, size, s, p); } /* And find the next prime */ } while ((i = sieveSearch(small, SMALL, i)) != 0); #ifdef MSDOS bniMemFree(small, SMALL); #endif return 0; /* Success */ } tred">LUklbXJvd0c2Iy9JK21vZHVsZW5hbWVHNiJJLFR5cGVzZXR0aW5nR0koX3N5c2xpYkdGJzYoLUkmbWZyYWNHRiQ2KC1GIzYlLUkjbW9HRiQ2MFEwJkRpZmZlcmVudGlhbEQ7RicvJSxtYXRodmFyaWFudEdRJ25vcm1hbEYnLyUmZmVuY2VHUSZ1bnNldEYnLyUqc2VwYXJhdG9yR0Y5LyUpc3RyZXRjaHlHRjkvJSpzeW1tZXRyaWNHRjkvJShsYXJnZW9wR0Y5LyUubW92YWJsZWxpbWl0c0dGOS8lJ2FjY2VudEdGOS8lJWZvcm1HUSFGJy8lJ2xzcGFjZUdGSC8lJ3JzcGFjZUdGSC8lKG1pbnNpemVHRkgvJShtYXhzaXplR0ZILUYxNjBRIn5GJ0Y0L0Y4USZmYWxzZUYnL0Y7RlUvRj1GVS9GP0ZVL0ZBRlUvRkNGVS9GRUZVRkYvRkpRJDBlbUYnL0ZMRmduL0ZOUSIxRicvRlBRKWluZmluaXR5RictSSNtaUdGJDYlUSJnRicvJSdpdGFsaWNHUSV0cnVlRicvRjVRJ2l0YWxpY0YnLUYjNiVGMEZRLUZebzYlUSJ4RidGYW9GZG8vJS5saW5ldGhpY2tuZXNzR1EiMUYnLyUrZGVub21hbGlnbkdRJ2NlbnRlckYnLyUpbnVtYWxpZ25HRmBwLyUpYmV2ZWxsZWRHRlVGUS1JKG1mZW5jZWRHRiQ2JC1GIzYjLUZebzYlUSN4MEYnRmFvRmRvRjQtRjE2MFEiPUYnRjRGVEZWRldGWEZZRlpGZW4vRkdRJmluZml4RicvRkpRL3RoaWNrbWF0aHNwYWNlRicvRkxG