13 #include "util/random.h"
18 static int seeded
= 0;
29 pseudorandom_nonce(unsigned char buf
[], size_t size
)
31 static int initialized
= 0;
32 static int accept_bits
;
33 static int accept_mask
;
34 unsigned int got_mask
;
35 unsigned int got_random
;
43 /* 32767 <= RAND_MAX <= INT_MAX. Find the largest
44 * accept_mask such that accept_mask <= RAND_MAX and
45 * accept_mask + 1 is a power of two. */
52 accept_mask
= (accept_mask
<< 1) + 1U;
54 if (accept_mask
> (unsigned int) RAND_MAX
) {
62 got_mask
= got_random
= 0U;
63 for (index
= 0; index
< size
; ) {
64 if (got_mask
>= UCHAR_MAX
) {
65 buf
[index
++] = (unsigned char) got_random
;
66 got_mask
>>= CHAR_BIT
;
67 got_random
>>= CHAR_BIT
;
69 unsigned int candidate
;
73 } while (candidate
> accept_mask
);
75 /* These shifts can discard some bits. */
76 got_mask
= (got_mask
<< accept_bits
) | accept_mask
;
77 got_random
= (got_random
<< accept_bits
) | candidate
;
82 /** Fill a buffer with random bytes. The bytes are not
83 * cryptographically random enough to be used in a key, but they
84 * should be good enough for a nonce or boundary string that may
85 * be sent in cleartext.
87 * If CONFIG_SSL is defined, then this function is instead defined in
88 * src/network/ssl/ssl.c, and it gets random numbers directly from the
89 * selected SSL library. */
91 random_nonce(unsigned char buf
[], size_t size
)
94 FILE *f
= fopen("/dev/urandom", "rb");
96 if (!f
) f
= fopen("/dev/prandom", "rb"); /* OpenBSD */
98 i
= fread(data
, 1, length
, f
);
102 /* If the random device did not exist or could not provide
103 * enough data, then fill the buffer with rand(). The
104 * resulting numbers may be predictable but they provide
105 * ELinks with at least some way to generate boundary strings
106 * for multipart uploads. A more secure algorithm and entropy
107 * collection could be implemented, but there doesn't seem to
108 * be much point as SSL libraries already provide this
111 pseudorandom_nonce(buf
+ i
, size
- i
);
114 #endif /* ndef CONFIG_SSL */