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 
26 /** @file
27  *
28  * Hardware random number generator
29  *
30  */
31 
32 #include <errno.h>
33 #include <ipxe/cpuid.h>
34 #include <ipxe/entropy.h>
35 #include <ipxe/drbg.h>
36 
37 struct entropy_source rdrand_entropy __entropy_source ( ENTROPY_PREFERRED );
38 
39 /** Number of times to retry RDRAND instruction */
40 #define RDRAND_RETRY_COUNT 16
41 
42 /** Colour for debug messages */
43 #define colour &rdrand_entropy
44 
45 /**
46  * Enable entropy gathering
47  *
48  * @ret rc Return status code
49  */
50 static int rdrand_entropy_enable ( void ) {
51  struct x86_features features;
52 
53  /* Check that RDRAND is supported */
55  if ( ! ( features.intel.ecx & CPUID_FEATURES_INTEL_ECX_RDRAND ) ) {
56  DBGC ( colour, "RDRAND not supported\n" );
57  return -ENOTSUP;
58  }
59 
60  /* Data returned by RDRAND is theoretically full entropy, up
61  * to a security strength of 128 bits, so assume that each
62  * sample contains exactly 8 bits of entropy.
63  */
64  if ( DRBG_SECURITY_STRENGTH > 128 )
65  return -ENOTSUP;
66  entropy_init ( &rdrand_entropy, MIN_ENTROPY ( 8.0 ) );
67 
68  return 0;
69 }
70 
71 /**
72  * Get noise sample
73  *
74  * @ret noise Noise sample
75  * @ret rc Return status code
76  */
77 static int rdrand_get_noise ( noise_sample_t *noise ) {
78  unsigned int result;
79  unsigned int discard_c;
80  unsigned int ok;
81 
82  /* Issue RDRAND, retrying until CF is set */
83  __asm__ ( "\n1:\n\t"
84  "rdrand %0\n\t"
85  "sbb %1, %1\n\t"
86  "loopz 1b\n\t"
87  : "=r" ( result ), "=r" ( ok ), "=c" ( discard_c )
88  : "2" ( RDRAND_RETRY_COUNT ) );
89  if ( ! ok ) {
90  DBGC ( colour, "RDRAND failed to become ready\n" );
91  return -EBUSY;
92  }
93 
94  *noise = result;
95  return 0;
96 }
97 
98 /** Hardware random number generator entropy source */
99 struct entropy_source rdrand_entropy __entropy_source ( ENTROPY_PREFERRED ) = {
100  .name = "rdrand",
101  .enable = rdrand_entropy_enable,
102  .get_noise = rdrand_get_noise,
103 };
static const void const void void * result
Definition: crypto.h:335
#define EBUSY
Device or resource busy.
Definition: errno.h:338
DRBG mechanism.
Error codes.
#define RDRAND_RETRY_COUNT
Number of times to retry RDRAND instruction.
Definition: rdrand.c:40
#define colour
Colour for debug messages.
Definition: rdrand.c:43
#define DBGC(...)
Definition: compiler.h:505
void x86_features(struct x86_features *features)
Get x86 CPU features.
Definition: cpuid.c:163
x86 CPU features
Definition: cpuid.h:23
An entropy source.
Definition: entropy.h:116
#define ENOTSUP
Operation not supported.
Definition: errno.h:589
const char * name
Name.
Definition: entropy.h:118
x86 CPU feature detection
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
uint32_t features
Supported features.
Definition: ena.h:16
#define MIN_ENTROPY(bits)
Construct a min-entropy fixed-point value.
Definition: entropy.h:42
static int rdrand_entropy_enable(void)
Enable entropy gathering.
Definition: rdrand.c:50
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:21
static int rdrand_get_noise(noise_sample_t *noise)
Get noise sample.
Definition: rdrand.c:77
long discard_c
Definition: bigint.h:32
#define DRBG_SECURITY_STRENGTH
Security strength.
Definition: drbg.h:30
#define ENTROPY_PREFERRED
Preferred entropy source.
Definition: entropy.h:179
static void entropy_init(struct entropy_source *source, min_entropy_t min_entropy_per_sample)
Initialise entropy source.
Definition: entropy.h:489
#define ok(success)
Definition: test.h:46
Entropy source.
#define CPUID_FEATURES_INTEL_ECX_RDRAND
RDRAND instruction is supported.
Definition: cpuid.h:43