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