From: Mark Wooding Date: Mon, 6 Apr 2020 00:07:41 +0000 (+0000) Subject: base/dispatch.c, rand/rand.c, and asm: Support `rdseed' for quick noise. X-Git-Tag: 2.6.0~1 X-Git-Url: https://git.distorted.org.uk/~mdw/catacomb/commitdiff_plain/6c0946ef1f1fa9b75b8c6d65ea0554ff4e1ec4eb base/dispatch.c, rand/rand.c, and asm: Support `rdseed' for quick noise. Prefer the `rdseed' instruction over `rdrand' for quick randomness, if it's available. --- diff --git a/base/dispatch-x86ish.S b/base/dispatch-x86ish.S index b3b6d1cb..57d8d32b 100644 --- a/base/dispatch-x86ish.S +++ b/base/dispatch-x86ish.S @@ -158,10 +158,11 @@ ENDFUNC /// Checking `rdrand'. FUNC(dispatch_x86ish_rdrand) - // Enter with two arguments: a code OP requesting `rdrand' (0), and a - // pointer X_OUT to a 32-bit word. Try to generate a random word - // using the requested instruction. If successful, set *X_OUT to the - // generated word, and return zero; otherwise, return -1. + // Enter with two arguments: a code OP requesting either `rdrand' (0) + // or `rdseed' (1), and a pointer X_OUT to a 32-bit word. Try to + // generate a random word using the requested instruction'. If + // successful, set *X_OUT to the generated word, and return zero; + // otherwise, return -1. #if CPUFAM_X86 # define OP eax @@ -182,13 +183,22 @@ FUNC(dispatch_x86ish_rdrand) #endif endprologue + cmp OP, 0 mov COUNT, 16 // fairly persistent + jne 1f + 0: rdrand eax jc 9f dec COUNT jnz 0b jmp 8f +1: rdseed eax + jc 9f + dec COUNT + jnz 1b + jmp 8f + // Failed to come up with a random value. 8: mov eax, -1 ret diff --git a/base/dispatch.c b/base/dispatch.c index bda7f88e..50c842e1 100644 --- a/base/dispatch.c +++ b/base/dispatch.c @@ -56,6 +56,8 @@ enum { # define CPUID1C_AVX (1u << 28) # define CPUID1C_RDRAND (1u << 30) + CPUID_7_0_B, /* eax = 7, ecx = 0 => ebx&?? */ +# define CPUID70B_RDSEED (1u << 18) }; struct cpuid { unsigned a, b, c, d; }; @@ -99,6 +101,10 @@ static int cpuid_feature_p(unsigned leaf, unsigned bits) if (cpuid_maxleaf() < 1) return (0); cpuid(&c, 1, 0); r = c.c; break; + case CPUID_7_0_B: + if (cpuid_maxleaf() < 7) return (0); + cpuid(&c, 7, 0); r = c.b; + break; default: assert(!"unknown cpuid leaf"); } @@ -139,6 +145,7 @@ static int rdrand_works_p(unsigned op) switch (op) { case OP_RDRAND: what = "RDRAND"; break; + case OP_RDSEED: what = "RDSEED"; break; default: assert(!"unexpected op"); } @@ -527,6 +534,9 @@ int cpu_feature_p(int feat) CASE_CPUFEAT(X86_PCLMUL, "x86:pclmul", cpuid_feature_p(CPUID_1_C, CPUID1C_PCLMUL) && xmm_registers_available_p()); + CASE_CPUFEAT(X86_RDSEED, "x86:rdseed", + cpuid_feature_p(CPUID_7_0_B, CPUID70B_RDSEED) && + rdrand_works_p(OP_RDSEED)); #endif #ifdef CAPMAP # define FEATP__CASE(feat, tok) \ diff --git a/base/dispatch.h b/base/dispatch.h index 7c083821..2c78d92a 100644 --- a/base/dispatch.h +++ b/base/dispatch.h @@ -180,12 +180,13 @@ enum { CPUFEAT_ARM_NEON, /* Advanced SIMD (v1 or v2) */ CPUFEAT_ARM_V4, /* VFPv4 and/or SIMD v2 */ CPUFEAT_ARM_D32, /* 32 double registers, not 16 */ - CPUFEAT_X86_RDRAND, /* Built-in entropy source */ + CPUFEAT_X86_RDRAND, /* Built-in cooked entropy source */ CPUFEAT_ARM_AES, /* AES instructions */ CPUFEAT_X86_AVX, /* AVX 1 (i.e., 256-bit YMM regs) */ CPUFEAT_X86_SSSE3, /* Supplementary SSE 3 */ CPUFEAT_X86_PCLMUL, /* Carry-less multiplication */ - CPUFEAT_ARM_PMULL /* Polynomial multiplication */ + CPUFEAT_ARM_PMULL, /* Polynomial multiplication */ + CPUFEAT_X86_RDSEED /* Built-in raw entropy source */ }; extern int cpu_feature_p(int /*feat*/); diff --git a/debian/catacomb2.symbols b/debian/catacomb2.symbols index 84ff8938..c06cbdf6 100644 --- a/debian/catacomb2.symbols +++ b/debian/catacomb2.symbols @@ -653,6 +653,7 @@ libcatacomb.so.2 catacomb2 #MINVER# rand_seed@Base 2.2.3 rand_quick@Base 2.5.2 (optional|arch=i386 amd64)rand_quick_x86ish_rdrand@Base 2.5.0 + (optional|arch=i386 amd64)rand_quick_x86ish_rdseed@Base 2.5.99~ rand_key@Base 2.5.2 rand_add@Base 2.2.3 rand_goodbits@Base 2.2.3 diff --git a/rand/rand-x86ish.S b/rand/rand-x86ish.S index 70907feb..b91a9373 100644 --- a/rand/rand-x86ish.S +++ b/rand/rand-x86ish.S @@ -74,6 +74,34 @@ FUNC(rand_quick_x86ish_rdrand) // Failed. mov eax, -1 jmp 9f +ENDFUNC + +FUNC(rand_quick_x86ish_rdseed) + // Enter with a pointer to the random context in the first argument. + // Return zero on success, or -1 on error. + +#if CPUFAM_X86 + mov edx, [SP + 4] + stalloc 28 +#endif +#if CPUFAM_AMD64 && ABI_SYSV + stalloc 8 +#endif +#if CPUFAM_AMD64 && ABI_WIN + stalloc 40 +#endif + endprologue + + // Try to fetch a random number. + mov COUNT, 16 +0: rdseed AX + jc 1f + dec COUNT + jnz 0b + + // Failed. + mov eax, -1 + jmp 9f // Success. 1: diff --git a/rand/rand.c b/rand/rand.c index 304c68dc..3b056332 100644 --- a/rand/rand.c +++ b/rand/rand.c @@ -163,11 +163,14 @@ static int trivial_quick(rand_pool *r) { return (-1); } #if CPUFAM_X86 || CPUFAM_AMD64 extern int rand_quick_x86ish_rdrand(rand_pool */*r*/); +extern int rand_quick_x86ish_rdseed(rand_pool */*r*/); #endif static quick__functype *pick_quick(void) { #if CPUFAM_X86 || CPUFAM_AMD64 + DISPATCH_PICK_COND(rand_quick, rand_quick_x86ish_rdseed, + cpu_feature_p(CPUFEAT_X86_RDSEED)); DISPATCH_PICK_COND(rand_quick, rand_quick_x86ish_rdrand, cpu_feature_p(CPUFEAT_X86_RDRAND)); #endif