From: Mark Wooding Date: Mon, 16 Dec 2019 17:20:15 +0000 (+0000) Subject: Merge branch '2.4.x' into 2.5.x X-Git-Tag: 2.5.2~8 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~mdw/git/catacomb/commitdiff_plain/89717a56084f7cac56330c8527fbaff99b15709b?hp=-c Merge branch '2.4.x' into 2.5.x * 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. --- 89717a56084f7cac56330c8527fbaff99b15709b diff --combined base/dispatch.c index bea97b40,42c64ee5..abd019f6 --- a/base/dispatch.c +++ b/base/dispatch.c @@@ -46,10 -46,7 +46,10 @@@ # 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 f10d585f,84185e33..f0606591 --- a/math/pgen.c +++ b/math/pgen.c @@@ -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; } } @@@ -319,33 -319,28 +319,33 @@@ * @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 ----------------------------------------------------------*/