2 * Copyright (c) 2012-2014, Intel Corporation
3 * Authors: Richard B. Hill <richard.b.hill@intel.com>,
4 * H. Peter Anvin <hpa@linux.intel.com>,
5 * John P. Mechalas <john.p.mechalas@intel.com>
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms and conditions of the GNU General Public License,
9 * version 2, as published by the Free Software Foundation.
11 * This program is distributed in the hope it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * You should have received a copy of the GNU General Public License along with
17 * this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
25 #error Invalid or missing autoconf build environment
28 #include "rng-tools-config.h"
33 #include <sys/types.h>
47 #include "rngd_entsource.h"
49 #if defined(__i386__) || defined(__x86_64__)
51 /* Struct for CPUID return values */
53 uint32_t eax
, ecx
, edx
, ebx
;
57 * Get data from RDRAND. The count is in bytes, but the function can
58 * round *up* the count to the nearest 4- or 8-byte boundary. The caller
59 * needs to take that into account. count must not be zero.
61 * The function returns the number of bytes actually written.
63 extern unsigned int x86_rdrand_bytes(void *ptr
, unsigned int count
);
66 * Get data from RDSEED (preferentially) or RDRAND into separate
67 * buffers. Returns when either buffer is full. Same conditions
68 * apply as for x86_rdrand_bytes().
70 extern void x86_rdseed_or_rdrand_bytes(void *seed_ptr
, unsigned int *seed_cnt
,
71 void *rand_ptr
, unsigned int *rand_cnt
);
73 /* Condition RDRAND for seed-grade entropy */
74 extern void x86_aes_mangle(void *data
, void *state
);
76 /* Expand an AES key for future use */
77 extern void x86_aes_expand_key(const void *key
);
80 typedef uint64_t unative_t
; /* x86-64 or x32 */
82 typedef uint32_t unative_t
; /* i386 */
85 /* Checking eflags to confirm cpuid instruction available */
86 static inline int x86_has_eflag(unative_t flag
)
99 : "=&r" (f0
), "=&r" (f1
)
101 return !!((f0
^f1
) & flag
);
104 static inline int x86_has_cpuid(void)
107 return x86_has_eflag(1 << 21); /* ID flag */
109 return 1; /* x86-64 always has CPUID */
113 /* Calling cpuid instruction to verify rdrand and aes-ni capability */
114 static void cpuid(unsigned int leaf
, unsigned int subleaf
, struct cpuid
*out
)
117 /* %ebx is a forbidden register if we compile with -fPIC or -fPIE */
118 asm volatile("movl %%ebx,%0 ; cpuid ; xchgl %%ebx,%0"
123 : "a" (leaf
), "c" (subleaf
));
130 : "a" (leaf
), "c" (subleaf
));
134 /* Read data from the drng in chunks of 128 bytes for AES scrambling */
136 #define CHUNK_SIZE (AES_BLOCK*8) /* 8 parallel streams */
137 #define RDRAND_ROUNDS 512 /* 512:1 data reduction */
139 static unsigned char iv_buf
[CHUNK_SIZE
] __attribute__((aligned(128)));
140 static int have_aesni
, have_rdseed
;
142 /* Necessary if we have RDRAND but not AES-NI */
144 #ifdef HAVE_LIBGCRYPT
146 #define MIN_GCRYPT_VERSION "1.0.0"
148 static gcry_cipher_hd_t gcry_cipher_hd
;
152 static inline int gcrypt_mangle(unsigned char *tmp
)
154 #ifdef HAVE_LIBGCRYPT
155 gcry_error_t gcry_error
;
157 /* Encrypt tmp in-place. */
159 gcry_error
= gcry_cipher_encrypt(gcry_cipher_hd
, tmp
,
160 AES_BLOCK
* RDRAND_ROUNDS
,
164 message(LOG_DAEMON
|LOG_ERR
,
165 "gcry_cipher_encrypt error: %s\n",
166 gcry_strerror(gcry_error
));
176 int xread_drng(void *buf
, size_t size
, struct rng
*ent_src
)
178 static unsigned char rdrand_buf
[CHUNK_SIZE
* RDRAND_ROUNDS
]
179 __attribute__((aligned(128)));
180 static unsigned int rdrand_bytes
= 0;
181 unsigned char rdseed_buf
[CHUNK_SIZE
]
182 __attribute__((aligned(128)));
185 unsigned char *rdrand_ptr
, *data
;
186 unsigned int rand_bytes
, seed_bytes
;
191 rand_bytes
= (have_aesni
192 ? CHUNK_SIZE
* RDRAND_ROUNDS
193 : AES_BLOCK
* RDRAND_ROUNDS
)
196 if (rand_bytes
== 0) {
197 /* We already have a full rdrand_buf */
199 x86_aes_mangle(rdrand_buf
, iv_buf
);
202 } else if (!gcrypt_mangle(rdrand_buf
)) {
204 AES_BLOCK
* (RDRAND_ROUNDS
- 1);
213 rdrand_ptr
= rdrand_buf
+ rdrand_bytes
;
216 seed_bytes
= sizeof rdseed_buf
;
217 x86_rdseed_or_rdrand_bytes(rdseed_buf
, &seed_bytes
,
218 rdrand_ptr
, &rand_bytes
);
220 rand_bytes
= x86_rdrand_bytes(rdrand_ptr
, rand_bytes
);
224 rdrand_bytes
+= rand_bytes
;
232 continue; /* No data ready yet */
235 chunk
= (chunk
> size
) ? size
: chunk
;
236 memcpy(p
, data
, chunk
);
244 static int init_aesni(const void *key
)
249 x86_aes_expand_key(key
);
253 static int init_gcrypt(const void *key
)
255 #ifdef HAVE_LIBGCRYPT
256 gcry_error_t gcry_error
;
258 if (!gcry_check_version(MIN_GCRYPT_VERSION
)) {
259 message(LOG_DAEMON
|LOG_ERR
,
260 "libgcrypt version mismatch: have %s, require >= %s\n",
261 gcry_check_version(NULL
), MIN_GCRYPT_VERSION
);
265 gcry_error
= gcry_cipher_open(&gcry_cipher_hd
, GCRY_CIPHER_AES128
,
266 GCRY_CIPHER_MODE_CBC
, 0);
269 gcry_error
= gcry_cipher_setkey(gcry_cipher_hd
, key
, AES_BLOCK
);
273 * Only need the first 16 bytes of iv_buf. AES-NI can
274 * encrypt multiple blocks in parallel but we can't.
276 gcry_error
= gcry_cipher_setiv(gcry_cipher_hd
, iv_buf
, AES_BLOCK
);
280 message(LOG_DAEMON
|LOG_ERR
,
281 "could not set key or IV: %s\n",
282 gcry_strerror(gcry_error
));
283 gcry_cipher_close(gcry_cipher_hd
);
294 * Confirm RDRAND capabilities for drng entropy source
296 int init_drng_entropy_source(struct rng
*ent_src
)
299 /* We need RDRAND, but AESni is optional */
300 const uint32_t features_ecx1_rdrand
= 1 << 30;
301 const uint32_t features_ecx1_aesni
= 1 << 25;
302 const uint32_t features_ebx7_rdseed
= 1 << 18;
303 uint32_t max_cpuid_leaf
;
304 static unsigned char key
[AES_BLOCK
] = {
305 0x00,0x10,0x20,0x30,0x40,0x50,0x60,0x70,
306 0x80,0x90,0xa0,0xb0,0xc0,0xd0,0xe0,0xf0
307 }; /* AES data reduction key */
308 unsigned char xkey
[AES_BLOCK
]; /* Material to XOR into the key */
312 if (!x86_has_cpuid())
313 return 1; /* No CPUID instruction */
316 max_cpuid_leaf
= info
.eax
;
318 if (max_cpuid_leaf
< 1)
322 if (!(info
.ecx
& features_ecx1_rdrand
))
325 have_aesni
= !!(info
.ecx
& features_ecx1_aesni
);
328 if (max_cpuid_leaf
>= 7) {
330 if (info
.ebx
& features_ebx7_rdseed
)
334 /* Randomize the AES data reduction key the best we can */
335 if (x86_rdrand_bytes(xkey
, sizeof xkey
) != sizeof xkey
)
338 fd
= open("/dev/urandom", O_RDONLY
);
340 read(fd
, key
, sizeof key
);
344 for (i
= 0; i
< (int)sizeof key
; i
++)
347 /* Initialize the IV buffer */
348 if (x86_rdrand_bytes(iv_buf
, CHUNK_SIZE
) != CHUNK_SIZE
)
351 if (init_aesni(key
) && init_gcrypt(key
))
352 return 1; /* We need one crypto or the other... */
354 src_list_add(ent_src
);
355 /* Bootstrap FIPS tests */
356 ent_src
->fipsctx
= malloc(sizeof(fips_ctx_t
));
357 fips_init(ent_src
->fipsctx
, 0);
361 #else /* Not i386 or x86-64 */
363 int init_drng_entropy_source(struct rng
*ent_src
)
369 int xread_drng(void *buf
, size_t size
, struct rng
*ent_src
)
378 #endif /* Not i386 or x86-64 */