]> git.saurik.com Git - apple/security.git/blobdiff - Security/libsecurity_cryptkit/lib/feeRandom.c
Security-57031.1.35.tar.gz
[apple/security.git] / 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 (file)
index 0000000..1fedc6c
--- /dev/null
@@ -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 <stdlib.h>
+#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; j<RAND_GIANT_DIGITS; j++) {
+           rinst->C->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; i<RAND_GIANT_DIGITS; i++) {
+               tmp->n[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; i<RAND_GIANT_DIGITS; i++) {
+               tmp->n[i] = (giantDigit)entropy;
+       }
+               mulg(tmp, rinst->A);
+        addg(rinst->C, rinst->A);
+        pmod(rinst->A, RANDBITS);
+        /* leave C alone */
+               returnGiant(tmp);
+}