]> diplodocus.org Git - nmh/blob - sbr/m_rand.c
Various IMAP protocol improvements
[nmh] / sbr / m_rand.c
1 /* m_rand.c -- provides pseudorandom bytes
2 *
3 * This code is Copyright (c) 2012, by the authors of nmh. See the
4 * COPYRIGHT file in the root directory of the nmh distribution for
5 * complete copyright information.
6 */
7
8 #include <stdlib.h> /* for abs(), srand(), rand(), arc4random() */
9 #include <stdbool.h>
10 #include <stdio.h> /* for fopen(), fread(), fclose() */
11 #include <unistd.h> /* for getpid() */
12 #include <time.h> /* for time() */
13
14 #include <config.h>
15 #include "m_rand.h"
16
17 #if !HAVE_ARC4RANDOM
18 static bool seeded = false;
19 #endif
20
21
22 int
23 m_rand (unsigned char *buf, size_t n)
24 {
25 #if !HAVE_ARC4RANDOM
26 if (! seeded) {
27 FILE *devurandom;
28 unsigned int seed;
29
30 if ((devurandom = fopen ("/dev/urandom", "r"))) {
31 if (fread (&seed, sizeof (seed), 1, devurandom) == 1)
32 seeded = true;
33 fclose (devurandom);
34 }
35
36 if (! seeded) {
37 /* This seed calculation is from Helmut G. Katzgraber, "Random
38 Numbers in Scientific Computing: An Introduction",
39 arXiv:1005.4117v1 [physics.comp-ph], 22 May 2010, p. 19.
40 time() and getpid() shouldn't fail on POSIX platforms. */
41 seed = abs ((int) ((time (0) * 181 * ((getpid ()-83) * 359)) % 104729));
42 seeded = true;
43 }
44
45 srand (seed);
46 }
47
48 while (n > 0) {
49 int rnd = rand ();
50 unsigned char *rndp = (unsigned char *) &rnd;
51 unsigned int i;
52
53 for (i = 0; i < sizeof rnd && n > 0; ++i, --n) {
54 *buf++ = *rndp++;
55 }
56 }
57 #else
58 arc4random_buf(buf, n);
59 #endif
60
61 return 0;
62 }