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