X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/80e2389990082500d76eb566d4946be3e786c3ef..d8f41ccd20de16f8ebe2ccc84d47bf1cb2b26bbb:/Security/libsecurity_cryptkit/lib/feeRandom.c diff --git a/Security/libsecurity_cryptkit/lib/feeRandom.c b/Security/libsecurity_cryptkit/lib/feeRandom.c new file mode 100644 index 00000000..1fedc6ca --- /dev/null +++ b/Security/libsecurity_cryptkit/lib/feeRandom.c @@ -0,0 +1,206 @@ +/* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. + * + * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT + * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE + * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE + * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, + * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL + * EXPOSE YOU TO LIABILITY. + *************************************************************************** + * + * FeeRandom.c - generic, portable random number generator object + * + * Revision History + * ---------------- + * 10/06/98 ap + * Changed to compile with C++. + * 19 Jun 97 at Apple + * Eliminated predictability of bytes 4 thru 15 of random data + * 18 Jun 97 at Apple + * Reduced size of per-instance giants from 128 to 32 shorts + * 23 Aug 96 at NeXT + * Created, based on Blaine Garst's NSRandomNumberGenerator class + */ + +#include "feeRandom.h" +#include "giantIntegers.h" +#include "elliptic.h" +#include "falloc.h" +#include "feeDebug.h" +#include "byteRep.h" +#include +#include "platform.h" + +/* + * 1 ==> do extra nextNum on feeRandAllocWithSeed() + */ +#define EXTRA_NEXT_NUM 0 + +#define RANDBITS 128 /* must be 0 mod GIANT_BITS_PER_DIGIT */ +#define RAND_GIANT_DIGITS (RANDBITS/GIANT_BITS_PER_DIGIT) + +typedef struct { + giant A; + giant C; + giant SEED; + giant x; +} randInst; + +#if GIANTS_VIA_STACK + +/* + * Prime the curveParams and giants modules for quick allocs of giants. + */ +static int giantsInitd = 0; + +static void feeRandInitGiants() +{ + if(giantsInitd) { + return; + } + curveParamsInitGiants(); + giantsInitd = 1; +} +#endif + +static void pmod(giant x, int bits) { + /* Force x to be x (mod 2^bits). */ + int j; + int digits = bits / GIANT_BITS_PER_DIGIT; + + for(j = (digits-1); j >= 0; j--) { + if(x->n[j] != 0) break; + } + x->sign = j+1; +} + + +feeRand feeRandAllocWithSeed(unsigned seed) +{ + randInst *rinst = (randInst *) fmalloc(sizeof(randInst)); + int digits = RAND_GIANT_DIGITS * 4; + unsigned j; + + #if GIANTS_VIA_STACK + feeRandInitGiants(); + #endif + rinst->SEED = newGiant(digits); + rinst->C = newGiant(digits); + rinst->A = newGiant(digits); + rinst->x = newGiant(digits); + rinst->C->sign = rinst->A->sign = rinst->SEED->sign = RAND_GIANT_DIGITS; + for(j=0; jC->n[j] = (giantDigit)(seed + 0xdddddddd - j); + rinst->A->n[j] = (giantDigit)(seed + 0xfff12223 + j); + rinst->SEED->n[j] = (giantDigit)(seed + j); + } + + /* + * on the first feeRandBytes or feeRandNextNum, bytes 4 and 5 of + * the result are duplicated 4.5 times (up to byte 15). Subsequent + * data is indeed random. Thus... + */ + #if EXTRA_NEXT_NUM + feeRandNextNum(rinst); + #endif // EXTRA_NEXT_NUM + return rinst; +} + +feeRand feeRandAlloc(void) +{ + return feeRandAllocWithSeed(createRandomSeed()); +} + +void feeRandFree(feeRand frand) +{ + randInst *rinst = (randInst *) frand; + + clearGiant(rinst->A); + freeGiant(rinst->A); + clearGiant(rinst->C); + freeGiant(rinst->C); + clearGiant(rinst->SEED); + freeGiant(rinst->SEED); + clearGiant(rinst->x); + freeGiant(rinst->x); + ffree(rinst); +} + +unsigned feeRandNextNum(feeRand frand) +{ + randInst *rinst = (randInst *) frand; + unsigned rtn; + + mulg(rinst->A, rinst->SEED); + addg(rinst->C, rinst->SEED); + pmod(rinst->SEED, RANDBITS); + gtog(rinst->SEED, rinst->x); + + /* + * FIXME - this is not quite correct; rinst->x only has 4 bytes + * of valid data if RANDBITS is known to be greater than or equal + * to 32. + */ + rtn = byteRepToInt((unsigned char *)&rinst->x->n); + return rtn; +} + +void feeRandBytes(feeRand frand, + unsigned char *bytes, /* must be alloc'd by caller */ + unsigned numBytes) +{ + randInst *rinst = (randInst *) frand; + int length; + unsigned toCopy; + unsigned char *cp = bytes; + + for (length = numBytes; length > 0; length -= RANDBITS/8) { + mulg(rinst->A, rinst->SEED); + addg(rinst->C, rinst->SEED); + pmod(rinst->SEED, RANDBITS); + gtog(rinst->SEED, rinst->x); + + toCopy = RANDBITS/8; + if(length < toCopy) { + toCopy = length; + } + + /* + * FIXME - not 100% platform independent.... + */ + bcopy(rinst->x->n, cp, toCopy); + cp += toCopy; + } +} + +/* new function, 5 March 1999 - dmitch */ +void feeRandAddEntropy(feeRand frand, unsigned entropy) +{ + randInst *rinst = (randInst *) frand; + giant tmp = borrowGiant(RAND_GIANT_DIGITS); + unsigned i; + + if(entropy == 0) { + /* boy would that be a mistake */ + entropy = 0x12345; + } + for(i=0; in[i] = (giantDigit)entropy; + } + tmp->sign = RAND_GIANT_DIGITS; + mulg(tmp, rinst->SEED); + addg(rinst->C, rinst->SEED); + pmod(rinst->SEED, RANDBITS); + entropy ^= 0xff0ff0ff; + if(entropy == 0) { + entropy = 0x12345; + } + for(i=0; in[i] = (giantDigit)entropy; + } + mulg(tmp, rinst->A); + addg(rinst->C, rinst->A); + pmod(rinst->A, RANDBITS); + /* leave C alone */ + returnGiant(tmp); +}