]> granicus.if.org Git - json-c/commitdiff
Issue #589: drop the rdrand test loops to just 3, tweak comments and add some links...
authorEric Haszlakiewicz <erh+git@nimenees.com>
Mon, 4 May 2020 01:29:02 +0000 (01:29 +0000)
committerEric Haszlakiewicz <erh+git@nimenees.com>
Mon, 4 May 2020 01:33:15 +0000 (01:33 +0000)
random_seed.c

index 4ddcb07d16b1293fba6a70006e621480820052b9..b5f8a0795e96b2b0d7018501175562260db09921 100644 (file)
@@ -45,36 +45,46 @@ static void do_cpuid(int regs[], int h)
 
 static int get_rdrand_seed(void);
 
-// Valid values are -1 (haven't tested), 0 (no), and 1 (yes).
+/* Valid values are -1 (haven't tested), 0 (no), and 1 (yes). */
 static int _has_rdrand = -1;
 
 static int has_rdrand(void)
 {
-       if (_has_rdrand == -1)
+       if (_has_rdrand != -1)
        {
-               // CPUID.01H:ECX.RDRAND[bit 30] == 1
-               int regs[4];
-               do_cpuid(regs, 1);
-               if (!(regs[2] & (1 << 30)))
-               {
-                       _has_rdrand = 0;
-               } else
+               return _has_rdrand;
+       }
+
+       /* CPUID.01H:ECX.RDRAND[bit 30] == 1 */
+       int regs[4];
+       do_cpuid(regs, 1);
+       if (!(regs[2] & (1 << 30)))
+       {
+               _has_rdrand = 0;
+               return 0;
+       }
+
+       /*
+        * Some CPUs advertise RDRAND in CPUID, but return 0xFFFFFFFF
+        * unconditionally. To avoid locking up later, test RDRAND here. If over
+        * 3 trials RDRAND has returned the same value, declare it broken.
+        * Example CPUs are AMD Ryzen 3000 series
+        * and much older AMD APUs, such as the E1-1500
+        * https://github.com/systemd/systemd/issues/11810
+        * https://linuxreviews.org/RDRAND_stops_returning_random_values_on_older_AMD_CPUs_after_suspend
+        */
+       _has_rdrand = 0;
+       int prev = get_rdrand_seed();
+       for (int i = 0; i < 3; i++)
+       {
+               int temp = get_rdrand_seed();
+               if (temp != prev)
                {
-                       // Some CPUs advertise RDRAND in CPUID, but return 0xFFFFFFFF
-                       // unconditionally. To avoid locking up later, test RDRAND here. If over
-                       // 10 trials RDRAND has returned the same value, declare it broken.
-                       _has_rdrand = 0;
-                       int prev = get_rdrand_seed();
-                       for (int i = 0; i < 10; i++) {
-                               int temp = get_rdrand_seed();
-                               if (temp != prev) {
-                                       _has_rdrand = 1;
-                                       break;
-                               }
-
-                               prev = temp;
-                       }
+                       _has_rdrand = 1;
+                       break;
                }
+
+               prev = temp;
        }
 
        return _has_rdrand;
@@ -92,7 +102,7 @@ static int get_rdrand_seed(void)
 {
        DEBUG_SEED("get_rdrand_seed");
        int _eax;
-       // rdrand eax
+       /* rdrand eax */
        /* clang-format off */
        __asm__ __volatile__("1: .byte 0x0F\n"
                             "   .byte 0xC7\n"
@@ -132,7 +142,7 @@ static int get_rdrand_seed(void)
        DEBUG_SEED("get_rdrand_seed");
        int _eax;
 retry:
-       // rdrand eax
+       /* rdrand eax */
        __asm _emit 0x0F __asm _emit 0xC7 __asm _emit 0xF0
        __asm jnc retry
        __asm mov _eax, eax
@@ -206,6 +216,10 @@ static int get_dev_random_seed(void)
 
 /* clang-format off */
 #include <windows.h>
+
+/* Caution: these blank lines must remain so clang-format doesn't reorder
+   includes to put windows.h after wincrypt.h */
+
 #include <wincrypt.h>
 /* clang-format on */
 #ifndef __GNUC__