Robustness fixes for KEXINIT handling and others. In particular, I've
[u/mdw/putty] / unix / uxnoise.c
CommitLineData
c5e438ec 1/*
2 * Noise generation for PuTTY's cryptographic random number
3 * generator.
4 */
5
6#include <stdio.h>
7#include <fcntl.h>
8#include <unistd.h>
9#include <sys/time.h>
d9c40fd6 10#include <sys/resource.h>
c5e438ec 11
12#include "putty.h"
13#include "ssh.h"
14#include "storage.h"
15
d9c40fd6 16static int read_dev_urandom(char *buf, int len)
c5e438ec 17{
18 int fd;
19 int ngot, ret;
20
21 fd = open("/dev/urandom", O_RDONLY);
d9c40fd6 22 if (fd < 0)
23 return 0;
c5e438ec 24
25 ngot = 0;
26 while (ngot < len) {
27 ret = read(fd, buf+ngot, len-ngot);
28 if (ret < 0) {
d9c40fd6 29 close(fd);
30 return 0;
c5e438ec 31 }
32 ngot += ret;
33 }
d9c40fd6 34
35 return 1;
c5e438ec 36}
37
38/*
d9c40fd6 39 * This function is called once, at PuTTY startup. It will do some
40 * slightly silly things such as fetching an entire process listing
41 * and scanning /tmp, load the saved random seed from disk, and
42 * also read 32 bytes out of /dev/urandom.
c5e438ec 43 */
44
45void noise_get_heavy(void (*func) (void *, int))
46{
d9c40fd6 47 char buf[512];
48 FILE *fp;
49 int ret;
50
51 if (read_dev_urandom(buf, 32))
52 func(buf, 32);
53
54 fp = popen("ps -axu 2>/dev/null", "r");
55 while ( (ret = fread(buf, 1, sizeof(buf), fp)) > 0)
56 func(buf, ret);
57 pclose(fp);
58
59 fp = popen("ls -al /tmp 2>/dev/null", "r");
60 while ( (ret = fread(buf, 1, sizeof(buf), fp)) > 0)
61 func(buf, ret);
62 pclose(fp);
63
64 read_random_seed(func);
c5e438ec 65}
66
67void random_save_seed(void)
68{
d9c40fd6 69 int len;
70 void *data;
71
72 if (random_active) {
73 random_get_savedata(&data, &len);
74 write_random_seed(data, len);
75 }
c5e438ec 76}
77
78/*
d9c40fd6 79 * This function is called every time the random pool needs
c5e438ec 80 * stirring, and will acquire the system time.
81 */
82void noise_get_light(void (*func) (void *, int))
83{
84 struct timeval tv;
85 gettimeofday(&tv, NULL);
86 func(&tv, sizeof(tv));
87}
88
89/*
d9c40fd6 90 * This function is called on a timer, and grabs as much changeable
91 * system data as it can quickly get its hands on.
c5e438ec 92 */
93void noise_regular(void)
94{
d9c40fd6 95 int fd;
96 int ret;
97 char buf[512];
98 struct rusage rusage;
99
100 if ((fd = open("/proc/meminfo", O_RDONLY)) >= 0) {
101 while ( (ret = read(fd, buf, sizeof(buf))) > 0)
102 random_add_noise(buf, ret);
103 close(fd);
104 }
105 if ((fd = open("/proc/stat", O_RDONLY)) >= 0) {
106 while ( (ret = read(fd, buf, sizeof(buf))) > 0)
107 random_add_noise(buf, ret);
108 close(fd);
109 }
110 getrusage(RUSAGE_SELF, &rusage);
111 random_add_noise(&rusage, sizeof(rusage));
c5e438ec 112}
113
114/*
115 * This function is called on every keypress or mouse move, and
116 * will add the current time to the noise pool. It gets the scan
117 * code or mouse position passed in, and adds that too.
118 */
119void noise_ultralight(unsigned long data)
120{
121 struct timeval tv;
122 gettimeofday(&tv, NULL);
123 random_add_noise(&tv, sizeof(tv));
124 random_add_noise(&data, sizeof(data));
125}