noise.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  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 bool 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 false;
  22. ngot = 0;
  23. while (ngot < len) {
  24. ret = read(fd, buf+ngot, len-ngot);
  25. if (ret < 0) {
  26. close(fd);
  27. return false;
  28. }
  29. ngot += ret;
  30. }
  31. close(fd);
  32. return true;
  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. bool got_dev_urandom = false;
  46. if (read_dev_urandom(buf, 32)) {
  47. got_dev_urandom = true;
  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. }
  72. /*
  73. * This function is called on a timer, and grabs as much changeable
  74. * system data as it can quickly get its hands on.
  75. */
  76. void noise_regular(void)
  77. {
  78. int fd;
  79. int ret;
  80. char buf[512];
  81. struct rusage rusage;
  82. if ((fd = open("/proc/meminfo", O_RDONLY)) >= 0) {
  83. while ( (ret = read(fd, buf, sizeof(buf))) > 0)
  84. random_add_noise(NOISE_SOURCE_MEMINFO, buf, ret);
  85. close(fd);
  86. }
  87. if ((fd = open("/proc/stat", O_RDONLY)) >= 0) {
  88. while ( (ret = read(fd, buf, sizeof(buf))) > 0)
  89. random_add_noise(NOISE_SOURCE_STAT, buf, ret);
  90. close(fd);
  91. }
  92. getrusage(RUSAGE_SELF, &rusage);
  93. random_add_noise(NOISE_SOURCE_RUSAGE, &rusage, sizeof(rusage));
  94. }
  95. /*
  96. * This function is called on every keypress or mouse move, and
  97. * will add the current time to the noise pool. It gets the scan
  98. * code or mouse position passed in, and adds that too.
  99. */
  100. void noise_ultralight(NoiseSourceId id, unsigned long data)
  101. {
  102. struct timeval tv;
  103. gettimeofday(&tv, NULL);
  104. random_add_noise(NOISE_SOURCE_TIME, &tv, sizeof(tv));
  105. random_add_noise(id, &data, sizeof(data));
  106. }
  107. uint64_t prng_reseed_time_ms(void)
  108. {
  109. struct timeval tv;
  110. gettimeofday(&tv, NULL);
  111. return tv.tv_sec * 1000 + tv.tv_usec / 1000;
  112. }