comparison random.c @ 347:381834084475 debug-unrandom

be sure not to include uninitialised buffers in the unrandom number generator
author Matt Johnston <matt@ucc.asn.au>
date Fri, 04 Aug 2006 17:37:45 +0000
parents 959c66ccf1b5
children e66eec4dcba7
comparison
equal deleted inserted replaced
346:ed24dfc44904 347:381834084475
36 36
37 static unsigned char hashpool[SHA1_HASH_SIZE]; 37 static unsigned char hashpool[SHA1_HASH_SIZE];
38 38
39 #define INIT_SEED_SIZE 32 /* 256 bits */ 39 #define INIT_SEED_SIZE 32 /* 256 bits */
40 40
41 static void readrand(unsigned char* buf, unsigned int buflen);
42
43 /* The basic setup is we read some data from /dev/(u)random or prngd and hash it
44 * into hashpool. To read data, we hash together current hashpool contents,
45 * and a counter. We feed more data in by hashing the current pool and new
46 * data into the pool.
47 *
48 * It is important to ensure that counter doesn't wrap around before we
49 * feed in new entropy.
50 *
51 */
52
53 static void readrand(unsigned char* buf, unsigned int buflen) {
54
55 static int already_blocked = 0;
56 int readfd;
57 unsigned int readpos;
58 int readlen;
59 #ifdef DROPBEAR_PRNGD_SOCKET
60 struct sockaddr_un egdsock;
61 char egdcmd[2];
62 #endif
63
64 #ifdef DROPBEAR_RANDOM_DEV
65 readfd = open(DROPBEAR_RANDOM_DEV, O_RDONLY);
66 if (readfd < 0) {
67 dropbear_exit("couldn't open random device");
68 }
69 #endif
70
71 #ifdef DROPBEAR_PRNGD_SOCKET
72 memset((void*)&egdsock, 0x0, sizeof(egdsock));
73 egdsock.sun_family = AF_UNIX;
74 strlcpy(egdsock.sun_path, DROPBEAR_PRNGD_SOCKET,
75 sizeof(egdsock.sun_path));
76
77 readfd = socket(PF_UNIX, SOCK_STREAM, 0);
78 if (readfd < 0) {
79 dropbear_exit("couldn't open random device");
80 }
81 /* todo - try various common locations */
82 if (connect(readfd, (struct sockaddr*)&egdsock,
83 sizeof(struct sockaddr_un)) < 0) {
84 dropbear_exit("couldn't open random device");
85 }
86
87 if (buflen > 255)
88 dropbear_exit("can't request more than 255 bytes from egd");
89 egdcmd[0] = 0x02; /* blocking read */
90 egdcmd[1] = (unsigned char)buflen;
91 if (write(readfd, egdcmd, 2) < 0)
92 dropbear_exit("can't send command to egd");
93 #endif
94
95 /* read the actual random data */
96
97 close (readfd);
98 }
99
100 /* initialise the prng from /dev/(u)random or prngd */ 41 /* initialise the prng from /dev/(u)random or prngd */
101 void seedrandom() { 42 void seedrandom() {
102
103 unsigned char readbuf[INIT_SEED_SIZE];
104
105 hash_state hs;
106 43
107 /* initialise so that things won't warn about 44 /* initialise so that things won't warn about
108 * hashing an undefined buffer */ 45 * hashing an undefined buffer */
109 if (!donerandinit) { 46 m_burn(hashpool, sizeof(hashpool));
110 m_burn(hashpool, sizeof(hashpool));
111 }
112
113 /* get the seed data */
114 readrand(readbuf, sizeof(readbuf));
115
116 /* hash in the new seed data */
117 sha1_init(&hs);
118 sha1_process(&hs, (void*)hashpool, sizeof(hashpool));
119 sha1_process(&hs, (void*)readbuf, sizeof(readbuf));
120 sha1_done(&hs, hashpool);
121 47
122 counter = 0; 48 counter = 0;
123 donerandinit = 1; 49 donerandinit = 1;
124 } 50 }
125 51