Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


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