2 * Copyright (c) 2012, 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 /* Only necessary for 32 bit processors */
63 #if defined (__i386__)
64 static int x86_has_eflag(uint32_t flag
)
77 : "=&r" (f0
), "=&r" (f1
)
79 return !!((f0
^f1
) & flag
);
83 /* Calling cpuid instruction to verify rdrand and aes-ni capability */
84 static void cpuid(unsigned int leaf
, unsigned int subleaf
, struct cpuid
*out
)
87 /* %ebx is a forbidden register if we compile with -fPIC or -fPIE */
88 asm volatile("movl %%ebx,%0 ; cpuid ; xchgl %%ebx,%0"
93 : "a" (leaf
), "c" (subleaf
));
100 : "a" (leaf
), "c" (subleaf
));
104 /* Read data from the drng in chunks of 128 bytes for AES scrambling */
105 #define CHUNK_SIZE (16*8)
107 static unsigned char iv_buf
[CHUNK_SIZE
] __attribute__((aligned(128)));
108 static int have_aesni
= 0;
110 /* Necessary if we have RDRAND but not AES-NI */
112 #ifdef HAVE_LIBGCRYPT
114 #define MIN_GCRYPT_VERSION "1.0.0"
116 static gcry_cipher_hd_t gcry_cipher_hd
;
118 /* Arbitrary 128-bit AES key 0x00102030405060708090A0B0C0D0E0F0 */
120 static const unsigned char key
[16]= {
121 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
122 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0
128 int xread_drng(void *buf
, size_t size
, struct rng
*ent_src
)
132 const int rdrand_round_count
= 512;
133 unsigned char tmp
[CHUNK_SIZE
] __attribute__((aligned(128)));
137 for (i
= 0; i
< rdrand_round_count
; i
++) {
138 if (!x86_rdrand_nlong(tmp
, CHUNK_SIZE
/sizeof(long))) {
139 message(LOG_DAEMON
|LOG_ERR
, "read error\n");
143 // Use 128-bit AES in CBC mode to mangle our random data
145 if ( have_aesni
) x86_aes_mangle(tmp
, iv_buf
);
147 #ifdef HAVE_LIBGCRYPT
148 gcry_error_t gcry_error
;
150 /* Encrypt tmp in-place. */
152 gcry_error
= gcry_cipher_encrypt(gcry_cipher_hd
,
153 tmp
, CHUNK_SIZE
, NULL
, 0);
156 message(LOG_DAEMON
|LOG_ERR
,
157 "gcry_cipher_encrypt error: %s\n",
158 gcry_strerror(gcry_error
));
166 chunk
= (sizeof(tmp
) > size
) ? size
: sizeof(tmp
);
167 memcpy(p
, tmp
, chunk
);
176 * Confirm RDRAND capabilities for drng entropy source
178 int init_drng_entropy_source(struct rng
*ent_src
)
181 /* We need RDRAND, but AESni is optional */
182 const uint32_t features_ecx1_rdrand
= 1 << 30;
183 const uint32_t features_ecx1_aesni
= 1 << 25;
185 #if defined(__i386__)
186 if (!x86_has_eflag(1 << 21))
187 return 1; /* No CPUID instruction */
194 if (! (info
.ecx
& features_ecx1_rdrand
) )
197 have_aesni
= (info
.ecx
& features_ecx1_aesni
) ? 1 : 0;
198 #ifndef HAVE_LIBGCRYPT
199 if ( ! have_aesni
) return 1;
202 /* Initialize the IV buffer */
203 if (!x86_rdrand_nlong(iv_buf
, CHUNK_SIZE
/sizeof(long)))
206 #ifdef HAVE_LIBGCRYPT
207 if ( ! have_aesni
) {
208 gcry_error_t gcry_error
;
210 if (! gcry_check_version(MIN_GCRYPT_VERSION
) ) {
211 message(LOG_DAEMON
|LOG_ERR
,
212 "libgcrypt version mismatch: have %s, require >= %s\n",
213 gcry_check_version(NULL
), MIN_GCRYPT_VERSION
);
217 gcry_error
= gcry_cipher_open(&gcry_cipher_hd
,
218 GCRY_CIPHER_AES128
, GCRY_CIPHER_MODE_CBC
, 0);
220 if ( ! gcry_error
) {
221 gcry_error
= gcry_cipher_setkey(gcry_cipher_hd
, key
, 16);
224 if ( ! gcry_error
) {
226 * Only need the first 16 bytes of iv_buf. AES-NI can
227 * encrypt multiple blocks in parallel but we can't.
230 gcry_error
= gcry_cipher_setiv(gcry_cipher_hd
, iv_buf
, 16);
234 message(LOG_DAEMON
|LOG_ERR
,
235 "could not set key or IV: %s\n",
236 gcry_strerror(gcry_error
));
237 gcry_cipher_close(gcry_cipher_hd
);
243 src_list_add(ent_src
);
244 /* Bootstrap FIPS tests */
245 ent_src
->fipsctx
= malloc(sizeof(fips_ctx_t
));
246 fips_init(ent_src
->fipsctx
, 0);
250 #else /* Not i386 or x86-64 */
252 int init_drng_entropy_source(struct rng
*ent_src
)
258 int xread_drng(void *buf
, size_t size
, struct rng
*ent_src
)
267 #endif /* Not i386 or x86-64 */