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
;
56 /* Get data from RDRAND */
57 extern int x86_rdrand_nlong(void *ptr
, size_t count
);
58 /* Conditioning RDRAND for seed-grade entropy */
59 extern void x86_aes_mangle(void *data
, void *state
);
61 /* Checking eflags to confirm cpuid instruction available */
62 static inline int x86_has_eflag(unsigned long flag
)
75 : "=&r" (f0
), "=&r" (f1
)
77 return !!((f0
^f1
) & flag
);
80 static inline int x86_has_cpuid(void)
83 return x86_has_eflag(1 << 21); /* ID flag */
85 return 1; /* x86-64 always has CPUID */
89 /* Calling cpuid instruction to verify rdrand and aes-ni capability */
90 static void cpuid(unsigned int leaf
, unsigned int subleaf
, struct cpuid
*out
)
93 /* %ebx is a forbidden register if we compile with -fPIC or -fPIE */
94 asm volatile("movl %%ebx,%0 ; cpuid ; xchgl %%ebx,%0"
99 : "a" (leaf
), "c" (subleaf
));
106 : "a" (leaf
), "c" (subleaf
));
110 /* Read data from the drng in chunks of 128 bytes for AES scrambling */
111 #define CHUNK_SIZE (16*8)
113 static unsigned char iv_buf
[CHUNK_SIZE
] __attribute__((aligned(128)));
114 static int have_aesni
;
116 /* Necessary if we have RDRAND but not AES-NI */
118 #ifdef HAVE_LIBGCRYPT
120 #define MIN_GCRYPT_VERSION "1.0.0"
122 static gcry_cipher_hd_t gcry_cipher_hd
;
126 static inline int gcrypt_mangle(unsigned char *tmp
)
128 #ifdef HAVE_LIBGCRYPT
129 gcry_error_t gcry_error
;
131 /* Encrypt tmp in-place. */
133 gcry_error
= gcry_cipher_encrypt(gcry_cipher_hd
, tmp
, CHUNK_SIZE
,
137 message(LOG_DAEMON
|LOG_ERR
,
138 "gcry_cipher_encrypt error: %s\n",
139 gcry_strerror(gcry_error
));
148 int xread_drng(void *buf
, size_t size
, struct rng
*ent_src
)
152 const int rdrand_round_count
= 512;
153 unsigned char tmp
[CHUNK_SIZE
] __attribute__((aligned(128)));
157 for (i
= 0; i
< rdrand_round_count
; i
++) {
158 if (!x86_rdrand_nlong(tmp
, CHUNK_SIZE
/sizeof(long))) {
159 message(LOG_DAEMON
|LOG_ERR
, "read error\n");
164 * Use 128-bit AES in CBC mode to reduce the
165 * data by a factor of rdrand_round_count
168 x86_aes_mangle(tmp
, iv_buf
);
169 else if (gcrypt_mangle(tmp
))
172 chunk
= (sizeof(tmp
) > size
) ? size
: sizeof(tmp
);
173 memcpy(p
, tmp
, chunk
);
181 static int init_gcrypt(void)
183 #ifdef HAVE_LIBGCRYPT
184 /* Arbitrary 128-bit AES key 0x00102030405060708090A0B0C0D0E0F0 */
185 static const unsigned char key
[16] = {
186 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
187 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0
189 gcry_error_t gcry_error
;
191 if (!gcry_check_version(MIN_GCRYPT_VERSION
)) {
192 message(LOG_DAEMON
|LOG_ERR
,
193 "libgcrypt version mismatch: have %s, require >= %s\n",
194 gcry_check_version(NULL
), MIN_GCRYPT_VERSION
);
198 gcry_error
= gcry_cipher_open(&gcry_cipher_hd
, GCRY_CIPHER_AES128
,
199 GCRY_CIPHER_MODE_CBC
, 0);
202 gcry_error
= gcry_cipher_setkey(gcry_cipher_hd
, key
, 16);
206 * Only need the first 16 bytes of iv_buf. AES-NI can
207 * encrypt multiple blocks in parallel but we can't.
209 gcry_error
= gcry_cipher_setiv(gcry_cipher_hd
, iv_buf
, 16);
213 message(LOG_DAEMON
|LOG_ERR
,
214 "could not set key or IV: %s\n",
215 gcry_strerror(gcry_error
));
216 gcry_cipher_close(gcry_cipher_hd
);
226 * Confirm RDRAND capabilities for drng entropy source
228 int init_drng_entropy_source(struct rng
*ent_src
)
231 /* We need RDRAND, but AESni is optional */
232 const uint32_t features_ecx1_rdrand
= 1 << 30;
233 const uint32_t features_ecx1_aesni
= 1 << 25;
235 if (!x86_has_cpuid())
236 return 1; /* No CPUID instruction */
242 if (!(info
.ecx
& features_ecx1_rdrand
))
245 have_aesni
= !!(info
.ecx
& features_ecx1_aesni
);
247 /* Initialize the AES key */
249 /* Initialize the IV buffer */
250 if (!x86_rdrand_nlong(iv_buf
, CHUNK_SIZE
/sizeof(long)))
253 if (!have_aesni
&& init_gcrypt())
254 return 1; /* We need one crypto or the other... */
256 src_list_add(ent_src
);
257 /* Bootstrap FIPS tests */
258 ent_src
->fipsctx
= malloc(sizeof(fips_ctx_t
));
259 fips_init(ent_src
->fipsctx
, 0);
263 #else /* Not i386 or x86-64 */
265 int init_drng_entropy_source(struct rng
*ent_src
)
271 int xread_drng(void *buf
, size_t size
, struct rng
*ent_src
)
280 #endif /* Not i386 or x86-64 */