]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
random-util: make use of GRND_INSECURE when it is defined
authorLennart Poettering <lennart@poettering.net>
Sun, 10 May 2020 09:15:16 +0000 (11:15 +0200)
committerLennart Poettering <lennart@poettering.net>
Sun, 10 May 2020 09:15:16 +0000 (11:15 +0200)
kernel 5.6 added support for a new flag for getrandom(): GRND_INSECURE.
If we set it we can get some random data out of the kernel random pool,
even if it is not yet initializated. This is great for us to initialize
hash table seeds and such, where it is OK if they are crap initially. We
used RDRAND for these cases so far, but RDRAND is only available on
newer CPUs and some archs. Let's now use GRND_INSECURE for these cases
as well, which means we won't needlessly delay boot anymore even on
archs/CPUs that do not have RDRAND.

Of course we never set this flag when generating crypto keys or uuids.
Which makes it different from RDRAND for us (and is the reason I think
we should keep explicit RDRAND support in): RDRAND we don't trust enough
for crypto keys. But we do trust it enough for UUIDs.

src/basic/missing_random.h
src/basic/random-util.c
src/basic/random-util.h
src/test/test-random-util.c

index 2e76031b325c5e3904413a953349ed75e9a61f22..17af87a3aefe9b77f88866552d1f0cb2fadcdf74 100644 (file)
@@ -14,3 +14,7 @@
 #ifndef GRND_RANDOM
 #define GRND_RANDOM 0x0002
 #endif
+
+#ifndef GRND_INSECURE
+#define GRND_INSECURE 0x0004
+#endif
index c32e6e2aac92f137df07038f0233a64de52a277c..73cc7272db41cfd8c2331da5030043f6e31b8b1c 100644 (file)
@@ -208,7 +208,9 @@ int genuine_random_bytes(void *p, size_t n, RandomFlags flags) {
         if (have_syscall != 0 && !HAS_FEATURE_MEMORY_SANITIZER) {
 
                 for (;;) {
-                        r = getrandom(p, n, FLAGS_SET(flags, RANDOM_BLOCK) ? 0 : GRND_NONBLOCK);
+                        r = getrandom(p, n,
+                                      (FLAGS_SET(flags, RANDOM_BLOCK) ? 0 : GRND_NONBLOCK) |
+                                      (FLAGS_SET(flags, RANDOM_ALLOW_INSECURE) ? GRND_INSECURE : 0));
                         if (r > 0) {
                                 have_syscall = true;
 
@@ -264,6 +266,18 @@ int genuine_random_bytes(void *p, size_t n, RandomFlags flags) {
 
                                 /* Use /dev/urandom instead */
                                 break;
+
+                        } else if (errno == EINVAL) {
+
+                                /* Most likely: unknown flag. We know that GRND_INSECURE might cause this,
+                                 * hence try without. */
+
+                                if (FLAGS_SET(flags, RANDOM_ALLOW_INSECURE)) {
+                                        flags = flags &~ RANDOM_ALLOW_INSECURE;
+                                        continue;
+                                }
+
+                                return -errno;
                         } else
                                 return -errno;
                 }
@@ -395,7 +409,7 @@ void random_bytes(void *p, size_t n) {
          * This function is hence not useful for generating UUIDs or cryptographic key material.
          */
 
-        if (genuine_random_bytes(p, n, RANDOM_EXTEND_WITH_PSEUDO|RANDOM_MAY_FAIL|RANDOM_ALLOW_RDRAND) >= 0)
+        if (genuine_random_bytes(p, n, RANDOM_EXTEND_WITH_PSEUDO|RANDOM_MAY_FAIL|RANDOM_ALLOW_RDRAND|RANDOM_ALLOW_INSECURE) >= 0)
                 return;
 
         /* If for some reason some user made /dev/urandom unavailable to us, or the kernel has no entropy, use a PRNG instead. */
index facc11b976fbdba8376920af2966cb3f6cb4de21..d8e067d96e877af94aaa00fea1e1454eb6d1ee59 100644 (file)
@@ -10,6 +10,7 @@ typedef enum RandomFlags {
         RANDOM_BLOCK              = 1 << 1, /* Rather block than return crap randomness (only if the kernel supports that) */
         RANDOM_MAY_FAIL           = 1 << 2, /* If we can't get any randomness at all, return early with -ENODATA */
         RANDOM_ALLOW_RDRAND       = 1 << 3, /* Allow usage of the CPU RNG */
+        RANDOM_ALLOW_INSECURE     = 1 << 4, /* Allow usage of GRND_INSECURE flag to kernel's getrandom() API */
 } RandomFlags;
 
 int genuine_random_bytes(void *p, size_t n, RandomFlags flags); /* returns "genuine" randomness, optionally filled up with pseudo random, if not enough is available */
index 94c431f7e6084ea88c649efada378ec91852c145..ad5bc72a4e138c0e1e3ca68155a3b47765130541 100644 (file)
@@ -58,6 +58,7 @@ int main(int argc, char **argv) {
         test_genuine_random_bytes(0);
         test_genuine_random_bytes(RANDOM_BLOCK);
         test_genuine_random_bytes(RANDOM_ALLOW_RDRAND);
+        test_genuine_random_bytes(RANDOM_ALLOW_INSECURE);
 
         test_pseudo_random_bytes();