]>
git.ipfire.org Git - thirdparty/rng-tools.git/blob - rngd_rdrand.c
2 * Copyright (c) 2012, Intel Corporation
3 * Authors: Richard B. Hill <richard.b.hill@intel.com>,
4 * H. Peter Anvin <hpa@linux.intel.com>
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * You should have received a copy of the GNU General Public License along with
16 * this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
24 #error Invalid or missing autoconf build environment
27 #include "rng-tools-config.h"
32 #include <sys/types.h>
43 #include "rngd_entsource.h"
45 #if defined(__i386__) || defined(__x86_64__)
47 /* Struct for CPUID return values */
49 uint32_t eax
, ecx
, edx
, ebx
;
52 /* Get data from RDRAND */
53 extern int x86_rdrand_nlong(void *ptr
, size_t count
);
54 /* Conditioning RDRAND for seed-grade entropy */
55 extern void x86_aes_mangle(void *data
, void *state
);
57 /* Checking eflags to confirm cpuid instruction available */
58 /* Only necessary for 32 bit processors */
59 #if defined (__i386__)
60 static int x86_has_eflag(uint32_t flag
)
73 : "=&r" (f0
), "=&r" (f1
)
75 return !!((f0
^f1
) & flag
);
79 /* Calling cpuid instruction to verify rdrand capability */
80 static void cpuid(unsigned int leaf
, unsigned int subleaf
, struct cpuid
*out
)
83 /* %ebx is a forbidden register if we compile with -fPIC or -fPIE */
84 asm volatile("movl %%ebx,%0 ; cpuid ; xchgl %%ebx,%0"
89 : "a" (leaf
), "c" (subleaf
));
96 : "a" (leaf
), "c" (subleaf
));
100 /* Read data from the drng in chunks of 128 bytes for AES scrambling */
101 #define CHUNK_SIZE (16*8)
103 static unsigned char iv_buf
[CHUNK_SIZE
] __attribute__((aligned(128)));
105 int xread_drng(void *buf
, size_t size
, struct rng
*ent_src
)
109 const int rdrand_round_count
= 512;
110 unsigned char tmp
[CHUNK_SIZE
] __attribute__((aligned(128)));
114 for (i
= 0; i
< rdrand_round_count
; i
++) {
115 if (!x86_rdrand_nlong(tmp
, CHUNK_SIZE
/sizeof(long))) {
116 message(LOG_DAEMON
|LOG_ERR
, "read error\n");
119 x86_aes_mangle(tmp
, iv_buf
);
121 chunk
= (sizeof(tmp
) > size
) ? size
: sizeof(tmp
);
122 memcpy(p
, tmp
, chunk
);
131 * Confirm RDRAND capabilities for drng entropy source
133 int init_drng_entropy_source(struct rng
*ent_src
)
136 /* We need RDRAND and AESni */
137 const uint32_t need_features_ecx1
= (1 << 30) | (1 << 25);
139 #if defined(__i386__)
140 if (!x86_has_eflag(1 << 21))
141 return 1; /* No CPUID instruction */
148 if ((info
.ecx
& need_features_ecx1
) != need_features_ecx1
)
151 /* Initialize the IV buffer */
152 if (!x86_rdrand_nlong(iv_buf
, CHUNK_SIZE
/sizeof(long)))
155 src_list_add(ent_src
);
156 /* Bootstrap FIPS tests */
157 ent_src
->fipsctx
= malloc(sizeof(fips_ctx_t
));
158 fips_init(ent_src
->fipsctx
, 0);
162 #else /* Not i386 or x86-64 */
164 int init_drng_entropy_source(struct rng
*ent_src
)
170 int xread_drng(void *buf
, size_t size
, struct rng
*ent_src
)
179 #endif /* Not i386 or x86-64 */