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 
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25 FILE_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 
38 struct entropy_source rdrand_entropy __entropy_source ( ENTROPY_PREFERRED );
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  */
51 static int rdrand_entropy_enable ( void ) {
52  struct x86_features features;
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  */
78 static 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 */
100 struct entropy_source rdrand_entropy __entropy_source ( ENTROPY_PREFERRED ) = {
101  .name = "rdrand",
102  .enable = rdrand_entropy_enable,
103  .get_noise = rdrand_get_noise,
104 };
#define EBUSY
Device or resource busy.
Definition: errno.h:339
DRBG mechanism.
Error codes.
#define RDRAND_RETRY_COUNT
Number of times to retry RDRAND instruction.
Definition: rdrand.c:41
#define colour
Colour for debug messages.
Definition: rdrand.c:44
#define DBGC(...)
Definition: compiler.h:505
void x86_features(struct x86_features *features)
Get x86 CPU features.
Definition: cpuid.c:164
x86 CPU features
Definition: cpuid.h:24
An entropy source.
Definition: entropy.h:117
#define ENOTSUP
Operation not supported.
Definition: errno.h:590
const char * name
Name.
Definition: entropy.h:119
x86 CPU feature detection
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
uint32_t features
Supported features.
Definition: ena.h:16
FILE_SECBOOT(PERMITTED)
#define MIN_ENTROPY(bits)
Construct a min-entropy fixed-point value.
Definition: entropy.h:43
static int rdrand_entropy_enable(void)
Enable entropy gathering.
Definition: rdrand.c:51
uint16_t result
Definition: hyperv.h:33
struct entropy_source rdrand_entropy __entropy_source(ENTROPY_PREFERRED)
Hardware random number generator entropy source.
__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")
uint8_t noise_sample_t
A noise sample.
Definition: entropy.h:22
static int rdrand_get_noise(noise_sample_t *noise)
Get noise sample.
Definition: rdrand.c:78
long discard_c
Definition: bigint.h:33
#define DRBG_SECURITY_STRENGTH
Security strength.
Definition: drbg.h:31
#define ENTROPY_PREFERRED
Preferred entropy source.
Definition: entropy.h:180
static void entropy_init(struct entropy_source *source, min_entropy_t min_entropy_per_sample)
Initialise entropy source.
Definition: entropy.h:490
#define ok(success)
Definition: test.h:46
Entropy source.
#define CPUID_FEATURES_INTEL_ECX_RDRAND
RDRAND instruction is supported.
Definition: cpuid.h:47