From: Mark Wooding Date: Mon, 16 Dec 2019 17:21:25 +0000 (+0000) Subject: Merge branch '2.5.x' X-Git-Tag: 2.6.0~54 X-Git-Url: https://git.distorted.org.uk/~mdw/catacomb/commitdiff_plain/119bdfc4c80e313417047de10700e6b8c3955d0d Merge branch '2.5.x' * 2.5.x: debian/catacomb2.symbols: Bump versions for fixed functions. 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. --- 119bdfc4c80e313417047de10700e6b8c3955d0d diff --cc base/dispatch.c index c8bbc0b9,abd019f6..459302f0 --- a/base/dispatch.c +++ b/base/dispatch.c @@@ -95,12 -162,98 +95,65 @@@ static int cpuid_features_p(unsigned db static int xmm_registers_available_p(void) { -#ifdef __GNUC__ - unsigned f; - /* This hack is by Agner Fog. Use FXSAVE/FXRSTOR to figure out whether the - * XMM registers are actually alive. - */ - if (!cpuid_features_p(CPUID1D_FXSR, 0)) return (0); -# if CPUFAM_X86 - __asm__ ("movl %%esp, %%edx; subl $512, %%esp; andl $~15, %%esp\n" - "fxsave (%%esp)\n" - "movl 160(%%esp), %%eax; xorl $0xaaaa5555, 160(%%esp)\n" - "fxrstor (%%esp); fxsave (%%esp)\n" - "movl 160(%%esp), %%ecx; movl %%eax, 160(%%esp)\n" - "fxrstor (%%esp); movl %%edx, %%esp\n" - "xorl %%ecx, %%eax" - : "=a" (f) - : /* no inputs */ - : "%ecx", "%edx"); -# elif CPUFAM_AMD64 - __asm__ ("movq %%rsp, %%rdx; subq $512, %%rsp; andq $~15, %%rsp\n" - "fxsave (%%rsp)\n" - "movl 160(%%rsp), %%eax; xorl $0xaaaa5555, 160(%%rsp)\n" - "fxrstor (%%rsp); fxsave (%%rsp)\n" - "movl 160(%%rsp), %%ecx; movl %%eax, 160(%%rsp)\n" - "fxrstor (%%rsp); movq %%rdx, %%rsp\n" - "xorl %%ecx, %%eax" - : "=a" (f) - : /* no inputs */ - : "%ecx", "%rdx"); -# else -# error "I'm confused." -# endif + int f = dispatch_x86ish_xmmregisters_p(); + dispatch_debug("XMM registers %savailable", f ? "" : "not "); return (f); -#else - dispatch_debug("GNU inline assembler not available; can't check for XMM"); - return (0); -#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 -------------------*/