]> git.ipfire.org Git - thirdparty/rng-tools.git/blame - rngd_rdrand.c
Release version 5.
[thirdparty/rng-tools.git] / rngd_rdrand.c
CommitLineData
101309bc 1/*
62dec321 2 * Copyright (c) 2012-2014, Intel Corporation
101309bc 3 * Authors: Richard B. Hill <richard.b.hill@intel.com>,
04361df2
JM
4 * H. Peter Anvin <hpa@linux.intel.com>,
5 * John P. Mechalas <john.p.mechalas@intel.com>
101309bc
PA
6 *
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.
10 *
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
14 * more details.
15 *
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.
19 *
20 */
21
22#define _GNU_SOURCE
23
24#ifndef HAVE_CONFIG_H
25#error Invalid or missing autoconf build environment
26#endif
27
28#include "rng-tools-config.h"
29
30#include <unistd.h>
31#include <stdint.h>
32#include <stdlib.h>
33#include <sys/types.h>
34#include <sys/stat.h>
35#include <fcntl.h>
36#include <errno.h>
37#include <syslog.h>
38#include <string.h>
39#include <stddef.h>
04361df2
JM
40#ifdef HAVE_LIBGCRYPT
41#include <gcrypt.h>
42#endif
101309bc
PA
43
44#include "rngd.h"
45#include "fips.h"
46#include "exits.h"
47#include "rngd_entsource.h"
48
49#if defined(__i386__) || defined(__x86_64__)
50
101309bc
PA
51/* Struct for CPUID return values */
52struct cpuid {
53 uint32_t eax, ecx, edx, ebx;
54};
55
3164d3eb
PA
56/*
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
f655a53a 59 * needs to take that into account. count must not be zero.
3164d3eb
PA
60 *
61 * The function returns the number of bytes actually written.
62 */
63extern unsigned int x86_rdrand_bytes(void *ptr, unsigned int count);
64
f655a53a
PA
65/*
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().
69 */
70extern void x86_rdseed_or_rdrand_bytes(void *seed_ptr, unsigned int *seed_cnt,
71 void *rand_ptr, unsigned int *rand_cnt);
72
3164d3eb 73/* Condition RDRAND for seed-grade entropy */
101309bc 74extern void x86_aes_mangle(void *data, void *state);
3164d3eb 75
94f03c9a
PA
76/* Expand an AES key for future use */
77extern void x86_aes_expand_key(const void *key);
101309bc 78
0ad21ad0
PA
79#ifdef __x86_64__
80typedef uint64_t unative_t; /* x86-64 or x32 */
81#else
82typedef uint32_t unative_t; /* i386 */
83#endif
84
101309bc 85/* Checking eflags to confirm cpuid instruction available */
0ad21ad0 86static inline int x86_has_eflag(unative_t flag)
101309bc 87{
0ad21ad0 88 unative_t f0, f1;
62dec321
PA
89 asm("pushf ; "
90 "pushf ; "
91 "pop %0 ; "
92 "mov %0,%1 ; "
93 "xor %2,%1 ; "
94 "push %1 ; "
95 "popf ; "
96 "pushf ; "
97 "pop %1 ; "
98 "popf"
99 : "=&r" (f0), "=&r" (f1)
100 : "ri" (flag));
101 return !!((f0^f1) & flag);
101309bc 102}
62dec321
PA
103
104static inline int x86_has_cpuid(void)
105{
106#ifdef __i386__
107 return x86_has_eflag(1 << 21); /* ID flag */
108#else
109 return 1; /* x86-64 always has CPUID */
101309bc 110#endif
62dec321 111}
101309bc 112
04361df2 113/* Calling cpuid instruction to verify rdrand and aes-ni capability */
101309bc
PA
114static void cpuid(unsigned int leaf, unsigned int subleaf, struct cpuid *out)
115{
116#ifdef __i386__
117 /* %ebx is a forbidden register if we compile with -fPIC or -fPIE */
118 asm volatile("movl %%ebx,%0 ; cpuid ; xchgl %%ebx,%0"
119 : "=r" (out->ebx),
120 "=a" (out->eax),
121 "=c" (out->ecx),
122 "=d" (out->edx)
123 : "a" (leaf), "c" (subleaf));
124#else
125 asm volatile("cpuid"
126 : "=b" (out->ebx),
127 "=a" (out->eax),
128 "=c" (out->ecx),
129 "=d" (out->edx)
130 : "a" (leaf), "c" (subleaf));
131#endif
132}
133
932e25b2 134/* Read data from the drng in chunks of 128 bytes for AES scrambling */
3e89e082
PA
135#define AES_BLOCK 16
136#define CHUNK_SIZE (AES_BLOCK*8) /* 8 parallel streams */
137#define RDRAND_ROUNDS 512 /* 512:1 data reduction */
932e25b2
PA
138
139static unsigned char iv_buf[CHUNK_SIZE] __attribute__((aligned(128)));
f655a53a 140static int have_aesni, have_rdseed;
04361df2
JM
141
142/* Necessary if we have RDRAND but not AES-NI */
143
144#ifdef HAVE_LIBGCRYPT
145
146#define MIN_GCRYPT_VERSION "1.0.0"
147
148static gcry_cipher_hd_t gcry_cipher_hd;
149
62dec321 150#endif
04361df2 151
62dec321
PA
152static inline int gcrypt_mangle(unsigned char *tmp)
153{
154#ifdef HAVE_LIBGCRYPT
155 gcry_error_t gcry_error;
04361df2 156
62dec321 157 /* Encrypt tmp in-place. */
04361df2 158
3e89e082
PA
159 gcry_error = gcry_cipher_encrypt(gcry_cipher_hd, tmp,
160 AES_BLOCK * RDRAND_ROUNDS,
62dec321
PA
161 NULL, 0);
162
163 if (gcry_error) {
164 message(LOG_DAEMON|LOG_ERR,
165 "gcry_cipher_encrypt error: %s\n",
166 gcry_strerror(gcry_error));
167 return -1;
168 }
169 return 0;
170#else
94f03c9a 171 (void)tmp;
62dec321
PA
172 return -1;
173#endif
174}
932e25b2 175
101309bc
PA
176int xread_drng(void *buf, size_t size, struct rng *ent_src)
177{
f655a53a
PA
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)));
932e25b2
PA
183 char *p = buf;
184 size_t chunk;
f655a53a
PA
185 unsigned char *rdrand_ptr, *data;
186 unsigned int rand_bytes, seed_bytes;
101309bc 187
94f03c9a
PA
188 (void)ent_src;
189
932e25b2 190 while (size) {
f655a53a
PA
191 rand_bytes = (have_aesni
192 ? CHUNK_SIZE * RDRAND_ROUNDS
193 : AES_BLOCK * RDRAND_ROUNDS)
194 - rdrand_bytes;
195
196 if (rand_bytes == 0) {
197 /* We already have a full rdrand_buf */
198 if (have_aesni) {
199 x86_aes_mangle(rdrand_buf, iv_buf);
200 data = iv_buf;
201 chunk = CHUNK_SIZE;
202 } else if (!gcrypt_mangle(rdrand_buf)) {
203 data = rdrand_buf +
204 AES_BLOCK * (RDRAND_ROUNDS - 1);
205 chunk = AES_BLOCK;
206 } else {
207 return -1;
208 }
209 rdrand_bytes = 0;
210 goto have_data;
3e89e082
PA
211 }
212
f655a53a
PA
213 rdrand_ptr = rdrand_buf + rdrand_bytes;
214
215 if (have_rdseed) {
216 seed_bytes = sizeof rdseed_buf;
217 x86_rdseed_or_rdrand_bytes(rdseed_buf, &seed_bytes,
218 rdrand_ptr, &rand_bytes);
3e89e082 219 } else {
f655a53a
PA
220 rand_bytes = x86_rdrand_bytes(rdrand_ptr, rand_bytes);
221 seed_bytes = 0;
101309bc 222 }
3e89e082 223
f655a53a
PA
224 rdrand_bytes += rand_bytes;
225
226 if (seed_bytes) {
227 data = rdseed_buf;
228 chunk = seed_bytes;
229 goto have_data;
230 }
231
232 continue; /* No data ready yet */
233
234 have_data:
3e89e082
PA
235 chunk = (chunk > size) ? size : chunk;
236 memcpy(p, data, chunk);
932e25b2
PA
237 p += chunk;
238 size -= chunk;
101309bc
PA
239 }
240
101309bc
PA
241 return 0;
242}
243
94f03c9a
PA
244static int init_aesni(const void *key)
245{
246 if (!have_aesni)
247 return 1;
248
249 x86_aes_expand_key(key);
250 return 0;
251}
252
253static int init_gcrypt(const void *key)
62dec321
PA
254{
255#ifdef HAVE_LIBGCRYPT
62dec321
PA
256 gcry_error_t gcry_error;
257
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);
262 return 1;
263 }
264
265 gcry_error = gcry_cipher_open(&gcry_cipher_hd, GCRY_CIPHER_AES128,
266 GCRY_CIPHER_MODE_CBC, 0);
267
268 if (!gcry_error)
3e89e082 269 gcry_error = gcry_cipher_setkey(gcry_cipher_hd, key, AES_BLOCK);
62dec321
PA
270
271 if (!gcry_error) {
272 /*
273 * Only need the first 16 bytes of iv_buf. AES-NI can
274 * encrypt multiple blocks in parallel but we can't.
275 */
3e89e082 276 gcry_error = gcry_cipher_setiv(gcry_cipher_hd, iv_buf, AES_BLOCK);
62dec321
PA
277 }
278
279 if (gcry_error) {
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);
284 return 1;
285 }
286 return 0;
287#else
94f03c9a 288 (void)key;
62dec321
PA
289 return 1;
290#endif
291}
292
101309bc
PA
293/*
294 * Confirm RDRAND capabilities for drng entropy source
295 */
296int init_drng_entropy_source(struct rng *ent_src)
297{
298 struct cpuid info;
04361df2
JM
299 /* We need RDRAND, but AESni is optional */
300 const uint32_t features_ecx1_rdrand = 1 << 30;
62dec321 301 const uint32_t features_ecx1_aesni = 1 << 25;
f655a53a
PA
302 const uint32_t features_ebx7_rdseed = 1 << 18;
303 uint32_t max_cpuid_leaf;
3e89e082 304 static unsigned char key[AES_BLOCK] = {
94f03c9a
PA
305 0x00,0x10,0x20,0x30,0x40,0x50,0x60,0x70,
306 0x80,0x90,0xa0,0xb0,0xc0,0xd0,0xe0,0xf0
307 }; /* AES data reduction key */
3e89e082 308 unsigned char xkey[AES_BLOCK]; /* Material to XOR into the key */
94f03c9a
PA
309 int fd;
310 int i;
101309bc 311
62dec321 312 if (!x86_has_cpuid())
101309bc 313 return 1; /* No CPUID instruction */
101309bc
PA
314
315 cpuid(0, 0, &info);
f655a53a
PA
316 max_cpuid_leaf = info.eax;
317
318 if (max_cpuid_leaf < 1)
101309bc 319 return 1;
f655a53a 320
101309bc 321 cpuid(1, 0, &info);
62dec321 322 if (!(info.ecx & features_ecx1_rdrand))
101309bc
PA
323 return 1;
324
62dec321
PA
325 have_aesni = !!(info.ecx & features_ecx1_aesni);
326
f655a53a
PA
327 have_rdseed = 0;
328 if (max_cpuid_leaf >= 7) {
329 cpuid(7, 0, &info);
330 if (info.ebx & features_ebx7_rdseed)
331 have_rdseed = 1;
332 }
333
94f03c9a 334 /* Randomize the AES data reduction key the best we can */
3164d3eb 335 if (x86_rdrand_bytes(xkey, sizeof xkey) != sizeof xkey)
94f03c9a
PA
336 return 1;
337
338 fd = open("/dev/urandom", O_RDONLY);
339 if (fd >= 0) {
340 read(fd, key, sizeof key);
341 close(fd);
342 }
343
f655a53a 344 for (i = 0; i < (int)sizeof key; i++)
94f03c9a 345 key[i] ^= xkey[i];
04361df2 346
932e25b2 347 /* Initialize the IV buffer */
3164d3eb 348 if (x86_rdrand_bytes(iv_buf, CHUNK_SIZE) != CHUNK_SIZE)
932e25b2
PA
349 return 1;
350
94f03c9a 351 if (init_aesni(key) && init_gcrypt(key))
62dec321 352 return 1; /* We need one crypto or the other... */
04361df2 353
101309bc
PA
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);
358 return 0;
359}
360
361#else /* Not i386 or x86-64 */
362
363int init_drng_entropy_source(struct rng *ent_src)
364{
365 (void)ent_src;
366 return 1;
367}
368
369int xread_drng(void *buf, size_t size, struct rng *ent_src)
370{
371 (void)buf;
372 (void)size;
373 (void)ent_src;
374
375 return -1;
376}
377
378#endif /* Not i386 or x86-64 */