git.iko.soy/typeable/entropy
on main help sign in
Fix #12 and #13 (RDRAND + i386 symbol missing bug)

x86 rdrand support is sketched but we do not use RDRAND thanks to a codegen bug (it appears) in GCC. Notice clang works fine.

commitb1dd48b255cb5a19e65e7cbaa7fceecae1aeefaa authorThomas M. DuBuisson <tommd@galois.com> dateTue 10 Jun 2014, 23:09 (12 years ago) parent5796ceb
4 files changed+63−9
System/EntropyNix.hs+8−1 cbits/rdrand.c+44 cbits/rdrand.h−2 entropy.cabal+11−6
System/EntropyNix.hs+8−1
@@ -24,7 +24,15 @@ import Foreign.Ptr
2424import Foreign.C.Types
2525import Data.ByteString.Internal as B
2626
27+#ifdef arch_i386
28+-- See .cabal wrt GCC 4.8.2 asm compilation bug
29+#undef HAVE_RDRAND
30+#endif
31+
2732#ifdef XEN
33+#ifndef HAVE_RDRAND
34+#error "The entropy package requires RDRAND support when using the halvm/Xen"
35+#endif
2836data CryptHandle = UseRdRand -- or die trying
2937#else
3038
@@ -108,4 +116,3 @@ foreign import ccall unsafe "get_rand_bytes"
108116cpuHasRdRand :: IO Bool
109117cpuHasRdRand = (/= 0) `fmap` c_cpu_has_rdrand
110118#endif
111−
cbits/rdrand.c+44
@@ -20,6 +20,7 @@ inline int _rdrand64_step(uint64_t *therand)
2020 return (int) err;
2121}
2222
23+#ifdef arch_x86_64
2324// Returns 0 on success, non-zero on failure.
2425int get_rand_bytes(uint8_t *therand, size_t len)
2526{
@@ -51,5 +52,48 @@ int get_rand_bytes(uint8_t *therand, size_t len)
5152 }
5253 return fail;
5354}
55+#endif /* x86-64 */
56+
57+#ifdef arch_i386
58+// Returns 1 on success
59+inline int _rdrand32_step(uint32_t *therand)
60+{
61+ unsigned char err;
62+ asm volatile("rdrand %0 ; setc %1"
63+ : "=r" (*therand), "=qm" (err));
64+ return (int) err;
65+}
66+
67+int get_rand_bytes(uint8_t *therand, size_t len)
68+{
69+ int cnt;
70+ int fail=0;
71+ uint8_t *p = therand;
72+ uint8_t *end = therand + len;
73+ if((uint32_t)p % sizeof(uint32_t) != 0) {
74+ uint32_t tmp;
75+ fail |= !_rdrand32_step(&tmp);
76+ while((uint32_t)p % sizeof(uint32_t) != 0 && p != end) {
77+ *p = (uint8_t)(tmp & 0xFF);
78+ tmp = tmp >> 8;
79+ p++;
80+ }
81+ }
82+ for(; p <= end - sizeof(uint32_t); p+=sizeof(uint32_t)) {
83+ fail |= !_rdrand32_step((uint32_t *)p);
84+ }
85+ if(p != end) {
86+ uint32_t tmp;
87+ int cnt;
88+ fail |= !_rdrand32_step(&tmp);
89+ while(p != end) {
90+ *p = (uint8_t)(tmp & 0xFF);
91+ tmp = tmp >> 8;
92+ p++;
93+ }
94+ }
95+ return fail;
96+}
97+#endif /* i386 */
5498
5599#endif // RDRAND
cbits/rdrand.h−2
@@ -2,11 +2,9 @@
22#ifdef HAVE_RDRAND
33#include <stdint.h>
44
5−#ifdef arch_x86_64
65int cpu_has_rdrand()
76
87// Returns 0 on success, non-zero on failure.
98int get_rand_bytes(uint8_t *therand, size_t len)
10−#endif /* arch_x86_64 */
119#endif // HAVE_RDRAND
1210#endif // rdrand_h
entropy.cabal+11−6
@@ -1,9 +1,9 @@
11name: entropy
2−version: 0.3
2+version: 0.3.1
33description: A platform independent method to obtain cryptographically strong entropy
4− (urandom on Linux, CryptAPI on Windows, patches welcome).
4+ (RDRAND when available anywhere, urandom on nix, CryptAPI on Windows, patches welcome).
55 Users looking for cryptographically strong (number-theoretically
6− sound) PRNGs should see the 'DRBG' package too!
6+ sound) PRNGs should see the 'DRBG' package too.
77synopsis: A platform independent entropy source
88license: BSD3
99license-file: LICENSE
@@ -19,7 +19,7 @@ stability: stable
1919build-type: Custom
2020-- ^^ Test for RDRAND support using 'ghc'
2121cabal-version: >=1.10
22−tested-with: GHC == 7.6.3
22+tested-with: GHC == 7.8.2
2323-- data-files:
2424extra-source-files: ./cbits/rdrand.c, ./cbits/rdrand.h, README.md
2525
@@ -29,6 +29,7 @@ extra-source-files: ./cbits/rdrand.c, ./cbits/rdrand.h, README.md
2929flag halvm
3030 description: Build for the HaLVM
3131 default: False
32+
3233library
3334 ghc-options: -O2
3435 exposed-modules: System.Entropy
@@ -41,16 +42,20 @@ library
4142 default-language: Haskell2010
4243 if(flag(halvm))
4344 cpp-options: -DXEN -DHAVE_RDRAND
45+ cc-options: -DXEN -DHAVE_RDRAND
4446 if arch(x86_64)
4547 cpp-options: -Darch_x86_64
48+ -- gcc 4.8.2 on i386 fails to compile rdrand.c when using -fPIC!
49+ c-sources: cbits/rdrand.c
50+ include-dirs: cbits
51+ if arch(i386)
52+ cpp-options: -Darch_i386
4653 if os(windows)
4754 cpp-options: -DisWindows
4855 extra-libraries: advapi32
4956 else
5057 if !flag(halvm)
5158 Build-Depends: unix
52− c-sources: cbits/rdrand.c
53− include-dirs: cbits
5459
5560source-repository head
5661 type: git