NeoMutt  2022-04-29-247-gc6aae8
Teaching an old dog new tricks
DOXYGEN
random.c
Go to the documentation of this file.
1
29#include "config.h"
30#include <stddef.h>
31#include <errno.h>
32#include <stdint.h>
33#include <stdio.h>
34#include <string.h>
35#include "random.h"
36#include "exit.h"
37#include "logging.h"
38#include "message.h"
39#ifdef HAVE_SYS_RANDOM_H
40#include <sys/random.h>
41#endif
42
43static FILE *fp_random = NULL;
44
45static const unsigned char base32[] = "abcdefghijklmnopqrstuvwxyz234567";
46
54static int mutt_randbuf(void *buf, size_t buflen)
55{
56 if (buflen > 1048576)
57 {
58 mutt_error(_("mutt_randbuf buflen=%zu"), buflen);
59 return -1;
60 }
61
62#ifdef HAVE_GETRANDOM
63 ssize_t rc;
64 ssize_t count = 0;
65 do
66 {
67 // getrandom() can return less than requested if there's insufficient
68 // entropy or it's interrupted by a signal.
69 rc = getrandom((char *) buf + count, buflen - count, 0);
70 if (rc > 0)
71 count += rc;
72 } while (((rc >= 0) && (count < buflen)) || ((rc == -1) && (errno == EINTR)));
73 if (count == buflen)
74 return 0;
75#endif
76 /* let's try urandom in case we're on an old kernel, or the user has
77 * configured selinux, seccomp or something to not allow getrandom */
78 if (!fp_random)
79 {
80 fp_random = fopen("/dev/urandom", "rb");
81 if (!fp_random)
82 {
83 mutt_error(_("open /dev/urandom: %s"), strerror(errno));
84 return -1;
85 }
86 setbuf(fp_random, NULL);
87 }
88 if (fread(buf, 1, buflen, fp_random) != buflen)
89 {
90 mutt_error(_("read /dev/urandom: %s"), strerror(errno));
91 return -1;
92 }
93
94 return 0;
95}
96
102void mutt_rand_base32(char *buf, size_t buflen)
103{
104 uint8_t *p = (uint8_t *) buf;
105
106 if (mutt_randbuf(p, buflen) < 0)
107 mutt_exit(1);
108 for (size_t pos = 0; pos < buflen; pos++)
109 p[pos] = base32[p[pos] % 32];
110}
111
116uint32_t mutt_rand32(void)
117{
118 uint32_t num = 0;
119
120 if (mutt_randbuf(&num, sizeof(num)) < 0)
121 mutt_exit(1);
122 return num;
123}
124
129uint64_t mutt_rand64(void)
130{
131 uint64_t num = 0;
132
133 if (mutt_randbuf(&num, sizeof(num)) < 0)
134 mutt_exit(1);
135 return num;
136}
Leave the program NOW.
#define mutt_error(...)
Definition: logging.h:87
Logging Dispatcher.
void mutt_exit(int code)
Leave NeoMutt NOW.
Definition: main.c:248
Message logging.
#define _(a)
Definition: message.h:28
uint64_t mutt_rand64(void)
Create a 64-bit random number.
Definition: random.c:129
static int mutt_randbuf(void *buf, size_t buflen)
Fill a buffer with randomness.
Definition: random.c:54
uint32_t mutt_rand32(void)
Create a 32-bit random number.
Definition: random.c:116
static FILE * fp_random
Definition: random.c:43
void mutt_rand_base32(char *buf, size_t buflen)
Fill a buffer with a base32-encoded random string.
Definition: random.c:102
static const unsigned char base32[]
Definition: random.c:45
Random number/string functions.