1 #ifdef HAVE_RDRAND
2 
3 #include <stdint.h>
4 #include <stdlib.h>
5 
cpu_has_rdrand()6 int cpu_has_rdrand()
7 {
8     uint32_t ax,bx,cx,dx,func=1;
9     __asm__ volatile ("cpuid":\
10             "=a" (ax), "=b" (bx), "=c" (cx), "=d" (dx) : "a" (func));
11     return (cx & 0x40000000);
12 }
13 
14 #ifdef arch_x86_64
15 // Returns 1 on success
_rdrand64_step(uint64_t * therand)16 static inline int _rdrand64_step(uint64_t *therand)
17 {
18      unsigned char err;
19      asm volatile("rdrand %0 ; setc %1"
20                  : "=r" (*therand), "=qm" (err));
21      return (int) err;
22 }
23 
24 // Returns 0 on success, non-zero on failure.
get_rand_bytes(uint8_t * therand,size_t len)25 int get_rand_bytes(uint8_t *therand, size_t len)
26 {
27     int cnt;
28     int fail=0;
29     uint8_t *p = therand;
30     uint8_t *end = therand + len;
31     if((uint64_t)p%8 != 0) {
32         uint64_t tmp;
33         fail |= !_rdrand64_step(&tmp);
34         while((uint64_t)p%8 != 0 && p != end) {
35             *p = (uint8_t)(tmp & 0xFF);
36             tmp = tmp >> 8;
37             p++;
38         }
39     }
40     for(; p <= end - sizeof(uint64_t); p+=sizeof(uint64_t)) {
41         fail |= !_rdrand64_step((uint64_t *)p);
42     }
43     if(p != end) {
44         uint64_t tmp;
45         int cnt;
46         fail |= !_rdrand64_step(&tmp);
47         while(p != end) {
48             *p = (uint8_t)(tmp & 0xFF);
49             tmp = tmp >> 8;
50             p++;
51         }
52     }
53     return fail;
54 }
55 #endif /* x86-64 */
56 
57 #ifdef arch_i386
58 // Returns 1 on success
_rdrand32_step(uint32_t * therand)59 static 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 
get_rand_bytes(uint8_t * therand,size_t len)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 */
98 
99 #endif // RDRAND
100