1*10465441SEvalZero /*****************************************************************************
2*10465441SEvalZero * randm.c - Random number generator program file.
3*10465441SEvalZero *
4*10465441SEvalZero * Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.
5*10465441SEvalZero * Copyright (c) 1998 by Global Election Systems Inc.
6*10465441SEvalZero *
7*10465441SEvalZero * The authors hereby grant permission to use, copy, modify, distribute,
8*10465441SEvalZero * and license this software and its documentation for any purpose, provided
9*10465441SEvalZero * that existing copyright notices are retained in all copies and that this
10*10465441SEvalZero * notice and the following disclaimer are included verbatim in any
11*10465441SEvalZero * distributions. No written agreement, license, or royalty fee is required
12*10465441SEvalZero * for any of the authorized uses.
13*10465441SEvalZero *
14*10465441SEvalZero * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
15*10465441SEvalZero * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16*10465441SEvalZero * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17*10465441SEvalZero * IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
18*10465441SEvalZero * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19*10465441SEvalZero * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20*10465441SEvalZero * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21*10465441SEvalZero * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22*10465441SEvalZero * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23*10465441SEvalZero * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24*10465441SEvalZero *
25*10465441SEvalZero ******************************************************************************
26*10465441SEvalZero * REVISION HISTORY
27*10465441SEvalZero *
28*10465441SEvalZero * 03-01-01 Marc Boucher <[email protected]>
29*10465441SEvalZero * Ported to lwIP.
30*10465441SEvalZero * 98-06-03 Guy Lancaster <[email protected]>, Global Election Systems Inc.
31*10465441SEvalZero * Extracted from avos.
32*10465441SEvalZero *****************************************************************************/
33*10465441SEvalZero
34*10465441SEvalZero #include "lwip/opt.h"
35*10465441SEvalZero
36*10465441SEvalZero #if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */
37*10465441SEvalZero
38*10465441SEvalZero #include "md5.h"
39*10465441SEvalZero #include "randm.h"
40*10465441SEvalZero
41*10465441SEvalZero #include "ppp_impl.h"
42*10465441SEvalZero #include "pppdebug.h"
43*10465441SEvalZero
44*10465441SEvalZero #include <string.h>
45*10465441SEvalZero
46*10465441SEvalZero #if MD5_SUPPORT /* this module depends on MD5 */
47*10465441SEvalZero #define RANDPOOLSZ 16 /* Bytes stored in the pool of randomness. */
48*10465441SEvalZero
49*10465441SEvalZero /*****************************/
50*10465441SEvalZero /*** LOCAL DATA STRUCTURES ***/
51*10465441SEvalZero /*****************************/
52*10465441SEvalZero static char randPool[RANDPOOLSZ]; /* Pool of randomness. */
53*10465441SEvalZero static long randCount = 0; /* Pseudo-random incrementer */
54*10465441SEvalZero
55*10465441SEvalZero
56*10465441SEvalZero /***********************************/
57*10465441SEvalZero /*** PUBLIC FUNCTION DEFINITIONS ***/
58*10465441SEvalZero /***********************************/
59*10465441SEvalZero /*
60*10465441SEvalZero * Initialize the random number generator.
61*10465441SEvalZero *
62*10465441SEvalZero * Since this is to be called on power up, we don't have much
63*10465441SEvalZero * system randomess to work with. Here all we use is the
64*10465441SEvalZero * real-time clock. We'll accumulate more randomness as soon
65*10465441SEvalZero * as things start happening.
66*10465441SEvalZero */
67*10465441SEvalZero void
avRandomInit()68*10465441SEvalZero avRandomInit()
69*10465441SEvalZero {
70*10465441SEvalZero avChurnRand(NULL, 0);
71*10465441SEvalZero }
72*10465441SEvalZero
73*10465441SEvalZero /*
74*10465441SEvalZero * Churn the randomness pool on a random event. Call this early and often
75*10465441SEvalZero * on random and semi-random system events to build randomness in time for
76*10465441SEvalZero * usage. For randomly timed events, pass a null pointer and a zero length
77*10465441SEvalZero * and this will use the system timer and other sources to add randomness.
78*10465441SEvalZero * If new random data is available, pass a pointer to that and it will be
79*10465441SEvalZero * included.
80*10465441SEvalZero *
81*10465441SEvalZero * Ref: Applied Cryptography 2nd Ed. by Bruce Schneier p. 427
82*10465441SEvalZero */
83*10465441SEvalZero void
avChurnRand(char * randData,u32_t randLen)84*10465441SEvalZero avChurnRand(char *randData, u32_t randLen)
85*10465441SEvalZero {
86*10465441SEvalZero MD5_CTX md5;
87*10465441SEvalZero
88*10465441SEvalZero /* LWIP_DEBUGF(LOG_INFO, ("churnRand: %u@%P\n", randLen, randData)); */
89*10465441SEvalZero MD5Init(&md5);
90*10465441SEvalZero MD5Update(&md5, (u_char *)randPool, sizeof(randPool));
91*10465441SEvalZero if (randData) {
92*10465441SEvalZero MD5Update(&md5, (u_char *)randData, randLen);
93*10465441SEvalZero } else {
94*10465441SEvalZero struct {
95*10465441SEvalZero /* INCLUDE fields for any system sources of randomness */
96*10465441SEvalZero char foobar;
97*10465441SEvalZero } sysData;
98*10465441SEvalZero
99*10465441SEvalZero /* Load sysData fields here. */
100*10465441SEvalZero MD5Update(&md5, (u_char *)&sysData, sizeof(sysData));
101*10465441SEvalZero }
102*10465441SEvalZero MD5Final((u_char *)randPool, &md5);
103*10465441SEvalZero /* LWIP_DEBUGF(LOG_INFO, ("churnRand: -> 0\n")); */
104*10465441SEvalZero }
105*10465441SEvalZero
106*10465441SEvalZero /*
107*10465441SEvalZero * Use the random pool to generate random data. This degrades to pseudo
108*10465441SEvalZero * random when used faster than randomness is supplied using churnRand().
109*10465441SEvalZero * Note: It's important that there be sufficient randomness in randPool
110*10465441SEvalZero * before this is called for otherwise the range of the result may be
111*10465441SEvalZero * narrow enough to make a search feasible.
112*10465441SEvalZero *
113*10465441SEvalZero * Ref: Applied Cryptography 2nd Ed. by Bruce Schneier p. 427
114*10465441SEvalZero *
115*10465441SEvalZero * XXX Why does he not just call churnRand() for each block? Probably
116*10465441SEvalZero * so that you don't ever publish the seed which could possibly help
117*10465441SEvalZero * predict future values.
118*10465441SEvalZero * XXX Why don't we preserve md5 between blocks and just update it with
119*10465441SEvalZero * randCount each time? Probably there is a weakness but I wish that
120*10465441SEvalZero * it was documented.
121*10465441SEvalZero */
122*10465441SEvalZero void
avGenRand(char * buf,u32_t bufLen)123*10465441SEvalZero avGenRand(char *buf, u32_t bufLen)
124*10465441SEvalZero {
125*10465441SEvalZero MD5_CTX md5;
126*10465441SEvalZero u_char tmp[16];
127*10465441SEvalZero u32_t n;
128*10465441SEvalZero
129*10465441SEvalZero while (bufLen > 0) {
130*10465441SEvalZero n = LWIP_MIN(bufLen, RANDPOOLSZ);
131*10465441SEvalZero MD5Init(&md5);
132*10465441SEvalZero MD5Update(&md5, (u_char *)randPool, sizeof(randPool));
133*10465441SEvalZero MD5Update(&md5, (u_char *)&randCount, sizeof(randCount));
134*10465441SEvalZero MD5Final(tmp, &md5);
135*10465441SEvalZero randCount++;
136*10465441SEvalZero MEMCPY(buf, tmp, n);
137*10465441SEvalZero buf += n;
138*10465441SEvalZero bufLen -= n;
139*10465441SEvalZero }
140*10465441SEvalZero }
141*10465441SEvalZero
142*10465441SEvalZero /*
143*10465441SEvalZero * Return a new random number.
144*10465441SEvalZero */
145*10465441SEvalZero u32_t
avRandom()146*10465441SEvalZero avRandom()
147*10465441SEvalZero {
148*10465441SEvalZero u32_t newRand;
149*10465441SEvalZero
150*10465441SEvalZero avGenRand((char *)&newRand, sizeof(newRand));
151*10465441SEvalZero
152*10465441SEvalZero return newRand;
153*10465441SEvalZero }
154*10465441SEvalZero
155*10465441SEvalZero #else /* MD5_SUPPORT */
156*10465441SEvalZero
157*10465441SEvalZero /*****************************/
158*10465441SEvalZero /*** LOCAL DATA STRUCTURES ***/
159*10465441SEvalZero /*****************************/
160*10465441SEvalZero static int avRandomized = 0; /* Set when truely randomized. */
161*10465441SEvalZero static u32_t avRandomSeed = 0; /* Seed used for random number generation. */
162*10465441SEvalZero
163*10465441SEvalZero
164*10465441SEvalZero /***********************************/
165*10465441SEvalZero /*** PUBLIC FUNCTION DEFINITIONS ***/
166*10465441SEvalZero /***********************************/
167*10465441SEvalZero /*
168*10465441SEvalZero * Initialize the random number generator.
169*10465441SEvalZero *
170*10465441SEvalZero * Here we attempt to compute a random number seed but even if
171*10465441SEvalZero * it isn't random, we'll randomize it later.
172*10465441SEvalZero *
173*10465441SEvalZero * The current method uses the fields from the real time clock,
174*10465441SEvalZero * the idle process counter, the millisecond counter, and the
175*10465441SEvalZero * hardware timer tick counter. When this is invoked
176*10465441SEvalZero * in startup(), then the idle counter and timer values may
177*10465441SEvalZero * repeat after each boot and the real time clock may not be
178*10465441SEvalZero * operational. Thus we call it again on the first random
179*10465441SEvalZero * event.
180*10465441SEvalZero */
181*10465441SEvalZero void
avRandomInit()182*10465441SEvalZero avRandomInit()
183*10465441SEvalZero {
184*10465441SEvalZero #if 0
185*10465441SEvalZero /* Get a pointer into the last 4 bytes of clockBuf. */
186*10465441SEvalZero u32_t *lptr1 = (u32_t *)((char *)&clockBuf[3]);
187*10465441SEvalZero
188*10465441SEvalZero /*
189*10465441SEvalZero * Initialize our seed using the real-time clock, the idle
190*10465441SEvalZero * counter, the millisecond timer, and the hardware timer
191*10465441SEvalZero * tick counter. The real-time clock and the hardware
192*10465441SEvalZero * tick counter are the best sources of randomness but
193*10465441SEvalZero * since the tick counter is only 16 bit (and truncated
194*10465441SEvalZero * at that), the idle counter and millisecond timer
195*10465441SEvalZero * (which may be small values) are added to help
196*10465441SEvalZero * randomize the lower 16 bits of the seed.
197*10465441SEvalZero */
198*10465441SEvalZero readClk();
199*10465441SEvalZero avRandomSeed += *(u32_t *)clockBuf + *lptr1 + OSIdleCtr
200*10465441SEvalZero + ppp_mtime() + ((u32_t)TM1 << 16) + TM1;
201*10465441SEvalZero #else
202*10465441SEvalZero avRandomSeed += sys_jiffies(); /* XXX */
203*10465441SEvalZero #endif
204*10465441SEvalZero
205*10465441SEvalZero /* Initialize the Borland random number generator. */
206*10465441SEvalZero srand((unsigned)avRandomSeed);
207*10465441SEvalZero }
208*10465441SEvalZero
209*10465441SEvalZero /*
210*10465441SEvalZero * Randomize our random seed value. Here we use the fact that
211*10465441SEvalZero * this function is called at *truely random* times by the polling
212*10465441SEvalZero * and network functions. Here we only get 16 bits of new random
213*10465441SEvalZero * value but we use the previous value to randomize the other 16
214*10465441SEvalZero * bits.
215*10465441SEvalZero */
216*10465441SEvalZero void
avRandomize(void)217*10465441SEvalZero avRandomize(void)
218*10465441SEvalZero {
219*10465441SEvalZero static u32_t last_jiffies;
220*10465441SEvalZero
221*10465441SEvalZero if (!avRandomized) {
222*10465441SEvalZero avRandomized = !0;
223*10465441SEvalZero avRandomInit();
224*10465441SEvalZero /* The initialization function also updates the seed. */
225*10465441SEvalZero } else {
226*10465441SEvalZero /* avRandomSeed += (avRandomSeed << 16) + TM1; */
227*10465441SEvalZero avRandomSeed += (sys_jiffies() - last_jiffies); /* XXX */
228*10465441SEvalZero }
229*10465441SEvalZero last_jiffies = sys_jiffies();
230*10465441SEvalZero }
231*10465441SEvalZero
232*10465441SEvalZero /*
233*10465441SEvalZero * Return a new random number.
234*10465441SEvalZero * Here we use the Borland rand() function to supply a pseudo random
235*10465441SEvalZero * number which we make truely random by combining it with our own
236*10465441SEvalZero * seed which is randomized by truely random events.
237*10465441SEvalZero * Thus the numbers will be truely random unless there have been no
238*10465441SEvalZero * operator or network events in which case it will be pseudo random
239*10465441SEvalZero * seeded by the real time clock.
240*10465441SEvalZero */
241*10465441SEvalZero u32_t
avRandom()242*10465441SEvalZero avRandom()
243*10465441SEvalZero {
244*10465441SEvalZero return ((((u32_t)rand() << 16) + rand()) + avRandomSeed);
245*10465441SEvalZero }
246*10465441SEvalZero
247*10465441SEvalZero #endif /* MD5_SUPPORT */
248*10465441SEvalZero
249*10465441SEvalZero #endif /* PPP_SUPPORT */
250