xref: /kernel/linux/linux-5.10/crypto/ansi_cprng.c (revision 8c2ecf20)
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * PRNG: Pseudo Random Number Generator
4 *       Based on NIST Recommended PRNG From ANSI X9.31 Appendix A.2.4 using
5 *       AES 128 cipher
6 *
7 *  (C) Neil Horman <nhorman@tuxdriver.com>
8 */
9
10#include <crypto/internal/rng.h>
11#include <linux/err.h>
12#include <linux/init.h>
13#include <linux/module.h>
14#include <linux/moduleparam.h>
15#include <linux/string.h>
16
17#define DEFAULT_PRNG_KEY "0123456789abcdef"
18#define DEFAULT_PRNG_KSZ 16
19#define DEFAULT_BLK_SZ 16
20#define DEFAULT_V_SEED "zaybxcwdveuftgsh"
21
22/*
23 * Flags for the prng_context flags field
24 */
25
26#define PRNG_FIXED_SIZE 0x1
27#define PRNG_NEED_RESET 0x2
28
29/*
30 * Note: DT is our counter value
31 *	 I is our intermediate value
32 *	 V is our seed vector
33 * See http://csrc.nist.gov/groups/STM/cavp/documents/rng/931rngext.pdf
34 * for implementation details
35 */
36
37
38struct prng_context {
39	spinlock_t prng_lock;
40	unsigned char rand_data[DEFAULT_BLK_SZ];
41	unsigned char last_rand_data[DEFAULT_BLK_SZ];
42	unsigned char DT[DEFAULT_BLK_SZ];
43	unsigned char I[DEFAULT_BLK_SZ];
44	unsigned char V[DEFAULT_BLK_SZ];
45	u32 rand_data_valid;
46	struct crypto_cipher *tfm;
47	u32 flags;
48};
49
50static int dbg;
51
52static void hexdump(char *note, unsigned char *buf, unsigned int len)
53{
54	if (dbg) {
55		printk(KERN_CRIT "%s", note);
56		print_hex_dump(KERN_CONT, "", DUMP_PREFIX_OFFSET,
57				16, 1,
58				buf, len, false);
59	}
60}
61
62#define dbgprint(format, args...) do {\
63if (dbg)\
64	printk(format, ##args);\
65} while (0)
66
67static void xor_vectors(unsigned char *in1, unsigned char *in2,
68			unsigned char *out, unsigned int size)
69{
70	int i;
71
72	for (i = 0; i < size; i++)
73		out[i] = in1[i] ^ in2[i];
74
75}
76/*
77 * Returns DEFAULT_BLK_SZ bytes of random data per call
78 * returns 0 if generation succeeded, <0 if something went wrong
79 */
80static int _get_more_prng_bytes(struct prng_context *ctx, int cont_test)
81{
82	int i;
83	unsigned char tmp[DEFAULT_BLK_SZ];
84	unsigned char *output = NULL;
85
86
87	dbgprint(KERN_CRIT "Calling _get_more_prng_bytes for context %p\n",
88		ctx);
89
90	hexdump("Input DT: ", ctx->DT, DEFAULT_BLK_SZ);
91	hexdump("Input I: ", ctx->I, DEFAULT_BLK_SZ);
92	hexdump("Input V: ", ctx->V, DEFAULT_BLK_SZ);
93
94	/*
95	 * This algorithm is a 3 stage state machine
96	 */
97	for (i = 0; i < 3; i++) {
98
99		switch (i) {
100		case 0:
101			/*
102			 * Start by encrypting the counter value
103			 * This gives us an intermediate value I
104			 */
105			memcpy(tmp, ctx->DT, DEFAULT_BLK_SZ);
106			output = ctx->I;
107			hexdump("tmp stage 0: ", tmp, DEFAULT_BLK_SZ);
108			break;
109		case 1:
110
111			/*
112			 * Next xor I with our secret vector V
113			 * encrypt that result to obtain our
114			 * pseudo random data which we output
115			 */
116			xor_vectors(ctx->I, ctx->V, tmp, DEFAULT_BLK_SZ);
117			hexdump("tmp stage 1: ", tmp, DEFAULT_BLK_SZ);
118			output = ctx->rand_data;
119			break;
120		case 2:
121			/*
122			 * First check that we didn't produce the same
123			 * random data that we did last time around through this
124			 */
125			if (!memcmp(ctx->rand_data, ctx->last_rand_data,
126					DEFAULT_BLK_SZ)) {
127				if (cont_test) {
128					panic("cprng %p Failed repetition check!\n",
129						ctx);
130				}
131
132				printk(KERN_ERR
133					"ctx %p Failed repetition check!\n",
134					ctx);
135
136				ctx->flags |= PRNG_NEED_RESET;
137				return -EINVAL;
138			}
139			memcpy(ctx->last_rand_data, ctx->rand_data,
140				DEFAULT_BLK_SZ);
141
142			/*
143			 * Lastly xor the random data with I
144			 * and encrypt that to obtain a new secret vector V
145			 */
146			xor_vectors(ctx->rand_data, ctx->I, tmp,
147				DEFAULT_BLK_SZ);
148			output = ctx->V;
149			hexdump("tmp stage 2: ", tmp, DEFAULT_BLK_SZ);
150			break;
151		}
152
153
154		/* do the encryption */
155		crypto_cipher_encrypt_one(ctx->tfm, output, tmp);
156
157	}
158
159	/*
160	 * Now update our DT value
161	 */
162	for (i = DEFAULT_BLK_SZ - 1; i >= 0; i--) {
163		ctx->DT[i] += 1;
164		if (ctx->DT[i] != 0)
165			break;
166	}
167
168	dbgprint("Returning new block for context %p\n", ctx);
169	ctx->rand_data_valid = 0;
170
171	hexdump("Output DT: ", ctx->DT, DEFAULT_BLK_SZ);
172	hexdump("Output I: ", ctx->I, DEFAULT_BLK_SZ);
173	hexdump("Output V: ", ctx->V, DEFAULT_BLK_SZ);
174	hexdump("New Random Data: ", ctx->rand_data, DEFAULT_BLK_SZ);
175
176	return 0;
177}
178
179/* Our exported functions */
180static int get_prng_bytes(char *buf, size_t nbytes, struct prng_context *ctx,
181				int do_cont_test)
182{
183	unsigned char *ptr = buf;
184	unsigned int byte_count = (unsigned int)nbytes;
185	int err;
186
187
188	spin_lock_bh(&ctx->prng_lock);
189
190	err = -EINVAL;
191	if (ctx->flags & PRNG_NEED_RESET)
192		goto done;
193
194	/*
195	 * If the FIXED_SIZE flag is on, only return whole blocks of
196	 * pseudo random data
197	 */
198	err = -EINVAL;
199	if (ctx->flags & PRNG_FIXED_SIZE) {
200		if (nbytes < DEFAULT_BLK_SZ)
201			goto done;
202		byte_count = DEFAULT_BLK_SZ;
203	}
204
205	/*
206	 * Return 0 in case of success as mandated by the kernel
207	 * crypto API interface definition.
208	 */
209	err = 0;
210
211	dbgprint(KERN_CRIT "getting %d random bytes for context %p\n",
212		byte_count, ctx);
213
214
215remainder:
216	if (ctx->rand_data_valid == DEFAULT_BLK_SZ) {
217		if (_get_more_prng_bytes(ctx, do_cont_test) < 0) {
218			memset(buf, 0, nbytes);
219			err = -EINVAL;
220			goto done;
221		}
222	}
223
224	/*
225	 * Copy any data less than an entire block
226	 */
227	if (byte_count < DEFAULT_BLK_SZ) {
228empty_rbuf:
229		while (ctx->rand_data_valid < DEFAULT_BLK_SZ) {
230			*ptr = ctx->rand_data[ctx->rand_data_valid];
231			ptr++;
232			byte_count--;
233			ctx->rand_data_valid++;
234			if (byte_count == 0)
235				goto done;
236		}
237	}
238
239	/*
240	 * Now copy whole blocks
241	 */
242	for (; byte_count >= DEFAULT_BLK_SZ; byte_count -= DEFAULT_BLK_SZ) {
243		if (ctx->rand_data_valid == DEFAULT_BLK_SZ) {
244			if (_get_more_prng_bytes(ctx, do_cont_test) < 0) {
245				memset(buf, 0, nbytes);
246				err = -EINVAL;
247				goto done;
248			}
249		}
250		if (ctx->rand_data_valid > 0)
251			goto empty_rbuf;
252		memcpy(ptr, ctx->rand_data, DEFAULT_BLK_SZ);
253		ctx->rand_data_valid += DEFAULT_BLK_SZ;
254		ptr += DEFAULT_BLK_SZ;
255	}
256
257	/*
258	 * Now go back and get any remaining partial block
259	 */
260	if (byte_count)
261		goto remainder;
262
263done:
264	spin_unlock_bh(&ctx->prng_lock);
265	dbgprint(KERN_CRIT "returning %d from get_prng_bytes in context %p\n",
266		err, ctx);
267	return err;
268}
269
270static void free_prng_context(struct prng_context *ctx)
271{
272	crypto_free_cipher(ctx->tfm);
273}
274
275static int reset_prng_context(struct prng_context *ctx,
276			      const unsigned char *key, size_t klen,
277			      const unsigned char *V, const unsigned char *DT)
278{
279	int ret;
280	const unsigned char *prng_key;
281
282	spin_lock_bh(&ctx->prng_lock);
283	ctx->flags |= PRNG_NEED_RESET;
284
285	prng_key = (key != NULL) ? key : (unsigned char *)DEFAULT_PRNG_KEY;
286
287	if (!key)
288		klen = DEFAULT_PRNG_KSZ;
289
290	if (V)
291		memcpy(ctx->V, V, DEFAULT_BLK_SZ);
292	else
293		memcpy(ctx->V, DEFAULT_V_SEED, DEFAULT_BLK_SZ);
294
295	if (DT)
296		memcpy(ctx->DT, DT, DEFAULT_BLK_SZ);
297	else
298		memset(ctx->DT, 0, DEFAULT_BLK_SZ);
299
300	memset(ctx->rand_data, 0, DEFAULT_BLK_SZ);
301	memset(ctx->last_rand_data, 0, DEFAULT_BLK_SZ);
302
303	ctx->rand_data_valid = DEFAULT_BLK_SZ;
304
305	ret = crypto_cipher_setkey(ctx->tfm, prng_key, klen);
306	if (ret) {
307		dbgprint(KERN_CRIT "PRNG: setkey() failed flags=%x\n",
308			crypto_cipher_get_flags(ctx->tfm));
309		goto out;
310	}
311
312	ret = 0;
313	ctx->flags &= ~PRNG_NEED_RESET;
314out:
315	spin_unlock_bh(&ctx->prng_lock);
316	return ret;
317}
318
319static int cprng_init(struct crypto_tfm *tfm)
320{
321	struct prng_context *ctx = crypto_tfm_ctx(tfm);
322
323	spin_lock_init(&ctx->prng_lock);
324	ctx->tfm = crypto_alloc_cipher("aes", 0, 0);
325	if (IS_ERR(ctx->tfm)) {
326		dbgprint(KERN_CRIT "Failed to alloc tfm for context %p\n",
327				ctx);
328		return PTR_ERR(ctx->tfm);
329	}
330
331	if (reset_prng_context(ctx, NULL, DEFAULT_PRNG_KSZ, NULL, NULL) < 0)
332		return -EINVAL;
333
334	/*
335	 * after allocation, we should always force the user to reset
336	 * so they don't inadvertently use the insecure default values
337	 * without specifying them intentially
338	 */
339	ctx->flags |= PRNG_NEED_RESET;
340	return 0;
341}
342
343static void cprng_exit(struct crypto_tfm *tfm)
344{
345	free_prng_context(crypto_tfm_ctx(tfm));
346}
347
348static int cprng_get_random(struct crypto_rng *tfm,
349			    const u8 *src, unsigned int slen,
350			    u8 *rdata, unsigned int dlen)
351{
352	struct prng_context *prng = crypto_rng_ctx(tfm);
353
354	return get_prng_bytes(rdata, dlen, prng, 0);
355}
356
357/*
358 *  This is the cprng_registered reset method the seed value is
359 *  interpreted as the tuple { V KEY DT}
360 *  V and KEY are required during reset, and DT is optional, detected
361 *  as being present by testing the length of the seed
362 */
363static int cprng_reset(struct crypto_rng *tfm,
364		       const u8 *seed, unsigned int slen)
365{
366	struct prng_context *prng = crypto_rng_ctx(tfm);
367	const u8 *key = seed + DEFAULT_BLK_SZ;
368	const u8 *dt = NULL;
369
370	if (slen < DEFAULT_PRNG_KSZ + DEFAULT_BLK_SZ)
371		return -EINVAL;
372
373	if (slen >= (2 * DEFAULT_BLK_SZ + DEFAULT_PRNG_KSZ))
374		dt = key + DEFAULT_PRNG_KSZ;
375
376	reset_prng_context(prng, key, DEFAULT_PRNG_KSZ, seed, dt);
377
378	if (prng->flags & PRNG_NEED_RESET)
379		return -EINVAL;
380	return 0;
381}
382
383#ifdef CONFIG_CRYPTO_FIPS
384static int fips_cprng_get_random(struct crypto_rng *tfm,
385				 const u8 *src, unsigned int slen,
386				 u8 *rdata, unsigned int dlen)
387{
388	struct prng_context *prng = crypto_rng_ctx(tfm);
389
390	return get_prng_bytes(rdata, dlen, prng, 1);
391}
392
393static int fips_cprng_reset(struct crypto_rng *tfm,
394			    const u8 *seed, unsigned int slen)
395{
396	u8 rdata[DEFAULT_BLK_SZ];
397	const u8 *key = seed + DEFAULT_BLK_SZ;
398	int rc;
399
400	struct prng_context *prng = crypto_rng_ctx(tfm);
401
402	if (slen < DEFAULT_PRNG_KSZ + DEFAULT_BLK_SZ)
403		return -EINVAL;
404
405	/* fips strictly requires seed != key */
406	if (!memcmp(seed, key, DEFAULT_PRNG_KSZ))
407		return -EINVAL;
408
409	rc = cprng_reset(tfm, seed, slen);
410
411	if (!rc)
412		goto out;
413
414	/* this primes our continuity test */
415	rc = get_prng_bytes(rdata, DEFAULT_BLK_SZ, prng, 0);
416	prng->rand_data_valid = DEFAULT_BLK_SZ;
417
418out:
419	return rc;
420}
421#endif
422
423static struct rng_alg rng_algs[] = { {
424	.generate		= cprng_get_random,
425	.seed			= cprng_reset,
426	.seedsize		= DEFAULT_PRNG_KSZ + 2 * DEFAULT_BLK_SZ,
427	.base			=	{
428		.cra_name		= "stdrng",
429		.cra_driver_name	= "ansi_cprng",
430		.cra_priority		= 100,
431		.cra_ctxsize		= sizeof(struct prng_context),
432		.cra_module		= THIS_MODULE,
433		.cra_init		= cprng_init,
434		.cra_exit		= cprng_exit,
435	}
436#ifdef CONFIG_CRYPTO_FIPS
437}, {
438	.generate		= fips_cprng_get_random,
439	.seed			= fips_cprng_reset,
440	.seedsize		= DEFAULT_PRNG_KSZ + 2 * DEFAULT_BLK_SZ,
441	.base			=	{
442		.cra_name		= "fips(ansi_cprng)",
443		.cra_driver_name	= "fips_ansi_cprng",
444		.cra_priority		= 300,
445		.cra_ctxsize		= sizeof(struct prng_context),
446		.cra_module		= THIS_MODULE,
447		.cra_init		= cprng_init,
448		.cra_exit		= cprng_exit,
449	}
450#endif
451} };
452
453/* Module initalization */
454static int __init prng_mod_init(void)
455{
456	return crypto_register_rngs(rng_algs, ARRAY_SIZE(rng_algs));
457}
458
459static void __exit prng_mod_fini(void)
460{
461	crypto_unregister_rngs(rng_algs, ARRAY_SIZE(rng_algs));
462}
463
464MODULE_LICENSE("GPL");
465MODULE_DESCRIPTION("Software Pseudo Random Number Generator");
466MODULE_AUTHOR("Neil Horman <nhorman@tuxdriver.com>");
467module_param(dbg, int, 0);
468MODULE_PARM_DESC(dbg, "Boolean to enable debugging (0/1 == off/on)");
469subsys_initcall(prng_mod_init);
470module_exit(prng_mod_fini);
471MODULE_ALIAS_CRYPTO("stdrng");
472MODULE_ALIAS_CRYPTO("ansi_cprng");
473