1 /*
2  * Generate random material - Simple Nomad <thegnome@nmrc.org>
3  * Reworked for additional strength and entropy
4  * - Todd MacDermid <tmacd@synacklabs.net>
5  * Use #include "rand_gen.h" in your code.
6  *
7  * 08Sep2004 - Tweak for sched.h error on djgpp compat.
8  *
9  * 26Apr2003 - Tweak for djgpp compat.
10  *
11  * 21Apr2003 - Revised to use ISAAC as a stronger PRNG, and to use
12  *             processor timing as entropy source, a la chapter 10 of
13  *             "Building Secure Software" by John Viega and Gary McGraw
14  *
15  * 30Oct2002 - Initial revision. seedrandnum and getrandnum are basically
16  *             stolen from libnet, Copyright (c) 1998,1999 Mike D. Schiffman.
17  */
18 
19 #include <stdlib.h>
20 #include <sys/time.h>
21 #include <string.h>
22 #ifdef SCHED_YIELD
23 #include <sched.h>
24 #endif
25 #ifndef STANDARD
26 #include "standard.h"
27 #endif
28 #ifndef RAND
29 #include "rand.h"
30 #endif
31 #include "rand_gen.h"
32 
33 randctx ctx;
34 
35 /*
36  * seeds the prng, returns -1 if it fails, 1 if successful
37  * Entropy estimation: Viega and McGraw estimate that this method provides
38  * between 1 and 3 bits of entropy per sched_yield(). This puts us somewhere
39  * between 256 and 768 bits of entropy, which should be sufficient.
40  */
41 
seed_rand_num(void)42 int seed_rand_num(void)
43 {
44   struct timeval seed;
45   int i;
46 
47   for(i = 0; i < RANDSIZ; i++) {
48     if(gettimeofday(&seed, NULL) == -1) return (-1);
49     ctx.randrsl[i] ^= seed.tv_sec ^ seed.tv_usec;
50 #ifdef SCHED_YIELD /* djgpp doesn't support this */
51     sched_yield();
52 #endif
53   }
54   randinit(&ctx, TRUE);
55   return (1);
56 }
57 
58 /*
59  * returns a random number after being passed a value
60  */
get_rand_num(int i)61 unsigned long get_rand_num(int i)
62 {
63   unsigned long j;
64   j = rand(&ctx);
65 
66   switch (i)
67   {
68     case R_BIT: return (j % 0x2);               /* 0-1 */
69     case R_BYTE: return (j % 0xff);             /* 0-255 */
70     case R_SIGNEDWORD: return (j % 0x7fff);     /* 0-32768 */
71     case R_UNSIGNEDWORD: return (j % 0xffff);   /* 0-65535 */
72     case R_SIGNEDLONG: return (j % 0x7fffffff); /* 0-2147483647 */
73     case R_UNSIGNEDLONG: return (j);            /* 0-4294967295 */
74   }
75   return(0);
76 }
77 
78 /*
79  * Takes orig and filled material with origorigorig etc, len is length of
80  * material variable.
81  *
82  * Call like this:
83  *
84  * char *text;
85  * unsigned char somematerial[256];
86  *
87  * extend_mat(text,&somematerial[0],256);
88  */
extend_mat(char * orig,unsigned char * material,int len)89 void extend_mat(char *orig, unsigned char *material, int len)
90 {
91   int i,k,j=0;
92 
93   k = strlen(orig);
94   for(i=0;i<len;i++)
95   {
96     material[i] = orig[j++];
97     if(j == k) j=0;
98   }
99 }
100 /*
101  * writes random data to material, len is length of material, call
102  * seed_rand_num before calling this routine
103  *
104  * Call like this:
105  *
106  * unsigned char randmaterial[1024];
107  *
108  * gen_rand_mat(&randmaterial[0],1024);
109  */
gen_rand_mat(unsigned char * material,int len)110 void gen_rand_mat(unsigned char *material, int len)
111 {
112   int i;
113 
114   for(i=0;i<len;i++) material[i] = get_rand_num(R_BYTE);
115 }
116