-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathlrng_es_krng.c
100 lines (81 loc) · 2.44 KB
/
lrng_es_krng.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
/*
* LRNG Fast Entropy Source: Linux kernel RNG (random.c)
*
* Copyright (C) 2022, Stephan Mueller <smueller@chronox.de>
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/fips.h>
#include <linux/module.h>
#include <linux/random.h>
#include <linux/types.h>
#include "lrng_es_aux.h"
#include "lrng_es_krng.h"
static u32 krng_entropy = CONFIG_LRNG_KERNEL_RNG_ENTROPY_RATE;
#ifdef CONFIG_LRNG_RUNTIME_ES_CONFIG
module_param(krng_entropy, uint, 0644);
MODULE_PARM_DESC(krng_entropy, "Entropy in bits of 256 data bits from the kernel RNG noise source");
#endif
static atomic_t lrng_krng_initial_rate = ATOMIC_INIT(0);
static u32 lrng_krng_fips_entropylevel(u32 entropylevel)
{
return fips_enabled ? 0 : entropylevel;
}
static int lrng_krng_adjust_entropy(void)
{
u32 entropylevel;
krng_entropy = atomic_read_u32(&lrng_krng_initial_rate);
entropylevel = lrng_krng_fips_entropylevel(krng_entropy);
pr_debug("Kernel RNG is fully seeded, setting entropy rate to %u bits of entropy\n",
entropylevel);
lrng_drng_force_reseed();
if (entropylevel)
lrng_es_add_entropy();
return 0;
}
static u32 lrng_krng_entropylevel(u32 requested_bits)
{
static bool init = false;
if (unlikely(!init) && rng_is_initialized()) {
init = true;
lrng_krng_adjust_entropy();
}
return lrng_fast_noise_entropylevel(
lrng_krng_fips_entropylevel(krng_entropy), requested_bits);
}
static u32 lrng_krng_poolsize(void)
{
return lrng_krng_entropylevel(lrng_security_strength());
}
/*
* lrng_krng_get() - Get kernel RNG entropy
*
* @eb: entropy buffer to store entropy
* @requested_bits: requested entropy in bits
*/
static void lrng_krng_get(struct entropy_buf *eb, u32 requested_bits,
bool __unused)
{
u32 ent_bits = lrng_krng_entropylevel(requested_bits);
get_random_bytes(eb->e[lrng_ext_es_krng], requested_bits >> 3);
pr_debug("obtained %u bits of entropy from kernel RNG noise source\n",
ent_bits);
eb->e_bits[lrng_ext_es_krng] = ent_bits;
}
static void lrng_krng_es_state(unsigned char *buf, size_t buflen)
{
snprintf(buf, buflen,
" Available entropy: %u\n"
" Entropy Rate per 256 data bits: %u\n",
lrng_krng_poolsize(),
lrng_krng_entropylevel(256));
}
struct lrng_es_cb lrng_es_krng = {
.name = "KernelRNG",
.get_ent = lrng_krng_get,
.curr_entropy = lrng_krng_entropylevel,
.max_entropy = lrng_krng_poolsize,
.state = lrng_krng_es_state,
.reset = NULL,
.switch_hash = NULL,
};