git.iko.soy/typeable/entropy
on main help sign in
Fix #12 and #13 (RDRAND + i386 symbol missing bug)
b1dd48bThomas M. DuBuisson
System/EntropyNix.hs+8−1
@@ -24,7 +24,15 @@ import Foreign.Ptr
24import Foreign.C.Types
24import Foreign.C.Types
25import Data.ByteString.Internal as B
25import Data.ByteString.Internal as B
26
26
27+#ifdef arch_i386
28+-- See .cabal wrt GCC 4.8.2 asm compilation bug
29+#undef HAVE_RDRAND
30+#endif
31+
27#ifdef XEN
32#ifdef XEN
33+#ifndef HAVE_RDRAND
34+#error "The entropy package requires RDRAND support when using the halvm/Xen"
35+#endif
28data CryptHandle = UseRdRand -- or die trying
36data CryptHandle = UseRdRand -- or die trying
29#else
37#else
30
38
@@ -108,4 +116,3 @@ foreign import ccall unsafe "get_rand_bytes"
108cpuHasRdRand :: IO Bool
116cpuHasRdRand :: IO Bool
109cpuHasRdRand = (/= 0) `fmap` c_cpu_has_rdrand
117cpuHasRdRand = (/= 0) `fmap` c_cpu_has_rdrand
110#endif
118#endif
111−
cbits/rdrand.c+44
@@ -20,6 +20,7 @@ inline int _rdrand64_step(uint64_t *therand)
20 return (int) err;
20 return (int) err;
21}
21}
22
22
23+#ifdef arch_x86_64
23// Returns 0 on success, non-zero on failure.
24// Returns 0 on success, non-zero on failure.
24int get_rand_bytes(uint8_t *therand, size_t len)
25int get_rand_bytes(uint8_t *therand, size_t len)
25{
26{
@@ -51,5 +52,48 @@ int get_rand_bytes(uint8_t *therand, size_t len)
51 }
52 }
52 return fail;
53 return fail;
53}
54}
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 */
54
98
55#endif // RDRAND
99#endif // RDRAND
cbits/rdrand.h−2
@@ -2,11 +2,9 @@
2#ifdef HAVE_RDRAND
2#ifdef HAVE_RDRAND
3#include <stdint.h>
3#include <stdint.h>
4
4
5−#ifdef arch_x86_64
6int cpu_has_rdrand()
5int cpu_has_rdrand()
7
6
8// Returns 0 on success, non-zero on failure.
7// Returns 0 on success, non-zero on failure.
9int get_rand_bytes(uint8_t *therand, size_t len)
8int get_rand_bytes(uint8_t *therand, size_t len)
10−#endif /* arch_x86_64 */
11#endif // HAVE_RDRAND
9#endif // HAVE_RDRAND
12#endif // rdrand_h
10#endif // rdrand_h
entropy.cabal+11−6
@@ -1,9 +1,9 @@
1name: entropy
1name: entropy
2−version: 0.3
2+version: 0.3.1
3description: A platform independent method to obtain cryptographically strong entropy
3description: 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).
5 Users looking for cryptographically strong (number-theoretically
5 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.
7synopsis: A platform independent entropy source
7synopsis: A platform independent entropy source
8license: BSD3
8license: BSD3
9license-file: LICENSE
9license-file: LICENSE
@@ -19,7 +19,7 @@ stability: stable
19build-type: Custom
19build-type: Custom
20-- ^^ Test for RDRAND support using 'ghc'
20-- ^^ Test for RDRAND support using 'ghc'
21cabal-version: >=1.10
21cabal-version: >=1.10
22−tested-with: GHC == 7.6.3
22+tested-with: GHC == 7.8.2
23-- data-files:
23-- data-files:
24extra-source-files: ./cbits/rdrand.c, ./cbits/rdrand.h, README.md
24extra-source-files: ./cbits/rdrand.c, ./cbits/rdrand.h, README.md
25
25
@@ -29,6 +29,7 @@ extra-source-files: ./cbits/rdrand.c, ./cbits/rdrand.h, README.md
29flag halvm
29flag halvm
30 description: Build for the HaLVM
30 description: Build for the HaLVM
31 default: False
31 default: False
32+
32library
33library
33 ghc-options: -O2
34 ghc-options: -O2
34 exposed-modules: System.Entropy
35 exposed-modules: System.Entropy
@@ -41,16 +42,20 @@ library
41 default-language: Haskell2010
42 default-language: Haskell2010
42 if(flag(halvm))
43 if(flag(halvm))
43 cpp-options: -DXEN -DHAVE_RDRAND
44 cpp-options: -DXEN -DHAVE_RDRAND
45+ cc-options: -DXEN -DHAVE_RDRAND
44 if arch(x86_64)
46 if arch(x86_64)
45 cpp-options: -Darch_x86_64
47 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
46 if os(windows)
53 if os(windows)
47 cpp-options: -DisWindows
54 cpp-options: -DisWindows
48 extra-libraries: advapi32
55 extra-libraries: advapi32
49 else
56 else
50 if !flag(halvm)
57 if !flag(halvm)
51 Build-Depends: unix
58 Build-Depends: unix
52− c-sources: cbits/rdrand.c
53− include-dirs: cbits
54
59
55source-repository head
60source-repository head
56 type: git
61 type: git