uxnoise.c 3.1 KB

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