Sebastian Kuschel reports that pfd_closing can be called for a socket
[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>
26d755bc 7#include <stdlib.h>
8#include <errno.h>
9
c5e438ec 10#include <fcntl.h>
11#include <unistd.h>
12#include <sys/time.h>
d9c40fd6 13#include <sys/resource.h>
c5e438ec 14
15#include "putty.h"
16#include "ssh.h"
17#include "storage.h"
18
d9c40fd6 19static int read_dev_urandom(char *buf, int len)
c5e438ec 20{
21 int fd;
22 int ngot, ret;
23
24 fd = open("/dev/urandom", O_RDONLY);
d9c40fd6 25 if (fd < 0)
26 return 0;
c5e438ec 27
28 ngot = 0;
29 while (ngot < len) {
30 ret = read(fd, buf+ngot, len-ngot);
31 if (ret < 0) {
d9c40fd6 32 close(fd);
33 return 0;
c5e438ec 34 }
35 ngot += ret;
36 }
d9c40fd6 37
2fa6ce2c 38 close(fd);
39
d9c40fd6 40 return 1;
c5e438ec 41}
42
43/*
d9c40fd6 44 * This function is called once, at PuTTY startup. It will do some
45 * slightly silly things such as fetching an entire process listing
46 * and scanning /tmp, load the saved random seed from disk, and
47 * also read 32 bytes out of /dev/urandom.
c5e438ec 48 */
49
50void noise_get_heavy(void (*func) (void *, int))
51{
d9c40fd6 52 char buf[512];
53 FILE *fp;
54 int ret;
26d755bc 55 int got_dev_urandom = 0;
d9c40fd6 56
26d755bc 57 if (read_dev_urandom(buf, 32)) {
58 got_dev_urandom = 1;
d9c40fd6 59 func(buf, 32);
26d755bc 60 }
d9c40fd6 61
62 fp = popen("ps -axu 2>/dev/null", "r");
26d755bc 63 if (fp) {
64 while ( (ret = fread(buf, 1, sizeof(buf), fp)) > 0)
65 func(buf, ret);
66 pclose(fp);
67 } else if (!got_dev_urandom) {
68 fprintf(stderr, "popen: %s\n"
69 "Unable to access fallback entropy source\n", strerror(errno));
70 exit(1);
71 }
d9c40fd6 72
73 fp = popen("ls -al /tmp 2>/dev/null", "r");
26d755bc 74 if (fp) {
75 while ( (ret = fread(buf, 1, sizeof(buf), fp)) > 0)
76 func(buf, ret);
77 pclose(fp);
78 } else if (!got_dev_urandom) {
79 fprintf(stderr, "popen: %s\n"
80 "Unable to access fallback entropy source\n", strerror(errno));
81 exit(1);
82 }
d9c40fd6 83
84 read_random_seed(func);
e3ac3c05 85 random_save_seed();
c5e438ec 86}
87
88void random_save_seed(void)
89{
d9c40fd6 90 int len;
91 void *data;
92
93 if (random_active) {
94 random_get_savedata(&data, &len);
95 write_random_seed(data, len);
e3ac3c05 96 sfree(data);
d9c40fd6 97 }
c5e438ec 98}
99
100/*
d9c40fd6 101 * This function is called every time the random pool needs
c5e438ec 102 * stirring, and will acquire the system time.
103 */
104void noise_get_light(void (*func) (void *, int))
105{
106 struct timeval tv;
107 gettimeofday(&tv, NULL);
108 func(&tv, sizeof(tv));
109}
110
111/*
d9c40fd6 112 * This function is called on a timer, and grabs as much changeable
113 * system data as it can quickly get its hands on.
c5e438ec 114 */
115void noise_regular(void)
116{
d9c40fd6 117 int fd;
118 int ret;
119 char buf[512];
120 struct rusage rusage;
121
122 if ((fd = open("/proc/meminfo", O_RDONLY)) >= 0) {
123 while ( (ret = read(fd, buf, sizeof(buf))) > 0)
124 random_add_noise(buf, ret);
125 close(fd);
126 }
127 if ((fd = open("/proc/stat", O_RDONLY)) >= 0) {
128 while ( (ret = read(fd, buf, sizeof(buf))) > 0)
129 random_add_noise(buf, ret);
130 close(fd);
131 }
132 getrusage(RUSAGE_SELF, &rusage);
133 random_add_noise(&rusage, sizeof(rusage));
c5e438ec 134}
135
136/*
137 * This function is called on every keypress or mouse move, and
138 * will add the current time to the noise pool. It gets the scan
139 * code or mouse position passed in, and adds that too.
140 */
141void noise_ultralight(unsigned long data)
142{
143 struct timeval tv;
144 gettimeofday(&tv, NULL);
145 random_add_noise(&tv, sizeof(tv));
146 random_add_noise(&data, sizeof(data));
147}