]>
git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_cryptkit/lib/feeRandom.c
1 /* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved.
3 * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT
4 * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE
5 * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE
6 * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE,
7 * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL
8 * EXPOSE YOU TO LIABILITY.
9 ***************************************************************************
11 * FeeRandom.c - generic, portable random number generator object
16 * Changed to compile with C++.
18 * Eliminated predictability of bytes 4 thru 15 of random data
20 * Reduced size of per-instance giants from 128 to 32 shorts
22 * Created, based on Blaine Garst's NSRandomNumberGenerator class
25 #include "feeRandom.h"
26 #include "giantIntegers.h"
35 * 1 ==> do extra nextNum on feeRandAllocWithSeed()
37 #define EXTRA_NEXT_NUM 0
39 #define RANDBITS 128 /* must be 0 mod GIANT_BITS_PER_DIGIT */
40 #define RAND_GIANT_DIGITS (RANDBITS/GIANT_BITS_PER_DIGIT)
52 * Prime the curveParams and giants modules for quick allocs of giants.
54 static int giantsInitd
= 0;
56 static void feeRandInitGiants()
61 curveParamsInitGiants();
66 static void pmod(giant x
, int bits
) {
67 /* Force x to be x (mod 2^bits). */
69 int digits
= bits
/ GIANT_BITS_PER_DIGIT
;
71 for(j
= (digits
-1); j
>= 0; j
--) {
72 if(x
->n
[j
] != 0) break;
78 feeRand
feeRandAllocWithSeed(unsigned seed
)
80 randInst
*rinst
= (randInst
*) fmalloc(sizeof(randInst
));
81 int digits
= RAND_GIANT_DIGITS
* 4;
87 rinst
->SEED
= newGiant(digits
);
88 rinst
->C
= newGiant(digits
);
89 rinst
->A
= newGiant(digits
);
90 rinst
->x
= newGiant(digits
);
91 rinst
->C
->sign
= rinst
->A
->sign
= rinst
->SEED
->sign
= RAND_GIANT_DIGITS
;
92 for(j
=0; j
<RAND_GIANT_DIGITS
; j
++) {
93 rinst
->C
->n
[j
] = (giantDigit
)(seed
+ 0xdddddddd - j
);
94 rinst
->A
->n
[j
] = (giantDigit
)(seed
+ 0xfff12223 + j
);
95 rinst
->SEED
->n
[j
] = (giantDigit
)(seed
+ j
);
99 * on the first feeRandBytes or feeRandNextNum, bytes 4 and 5 of
100 * the result are duplicated 4.5 times (up to byte 15). Subsequent
101 * data is indeed random. Thus...
104 feeRandNextNum(rinst
);
105 #endif // EXTRA_NEXT_NUM
109 feeRand
feeRandAlloc(void)
111 return feeRandAllocWithSeed(createRandomSeed());
114 void feeRandFree(feeRand frand
)
116 randInst
*rinst
= (randInst
*) frand
;
118 clearGiant(rinst
->A
);
120 clearGiant(rinst
->C
);
122 clearGiant(rinst
->SEED
);
123 freeGiant(rinst
->SEED
);
124 clearGiant(rinst
->x
);
129 unsigned feeRandNextNum(feeRand frand
)
131 randInst
*rinst
= (randInst
*) frand
;
134 mulg(rinst
->A
, rinst
->SEED
);
135 addg(rinst
->C
, rinst
->SEED
);
136 pmod(rinst
->SEED
, RANDBITS
);
137 gtog(rinst
->SEED
, rinst
->x
);
140 * FIXME - this is not quite correct; rinst->x only has 4 bytes
141 * of valid data if RANDBITS is known to be greater than or equal
144 rtn
= byteRepToInt((unsigned char *)&rinst
->x
->n
);
148 void feeRandBytes(feeRand frand
,
149 unsigned char *bytes
, /* must be alloc'd by caller */
152 randInst
*rinst
= (randInst
*) frand
;
155 unsigned char *cp
= bytes
;
157 for (length
= numBytes
; length
> 0; length
-= RANDBITS
/8) {
158 mulg(rinst
->A
, rinst
->SEED
);
159 addg(rinst
->C
, rinst
->SEED
);
160 pmod(rinst
->SEED
, RANDBITS
);
161 gtog(rinst
->SEED
, rinst
->x
);
164 if(length
< toCopy
) {
169 * FIXME - not 100% platform independent....
171 bcopy(rinst
->x
->n
, cp
, toCopy
);
176 /* new function, 5 March 1999 - dmitch */
177 void feeRandAddEntropy(feeRand frand
, unsigned entropy
)
179 randInst
*rinst
= (randInst
*) frand
;
180 giant tmp
= borrowGiant(RAND_GIANT_DIGITS
);
184 /* boy would that be a mistake */
187 for(i
=0; i
<RAND_GIANT_DIGITS
; i
++) {
188 tmp
->n
[i
] = (giantDigit
)entropy
;
190 tmp
->sign
= RAND_GIANT_DIGITS
;
191 mulg(tmp
, rinst
->SEED
);
192 addg(rinst
->C
, rinst
->SEED
);
193 pmod(rinst
->SEED
, RANDBITS
);
194 entropy
^= 0xff0ff0ff;
198 for(i
=0; i
<RAND_GIANT_DIGITS
; i
++) {
199 tmp
->n
[i
] = (giantDigit
)entropy
;
202 addg(rinst
->C
, rinst
->A
);
203 pmod(rinst
->A
, RANDBITS
);