randm.c
上传用户:yyhongfa
上传日期:2013-01-18
资源大小:267k
文件大小:8k
开发平台:

C/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. #include "ppp.h"
  34. #if PPP_SUPPORT > 0
  35. #include "md5.h"
  36. #include "randm.h"
  37. #include "pppdebug.h"
  38. #if MD5_SUPPORT>0   /* this module depends on MD5 */
  39. #define RANDPOOLSZ 16   /* Bytes stored in the pool of randomness. */
  40. /*****************************/
  41. /*** LOCAL DATA STRUCTURES ***/
  42. /*****************************/
  43. static char randPool[RANDPOOLSZ];   /* Pool of randomness. */
  44. static long randCount = 0;      /* Pseudo-random incrementer */
  45. /***********************************/
  46. /*** PUBLIC FUNCTION DEFINITIONS ***/
  47. /***********************************/
  48. /*
  49.  * Initialize the random number generator.
  50.  *
  51.  * Since this is to be called on power up, we don't have much
  52.  *  system randomess to work with.  Here all we use is the
  53.  *  real-time clock.  We'll accumulate more randomness as soon
  54.  *  as things start happening.
  55.  */
  56. void avRandomInit()
  57. {
  58.     avChurnRand(NULL, 0);
  59. }
  60. /*
  61.  * Churn the randomness pool on a random event.  Call this early and often
  62.  *  on random and semi-random system events to build randomness in time for
  63.  *  usage.  For randomly timed events, pass a null pointer and a zero length
  64.  *  and this will use the system timer and other sources to add randomness.
  65.  *  If new random data is available, pass a pointer to that and it will be
  66.  *  included.
  67.  *
  68.  * Ref: Applied Cryptography 2nd Ed. by Bruce Schneier p. 427
  69.  */
  70. void avChurnRand(char *randData, u32_t randLen)
  71. {
  72.     MD5_CTX md5;
  73. /*  ppp_trace(LOG_INFO, "churnRand: %u@%Pn", randLen, randData); */
  74.     MD5Init(&md5);
  75.     MD5Update(&md5, (u_char *)randPool, sizeof(randPool));
  76.     if (randData)
  77.         MD5Update(&md5, (u_char *)randData, randLen);
  78.     else {
  79.         struct {
  80.             /* INCLUDE fields for any system sources of randomness */
  81.             char foobar;
  82.         } sysData;
  83.         /* Load sysData fields here. */
  84.         ;
  85.         MD5Update(&md5, (u_char *)&sysData, sizeof(sysData));
  86.     }
  87.     MD5Final((u_char *)randPool, &md5);
  88. /*  ppp_trace(LOG_INFO, "churnRand: -> 0n"); */
  89. }
  90. /*
  91.  * Use the random pool to generate random data.  This degrades to pseudo
  92.  *  random when used faster than randomness is supplied using churnRand().
  93.  * Note: It's important that there be sufficient randomness in randPool
  94.  *  before this is called for otherwise the range of the result may be
  95.  *  narrow enough to make a search feasible.
  96.  *
  97.  * Ref: Applied Cryptography 2nd Ed. by Bruce Schneier p. 427
  98.  *
  99.  * XXX Why does he not just call churnRand() for each block?  Probably
  100.  *  so that you don't ever publish the seed which could possibly help
  101.  *  predict future values.
  102.  * XXX Why don't we preserve md5 between blocks and just update it with
  103.  *  randCount each time?  Probably there is a weakness but I wish that
  104.  *  it was documented.
  105.  */
  106. void avGenRand(char *buf, u32_t bufLen)
  107. {
  108.     MD5_CTX md5;
  109.     u_char tmp[16];
  110.     u32_t n;
  111.     while (bufLen > 0) {
  112.         n = LWIP_MIN(bufLen, RANDPOOLSZ);
  113.         MD5Init(&md5);
  114.         MD5Update(&md5, (u_char *)randPool, sizeof(randPool));
  115.         MD5Update(&md5, (u_char *)&randCount, sizeof(randCount));
  116.         MD5Final(tmp, &md5);
  117.         randCount++;
  118.         memcpy(buf, tmp, n);
  119.         buf += n;
  120.         bufLen -= n;
  121.     }
  122. }
  123. /*
  124.  * Return a new random number.
  125.  */
  126. u32_t avRandom()
  127. {
  128.     u32_t newRand;
  129.     avGenRand((char *)&newRand, sizeof(newRand));
  130.     return newRand;
  131. }
  132. #else /* MD5_SUPPORT */
  133. /*****************************/
  134. /*** LOCAL DATA STRUCTURES ***/
  135. /*****************************/
  136. static int  avRandomized = 0;       /* Set when truely randomized. */
  137. static u32_t avRandomSeed = 0;      /* Seed used for random number generation. */
  138. /***********************************/
  139. /*** PUBLIC FUNCTION DEFINITIONS ***/
  140. /***********************************/
  141. /*
  142.  * Initialize the random number generator.
  143.  *
  144.  * Here we attempt to compute a random number seed but even if
  145.  * it isn't random, we'll randomize it later.
  146.  *
  147.  * The current method uses the fields from the real time clock,
  148.  * the idle process counter, the millisecond counter, and the
  149.  * hardware timer tick counter.  When this is invoked
  150.  * in startup(), then the idle counter and timer values may
  151.  * repeat after each boot and the real time clock may not be
  152.  * operational.  Thus we call it again on the first random
  153.  * event.
  154.  */
  155. void avRandomInit()
  156. {
  157. #if 0
  158.     /* Get a pointer into the last 4 bytes of clockBuf. */
  159.     u32_t *lptr1 = (u32_t *)((char *)&clockBuf[3]);
  160.     /*
  161.      * Initialize our seed using the real-time clock, the idle
  162.      * counter, the millisecond timer, and the hardware timer
  163.      * tick counter.  The real-time clock and the hardware
  164.      * tick counter are the best sources of randomness but
  165.      * since the tick counter is only 16 bit (and truncated
  166.      * at that), the idle counter and millisecond timer
  167.      * (which may be small values) are added to help
  168.      * randomize the lower 16 bits of the seed.
  169.      */
  170.     readClk();
  171.     avRandomSeed += *(u32_t *)clockBuf + *lptr1 + OSIdleCtr
  172.              + ppp_mtime() + ((u32_t)TM1 << 16) + TM1;
  173. #else
  174.     avRandomSeed += sys_jiffies(); /* XXX */
  175. #endif
  176.         
  177.     /* Initialize the Borland random number generator. */
  178.     srand((unsigned)avRandomSeed);
  179. }
  180. /*
  181.  * Randomize our random seed value.  Here we use the fact that
  182.  * this function is called at *truely random* times by the polling
  183.  * and network functions.  Here we only get 16 bits of new random
  184.  * value but we use the previous value to randomize the other 16
  185.  * bits.
  186.  */
  187. void avRandomize(void)
  188. {
  189.     static u32_t last_jiffies;
  190.     if (!avRandomized) {
  191.         avRandomized = !0;
  192.         avRandomInit();
  193.         /* The initialization function also updates the seed. */
  194.     } else {
  195. /*        avRandomSeed += (avRandomSeed << 16) + TM1; */
  196.      avRandomSeed += (sys_jiffies() - last_jiffies); /* XXX */
  197.     }
  198.     last_jiffies = sys_jiffies();
  199. }
  200. /*
  201.  * Return a new random number.
  202.  * Here we use the Borland rand() function to supply a pseudo random
  203.  * number which we make truely random by combining it with our own
  204.  * seed which is randomized by truely random events. 
  205.  * Thus the numbers will be truely random unless there have been no
  206.  * operator or network events in which case it will be pseudo random
  207.  * seeded by the real time clock.
  208.  */
  209. u32_t avRandom()
  210. {
  211.     return ((((u32_t)rand() << 16) + rand()) + avRandomSeed);
  212. }
  213. #endif /* MD5_SUPPORT */
  214. #endif /* PPP_SUPPORT */