iPXE
rdrand.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2023 Michael Brown <mbrown@fensystems.co.uk>.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
18 *
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
22 */
23
24FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25FILE_SECBOOT ( PERMITTED );
26
27/** @file
28 *
29 * Hardware random number generator
30 *
31 */
32
33#include <errno.h>
34#include <ipxe/cpuid.h>
35#include <ipxe/entropy.h>
36#include <ipxe/drbg.h>
37
39
40/** Number of times to retry RDRAND instruction */
41#define RDRAND_RETRY_COUNT 16
42
43/** Colour for debug messages */
44#define colour &rdrand_entropy
45
46/**
47 * Enable entropy gathering
48 *
49 * @ret rc Return status code
50 */
51static int rdrand_entropy_enable ( void ) {
53
54 /* Check that RDRAND is supported */
56 if ( ! ( features.intel.ecx & CPUID_FEATURES_INTEL_ECX_RDRAND ) ) {
57 DBGC ( colour, "RDRAND not supported\n" );
58 return -ENOTSUP;
59 }
60
61 /* Data returned by RDRAND is theoretically full entropy, up
62 * to a security strength of 128 bits, so assume that each
63 * sample contains exactly 8 bits of entropy.
64 */
65 if ( DRBG_SECURITY_STRENGTH > 128 )
66 return -ENOTSUP;
67 entropy_init ( &rdrand_entropy, MIN_ENTROPY ( 8.0 ) );
68
69 return 0;
70}
71
72/**
73 * Get noise sample
74 *
75 * @ret noise Noise sample
76 * @ret rc Return status code
77 */
78static int rdrand_get_noise ( noise_sample_t *noise ) {
79 unsigned int result;
80 unsigned int discard_c;
81 unsigned int ok;
82
83 /* Issue RDRAND, retrying until CF is set */
84 __asm__ ( "\n1:\n\t"
85 "rdrand %0\n\t"
86 "sbb %1, %1\n\t"
87 "loopz 1b\n\t"
88 : "=r" ( result ), "=r" ( ok ), "=c" ( discard_c )
89 : "2" ( RDRAND_RETRY_COUNT ) );
90 if ( ! ok ) {
91 DBGC ( colour, "RDRAND failed to become ready\n" );
92 return -EBUSY;
93 }
94
95 *noise = result;
96 return 0;
97}
98
99/** Hardware random number generator entropy source */
100struct entropy_source rdrand_entropy __entropy_source ( ENTROPY_PREFERRED ) = {
101 .name = "rdrand",
102 .enable = rdrand_entropy_enable,
103 .get_noise = rdrand_get_noise,
104};
#define colour
Colour for debug messages.
Definition acpi.c:42
uint16_t result
Definition hyperv.h:33
long discard_c
Definition bigint.h:33
void x86_features(struct x86_features *features)
Get x86 CPU features.
Definition cpuid.c:164
x86 CPU feature detection
#define CPUID_FEATURES_INTEL_ECX_RDRAND
RDRAND instruction is supported.
Definition cpuid.h:47
DRBG mechanism.
#define DRBG_SECURITY_STRENGTH
Security strength.
Definition drbg.h:31
uint32_t features
Supported features.
Definition ena.h:5
Error codes.
#define DBGC(...)
Definition compiler.h:505
#define ENTROPY_PREFERRED
Preferred entropy source.
Definition entropy.h:180
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
#define EBUSY
Device or resource busy.
Definition errno.h:339
#define ENOTSUP
Operation not supported.
Definition errno.h:590
#define FILE_SECBOOT(_status)
Declare a file's UEFI Secure Boot permission status.
Definition compiler.h:926
Entropy source.
static void entropy_init(struct entropy_source *source, min_entropy_t min_entropy_per_sample)
Initialise entropy source.
Definition entropy.h:490
#define MIN_ENTROPY(bits)
Construct a min-entropy fixed-point value.
Definition entropy.h:43
uint8_t noise_sample_t
A noise sample.
Definition entropy.h:22
#define __entropy_source(order)
Declare an entropy source.
Definition entropy.h:173
__asm__(".section \".rodata\", \"a\", " PROGBITS "\n\t" "\nprivate_key_data:\n\t" ".size private_key_data, ( . - private_key_data )\n\t" ".equ private_key_len, ( . - private_key_data )\n\t" ".previous\n\t")
#define RDRAND_RETRY_COUNT
Number of times to retry RDRAND instruction.
Definition rdrand.c:41
static int rdrand_get_noise(noise_sample_t *noise)
Get noise sample.
Definition rdrand.c:78
static int rdrand_entropy_enable(void)
Enable entropy gathering.
Definition rdrand.c:51
An entropy source.
Definition entropy.h:117
x86 CPU features
Definition cpuid.h:24
#define ok(success)
Definition test.h:46