Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of lwip by
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:29:37 by
