]>
Commit | Line | Data |
---|---|---|
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 */ |
52 | struct 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 | */ | |
63 | extern 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 | */ | |
70 | extern 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 | 74 | extern void x86_aes_mangle(void *data, void *state); |
3164d3eb | 75 | |
94f03c9a PA |
76 | /* Expand an AES key for future use */ |
77 | extern void x86_aes_expand_key(const void *key); | |
101309bc | 78 | |
0ad21ad0 PA |
79 | #ifdef __x86_64__ |
80 | typedef uint64_t unative_t; /* x86-64 or x32 */ | |
81 | #else | |
82 | typedef uint32_t unative_t; /* i386 */ | |
83 | #endif | |
84 | ||
101309bc | 85 | /* Checking eflags to confirm cpuid instruction available */ |
0ad21ad0 | 86 | static 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 | |
104 | static 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 |
114 | static 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 | |
139 | static unsigned char iv_buf[CHUNK_SIZE] __attribute__((aligned(128))); | |
f655a53a | 140 | static 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 | ||
148 | static gcry_cipher_hd_t gcry_cipher_hd; | |
149 | ||
62dec321 | 150 | #endif |
04361df2 | 151 | |
62dec321 PA |
152 | static 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 |
176 | int 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 |
244 | static 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 | ||
253 | static 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 | */ | |
296 | int 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 | ||
363 | int init_drng_entropy_source(struct rng *ent_src) | |
364 | { | |
365 | (void)ent_src; | |
366 | return 1; | |
367 | } | |
368 | ||
369 | int 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 */ |