xref: /linux/crypto/jitterentropy-kcapi.c (revision ccc9d4a6d640cbde05d519edeb727881646cf71b)
1dfc9fa91SStephan Mueller /*
2dfc9fa91SStephan Mueller  * Non-physical true random number generator based on timing jitter --
3dfc9fa91SStephan Mueller  * Linux Kernel Crypto API specific code
4dfc9fa91SStephan Mueller  *
5dfc9fa91SStephan Mueller  * Copyright Stephan Mueller <smueller@chronox.de>, 2015
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 
40dfc9fa91SStephan Mueller #include <linux/module.h>
41dfc9fa91SStephan Mueller #include <linux/slab.h>
42dfc9fa91SStephan Mueller #include <linux/module.h>
43dfc9fa91SStephan Mueller #include <linux/fips.h>
44dfc9fa91SStephan Mueller #include <linux/time.h>
45dfc9fa91SStephan Mueller #include <linux/crypto.h>
46dfc9fa91SStephan Mueller #include <crypto/internal/rng.h>
47dfc9fa91SStephan Mueller 
48dfc9fa91SStephan Mueller struct rand_data;
49dfc9fa91SStephan Mueller int jent_read_entropy(struct rand_data *ec, unsigned char *data,
50dfc9fa91SStephan Mueller 		      unsigned int len);
51dfc9fa91SStephan Mueller int jent_entropy_init(void);
52dfc9fa91SStephan Mueller struct rand_data *jent_entropy_collector_alloc(unsigned int osr,
53dfc9fa91SStephan Mueller 					       unsigned int flags);
54dfc9fa91SStephan Mueller void jent_entropy_collector_free(struct rand_data *entropy_collector);
55dfc9fa91SStephan Mueller 
56dfc9fa91SStephan Mueller /***************************************************************************
57dfc9fa91SStephan Mueller  * Helper function
58dfc9fa91SStephan Mueller  ***************************************************************************/
59dfc9fa91SStephan Mueller 
60dfc9fa91SStephan Mueller __u64 jent_rol64(__u64 word, unsigned int shift)
61dfc9fa91SStephan Mueller {
62dfc9fa91SStephan Mueller 	return rol64(word, shift);
63dfc9fa91SStephan Mueller }
64dfc9fa91SStephan Mueller 
65dfc9fa91SStephan Mueller void *jent_zalloc(unsigned int len)
66dfc9fa91SStephan Mueller {
67dfc9fa91SStephan Mueller 	return kzalloc(len, GFP_KERNEL);
68dfc9fa91SStephan Mueller }
69dfc9fa91SStephan Mueller 
70dfc9fa91SStephan Mueller void jent_zfree(void *ptr)
71dfc9fa91SStephan Mueller {
72dfc9fa91SStephan Mueller 	kzfree(ptr);
73dfc9fa91SStephan Mueller }
74dfc9fa91SStephan Mueller 
75dfc9fa91SStephan Mueller int jent_fips_enabled(void)
76dfc9fa91SStephan Mueller {
77dfc9fa91SStephan Mueller 	return fips_enabled;
78dfc9fa91SStephan Mueller }
79dfc9fa91SStephan Mueller 
80dfc9fa91SStephan Mueller void jent_panic(char *s)
81dfc9fa91SStephan Mueller {
82*0c5f0aa5SKees Cook 	panic("%s", s);
83dfc9fa91SStephan Mueller }
84dfc9fa91SStephan Mueller 
85dfc9fa91SStephan Mueller void jent_memcpy(void *dest, const void *src, unsigned int n)
86dfc9fa91SStephan Mueller {
87dfc9fa91SStephan Mueller 	memcpy(dest, src, n);
88dfc9fa91SStephan Mueller }
89dfc9fa91SStephan Mueller 
90dfc9fa91SStephan Mueller void jent_get_nstime(__u64 *out)
91dfc9fa91SStephan Mueller {
92dfc9fa91SStephan Mueller 	struct timespec ts;
93dfc9fa91SStephan Mueller 	__u64 tmp = 0;
94dfc9fa91SStephan Mueller 
95dfc9fa91SStephan Mueller 	tmp = random_get_entropy();
96dfc9fa91SStephan Mueller 
97dfc9fa91SStephan Mueller 	/*
98dfc9fa91SStephan Mueller 	 * If random_get_entropy does not return a value (which is possible on,
99dfc9fa91SStephan Mueller 	 * for example, MIPS), invoke __getnstimeofday
100dfc9fa91SStephan Mueller 	 * hoping that there are timers we can work with.
101dfc9fa91SStephan Mueller 	 */
102dfc9fa91SStephan Mueller 	if ((0 == tmp) &&
103dfc9fa91SStephan Mueller 	   (0 == __getnstimeofday(&ts))) {
104dfc9fa91SStephan Mueller 		tmp = ts.tv_sec;
105dfc9fa91SStephan Mueller 		tmp = tmp << 32;
106dfc9fa91SStephan Mueller 		tmp = tmp | ts.tv_nsec;
107dfc9fa91SStephan Mueller 	}
108dfc9fa91SStephan Mueller 
109dfc9fa91SStephan Mueller 	*out = tmp;
110dfc9fa91SStephan Mueller }
111dfc9fa91SStephan Mueller 
112dfc9fa91SStephan Mueller /***************************************************************************
113dfc9fa91SStephan Mueller  * Kernel crypto API interface
114dfc9fa91SStephan Mueller  ***************************************************************************/
115dfc9fa91SStephan Mueller 
116dfc9fa91SStephan Mueller struct jitterentropy {
117dfc9fa91SStephan Mueller 	spinlock_t jent_lock;
118dfc9fa91SStephan Mueller 	struct rand_data *entropy_collector;
119dfc9fa91SStephan Mueller };
120dfc9fa91SStephan Mueller 
121dfc9fa91SStephan Mueller static int jent_kcapi_init(struct crypto_tfm *tfm)
122dfc9fa91SStephan Mueller {
123dfc9fa91SStephan Mueller 	struct jitterentropy *rng = crypto_tfm_ctx(tfm);
124dfc9fa91SStephan Mueller 	int ret = 0;
125dfc9fa91SStephan Mueller 
126dfc9fa91SStephan Mueller 	rng->entropy_collector = jent_entropy_collector_alloc(1, 0);
127dfc9fa91SStephan Mueller 	if (!rng->entropy_collector)
128dfc9fa91SStephan Mueller 		ret = -ENOMEM;
129dfc9fa91SStephan Mueller 
130dfc9fa91SStephan Mueller 	spin_lock_init(&rng->jent_lock);
131dfc9fa91SStephan Mueller 	return ret;
132dfc9fa91SStephan Mueller }
133dfc9fa91SStephan Mueller 
134dfc9fa91SStephan Mueller static void jent_kcapi_cleanup(struct crypto_tfm *tfm)
135dfc9fa91SStephan Mueller {
136dfc9fa91SStephan Mueller 	struct jitterentropy *rng = crypto_tfm_ctx(tfm);
137dfc9fa91SStephan Mueller 
138dfc9fa91SStephan Mueller 	spin_lock(&rng->jent_lock);
139dfc9fa91SStephan Mueller 	if (rng->entropy_collector)
140dfc9fa91SStephan Mueller 		jent_entropy_collector_free(rng->entropy_collector);
141dfc9fa91SStephan Mueller 	rng->entropy_collector = NULL;
142dfc9fa91SStephan Mueller 	spin_unlock(&rng->jent_lock);
143dfc9fa91SStephan Mueller }
144dfc9fa91SStephan Mueller 
145dfc9fa91SStephan Mueller static int jent_kcapi_random(struct crypto_rng *tfm,
146dfc9fa91SStephan Mueller 			     const u8 *src, unsigned int slen,
147dfc9fa91SStephan Mueller 			     u8 *rdata, unsigned int dlen)
148dfc9fa91SStephan Mueller {
149dfc9fa91SStephan Mueller 	struct jitterentropy *rng = crypto_rng_ctx(tfm);
150dfc9fa91SStephan Mueller 	int ret = 0;
151dfc9fa91SStephan Mueller 
152dfc9fa91SStephan Mueller 	spin_lock(&rng->jent_lock);
153dfc9fa91SStephan Mueller 	ret = jent_read_entropy(rng->entropy_collector, rdata, dlen);
154dfc9fa91SStephan Mueller 	spin_unlock(&rng->jent_lock);
155dfc9fa91SStephan Mueller 
156dfc9fa91SStephan Mueller 	return ret;
157dfc9fa91SStephan Mueller }
158dfc9fa91SStephan Mueller 
159dfc9fa91SStephan Mueller static int jent_kcapi_reset(struct crypto_rng *tfm,
160dfc9fa91SStephan Mueller 			    const u8 *seed, unsigned int slen)
161dfc9fa91SStephan Mueller {
162dfc9fa91SStephan Mueller 	return 0;
163dfc9fa91SStephan Mueller }
164dfc9fa91SStephan Mueller 
165dfc9fa91SStephan Mueller static struct rng_alg jent_alg = {
166dfc9fa91SStephan Mueller 	.generate		= jent_kcapi_random,
167dfc9fa91SStephan Mueller 	.seed			= jent_kcapi_reset,
168dfc9fa91SStephan Mueller 	.seedsize		= 0,
169dfc9fa91SStephan Mueller 	.base			= {
170dfc9fa91SStephan Mueller 		.cra_name               = "jitterentropy_rng",
171dfc9fa91SStephan Mueller 		.cra_driver_name        = "jitterentropy_rng",
172dfc9fa91SStephan Mueller 		.cra_priority           = 100,
173dfc9fa91SStephan Mueller 		.cra_ctxsize            = sizeof(struct jitterentropy),
174dfc9fa91SStephan Mueller 		.cra_module             = THIS_MODULE,
175dfc9fa91SStephan Mueller 		.cra_init               = jent_kcapi_init,
176dfc9fa91SStephan Mueller 		.cra_exit               = jent_kcapi_cleanup,
177dfc9fa91SStephan Mueller 
178dfc9fa91SStephan Mueller 	}
179dfc9fa91SStephan Mueller };
180dfc9fa91SStephan Mueller 
181dfc9fa91SStephan Mueller static int __init jent_mod_init(void)
182dfc9fa91SStephan Mueller {
183dfc9fa91SStephan Mueller 	int ret = 0;
184dfc9fa91SStephan Mueller 
185dfc9fa91SStephan Mueller 	ret = jent_entropy_init();
186dfc9fa91SStephan Mueller 	if (ret) {
187dfc9fa91SStephan Mueller 		pr_info("jitterentropy: Initialization failed with host not compliant with requirements: %d\n", ret);
188dfc9fa91SStephan Mueller 		return -EFAULT;
189dfc9fa91SStephan Mueller 	}
190dfc9fa91SStephan Mueller 	return crypto_register_rng(&jent_alg);
191dfc9fa91SStephan Mueller }
192dfc9fa91SStephan Mueller 
193dfc9fa91SStephan Mueller static void __exit jent_mod_exit(void)
194dfc9fa91SStephan Mueller {
195dfc9fa91SStephan Mueller 	crypto_unregister_rng(&jent_alg);
196dfc9fa91SStephan Mueller }
197dfc9fa91SStephan Mueller 
198dfc9fa91SStephan Mueller module_init(jent_mod_init);
199dfc9fa91SStephan Mueller module_exit(jent_mod_exit);
200dfc9fa91SStephan Mueller 
201dfc9fa91SStephan Mueller MODULE_LICENSE("Dual BSD/GPL");
202dfc9fa91SStephan Mueller MODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>");
203dfc9fa91SStephan Mueller MODULE_DESCRIPTION("Non-physical True Random Number Generator based on CPU Jitter");
204dfc9fa91SStephan Mueller MODULE_ALIAS_CRYPTO("jitterentropy_rng");
205