chiark / gitweb /
Merge branch '2.4.x' into 2.5.x
authorMark Wooding <mdw@distorted.org.uk>
Mon, 16 Dec 2019 17:20:15 +0000 (17:20 +0000)
committerMark Wooding <mdw@distorted.org.uk>
Mon, 16 Dec 2019 17:20:15 +0000 (17:20 +0000)
* 2.4.x:
  rand/rand.c: Mix the pool key in `rand_gate' and `rand_stretch'.
  rand/lcrand.c: Swap flags and max so generator not advertised as strong.
  pub/dh-kcdsa.c: Free the correct factor.
  math/limlee.c: Don't leak the factor vector on overall failure.
  math/limlee.c: Handle an abort from `pgen' correctly.
  math/pgen.c: Don't free the tester if it's not set up.
  math/ec-exp.h: Fix segfault when base point is at infinity.
  key/key-data.c (key_copydata): Fix catastrophic bug.
  key/key-data.c (key_split): Fix long-standing reference leak.
  key/key-misc.c (key_bytag): Don't give up because a by-id search fails.
  base/dispatch.c, etc.: Check that `rdrand' works.

1  2 
base/dispatch.c
math/pgen.c

diff --combined base/dispatch.c
index bea97b4081e12b94ec6d39166aec7bbc2b4e2e55,42c64ee526b17896a73b61f35aeaf2ed9556a8f4..abd019f6349a15474e76a93c51b1957df084b942
  #  define EFLAGS_ID (1u << 21)
  #  define CPUID1D_SSE2 (1u << 26)
  #  define CPUID1D_FXSR (1u << 24)
 +#  define CPUID1C_PCLMUL (1u << 1)
 +#  define CPUID1C_SSSE3 (1u << 9)
  #  define CPUID1C_AESNI (1u << 25)
 +#  define CPUID1C_AVX (1u << 28)
  #  define CPUID1C_RDRAND (1u << 30)
  
  struct cpuid { unsigned a, b, c, d; };
@@@ -201,6 -198,59 +201,59 @@@ static int xmm_registers_available_p(vo
  #endif
  }
  
+ /* --- @rdrand_works_p@ --- *
+  *
+  *
+  * Arguments: ---
+  *
+  * Returns:   Nonzero if the `rdrand' instruction actually works.  Assumes
+  *            that it's already been verified to be safe to issue.
+  */
+ #ifdef __GNUC__
+ static int rdrand(unsigned *x)
+ {
+   int i, rc;
+   unsigned _t;
+   i = 16;
+   __asm__ ("" : "=g" (_t));
+   __asm__ ("0: rdrand %2; jc 1f; decl %1; jnz 0b\n"
+          "mov $-1, %0; jmp 9f\n"
+          "1: movl %2, (%3); xorl %0, %0\n"
+          "9:"
+          : "=r" (rc), "+r" (i), "+r" (_t)
+          : "r" (x)
+          : "cc");
+   return (rc);
+ }
+ #endif
+ static int rdrand_works_p(void)
+ {
+   unsigned ref, x, i;
+   /* Check that it doesn't always give the same answer.  Try four times: this
+    * will fail with probability %$2^{-128}$% with a truly random generator,
+    * which seems fair enough.
+    */
+   if (rdrand(&ref)) goto fail;
+   for (i = 0; i < 4; i++) {
+     if (rdrand(&x)) goto fail;
+     if (x != ref) goto not_stuck;
+   }
+   dispatch_debug("RDRAND always returns 0x%08x!", ref);
+   return (0);
+ not_stuck:
+   dispatch_debug("RDRAND instruction looks plausible");
+   return (1);
+ fail:
+   dispatch_debug("RDRAND instruction fails too often");
+   return (0);
+ }
  #endif
  
  /*----- General feature probing using auxiliary vectors -------------------*/
@@@ -284,15 -334,13 +337,15 @@@ static unsigned hwcaps = 0
        _(ARM_NEON, "arm:neon")                                         \
        _(ARM_V4, "arm:v4")                                             \
        _(ARM_D32, "arm:d32")                                           \
 -      _(ARM_AES, "arm:aes")
 +      _(ARM_AES, "arm:aes")                                           \
 +      _(ARM_PMULL, "arm:pmull")
  #endif
  #if CPUFAM_ARM64
  #  define WANTAUX(_)                                                  \
        WANT_AT_HWCAP(_)
  #  define CAPMAP(_)                                                   \
 -      _(ARM_AES, "arm:aes")
 +      _(ARM_AES, "arm:aes")                                           \
 +      _(ARM_PMULL, "arm:pmull")
  #endif
  
  /* Build the bitmask for `hwcaps' from the `CAPMAP' list. */
@@@ -406,13 -454,9 +459,13 @@@ static void probe_hwcaps(void
  #  ifdef HWCAP2_AES
    if (probed.hwcap2 & HWCAP2_AES) hw |= HF_ARM_AES;
  #  endif
 +#  ifdef HWCAP2_PMULL
 +  if (probed.hwcap2 & HWCAP2_PMULL) hw |= HF_ARM_PMULL;
 +#  endif
  #endif
  #if CPUFAM_ARM64
    if (probed.hwcap & HWCAP_AES) hw |= HF_ARM_AES;
 +  if (probed.hwcap & HWCAP_PMULL) hw |= HF_ARM_PMULL;
  #endif
  
    /* Store the bitmask of features we probed for everyone to see. */
@@@ -553,16 -597,7 +606,16 @@@ int cpu_feature_p(int feat
                 cpuid_features_p(CPUID1D_SSE2, CPUID1C_AESNI) &&
                 xmm_registers_available_p());
      CASE_CPUFEAT(X86_RDRAND, "x86:rdrand",
-                cpuid_features_p(0, CPUID1C_RDRAND));
+                cpuid_features_p(0, CPUID1C_RDRAND) && rdrand_works_p());
 +    CASE_CPUFEAT(X86_AVX, "x86:avx",
 +               cpuid_features_p(0, CPUID1C_AVX) &&
 +               xmm_registers_available_p());
 +    CASE_CPUFEAT(X86_SSSE3, "x86:ssse3",
 +               cpuid_features_p(0, CPUID1C_SSSE3) &&
 +               xmm_registers_available_p());
 +    CASE_CPUFEAT(X86_PCLMUL, "x86:pclmul",
 +               cpuid_features_p(0, CPUID1C_PCLMUL) &&
 +               xmm_registers_available_p());
  #endif
  #ifdef CAPMAP
  #  define FEATP__CASE(feat, tok)                                      \
diff --combined math/pgen.c
index f10d585f2e56af3e1bd7e8f7f69bafd809c92f21,84185e3390f52e5088fd14d37745ae979ebff981..f06065913688f0cc170930837bdd21f313a5d349
@@@ -283,7 -283,7 +283,7 @@@ mp *pgen(const char *name, mp *d, mp *m
        rc = PGEN_ABORT;
        if (!(act & A_DONE)) {
        act |= A_ENDSTEP | A_DONE;
-       if (p == P_TEST)
+       if (p == P_TEST && rq != PGEN_BEGIN)
          act |= A_ENDTEST;
        }
      }
   *            @grand *gr@ = a random number source
   *
   * Returns:   Nonzero if @p@ is really prime.
 + *
 + * Use:               Checks the primality of @p@.  If @p@ is prime, then this
 + *            function returns nonzero; if @p@ is really composite then it
 + *            %%\emph{probably}%% returns zero, but might not.
 + *
 + *            Currently, this function uses the Baillie--PSW test, which
 + *            combines a single Miller--Rabin test with witness 2 with a
 + *            single Frobenius test with parameters chosen using
 + *            Selfridge's `Method A'.  No composites are known which pass
 + *            this test, though it's conjectured that infinitely many
 + *            exist.
   */
  
  int pgen_primep(mp *p, grand *gr)
  {
 -  int i;
    rabin r;
 -  mp *x = MP_NEW;
 +  int rc;
  
    if (MP_NEGP(p)) return (0);
    switch (pfilt_smallfactor(p)) {
      case PGEN_DONE: return (1);
      case PGEN_FAIL: return (0);
    }
 -  rabin_create(&r, p);
 -  for (i = 32; i; i--) {
 -    x = mprand_range(x, p, gr, 0);
 -    if (rabin_rtest(&r, x) == PGEN_FAIL)
 -      break;
 -  }
 -  MP_DROP(x);
 -  rabin_destroy(&r);
 -  return (!i);
 +  rabin_create(&r, p); rc = rabin_test(&r, MP_TWO); rabin_destroy(&r);
 +  if (rc == PGEN_FAIL) return (0);
 +  rc = pgen_granfrob(p, 0, 0); if (rc == PGEN_FAIL) return (0);
 +  return (1);
  }
  
  /*----- Test rig ----------------------------------------------------------*/