1dfc9fa91SStephan Mueller /*
2dfc9fa91SStephan Mueller * Non-physical true random number generator based on timing jitter --
3dfc9fa91SStephan Mueller * Linux Kernel Crypto API specific code
4dfc9fa91SStephan Mueller *
5bb897c55SStephan Müller * Copyright Stephan Mueller <smueller@chronox.de>, 2015 - 2023
6dfc9fa91SStephan Mueller *
7dfc9fa91SStephan Mueller * Redistribution and use in source and binary forms, with or without
8dfc9fa91SStephan Mueller * modification, are permitted provided that the following conditions
9dfc9fa91SStephan Mueller * are met:
10dfc9fa91SStephan Mueller * 1. Redistributions of source code must retain the above copyright
11dfc9fa91SStephan Mueller * notice, and the entire permission notice in its entirety,
12dfc9fa91SStephan Mueller * including the disclaimer of warranties.
13dfc9fa91SStephan Mueller * 2. Redistributions in binary form must reproduce the above copyright
14dfc9fa91SStephan Mueller * notice, this list of conditions and the following disclaimer in the
15dfc9fa91SStephan Mueller * documentation and/or other materials provided with the distribution.
16dfc9fa91SStephan Mueller * 3. The name of the author may not be used to endorse or promote
17dfc9fa91SStephan Mueller * products derived from this software without specific prior
18dfc9fa91SStephan Mueller * written permission.
19dfc9fa91SStephan Mueller *
20dfc9fa91SStephan Mueller * ALTERNATIVELY, this product may be distributed under the terms of
21dfc9fa91SStephan Mueller * the GNU General Public License, in which case the provisions of the GPL2 are
22dfc9fa91SStephan Mueller * required INSTEAD OF the above restrictions. (This clause is
23dfc9fa91SStephan Mueller * necessary due to a potential bad interaction between the GPL and
24dfc9fa91SStephan Mueller * the restrictions contained in a BSD-style copyright.)
25dfc9fa91SStephan Mueller *
26dfc9fa91SStephan Mueller * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
27dfc9fa91SStephan Mueller * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
28dfc9fa91SStephan Mueller * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
29dfc9fa91SStephan Mueller * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
30dfc9fa91SStephan Mueller * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31dfc9fa91SStephan Mueller * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
32dfc9fa91SStephan Mueller * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
33dfc9fa91SStephan Mueller * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34dfc9fa91SStephan Mueller * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35dfc9fa91SStephan Mueller * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
36dfc9fa91SStephan Mueller * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
37dfc9fa91SStephan Mueller * DAMAGE.
38dfc9fa91SStephan Mueller */
39dfc9fa91SStephan Mueller
40bb897c55SStephan Müller #include <crypto/sha3.h>
413fde2fe9SStephan Müller #include <linux/fips.h>
420c3dc787SHerbert Xu #include <linux/kernel.h>
43dfc9fa91SStephan Mueller #include <linux/module.h>
44*01d798e9SHaixin Xu #include <linux/mutex.h>
45dfc9fa91SStephan Mueller #include <linux/slab.h>
46dfc9fa91SStephan Mueller #include <linux/time.h>
47dfc9fa91SStephan Mueller #include <crypto/internal/rng.h>
48dfc9fa91SStephan Mueller
49965d7286SBen Dooks #include "jitterentropy.h"
50dfc9fa91SStephan Mueller
51dfc9fa91SStephan Mueller /***************************************************************************
52dfc9fa91SStephan Mueller * Helper function
53dfc9fa91SStephan Mueller ***************************************************************************/
54dfc9fa91SStephan Mueller
jent_kvzalloc(unsigned int len)5559bcfd78SStephan Müller void *jent_kvzalloc(unsigned int len)
5659bcfd78SStephan Müller {
5759bcfd78SStephan Müller return kvzalloc(len, GFP_KERNEL);
5859bcfd78SStephan Müller }
5959bcfd78SStephan Müller
jent_kvzfree(void * ptr,unsigned int len)6059bcfd78SStephan Müller void jent_kvzfree(void *ptr, unsigned int len)
6159bcfd78SStephan Müller {
626e61ee1cSThorsten Blum kvfree_sensitive(ptr, len);
6359bcfd78SStephan Müller }
6459bcfd78SStephan Müller
jent_zalloc(unsigned int len)65dfc9fa91SStephan Mueller void *jent_zalloc(unsigned int len)
66dfc9fa91SStephan Mueller {
67dfc9fa91SStephan Mueller return kzalloc(len, GFP_KERNEL);
68dfc9fa91SStephan Mueller }
69dfc9fa91SStephan Mueller
jent_zfree(void * ptr)70dfc9fa91SStephan Mueller void jent_zfree(void *ptr)
71dfc9fa91SStephan Mueller {
72453431a5SWaiman Long kfree_sensitive(ptr);
73dfc9fa91SStephan Mueller }
74dfc9fa91SStephan Mueller
75b578456cSStephan Mueller /*
76b578456cSStephan Mueller * Obtain a high-resolution time stamp value. The time stamp is used to measure
77b578456cSStephan Mueller * the execution time of a given code path and its variations. Hence, the time
78b578456cSStephan Mueller * stamp must have a sufficiently high resolution.
79b578456cSStephan Mueller *
80b578456cSStephan Mueller * Note, if the function returns zero because a given architecture does not
81b578456cSStephan Mueller * implement a high-resolution time stamp, the RNG code's runtime test
82b578456cSStephan Mueller * will detect it and will not produce output.
83b578456cSStephan Mueller */
jent_get_nstime(__u64 * out)84dfc9fa91SStephan Mueller void jent_get_nstime(__u64 *out)
85dfc9fa91SStephan Mueller {
86dfc9fa91SStephan Mueller __u64 tmp = 0;
87dfc9fa91SStephan Mueller
88dfc9fa91SStephan Mueller tmp = random_get_entropy();
89dfc9fa91SStephan Mueller
90dfc9fa91SStephan Mueller /*
91b578456cSStephan Mueller * If random_get_entropy does not return a value, i.e. it is not
92b578456cSStephan Mueller * implemented for a given architecture, use a clock source.
93dfc9fa91SStephan Mueller * hoping that there are timers we can work with.
94dfc9fa91SStephan Mueller */
95b578456cSStephan Mueller if (tmp == 0)
96b578456cSStephan Mueller tmp = ktime_get_ns();
97dfc9fa91SStephan Mueller
98dfc9fa91SStephan Mueller *out = tmp;
9969f1c387SStephan Müller jent_raw_hires_entropy_store(tmp);
100dfc9fa91SStephan Mueller }
101dfc9fa91SStephan Mueller
jent_hash_time(struct sha3_ctx * hash_state,__u64 time,u8 * addtl,unsigned int addtl_len,__u64 hash_loop_cnt,unsigned int stuck)102ce260754SDavid Howells void jent_hash_time(struct sha3_ctx *hash_state, __u64 time, u8 *addtl,
103bb897c55SStephan Müller unsigned int addtl_len, __u64 hash_loop_cnt,
104bb897c55SStephan Müller unsigned int stuck)
105bb897c55SStephan Müller {
106ce260754SDavid Howells struct sha3_ctx tmp_state; /* zeroized by sha3_final() */
107bb897c55SStephan Müller u8 intermediary[SHA3_256_DIGEST_SIZE];
108bb897c55SStephan Müller __u64 j = 0;
109bb897c55SStephan Müller
1109aa7e045SEdward Adam Davis kmsan_unpoison_memory(intermediary, sizeof(intermediary));
111bb897c55SStephan Müller
112bb897c55SStephan Müller /*
113bb897c55SStephan Müller * This loop fills a buffer which is injected into the entropy pool.
114bb897c55SStephan Müller * The main reason for this loop is to execute something over which we
115bb897c55SStephan Müller * can perform a timing measurement. The injection of the resulting
116bb897c55SStephan Müller * data into the pool is performed to ensure the result is used and
117bb897c55SStephan Müller * the compiler cannot optimize the loop away in case the result is not
118bb897c55SStephan Müller * used at all. Yet that data is considered "additional information"
119bb897c55SStephan Müller * considering the terminology from SP800-90A without any entropy.
120bb897c55SStephan Müller *
121bb897c55SStephan Müller * Note, it does not matter which or how much data you inject, we are
122bb897c55SStephan Müller * interested in one Keccack1600 compression operation performed with
123ce260754SDavid Howells * the sha3_final.
124bb897c55SStephan Müller */
125bb897c55SStephan Müller for (j = 0; j < hash_loop_cnt; j++) {
126ce260754SDavid Howells sha3_256_init(&tmp_state);
127ce260754SDavid Howells sha3_update(&tmp_state, intermediary, sizeof(intermediary));
128ce260754SDavid Howells sha3_update(&tmp_state, addtl, addtl_len);
129ce260754SDavid Howells sha3_final(&tmp_state, intermediary);
130bb897c55SStephan Müller }
131bb897c55SStephan Müller
132bb897c55SStephan Müller /*
133bb897c55SStephan Müller * Inject the data from the previous loop into the pool. This data is
134bb897c55SStephan Müller * not considered to contain any entropy, but it stirs the pool a bit.
135bb897c55SStephan Müller */
136ce260754SDavid Howells sha3_update(hash_state, intermediary, sizeof(intermediary));
137bb897c55SStephan Müller
138bb897c55SStephan Müller /*
139bb897c55SStephan Müller * Insert the time stamp into the hash context representing the pool.
140bb897c55SStephan Müller *
141bb897c55SStephan Müller * If the time stamp is stuck, do not finally insert the value into the
142bb897c55SStephan Müller * entropy pool. Although this operation should not do any harm even
143bb897c55SStephan Müller * when the time stamp has no entropy, SP800-90B requires that any
144bb897c55SStephan Müller * conditioning operation to have an identical amount of input data
145bb897c55SStephan Müller * according to section 3.1.5.
146bb897c55SStephan Müller */
147735b7256SMarkus Theil if (stuck) {
148735b7256SMarkus Theil time = 0;
149bb897c55SStephan Müller }
150bb897c55SStephan Müller
151ce260754SDavid Howells sha3_update(hash_state, (u8 *)&time, sizeof(__u64));
152bb897c55SStephan Müller memzero_explicit(intermediary, sizeof(intermediary));
153bb897c55SStephan Müller }
154bb897c55SStephan Müller
jent_read_random_block(struct sha3_ctx * hash_state,char * dst,unsigned int dst_len)155ce260754SDavid Howells void jent_read_random_block(struct sha3_ctx *hash_state, char *dst,
156ce260754SDavid Howells unsigned int dst_len)
157bb897c55SStephan Müller {
158bb897c55SStephan Müller u8 jent_block[SHA3_256_DIGEST_SIZE];
159bb897c55SStephan Müller
160ce260754SDavid Howells /* Obtain data from entropy pool and re-initialize it */
161ce260754SDavid Howells sha3_final(hash_state, jent_block);
162ce260754SDavid Howells sha3_256_init(hash_state);
163ce260754SDavid Howells sha3_update(hash_state, jent_block, sizeof(jent_block));
164ce260754SDavid Howells
165ce260754SDavid Howells if (dst_len)
166bb897c55SStephan Müller memcpy(dst, jent_block, dst_len);
167bb897c55SStephan Müller
168bb897c55SStephan Müller memzero_explicit(jent_block, sizeof(jent_block));
169bb897c55SStephan Müller }
170bb897c55SStephan Müller
171dfc9fa91SStephan Mueller /***************************************************************************
172dfc9fa91SStephan Mueller * Kernel crypto API interface
173dfc9fa91SStephan Mueller ***************************************************************************/
174dfc9fa91SStephan Mueller
175dfc9fa91SStephan Mueller struct jitterentropy {
176*01d798e9SHaixin Xu struct mutex jent_lock;
177dfc9fa91SStephan Mueller struct rand_data *entropy_collector;
178ce260754SDavid Howells struct sha3_ctx hash_state;
179dfc9fa91SStephan Mueller };
180dfc9fa91SStephan Mueller
jent_kcapi_cleanup(struct crypto_tfm * tfm)181dfc9fa91SStephan Mueller static void jent_kcapi_cleanup(struct crypto_tfm *tfm)
182dfc9fa91SStephan Mueller {
183dfc9fa91SStephan Mueller struct jitterentropy *rng = crypto_tfm_ctx(tfm);
184dfc9fa91SStephan Mueller
185*01d798e9SHaixin Xu mutex_lock(&rng->jent_lock);
186bb897c55SStephan Müller
187ce260754SDavid Howells memzero_explicit(&rng->hash_state, sizeof(rng->hash_state));
188bb897c55SStephan Müller
189dfc9fa91SStephan Mueller if (rng->entropy_collector)
190dfc9fa91SStephan Mueller jent_entropy_collector_free(rng->entropy_collector);
191dfc9fa91SStephan Mueller rng->entropy_collector = NULL;
192*01d798e9SHaixin Xu mutex_unlock(&rng->jent_lock);
193dfc9fa91SStephan Mueller }
194dfc9fa91SStephan Mueller
jent_kcapi_init(struct crypto_tfm * tfm)195bb897c55SStephan Müller static int jent_kcapi_init(struct crypto_tfm *tfm)
196bb897c55SStephan Müller {
197bb897c55SStephan Müller struct jitterentropy *rng = crypto_tfm_ctx(tfm);
198ce260754SDavid Howells int ret = 0;
199bb897c55SStephan Müller
200*01d798e9SHaixin Xu mutex_init(&rng->jent_lock);
201bb897c55SStephan Müller
202d280d4d5SEric Biggers /* Use SHA3-256 as conditioner */
203ce260754SDavid Howells sha3_256_init(&rng->hash_state);
204bb897c55SStephan Müller
205ce260754SDavid Howells rng->entropy_collector = jent_entropy_collector_alloc(
206ce260754SDavid Howells CONFIG_CRYPTO_JITTERENTROPY_OSR, 0, &rng->hash_state);
207bb897c55SStephan Müller if (!rng->entropy_collector) {
208bb897c55SStephan Müller ret = -ENOMEM;
209bb897c55SStephan Müller goto err;
210bb897c55SStephan Müller }
211bb897c55SStephan Müller
212bb897c55SStephan Müller return 0;
213bb897c55SStephan Müller
214bb897c55SStephan Müller err:
215bb897c55SStephan Müller jent_kcapi_cleanup(tfm);
216bb897c55SStephan Müller return ret;
217bb897c55SStephan Müller }
218bb897c55SStephan Müller
jent_kcapi_random(struct crypto_rng * tfm,const u8 * src,unsigned int slen,u8 * rdata,unsigned int dlen)219dfc9fa91SStephan Mueller static int jent_kcapi_random(struct crypto_rng *tfm,
220dfc9fa91SStephan Mueller const u8 *src, unsigned int slen,
221dfc9fa91SStephan Mueller u8 *rdata, unsigned int dlen)
222dfc9fa91SStephan Mueller {
223dfc9fa91SStephan Mueller struct jitterentropy *rng = crypto_rng_ctx(tfm);
224dfc9fa91SStephan Mueller int ret = 0;
225dfc9fa91SStephan Mueller
226*01d798e9SHaixin Xu mutex_lock(&rng->jent_lock);
227764428feSStephan Müller
228dfc9fa91SStephan Mueller ret = jent_read_entropy(rng->entropy_collector, rdata, dlen);
229764428feSStephan Müller
2303fde2fe9SStephan Müller if (ret == -3) {
2313fde2fe9SStephan Müller /* Handle permanent health test error */
2323fde2fe9SStephan Müller /*
2333fde2fe9SStephan Müller * If the kernel was booted with fips=1, it implies that
2343fde2fe9SStephan Müller * the entire kernel acts as a FIPS 140 module. In this case
2353fde2fe9SStephan Müller * an SP800-90B permanent health test error is treated as
2363fde2fe9SStephan Müller * a FIPS module error.
2373fde2fe9SStephan Müller */
2383fde2fe9SStephan Müller if (fips_enabled)
2393fde2fe9SStephan Müller panic("Jitter RNG permanent health test failure\n");
240764428feSStephan Müller
2413fde2fe9SStephan Müller pr_err("Jitter RNG permanent health test failure\n");
2423fde2fe9SStephan Müller ret = -EFAULT;
2433fde2fe9SStephan Müller } else if (ret == -2) {
2443fde2fe9SStephan Müller /* Handle intermittent health test error */
2453fde2fe9SStephan Müller pr_warn_ratelimited("Reset Jitter RNG due to intermittent health test failure\n");
246764428feSStephan Müller ret = -EAGAIN;
2473fde2fe9SStephan Müller } else if (ret == -1) {
2483fde2fe9SStephan Müller /* Handle other errors */
249764428feSStephan Müller ret = -EINVAL;
250764428feSStephan Müller }
251764428feSStephan Müller
252*01d798e9SHaixin Xu mutex_unlock(&rng->jent_lock);
253dfc9fa91SStephan Mueller
254dfc9fa91SStephan Mueller return ret;
255dfc9fa91SStephan Mueller }
256dfc9fa91SStephan Mueller
jent_kcapi_reset(struct crypto_rng * tfm,const u8 * seed,unsigned int slen)257dfc9fa91SStephan Mueller static int jent_kcapi_reset(struct crypto_rng *tfm,
258dfc9fa91SStephan Mueller const u8 *seed, unsigned int slen)
259dfc9fa91SStephan Mueller {
260dfc9fa91SStephan Mueller return 0;
261dfc9fa91SStephan Mueller }
262dfc9fa91SStephan Mueller
263dfc9fa91SStephan Mueller static struct rng_alg jent_alg = {
264dfc9fa91SStephan Mueller .generate = jent_kcapi_random,
265dfc9fa91SStephan Mueller .seed = jent_kcapi_reset,
266dfc9fa91SStephan Mueller .seedsize = 0,
267dfc9fa91SStephan Mueller .base = {
268dfc9fa91SStephan Mueller .cra_name = "jitterentropy_rng",
269dfc9fa91SStephan Mueller .cra_driver_name = "jitterentropy_rng",
270dfc9fa91SStephan Mueller .cra_priority = 100,
271dfc9fa91SStephan Mueller .cra_ctxsize = sizeof(struct jitterentropy),
272dfc9fa91SStephan Mueller .cra_module = THIS_MODULE,
273dfc9fa91SStephan Mueller .cra_init = jent_kcapi_init,
274dfc9fa91SStephan Mueller .cra_exit = jent_kcapi_cleanup,
275dfc9fa91SStephan Mueller }
276dfc9fa91SStephan Mueller };
277dfc9fa91SStephan Mueller
jent_mod_init(void)278dfc9fa91SStephan Mueller static int __init jent_mod_init(void)
279dfc9fa91SStephan Mueller {
280ce260754SDavid Howells struct sha3_ctx hash_state;
281dfc9fa91SStephan Mueller int ret = 0;
282dfc9fa91SStephan Mueller
28369f1c387SStephan Müller jent_testing_init();
28469f1c387SStephan Müller
285ce260754SDavid Howells sha3_256_init(&hash_state);
286bb897c55SStephan Müller
287ce260754SDavid Howells ret = jent_entropy_init(CONFIG_CRYPTO_JITTERENTROPY_OSR, 0, &hash_state,
288ce260754SDavid Howells NULL);
289ce260754SDavid Howells memzero_explicit(&hash_state, sizeof(hash_state));
290dfc9fa91SStephan Mueller if (ret) {
2913fde2fe9SStephan Müller /* Handle permanent health test error */
2923fde2fe9SStephan Müller if (fips_enabled)
2933fde2fe9SStephan Müller panic("jitterentropy: Initialization failed with host not compliant with requirements: %d\n", ret);
2943fde2fe9SStephan Müller
29569f1c387SStephan Müller jent_testing_exit();
296dfc9fa91SStephan Mueller pr_info("jitterentropy: Initialization failed with host not compliant with requirements: %d\n", ret);
297dfc9fa91SStephan Mueller return -EFAULT;
298dfc9fa91SStephan Mueller }
299dfc9fa91SStephan Mueller return crypto_register_rng(&jent_alg);
300dfc9fa91SStephan Mueller }
301dfc9fa91SStephan Mueller
jent_mod_exit(void)302dfc9fa91SStephan Mueller static void __exit jent_mod_exit(void)
303dfc9fa91SStephan Mueller {
30469f1c387SStephan Müller jent_testing_exit();
305dfc9fa91SStephan Mueller crypto_unregister_rng(&jent_alg);
306dfc9fa91SStephan Mueller }
307dfc9fa91SStephan Mueller
3089c5b34c2SEric Biggers module_init(jent_mod_init);
309dfc9fa91SStephan Mueller module_exit(jent_mod_exit);
310dfc9fa91SStephan Mueller
311dfc9fa91SStephan Mueller MODULE_LICENSE("Dual BSD/GPL");
312dfc9fa91SStephan Mueller MODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>");
313dfc9fa91SStephan Mueller MODULE_DESCRIPTION("Non-physical True Random Number Generator based on CPU Jitter");
314dfc9fa91SStephan Mueller MODULE_ALIAS_CRYPTO("jitterentropy_rng");
315