NetServices Stack source
Dependents: HelloWorld ServoInterfaceBoardExample1 4180_Lab4
randm.c
00001 /***************************************************************************** 00002 * randm.c - Random number generator program file. 00003 * 00004 * Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. 00005 * Copyright (c) 1998 by Global Election Systems Inc. 00006 * 00007 * The authors hereby grant permission to use, copy, modify, distribute, 00008 * and license this software and its documentation for any purpose, provided 00009 * that existing copyright notices are retained in all copies and that this 00010 * notice and the following disclaimer are included verbatim in any 00011 * distributions. No written agreement, license, or royalty fee is required 00012 * for any of the authorized uses. 00013 * 00014 * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR 00015 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00016 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 00017 * IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00018 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 00019 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00020 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00021 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00022 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 00023 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00024 * 00025 ****************************************************************************** 00026 * REVISION HISTORY 00027 * 00028 * 03-01-01 Marc Boucher <marc@mbsi.ca> 00029 * Ported to lwIP. 00030 * 98-06-03 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc. 00031 * Extracted from avos. 00032 *****************************************************************************/ 00033 00034 #include "lwip/opt.h" 00035 00036 #if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ 00037 00038 #include "md5.h" 00039 #include "randm.h" 00040 00041 #include "ppp.h" 00042 #include "pppdebug.h" 00043 00044 #include <string.h> 00045 00046 #if MD5_SUPPORT /* this module depends on MD5 */ 00047 #define RANDPOOLSZ 16 /* Bytes stored in the pool of randomness. */ 00048 00049 /*****************************/ 00050 /*** LOCAL DATA STRUCTURES ***/ 00051 /*****************************/ 00052 static char randPool[RANDPOOLSZ]; /* Pool of randomness. */ 00053 static long randCount = 0; /* Pseudo-random incrementer */ 00054 00055 00056 /***********************************/ 00057 /*** PUBLIC FUNCTION DEFINITIONS ***/ 00058 /***********************************/ 00059 /* 00060 * Initialize the random number generator. 00061 * 00062 * Since this is to be called on power up, we don't have much 00063 * system randomess to work with. Here all we use is the 00064 * real-time clock. We'll accumulate more randomness as soon 00065 * as things start happening. 00066 */ 00067 void 00068 avRandomInit() 00069 { 00070 avChurnRand(NULL, 0); 00071 } 00072 00073 /* 00074 * Churn the randomness pool on a random event. Call this early and often 00075 * on random and semi-random system events to build randomness in time for 00076 * usage. For randomly timed events, pass a null pointer and a zero length 00077 * and this will use the system timer and other sources to add randomness. 00078 * If new random data is available, pass a pointer to that and it will be 00079 * included. 00080 * 00081 * Ref: Applied Cryptography 2nd Ed. by Bruce Schneier p. 427 00082 */ 00083 void 00084 avChurnRand(char *randData, u32_t randLen) 00085 { 00086 MD5_CTX md5; 00087 00088 /* LWIP_DEBUGF(LOG_INFO, ("churnRand: %u@%P\n", randLen, randData)); */ 00089 MD5Init(&md5); 00090 MD5Update(&md5, (u_char *)randPool, sizeof(randPool)); 00091 if (randData) { 00092 MD5Update(&md5, (u_char *)randData, randLen); 00093 } else { 00094 struct { 00095 /* INCLUDE fields for any system sources of randomness */ 00096 char foobar; 00097 } sysData; 00098 00099 /* Load sysData fields here. */ 00100 MD5Update(&md5, (u_char *)&sysData, sizeof(sysData)); 00101 } 00102 MD5Final((u_char *)randPool, &md5); 00103 /* LWIP_DEBUGF(LOG_INFO, ("churnRand: -> 0\n")); */ 00104 } 00105 00106 /* 00107 * Use the random pool to generate random data. This degrades to pseudo 00108 * random when used faster than randomness is supplied using churnRand(). 00109 * Note: It's important that there be sufficient randomness in randPool 00110 * before this is called for otherwise the range of the result may be 00111 * narrow enough to make a search feasible. 00112 * 00113 * Ref: Applied Cryptography 2nd Ed. by Bruce Schneier p. 427 00114 * 00115 * XXX Why does he not just call churnRand() for each block? Probably 00116 * so that you don't ever publish the seed which could possibly help 00117 * predict future values. 00118 * XXX Why don't we preserve md5 between blocks and just update it with 00119 * randCount each time? Probably there is a weakness but I wish that 00120 * it was documented. 00121 */ 00122 void 00123 avGenRand(char *buf, u32_t bufLen) 00124 { 00125 MD5_CTX md5; 00126 u_char tmp[16]; 00127 u32_t n; 00128 00129 while (bufLen > 0) { 00130 n = LWIP_MIN(bufLen, RANDPOOLSZ); 00131 MD5Init(&md5); 00132 MD5Update(&md5, (u_char *)randPool, sizeof(randPool)); 00133 MD5Update(&md5, (u_char *)&randCount, sizeof(randCount)); 00134 MD5Final(tmp, &md5); 00135 randCount++; 00136 MEMCPY(buf, tmp, n); 00137 buf += n; 00138 bufLen -= n; 00139 } 00140 } 00141 00142 /* 00143 * Return a new random number. 00144 */ 00145 u32_t 00146 avRandom() 00147 { 00148 u32_t newRand; 00149 00150 avGenRand((char *)&newRand, sizeof(newRand)); 00151 00152 return newRand; 00153 } 00154 00155 #else /* MD5_SUPPORT */ 00156 00157 /*****************************/ 00158 /*** LOCAL DATA STRUCTURES ***/ 00159 /*****************************/ 00160 static int avRandomized = 0; /* Set when truely randomized. */ 00161 static u32_t avRandomSeed = 0; /* Seed used for random number generation. */ 00162 00163 00164 /***********************************/ 00165 /*** PUBLIC FUNCTION DEFINITIONS ***/ 00166 /***********************************/ 00167 /* 00168 * Initialize the random number generator. 00169 * 00170 * Here we attempt to compute a random number seed but even if 00171 * it isn't random, we'll randomize it later. 00172 * 00173 * The current method uses the fields from the real time clock, 00174 * the idle process counter, the millisecond counter, and the 00175 * hardware timer tick counter. When this is invoked 00176 * in startup(), then the idle counter and timer values may 00177 * repeat after each boot and the real time clock may not be 00178 * operational. Thus we call it again on the first random 00179 * event. 00180 */ 00181 void 00182 avRandomInit() 00183 { 00184 #if 0 00185 /* Get a pointer into the last 4 bytes of clockBuf. */ 00186 u32_t *lptr1 = (u32_t *)((char *)&clockBuf[3]); 00187 00188 /* 00189 * Initialize our seed using the real-time clock, the idle 00190 * counter, the millisecond timer, and the hardware timer 00191 * tick counter. The real-time clock and the hardware 00192 * tick counter are the best sources of randomness but 00193 * since the tick counter is only 16 bit (and truncated 00194 * at that), the idle counter and millisecond timer 00195 * (which may be small values) are added to help 00196 * randomize the lower 16 bits of the seed. 00197 */ 00198 readClk(); 00199 avRandomSeed += *(u32_t *)clockBuf + *lptr1 + OSIdleCtr 00200 + ppp_mtime() + ((u32_t)TM1 << 16) + TM1; 00201 #else 00202 avRandomSeed += sys_jiffies(); /* XXX */ 00203 #endif 00204 00205 /* Initialize the Borland random number generator. */ 00206 srand((unsigned)avRandomSeed); 00207 } 00208 00209 /* 00210 * Randomize our random seed value. Here we use the fact that 00211 * this function is called at *truely random* times by the polling 00212 * and network functions. Here we only get 16 bits of new random 00213 * value but we use the previous value to randomize the other 16 00214 * bits. 00215 */ 00216 void 00217 avRandomize(void) 00218 { 00219 static u32_t last_jiffies; 00220 00221 if (!avRandomized) { 00222 avRandomized = !0; 00223 avRandomInit(); 00224 /* The initialization function also updates the seed. */ 00225 } else { 00226 /* avRandomSeed += (avRandomSeed << 16) + TM1; */ 00227 avRandomSeed += (sys_jiffies() - last_jiffies); /* XXX */ 00228 } 00229 last_jiffies = sys_jiffies(); 00230 } 00231 00232 /* 00233 * Return a new random number. 00234 * Here we use the Borland rand() function to supply a pseudo random 00235 * number which we make truely random by combining it with our own 00236 * seed which is randomized by truely random events. 00237 * Thus the numbers will be truely random unless there have been no 00238 * operator or network events in which case it will be pseudo random 00239 * seeded by the real time clock. 00240 */ 00241 u32_t 00242 avRandom() 00243 { 00244 return ((((u32_t)rand() << 16) + rand()) + avRandomSeed); 00245 } 00246 00247 #endif /* MD5_SUPPORT */ 00248 00249 #endif /* PPP_SUPPORT */
Generated on Tue Jul 12 2022 11:52:58 by 1.7.2