162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright IBM Corp. 2006, 2015
462306a36Sopenharmony_ci * Author(s): Jan Glauber <jan.glauber@de.ibm.com>
562306a36Sopenharmony_ci *	      Harald Freudenberger <freude@de.ibm.com>
662306a36Sopenharmony_ci * Driver for the s390 pseudo random number generator
762306a36Sopenharmony_ci */
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#define KMSG_COMPONENT "prng"
1062306a36Sopenharmony_ci#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#include <linux/fs.h>
1362306a36Sopenharmony_ci#include <linux/fips.h>
1462306a36Sopenharmony_ci#include <linux/init.h>
1562306a36Sopenharmony_ci#include <linux/kernel.h>
1662306a36Sopenharmony_ci#include <linux/device.h>
1762306a36Sopenharmony_ci#include <linux/miscdevice.h>
1862306a36Sopenharmony_ci#include <linux/module.h>
1962306a36Sopenharmony_ci#include <linux/moduleparam.h>
2062306a36Sopenharmony_ci#include <linux/mutex.h>
2162306a36Sopenharmony_ci#include <linux/cpufeature.h>
2262306a36Sopenharmony_ci#include <linux/random.h>
2362306a36Sopenharmony_ci#include <linux/slab.h>
2462306a36Sopenharmony_ci#include <linux/sched/signal.h>
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci#include <asm/debug.h>
2762306a36Sopenharmony_ci#include <linux/uaccess.h>
2862306a36Sopenharmony_ci#include <asm/timex.h>
2962306a36Sopenharmony_ci#include <asm/cpacf.h>
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ciMODULE_LICENSE("GPL");
3262306a36Sopenharmony_ciMODULE_AUTHOR("IBM Corporation");
3362306a36Sopenharmony_ciMODULE_DESCRIPTION("s390 PRNG interface");
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci#define PRNG_MODE_AUTO	  0
3762306a36Sopenharmony_ci#define PRNG_MODE_TDES	  1
3862306a36Sopenharmony_ci#define PRNG_MODE_SHA512  2
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_cistatic unsigned int prng_mode = PRNG_MODE_AUTO;
4162306a36Sopenharmony_cimodule_param_named(mode, prng_mode, int, 0);
4262306a36Sopenharmony_ciMODULE_PARM_DESC(prng_mode, "PRNG mode: 0 - auto, 1 - TDES, 2 - SHA512");
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci#define PRNG_CHUNKSIZE_TDES_MIN   8
4662306a36Sopenharmony_ci#define PRNG_CHUNKSIZE_TDES_MAX   (64*1024)
4762306a36Sopenharmony_ci#define PRNG_CHUNKSIZE_SHA512_MIN 64
4862306a36Sopenharmony_ci#define PRNG_CHUNKSIZE_SHA512_MAX (64*1024)
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_cistatic unsigned int prng_chunk_size = 256;
5162306a36Sopenharmony_cimodule_param_named(chunksize, prng_chunk_size, int, 0);
5262306a36Sopenharmony_ciMODULE_PARM_DESC(prng_chunk_size, "PRNG read chunk size in bytes");
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci#define PRNG_RESEED_LIMIT_TDES		 4096
5662306a36Sopenharmony_ci#define PRNG_RESEED_LIMIT_TDES_LOWER	 4096
5762306a36Sopenharmony_ci#define PRNG_RESEED_LIMIT_SHA512       100000
5862306a36Sopenharmony_ci#define PRNG_RESEED_LIMIT_SHA512_LOWER	10000
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_cistatic unsigned int prng_reseed_limit;
6162306a36Sopenharmony_cimodule_param_named(reseed_limit, prng_reseed_limit, int, 0);
6262306a36Sopenharmony_ciMODULE_PARM_DESC(prng_reseed_limit, "PRNG reseed limit");
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_cistatic bool trng_available;
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci/*
6762306a36Sopenharmony_ci * Any one who considers arithmetical methods of producing random digits is,
6862306a36Sopenharmony_ci * of course, in a state of sin. -- John von Neumann
6962306a36Sopenharmony_ci */
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_cistatic int prng_errorflag;
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci#define PRNG_GEN_ENTROPY_FAILED  1
7462306a36Sopenharmony_ci#define PRNG_SELFTEST_FAILED	 2
7562306a36Sopenharmony_ci#define PRNG_INSTANTIATE_FAILED  3
7662306a36Sopenharmony_ci#define PRNG_SEED_FAILED	 4
7762306a36Sopenharmony_ci#define PRNG_RESEED_FAILED	 5
7862306a36Sopenharmony_ci#define PRNG_GEN_FAILED		 6
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_cistruct prng_ws_s {
8162306a36Sopenharmony_ci	u8  parm_block[32];
8262306a36Sopenharmony_ci	u32 reseed_counter;
8362306a36Sopenharmony_ci	u64 byte_counter;
8462306a36Sopenharmony_ci};
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_cistruct prno_ws_s {
8762306a36Sopenharmony_ci	u32 res;
8862306a36Sopenharmony_ci	u32 reseed_counter;
8962306a36Sopenharmony_ci	u64 stream_bytes;
9062306a36Sopenharmony_ci	u8  V[112];
9162306a36Sopenharmony_ci	u8  C[112];
9262306a36Sopenharmony_ci};
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_cistruct prng_data_s {
9562306a36Sopenharmony_ci	struct mutex mutex;
9662306a36Sopenharmony_ci	union {
9762306a36Sopenharmony_ci		struct prng_ws_s prngws;
9862306a36Sopenharmony_ci		struct prno_ws_s prnows;
9962306a36Sopenharmony_ci	};
10062306a36Sopenharmony_ci	u8 *buf;
10162306a36Sopenharmony_ci	u32 rest;
10262306a36Sopenharmony_ci	u8 *prev;
10362306a36Sopenharmony_ci};
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_cistatic struct prng_data_s *prng_data;
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci/* initial parameter block for tdes mode, copied from libica */
10862306a36Sopenharmony_cistatic const u8 initial_parm_block[32] __initconst = {
10962306a36Sopenharmony_ci	0x0F, 0x2B, 0x8E, 0x63, 0x8C, 0x8E, 0xD2, 0x52,
11062306a36Sopenharmony_ci	0x64, 0xB7, 0xA0, 0x7B, 0x75, 0x28, 0xB8, 0xF4,
11162306a36Sopenharmony_ci	0x75, 0x5F, 0xD2, 0xA6, 0x8D, 0x97, 0x11, 0xFF,
11262306a36Sopenharmony_ci	0x49, 0xD8, 0x23, 0xF3, 0x7E, 0x21, 0xEC, 0xA0 };
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ci/*** helper functions ***/
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci/*
11862306a36Sopenharmony_ci * generate_entropy:
11962306a36Sopenharmony_ci * This function fills a given buffer with random bytes. The entropy within
12062306a36Sopenharmony_ci * the random bytes given back is assumed to have at least 50% - meaning
12162306a36Sopenharmony_ci * a 64 bytes buffer has at least 64 * 8 / 2 = 256 bits of entropy.
12262306a36Sopenharmony_ci * Within the function the entropy generation is done in junks of 64 bytes.
12362306a36Sopenharmony_ci * So the caller should also ask for buffer fill in multiples of 64 bytes.
12462306a36Sopenharmony_ci * The generation of the entropy is based on the assumption that every stckf()
12562306a36Sopenharmony_ci * invocation produces 0.5 bits of entropy. To accumulate 256 bits of entropy
12662306a36Sopenharmony_ci * at least 512 stckf() values are needed. The entropy relevant part of the
12762306a36Sopenharmony_ci * stckf value is bit 51 (counting starts at the left with bit nr 0) so
12862306a36Sopenharmony_ci * here we use the lower 4 bytes and exor the values into 2k of bufferspace.
12962306a36Sopenharmony_ci * To be on the save side, if there is ever a problem with stckf() the
13062306a36Sopenharmony_ci * other half of the page buffer is filled with bytes from urandom via
13162306a36Sopenharmony_ci * get_random_bytes(), so this function consumes 2k of urandom for each
13262306a36Sopenharmony_ci * requested 64 bytes output data. Finally the buffer page is condensed into
13362306a36Sopenharmony_ci * a 64 byte value by hashing with a SHA512 hash.
13462306a36Sopenharmony_ci */
13562306a36Sopenharmony_cistatic int generate_entropy(u8 *ebuf, size_t nbytes)
13662306a36Sopenharmony_ci{
13762306a36Sopenharmony_ci	int n, ret = 0;
13862306a36Sopenharmony_ci	u8 *pg, pblock[80] = {
13962306a36Sopenharmony_ci		/* 8 x 64 bit init values */
14062306a36Sopenharmony_ci		0x6A, 0x09, 0xE6, 0x67, 0xF3, 0xBC, 0xC9, 0x08,
14162306a36Sopenharmony_ci		0xBB, 0x67, 0xAE, 0x85, 0x84, 0xCA, 0xA7, 0x3B,
14262306a36Sopenharmony_ci		0x3C, 0x6E, 0xF3, 0x72, 0xFE, 0x94, 0xF8, 0x2B,
14362306a36Sopenharmony_ci		0xA5, 0x4F, 0xF5, 0x3A, 0x5F, 0x1D, 0x36, 0xF1,
14462306a36Sopenharmony_ci		0x51, 0x0E, 0x52, 0x7F, 0xAD, 0xE6, 0x82, 0xD1,
14562306a36Sopenharmony_ci		0x9B, 0x05, 0x68, 0x8C, 0x2B, 0x3E, 0x6C, 0x1F,
14662306a36Sopenharmony_ci		0x1F, 0x83, 0xD9, 0xAB, 0xFB, 0x41, 0xBD, 0x6B,
14762306a36Sopenharmony_ci		0x5B, 0xE0, 0xCD, 0x19, 0x13, 0x7E, 0x21, 0x79,
14862306a36Sopenharmony_ci		/* 128 bit counter total message bit length */
14962306a36Sopenharmony_ci		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
15062306a36Sopenharmony_ci		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00 };
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_ci	/* allocate one page stckf buffer */
15362306a36Sopenharmony_ci	pg = (u8 *) __get_free_page(GFP_KERNEL);
15462306a36Sopenharmony_ci	if (!pg) {
15562306a36Sopenharmony_ci		prng_errorflag = PRNG_GEN_ENTROPY_FAILED;
15662306a36Sopenharmony_ci		return -ENOMEM;
15762306a36Sopenharmony_ci	}
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci	/* fill the ebuf in chunks of 64 byte each */
16062306a36Sopenharmony_ci	while (nbytes) {
16162306a36Sopenharmony_ci		/* fill lower 2k with urandom bytes */
16262306a36Sopenharmony_ci		get_random_bytes(pg, PAGE_SIZE / 2);
16362306a36Sopenharmony_ci		/* exor upper 2k with 512 stckf values, offset 4 bytes each */
16462306a36Sopenharmony_ci		for (n = 0; n < 512; n++) {
16562306a36Sopenharmony_ci			int offset = (PAGE_SIZE / 2) + (n * 4) - 4;
16662306a36Sopenharmony_ci			u64 *p = (u64 *)(pg + offset);
16762306a36Sopenharmony_ci			*p ^= get_tod_clock_fast();
16862306a36Sopenharmony_ci		}
16962306a36Sopenharmony_ci		/* hash over the filled page */
17062306a36Sopenharmony_ci		cpacf_klmd(CPACF_KLMD_SHA_512, pblock, pg, PAGE_SIZE);
17162306a36Sopenharmony_ci		n = (nbytes < 64) ? nbytes : 64;
17262306a36Sopenharmony_ci		memcpy(ebuf, pblock, n);
17362306a36Sopenharmony_ci		ret += n;
17462306a36Sopenharmony_ci		ebuf += n;
17562306a36Sopenharmony_ci		nbytes -= n;
17662306a36Sopenharmony_ci	}
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_ci	memzero_explicit(pblock, sizeof(pblock));
17962306a36Sopenharmony_ci	memzero_explicit(pg, PAGE_SIZE);
18062306a36Sopenharmony_ci	free_page((unsigned long)pg);
18162306a36Sopenharmony_ci	return ret;
18262306a36Sopenharmony_ci}
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci/*** tdes functions ***/
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_cistatic void prng_tdes_add_entropy(void)
18862306a36Sopenharmony_ci{
18962306a36Sopenharmony_ci	__u64 entropy[4];
19062306a36Sopenharmony_ci	unsigned int i;
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_ci	for (i = 0; i < 16; i++) {
19362306a36Sopenharmony_ci		cpacf_kmc(CPACF_KMC_PRNG, prng_data->prngws.parm_block,
19462306a36Sopenharmony_ci			  (char *) entropy, (char *) entropy,
19562306a36Sopenharmony_ci			  sizeof(entropy));
19662306a36Sopenharmony_ci		memcpy(prng_data->prngws.parm_block, entropy, sizeof(entropy));
19762306a36Sopenharmony_ci	}
19862306a36Sopenharmony_ci}
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_cistatic void prng_tdes_seed(int nbytes)
20262306a36Sopenharmony_ci{
20362306a36Sopenharmony_ci	char buf[16];
20462306a36Sopenharmony_ci	int i = 0;
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_ci	BUG_ON(nbytes > sizeof(buf));
20762306a36Sopenharmony_ci
20862306a36Sopenharmony_ci	get_random_bytes(buf, nbytes);
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_ci	/* Add the entropy */
21162306a36Sopenharmony_ci	while (nbytes >= 8) {
21262306a36Sopenharmony_ci		*((__u64 *)prng_data->prngws.parm_block) ^= *((__u64 *)(buf+i));
21362306a36Sopenharmony_ci		prng_tdes_add_entropy();
21462306a36Sopenharmony_ci		i += 8;
21562306a36Sopenharmony_ci		nbytes -= 8;
21662306a36Sopenharmony_ci	}
21762306a36Sopenharmony_ci	prng_tdes_add_entropy();
21862306a36Sopenharmony_ci	prng_data->prngws.reseed_counter = 0;
21962306a36Sopenharmony_ci}
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_cistatic int __init prng_tdes_instantiate(void)
22362306a36Sopenharmony_ci{
22462306a36Sopenharmony_ci	int datalen;
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_ci	pr_debug("prng runs in TDES mode with "
22762306a36Sopenharmony_ci		 "chunksize=%d and reseed_limit=%u\n",
22862306a36Sopenharmony_ci		 prng_chunk_size, prng_reseed_limit);
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_ci	/* memory allocation, prng_data struct init, mutex init */
23162306a36Sopenharmony_ci	datalen = sizeof(struct prng_data_s) + prng_chunk_size;
23262306a36Sopenharmony_ci	prng_data = kzalloc(datalen, GFP_KERNEL);
23362306a36Sopenharmony_ci	if (!prng_data) {
23462306a36Sopenharmony_ci		prng_errorflag = PRNG_INSTANTIATE_FAILED;
23562306a36Sopenharmony_ci		return -ENOMEM;
23662306a36Sopenharmony_ci	}
23762306a36Sopenharmony_ci	mutex_init(&prng_data->mutex);
23862306a36Sopenharmony_ci	prng_data->buf = ((u8 *)prng_data) + sizeof(struct prng_data_s);
23962306a36Sopenharmony_ci	memcpy(prng_data->prngws.parm_block, initial_parm_block, 32);
24062306a36Sopenharmony_ci
24162306a36Sopenharmony_ci	/* initialize the PRNG, add 128 bits of entropy */
24262306a36Sopenharmony_ci	prng_tdes_seed(16);
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_ci	return 0;
24562306a36Sopenharmony_ci}
24662306a36Sopenharmony_ci
24762306a36Sopenharmony_ci
24862306a36Sopenharmony_cistatic void prng_tdes_deinstantiate(void)
24962306a36Sopenharmony_ci{
25062306a36Sopenharmony_ci	pr_debug("The prng module stopped "
25162306a36Sopenharmony_ci		 "after running in triple DES mode\n");
25262306a36Sopenharmony_ci	kfree_sensitive(prng_data);
25362306a36Sopenharmony_ci}
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_ci/*** sha512 functions ***/
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_cistatic int __init prng_sha512_selftest(void)
25962306a36Sopenharmony_ci{
26062306a36Sopenharmony_ci	/* NIST DRBG testvector for Hash Drbg, Sha-512, Count #0 */
26162306a36Sopenharmony_ci	static const u8 seed[] __initconst = {
26262306a36Sopenharmony_ci		0x6b, 0x50, 0xa7, 0xd8, 0xf8, 0xa5, 0x5d, 0x7a,
26362306a36Sopenharmony_ci		0x3d, 0xf8, 0xbb, 0x40, 0xbc, 0xc3, 0xb7, 0x22,
26462306a36Sopenharmony_ci		0xd8, 0x70, 0x8d, 0xe6, 0x7f, 0xda, 0x01, 0x0b,
26562306a36Sopenharmony_ci		0x03, 0xc4, 0xc8, 0x4d, 0x72, 0x09, 0x6f, 0x8c,
26662306a36Sopenharmony_ci		0x3e, 0xc6, 0x49, 0xcc, 0x62, 0x56, 0xd9, 0xfa,
26762306a36Sopenharmony_ci		0x31, 0xdb, 0x7a, 0x29, 0x04, 0xaa, 0xf0, 0x25 };
26862306a36Sopenharmony_ci	static const u8 V0[] __initconst = {
26962306a36Sopenharmony_ci		0x00, 0xad, 0xe3, 0x6f, 0x9a, 0x01, 0xc7, 0x76,
27062306a36Sopenharmony_ci		0x61, 0x34, 0x35, 0xf5, 0x4e, 0x24, 0x74, 0x22,
27162306a36Sopenharmony_ci		0x21, 0x9a, 0x29, 0x89, 0xc7, 0x93, 0x2e, 0x60,
27262306a36Sopenharmony_ci		0x1e, 0xe8, 0x14, 0x24, 0x8d, 0xd5, 0x03, 0xf1,
27362306a36Sopenharmony_ci		0x65, 0x5d, 0x08, 0x22, 0x72, 0xd5, 0xad, 0x95,
27462306a36Sopenharmony_ci		0xe1, 0x23, 0x1e, 0x8a, 0xa7, 0x13, 0xd9, 0x2b,
27562306a36Sopenharmony_ci		0x5e, 0xbc, 0xbb, 0x80, 0xab, 0x8d, 0xe5, 0x79,
27662306a36Sopenharmony_ci		0xab, 0x5b, 0x47, 0x4e, 0xdd, 0xee, 0x6b, 0x03,
27762306a36Sopenharmony_ci		0x8f, 0x0f, 0x5c, 0x5e, 0xa9, 0x1a, 0x83, 0xdd,
27862306a36Sopenharmony_ci		0xd3, 0x88, 0xb2, 0x75, 0x4b, 0xce, 0x83, 0x36,
27962306a36Sopenharmony_ci		0x57, 0x4b, 0xf1, 0x5c, 0xca, 0x7e, 0x09, 0xc0,
28062306a36Sopenharmony_ci		0xd3, 0x89, 0xc6, 0xe0, 0xda, 0xc4, 0x81, 0x7e,
28162306a36Sopenharmony_ci		0x5b, 0xf9, 0xe1, 0x01, 0xc1, 0x92, 0x05, 0xea,
28262306a36Sopenharmony_ci		0xf5, 0x2f, 0xc6, 0xc6, 0xc7, 0x8f, 0xbc, 0xf4 };
28362306a36Sopenharmony_ci	static const u8 C0[] __initconst = {
28462306a36Sopenharmony_ci		0x00, 0xf4, 0xa3, 0xe5, 0xa0, 0x72, 0x63, 0x95,
28562306a36Sopenharmony_ci		0xc6, 0x4f, 0x48, 0xd0, 0x8b, 0x5b, 0x5f, 0x8e,
28662306a36Sopenharmony_ci		0x6b, 0x96, 0x1f, 0x16, 0xed, 0xbc, 0x66, 0x94,
28762306a36Sopenharmony_ci		0x45, 0x31, 0xd7, 0x47, 0x73, 0x22, 0xa5, 0x86,
28862306a36Sopenharmony_ci		0xce, 0xc0, 0x4c, 0xac, 0x63, 0xb8, 0x39, 0x50,
28962306a36Sopenharmony_ci		0xbf, 0xe6, 0x59, 0x6c, 0x38, 0x58, 0x99, 0x1f,
29062306a36Sopenharmony_ci		0x27, 0xa7, 0x9d, 0x71, 0x2a, 0xb3, 0x7b, 0xf9,
29162306a36Sopenharmony_ci		0xfb, 0x17, 0x86, 0xaa, 0x99, 0x81, 0xaa, 0x43,
29262306a36Sopenharmony_ci		0xe4, 0x37, 0xd3, 0x1e, 0x6e, 0xe5, 0xe6, 0xee,
29362306a36Sopenharmony_ci		0xc2, 0xed, 0x95, 0x4f, 0x53, 0x0e, 0x46, 0x8a,
29462306a36Sopenharmony_ci		0xcc, 0x45, 0xa5, 0xdb, 0x69, 0x0d, 0x81, 0xc9,
29562306a36Sopenharmony_ci		0x32, 0x92, 0xbc, 0x8f, 0x33, 0xe6, 0xf6, 0x09,
29662306a36Sopenharmony_ci		0x7c, 0x8e, 0x05, 0x19, 0x0d, 0xf1, 0xb6, 0xcc,
29762306a36Sopenharmony_ci		0xf3, 0x02, 0x21, 0x90, 0x25, 0xec, 0xed, 0x0e };
29862306a36Sopenharmony_ci	static const u8 random[] __initconst = {
29962306a36Sopenharmony_ci		0x95, 0xb7, 0xf1, 0x7e, 0x98, 0x02, 0xd3, 0x57,
30062306a36Sopenharmony_ci		0x73, 0x92, 0xc6, 0xa9, 0xc0, 0x80, 0x83, 0xb6,
30162306a36Sopenharmony_ci		0x7d, 0xd1, 0x29, 0x22, 0x65, 0xb5, 0xf4, 0x2d,
30262306a36Sopenharmony_ci		0x23, 0x7f, 0x1c, 0x55, 0xbb, 0x9b, 0x10, 0xbf,
30362306a36Sopenharmony_ci		0xcf, 0xd8, 0x2c, 0x77, 0xa3, 0x78, 0xb8, 0x26,
30462306a36Sopenharmony_ci		0x6a, 0x00, 0x99, 0x14, 0x3b, 0x3c, 0x2d, 0x64,
30562306a36Sopenharmony_ci		0x61, 0x1e, 0xee, 0xb6, 0x9a, 0xcd, 0xc0, 0x55,
30662306a36Sopenharmony_ci		0x95, 0x7c, 0x13, 0x9e, 0x8b, 0x19, 0x0c, 0x7a,
30762306a36Sopenharmony_ci		0x06, 0x95, 0x5f, 0x2c, 0x79, 0x7c, 0x27, 0x78,
30862306a36Sopenharmony_ci		0xde, 0x94, 0x03, 0x96, 0xa5, 0x01, 0xf4, 0x0e,
30962306a36Sopenharmony_ci		0x91, 0x39, 0x6a, 0xcf, 0x8d, 0x7e, 0x45, 0xeb,
31062306a36Sopenharmony_ci		0xdb, 0xb5, 0x3b, 0xbf, 0x8c, 0x97, 0x52, 0x30,
31162306a36Sopenharmony_ci		0xd2, 0xf0, 0xff, 0x91, 0x06, 0xc7, 0x61, 0x19,
31262306a36Sopenharmony_ci		0xae, 0x49, 0x8e, 0x7f, 0xbc, 0x03, 0xd9, 0x0f,
31362306a36Sopenharmony_ci		0x8e, 0x4c, 0x51, 0x62, 0x7a, 0xed, 0x5c, 0x8d,
31462306a36Sopenharmony_ci		0x42, 0x63, 0xd5, 0xd2, 0xb9, 0x78, 0x87, 0x3a,
31562306a36Sopenharmony_ci		0x0d, 0xe5, 0x96, 0xee, 0x6d, 0xc7, 0xf7, 0xc2,
31662306a36Sopenharmony_ci		0x9e, 0x37, 0xee, 0xe8, 0xb3, 0x4c, 0x90, 0xdd,
31762306a36Sopenharmony_ci		0x1c, 0xf6, 0xa9, 0xdd, 0xb2, 0x2b, 0x4c, 0xbd,
31862306a36Sopenharmony_ci		0x08, 0x6b, 0x14, 0xb3, 0x5d, 0xe9, 0x3d, 0xa2,
31962306a36Sopenharmony_ci		0xd5, 0xcb, 0x18, 0x06, 0x69, 0x8c, 0xbd, 0x7b,
32062306a36Sopenharmony_ci		0xbb, 0x67, 0xbf, 0xe3, 0xd3, 0x1f, 0xd2, 0xd1,
32162306a36Sopenharmony_ci		0xdb, 0xd2, 0xa1, 0xe0, 0x58, 0xa3, 0xeb, 0x99,
32262306a36Sopenharmony_ci		0xd7, 0xe5, 0x1f, 0x1a, 0x93, 0x8e, 0xed, 0x5e,
32362306a36Sopenharmony_ci		0x1c, 0x1d, 0xe2, 0x3a, 0x6b, 0x43, 0x45, 0xd3,
32462306a36Sopenharmony_ci		0x19, 0x14, 0x09, 0xf9, 0x2f, 0x39, 0xb3, 0x67,
32562306a36Sopenharmony_ci		0x0d, 0x8d, 0xbf, 0xb6, 0x35, 0xd8, 0xe6, 0xa3,
32662306a36Sopenharmony_ci		0x69, 0x32, 0xd8, 0x10, 0x33, 0xd1, 0x44, 0x8d,
32762306a36Sopenharmony_ci		0x63, 0xb4, 0x03, 0xdd, 0xf8, 0x8e, 0x12, 0x1b,
32862306a36Sopenharmony_ci		0x6e, 0x81, 0x9a, 0xc3, 0x81, 0x22, 0x6c, 0x13,
32962306a36Sopenharmony_ci		0x21, 0xe4, 0xb0, 0x86, 0x44, 0xf6, 0x72, 0x7c,
33062306a36Sopenharmony_ci		0x36, 0x8c, 0x5a, 0x9f, 0x7a, 0x4b, 0x3e, 0xe2 };
33162306a36Sopenharmony_ci
33262306a36Sopenharmony_ci	u8 buf[sizeof(random)];
33362306a36Sopenharmony_ci	struct prno_ws_s ws;
33462306a36Sopenharmony_ci
33562306a36Sopenharmony_ci	memset(&ws, 0, sizeof(ws));
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_ci	/* initial seed */
33862306a36Sopenharmony_ci	cpacf_prno(CPACF_PRNO_SHA512_DRNG_SEED,
33962306a36Sopenharmony_ci		   &ws, NULL, 0, seed, sizeof(seed));
34062306a36Sopenharmony_ci
34162306a36Sopenharmony_ci	/* check working states V and C */
34262306a36Sopenharmony_ci	if (memcmp(ws.V, V0, sizeof(V0)) != 0
34362306a36Sopenharmony_ci	    || memcmp(ws.C, C0, sizeof(C0)) != 0) {
34462306a36Sopenharmony_ci		pr_err("The prng self test state test "
34562306a36Sopenharmony_ci		       "for the SHA-512 mode failed\n");
34662306a36Sopenharmony_ci		prng_errorflag = PRNG_SELFTEST_FAILED;
34762306a36Sopenharmony_ci		return -EIO;
34862306a36Sopenharmony_ci	}
34962306a36Sopenharmony_ci
35062306a36Sopenharmony_ci	/* generate random bytes */
35162306a36Sopenharmony_ci	cpacf_prno(CPACF_PRNO_SHA512_DRNG_GEN,
35262306a36Sopenharmony_ci		   &ws, buf, sizeof(buf), NULL, 0);
35362306a36Sopenharmony_ci	cpacf_prno(CPACF_PRNO_SHA512_DRNG_GEN,
35462306a36Sopenharmony_ci		   &ws, buf, sizeof(buf), NULL, 0);
35562306a36Sopenharmony_ci
35662306a36Sopenharmony_ci	/* check against expected data */
35762306a36Sopenharmony_ci	if (memcmp(buf, random, sizeof(random)) != 0) {
35862306a36Sopenharmony_ci		pr_err("The prng self test data test "
35962306a36Sopenharmony_ci		       "for the SHA-512 mode failed\n");
36062306a36Sopenharmony_ci		prng_errorflag = PRNG_SELFTEST_FAILED;
36162306a36Sopenharmony_ci		return -EIO;
36262306a36Sopenharmony_ci	}
36362306a36Sopenharmony_ci
36462306a36Sopenharmony_ci	return 0;
36562306a36Sopenharmony_ci}
36662306a36Sopenharmony_ci
36762306a36Sopenharmony_ci
36862306a36Sopenharmony_cistatic int __init prng_sha512_instantiate(void)
36962306a36Sopenharmony_ci{
37062306a36Sopenharmony_ci	int ret, datalen, seedlen;
37162306a36Sopenharmony_ci	u8 seed[128 + 16];
37262306a36Sopenharmony_ci
37362306a36Sopenharmony_ci	pr_debug("prng runs in SHA-512 mode "
37462306a36Sopenharmony_ci		 "with chunksize=%d and reseed_limit=%u\n",
37562306a36Sopenharmony_ci		 prng_chunk_size, prng_reseed_limit);
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_ci	/* memory allocation, prng_data struct init, mutex init */
37862306a36Sopenharmony_ci	datalen = sizeof(struct prng_data_s) + prng_chunk_size;
37962306a36Sopenharmony_ci	if (fips_enabled)
38062306a36Sopenharmony_ci		datalen += prng_chunk_size;
38162306a36Sopenharmony_ci	prng_data = kzalloc(datalen, GFP_KERNEL);
38262306a36Sopenharmony_ci	if (!prng_data) {
38362306a36Sopenharmony_ci		prng_errorflag = PRNG_INSTANTIATE_FAILED;
38462306a36Sopenharmony_ci		return -ENOMEM;
38562306a36Sopenharmony_ci	}
38662306a36Sopenharmony_ci	mutex_init(&prng_data->mutex);
38762306a36Sopenharmony_ci	prng_data->buf = ((u8 *)prng_data) + sizeof(struct prng_data_s);
38862306a36Sopenharmony_ci
38962306a36Sopenharmony_ci	/* selftest */
39062306a36Sopenharmony_ci	ret = prng_sha512_selftest();
39162306a36Sopenharmony_ci	if (ret)
39262306a36Sopenharmony_ci		goto outfree;
39362306a36Sopenharmony_ci
39462306a36Sopenharmony_ci	/* generate initial seed, we need at least  256 + 128 bits entropy. */
39562306a36Sopenharmony_ci	if (trng_available) {
39662306a36Sopenharmony_ci		/*
39762306a36Sopenharmony_ci		 * Trng available, so use it. The trng works in chunks of
39862306a36Sopenharmony_ci		 * 32 bytes and produces 100% entropy. So we pull 64 bytes
39962306a36Sopenharmony_ci		 * which gives us 512 bits entropy.
40062306a36Sopenharmony_ci		 */
40162306a36Sopenharmony_ci		seedlen = 2 * 32;
40262306a36Sopenharmony_ci		cpacf_trng(NULL, 0, seed, seedlen);
40362306a36Sopenharmony_ci	} else {
40462306a36Sopenharmony_ci		/*
40562306a36Sopenharmony_ci		 * No trng available, so use the generate_entropy() function.
40662306a36Sopenharmony_ci		 * This function works in 64 byte junks and produces
40762306a36Sopenharmony_ci		 * 50% entropy. So we pull 2*64 bytes which gives us 512 bits
40862306a36Sopenharmony_ci		 * of entropy.
40962306a36Sopenharmony_ci		 */
41062306a36Sopenharmony_ci		seedlen = 2 * 64;
41162306a36Sopenharmony_ci		ret = generate_entropy(seed, seedlen);
41262306a36Sopenharmony_ci		if (ret != seedlen)
41362306a36Sopenharmony_ci			goto outfree;
41462306a36Sopenharmony_ci	}
41562306a36Sopenharmony_ci
41662306a36Sopenharmony_ci	/* append the seed by 16 bytes of unique nonce */
41762306a36Sopenharmony_ci	store_tod_clock_ext((union tod_clock *)(seed + seedlen));
41862306a36Sopenharmony_ci	seedlen += 16;
41962306a36Sopenharmony_ci
42062306a36Sopenharmony_ci	/* now initial seed of the prno drng */
42162306a36Sopenharmony_ci	cpacf_prno(CPACF_PRNO_SHA512_DRNG_SEED,
42262306a36Sopenharmony_ci		   &prng_data->prnows, NULL, 0, seed, seedlen);
42362306a36Sopenharmony_ci	memzero_explicit(seed, sizeof(seed));
42462306a36Sopenharmony_ci
42562306a36Sopenharmony_ci	/* if fips mode is enabled, generate a first block of random
42662306a36Sopenharmony_ci	   bytes for the FIPS 140-2 Conditional Self Test */
42762306a36Sopenharmony_ci	if (fips_enabled) {
42862306a36Sopenharmony_ci		prng_data->prev = prng_data->buf + prng_chunk_size;
42962306a36Sopenharmony_ci		cpacf_prno(CPACF_PRNO_SHA512_DRNG_GEN,
43062306a36Sopenharmony_ci			   &prng_data->prnows,
43162306a36Sopenharmony_ci			   prng_data->prev, prng_chunk_size, NULL, 0);
43262306a36Sopenharmony_ci	}
43362306a36Sopenharmony_ci
43462306a36Sopenharmony_ci	return 0;
43562306a36Sopenharmony_ci
43662306a36Sopenharmony_cioutfree:
43762306a36Sopenharmony_ci	kfree(prng_data);
43862306a36Sopenharmony_ci	return ret;
43962306a36Sopenharmony_ci}
44062306a36Sopenharmony_ci
44162306a36Sopenharmony_ci
44262306a36Sopenharmony_cistatic void prng_sha512_deinstantiate(void)
44362306a36Sopenharmony_ci{
44462306a36Sopenharmony_ci	pr_debug("The prng module stopped after running in SHA-512 mode\n");
44562306a36Sopenharmony_ci	kfree_sensitive(prng_data);
44662306a36Sopenharmony_ci}
44762306a36Sopenharmony_ci
44862306a36Sopenharmony_ci
44962306a36Sopenharmony_cistatic int prng_sha512_reseed(void)
45062306a36Sopenharmony_ci{
45162306a36Sopenharmony_ci	int ret, seedlen;
45262306a36Sopenharmony_ci	u8 seed[64];
45362306a36Sopenharmony_ci
45462306a36Sopenharmony_ci	/* We need at least 256 bits of fresh entropy for reseeding */
45562306a36Sopenharmony_ci	if (trng_available) {
45662306a36Sopenharmony_ci		/* trng produces 256 bits entropy in 32 bytes */
45762306a36Sopenharmony_ci		seedlen = 32;
45862306a36Sopenharmony_ci		cpacf_trng(NULL, 0, seed, seedlen);
45962306a36Sopenharmony_ci	} else {
46062306a36Sopenharmony_ci		/* generate_entropy() produces 256 bits entropy in 64 bytes */
46162306a36Sopenharmony_ci		seedlen = 64;
46262306a36Sopenharmony_ci		ret = generate_entropy(seed, seedlen);
46362306a36Sopenharmony_ci		if (ret != sizeof(seed))
46462306a36Sopenharmony_ci			return ret;
46562306a36Sopenharmony_ci	}
46662306a36Sopenharmony_ci
46762306a36Sopenharmony_ci	/* do a reseed of the prno drng with this bytestring */
46862306a36Sopenharmony_ci	cpacf_prno(CPACF_PRNO_SHA512_DRNG_SEED,
46962306a36Sopenharmony_ci		   &prng_data->prnows, NULL, 0, seed, seedlen);
47062306a36Sopenharmony_ci	memzero_explicit(seed, sizeof(seed));
47162306a36Sopenharmony_ci
47262306a36Sopenharmony_ci	return 0;
47362306a36Sopenharmony_ci}
47462306a36Sopenharmony_ci
47562306a36Sopenharmony_ci
47662306a36Sopenharmony_cistatic int prng_sha512_generate(u8 *buf, size_t nbytes)
47762306a36Sopenharmony_ci{
47862306a36Sopenharmony_ci	int ret;
47962306a36Sopenharmony_ci
48062306a36Sopenharmony_ci	/* reseed needed ? */
48162306a36Sopenharmony_ci	if (prng_data->prnows.reseed_counter > prng_reseed_limit) {
48262306a36Sopenharmony_ci		ret = prng_sha512_reseed();
48362306a36Sopenharmony_ci		if (ret)
48462306a36Sopenharmony_ci			return ret;
48562306a36Sopenharmony_ci	}
48662306a36Sopenharmony_ci
48762306a36Sopenharmony_ci	/* PRNO generate */
48862306a36Sopenharmony_ci	cpacf_prno(CPACF_PRNO_SHA512_DRNG_GEN,
48962306a36Sopenharmony_ci		   &prng_data->prnows, buf, nbytes, NULL, 0);
49062306a36Sopenharmony_ci
49162306a36Sopenharmony_ci	/* FIPS 140-2 Conditional Self Test */
49262306a36Sopenharmony_ci	if (fips_enabled) {
49362306a36Sopenharmony_ci		if (!memcmp(prng_data->prev, buf, nbytes)) {
49462306a36Sopenharmony_ci			prng_errorflag = PRNG_GEN_FAILED;
49562306a36Sopenharmony_ci			return -EILSEQ;
49662306a36Sopenharmony_ci		}
49762306a36Sopenharmony_ci		memcpy(prng_data->prev, buf, nbytes);
49862306a36Sopenharmony_ci	}
49962306a36Sopenharmony_ci
50062306a36Sopenharmony_ci	return nbytes;
50162306a36Sopenharmony_ci}
50262306a36Sopenharmony_ci
50362306a36Sopenharmony_ci
50462306a36Sopenharmony_ci/*** file io functions ***/
50562306a36Sopenharmony_ci
50662306a36Sopenharmony_cistatic int prng_open(struct inode *inode, struct file *file)
50762306a36Sopenharmony_ci{
50862306a36Sopenharmony_ci	return nonseekable_open(inode, file);
50962306a36Sopenharmony_ci}
51062306a36Sopenharmony_ci
51162306a36Sopenharmony_ci
51262306a36Sopenharmony_cistatic ssize_t prng_tdes_read(struct file *file, char __user *ubuf,
51362306a36Sopenharmony_ci			      size_t nbytes, loff_t *ppos)
51462306a36Sopenharmony_ci{
51562306a36Sopenharmony_ci	int chunk, n, ret = 0;
51662306a36Sopenharmony_ci
51762306a36Sopenharmony_ci	/* lock prng_data struct */
51862306a36Sopenharmony_ci	if (mutex_lock_interruptible(&prng_data->mutex))
51962306a36Sopenharmony_ci		return -ERESTARTSYS;
52062306a36Sopenharmony_ci
52162306a36Sopenharmony_ci	while (nbytes) {
52262306a36Sopenharmony_ci		if (need_resched()) {
52362306a36Sopenharmony_ci			if (signal_pending(current)) {
52462306a36Sopenharmony_ci				if (ret == 0)
52562306a36Sopenharmony_ci					ret = -ERESTARTSYS;
52662306a36Sopenharmony_ci				break;
52762306a36Sopenharmony_ci			}
52862306a36Sopenharmony_ci			/* give mutex free before calling schedule() */
52962306a36Sopenharmony_ci			mutex_unlock(&prng_data->mutex);
53062306a36Sopenharmony_ci			schedule();
53162306a36Sopenharmony_ci			/* occupy mutex again */
53262306a36Sopenharmony_ci			if (mutex_lock_interruptible(&prng_data->mutex)) {
53362306a36Sopenharmony_ci				if (ret == 0)
53462306a36Sopenharmony_ci					ret = -ERESTARTSYS;
53562306a36Sopenharmony_ci				return ret;
53662306a36Sopenharmony_ci			}
53762306a36Sopenharmony_ci		}
53862306a36Sopenharmony_ci
53962306a36Sopenharmony_ci		/*
54062306a36Sopenharmony_ci		 * we lose some random bytes if an attacker issues
54162306a36Sopenharmony_ci		 * reads < 8 bytes, but we don't care
54262306a36Sopenharmony_ci		 */
54362306a36Sopenharmony_ci		chunk = min_t(int, nbytes, prng_chunk_size);
54462306a36Sopenharmony_ci
54562306a36Sopenharmony_ci		/* PRNG only likes multiples of 8 bytes */
54662306a36Sopenharmony_ci		n = (chunk + 7) & -8;
54762306a36Sopenharmony_ci
54862306a36Sopenharmony_ci		if (prng_data->prngws.reseed_counter > prng_reseed_limit)
54962306a36Sopenharmony_ci			prng_tdes_seed(8);
55062306a36Sopenharmony_ci
55162306a36Sopenharmony_ci		/* if the CPU supports PRNG stckf is present too */
55262306a36Sopenharmony_ci		*((unsigned long long *)prng_data->buf) = get_tod_clock_fast();
55362306a36Sopenharmony_ci
55462306a36Sopenharmony_ci		/*
55562306a36Sopenharmony_ci		 * Beside the STCKF the input for the TDES-EDE is the output
55662306a36Sopenharmony_ci		 * of the last operation. We differ here from X9.17 since we
55762306a36Sopenharmony_ci		 * only store one timestamp into the buffer. Padding the whole
55862306a36Sopenharmony_ci		 * buffer with timestamps does not improve security, since
55962306a36Sopenharmony_ci		 * successive stckf have nearly constant offsets.
56062306a36Sopenharmony_ci		 * If an attacker knows the first timestamp it would be
56162306a36Sopenharmony_ci		 * trivial to guess the additional values. One timestamp
56262306a36Sopenharmony_ci		 * is therefore enough and still guarantees unique input values.
56362306a36Sopenharmony_ci		 *
56462306a36Sopenharmony_ci		 * Note: you can still get strict X9.17 conformity by setting
56562306a36Sopenharmony_ci		 * prng_chunk_size to 8 bytes.
56662306a36Sopenharmony_ci		 */
56762306a36Sopenharmony_ci		cpacf_kmc(CPACF_KMC_PRNG, prng_data->prngws.parm_block,
56862306a36Sopenharmony_ci			  prng_data->buf, prng_data->buf, n);
56962306a36Sopenharmony_ci
57062306a36Sopenharmony_ci		prng_data->prngws.byte_counter += n;
57162306a36Sopenharmony_ci		prng_data->prngws.reseed_counter += n;
57262306a36Sopenharmony_ci
57362306a36Sopenharmony_ci		if (copy_to_user(ubuf, prng_data->buf, chunk)) {
57462306a36Sopenharmony_ci			ret = -EFAULT;
57562306a36Sopenharmony_ci			break;
57662306a36Sopenharmony_ci		}
57762306a36Sopenharmony_ci
57862306a36Sopenharmony_ci		nbytes -= chunk;
57962306a36Sopenharmony_ci		ret += chunk;
58062306a36Sopenharmony_ci		ubuf += chunk;
58162306a36Sopenharmony_ci	}
58262306a36Sopenharmony_ci
58362306a36Sopenharmony_ci	/* unlock prng_data struct */
58462306a36Sopenharmony_ci	mutex_unlock(&prng_data->mutex);
58562306a36Sopenharmony_ci
58662306a36Sopenharmony_ci	return ret;
58762306a36Sopenharmony_ci}
58862306a36Sopenharmony_ci
58962306a36Sopenharmony_ci
59062306a36Sopenharmony_cistatic ssize_t prng_sha512_read(struct file *file, char __user *ubuf,
59162306a36Sopenharmony_ci				size_t nbytes, loff_t *ppos)
59262306a36Sopenharmony_ci{
59362306a36Sopenharmony_ci	int n, ret = 0;
59462306a36Sopenharmony_ci	u8 *p;
59562306a36Sopenharmony_ci
59662306a36Sopenharmony_ci	/* if errorflag is set do nothing and return 'broken pipe' */
59762306a36Sopenharmony_ci	if (prng_errorflag)
59862306a36Sopenharmony_ci		return -EPIPE;
59962306a36Sopenharmony_ci
60062306a36Sopenharmony_ci	/* lock prng_data struct */
60162306a36Sopenharmony_ci	if (mutex_lock_interruptible(&prng_data->mutex))
60262306a36Sopenharmony_ci		return -ERESTARTSYS;
60362306a36Sopenharmony_ci
60462306a36Sopenharmony_ci	while (nbytes) {
60562306a36Sopenharmony_ci		if (need_resched()) {
60662306a36Sopenharmony_ci			if (signal_pending(current)) {
60762306a36Sopenharmony_ci				if (ret == 0)
60862306a36Sopenharmony_ci					ret = -ERESTARTSYS;
60962306a36Sopenharmony_ci				break;
61062306a36Sopenharmony_ci			}
61162306a36Sopenharmony_ci			/* give mutex free before calling schedule() */
61262306a36Sopenharmony_ci			mutex_unlock(&prng_data->mutex);
61362306a36Sopenharmony_ci			schedule();
61462306a36Sopenharmony_ci			/* occopy mutex again */
61562306a36Sopenharmony_ci			if (mutex_lock_interruptible(&prng_data->mutex)) {
61662306a36Sopenharmony_ci				if (ret == 0)
61762306a36Sopenharmony_ci					ret = -ERESTARTSYS;
61862306a36Sopenharmony_ci				return ret;
61962306a36Sopenharmony_ci			}
62062306a36Sopenharmony_ci		}
62162306a36Sopenharmony_ci		if (prng_data->rest) {
62262306a36Sopenharmony_ci			/* push left over random bytes from the previous read */
62362306a36Sopenharmony_ci			p = prng_data->buf + prng_chunk_size - prng_data->rest;
62462306a36Sopenharmony_ci			n = (nbytes < prng_data->rest) ?
62562306a36Sopenharmony_ci				nbytes : prng_data->rest;
62662306a36Sopenharmony_ci			prng_data->rest -= n;
62762306a36Sopenharmony_ci		} else {
62862306a36Sopenharmony_ci			/* generate one chunk of random bytes into read buf */
62962306a36Sopenharmony_ci			p = prng_data->buf;
63062306a36Sopenharmony_ci			n = prng_sha512_generate(p, prng_chunk_size);
63162306a36Sopenharmony_ci			if (n < 0) {
63262306a36Sopenharmony_ci				ret = n;
63362306a36Sopenharmony_ci				break;
63462306a36Sopenharmony_ci			}
63562306a36Sopenharmony_ci			if (nbytes < prng_chunk_size) {
63662306a36Sopenharmony_ci				n = nbytes;
63762306a36Sopenharmony_ci				prng_data->rest = prng_chunk_size - n;
63862306a36Sopenharmony_ci			} else {
63962306a36Sopenharmony_ci				n = prng_chunk_size;
64062306a36Sopenharmony_ci				prng_data->rest = 0;
64162306a36Sopenharmony_ci			}
64262306a36Sopenharmony_ci		}
64362306a36Sopenharmony_ci		if (copy_to_user(ubuf, p, n)) {
64462306a36Sopenharmony_ci			ret = -EFAULT;
64562306a36Sopenharmony_ci			break;
64662306a36Sopenharmony_ci		}
64762306a36Sopenharmony_ci		memzero_explicit(p, n);
64862306a36Sopenharmony_ci		ubuf += n;
64962306a36Sopenharmony_ci		nbytes -= n;
65062306a36Sopenharmony_ci		ret += n;
65162306a36Sopenharmony_ci	}
65262306a36Sopenharmony_ci
65362306a36Sopenharmony_ci	/* unlock prng_data struct */
65462306a36Sopenharmony_ci	mutex_unlock(&prng_data->mutex);
65562306a36Sopenharmony_ci
65662306a36Sopenharmony_ci	return ret;
65762306a36Sopenharmony_ci}
65862306a36Sopenharmony_ci
65962306a36Sopenharmony_ci
66062306a36Sopenharmony_ci/*** sysfs stuff ***/
66162306a36Sopenharmony_ci
66262306a36Sopenharmony_cistatic const struct file_operations prng_sha512_fops = {
66362306a36Sopenharmony_ci	.owner		= THIS_MODULE,
66462306a36Sopenharmony_ci	.open		= &prng_open,
66562306a36Sopenharmony_ci	.release	= NULL,
66662306a36Sopenharmony_ci	.read		= &prng_sha512_read,
66762306a36Sopenharmony_ci	.llseek		= noop_llseek,
66862306a36Sopenharmony_ci};
66962306a36Sopenharmony_cistatic const struct file_operations prng_tdes_fops = {
67062306a36Sopenharmony_ci	.owner		= THIS_MODULE,
67162306a36Sopenharmony_ci	.open		= &prng_open,
67262306a36Sopenharmony_ci	.release	= NULL,
67362306a36Sopenharmony_ci	.read		= &prng_tdes_read,
67462306a36Sopenharmony_ci	.llseek		= noop_llseek,
67562306a36Sopenharmony_ci};
67662306a36Sopenharmony_ci
67762306a36Sopenharmony_ci/* chunksize attribute (ro) */
67862306a36Sopenharmony_cistatic ssize_t prng_chunksize_show(struct device *dev,
67962306a36Sopenharmony_ci				   struct device_attribute *attr,
68062306a36Sopenharmony_ci				   char *buf)
68162306a36Sopenharmony_ci{
68262306a36Sopenharmony_ci	return scnprintf(buf, PAGE_SIZE, "%u\n", prng_chunk_size);
68362306a36Sopenharmony_ci}
68462306a36Sopenharmony_cistatic DEVICE_ATTR(chunksize, 0444, prng_chunksize_show, NULL);
68562306a36Sopenharmony_ci
68662306a36Sopenharmony_ci/* counter attribute (ro) */
68762306a36Sopenharmony_cistatic ssize_t prng_counter_show(struct device *dev,
68862306a36Sopenharmony_ci				 struct device_attribute *attr,
68962306a36Sopenharmony_ci				 char *buf)
69062306a36Sopenharmony_ci{
69162306a36Sopenharmony_ci	u64 counter;
69262306a36Sopenharmony_ci
69362306a36Sopenharmony_ci	if (mutex_lock_interruptible(&prng_data->mutex))
69462306a36Sopenharmony_ci		return -ERESTARTSYS;
69562306a36Sopenharmony_ci	if (prng_mode == PRNG_MODE_SHA512)
69662306a36Sopenharmony_ci		counter = prng_data->prnows.stream_bytes;
69762306a36Sopenharmony_ci	else
69862306a36Sopenharmony_ci		counter = prng_data->prngws.byte_counter;
69962306a36Sopenharmony_ci	mutex_unlock(&prng_data->mutex);
70062306a36Sopenharmony_ci
70162306a36Sopenharmony_ci	return scnprintf(buf, PAGE_SIZE, "%llu\n", counter);
70262306a36Sopenharmony_ci}
70362306a36Sopenharmony_cistatic DEVICE_ATTR(byte_counter, 0444, prng_counter_show, NULL);
70462306a36Sopenharmony_ci
70562306a36Sopenharmony_ci/* errorflag attribute (ro) */
70662306a36Sopenharmony_cistatic ssize_t prng_errorflag_show(struct device *dev,
70762306a36Sopenharmony_ci				   struct device_attribute *attr,
70862306a36Sopenharmony_ci				   char *buf)
70962306a36Sopenharmony_ci{
71062306a36Sopenharmony_ci	return scnprintf(buf, PAGE_SIZE, "%d\n", prng_errorflag);
71162306a36Sopenharmony_ci}
71262306a36Sopenharmony_cistatic DEVICE_ATTR(errorflag, 0444, prng_errorflag_show, NULL);
71362306a36Sopenharmony_ci
71462306a36Sopenharmony_ci/* mode attribute (ro) */
71562306a36Sopenharmony_cistatic ssize_t prng_mode_show(struct device *dev,
71662306a36Sopenharmony_ci			      struct device_attribute *attr,
71762306a36Sopenharmony_ci			      char *buf)
71862306a36Sopenharmony_ci{
71962306a36Sopenharmony_ci	if (prng_mode == PRNG_MODE_TDES)
72062306a36Sopenharmony_ci		return scnprintf(buf, PAGE_SIZE, "TDES\n");
72162306a36Sopenharmony_ci	else
72262306a36Sopenharmony_ci		return scnprintf(buf, PAGE_SIZE, "SHA512\n");
72362306a36Sopenharmony_ci}
72462306a36Sopenharmony_cistatic DEVICE_ATTR(mode, 0444, prng_mode_show, NULL);
72562306a36Sopenharmony_ci
72662306a36Sopenharmony_ci/* reseed attribute (w) */
72762306a36Sopenharmony_cistatic ssize_t prng_reseed_store(struct device *dev,
72862306a36Sopenharmony_ci				 struct device_attribute *attr,
72962306a36Sopenharmony_ci				 const char *buf, size_t count)
73062306a36Sopenharmony_ci{
73162306a36Sopenharmony_ci	if (mutex_lock_interruptible(&prng_data->mutex))
73262306a36Sopenharmony_ci		return -ERESTARTSYS;
73362306a36Sopenharmony_ci	prng_sha512_reseed();
73462306a36Sopenharmony_ci	mutex_unlock(&prng_data->mutex);
73562306a36Sopenharmony_ci
73662306a36Sopenharmony_ci	return count;
73762306a36Sopenharmony_ci}
73862306a36Sopenharmony_cistatic DEVICE_ATTR(reseed, 0200, NULL, prng_reseed_store);
73962306a36Sopenharmony_ci
74062306a36Sopenharmony_ci/* reseed limit attribute (rw) */
74162306a36Sopenharmony_cistatic ssize_t prng_reseed_limit_show(struct device *dev,
74262306a36Sopenharmony_ci				      struct device_attribute *attr,
74362306a36Sopenharmony_ci				      char *buf)
74462306a36Sopenharmony_ci{
74562306a36Sopenharmony_ci	return scnprintf(buf, PAGE_SIZE, "%u\n", prng_reseed_limit);
74662306a36Sopenharmony_ci}
74762306a36Sopenharmony_cistatic ssize_t prng_reseed_limit_store(struct device *dev,
74862306a36Sopenharmony_ci				       struct device_attribute *attr,
74962306a36Sopenharmony_ci				       const char *buf, size_t count)
75062306a36Sopenharmony_ci{
75162306a36Sopenharmony_ci	unsigned limit;
75262306a36Sopenharmony_ci
75362306a36Sopenharmony_ci	if (sscanf(buf, "%u\n", &limit) != 1)
75462306a36Sopenharmony_ci		return -EINVAL;
75562306a36Sopenharmony_ci
75662306a36Sopenharmony_ci	if (prng_mode == PRNG_MODE_SHA512) {
75762306a36Sopenharmony_ci		if (limit < PRNG_RESEED_LIMIT_SHA512_LOWER)
75862306a36Sopenharmony_ci			return -EINVAL;
75962306a36Sopenharmony_ci	} else {
76062306a36Sopenharmony_ci		if (limit < PRNG_RESEED_LIMIT_TDES_LOWER)
76162306a36Sopenharmony_ci			return -EINVAL;
76262306a36Sopenharmony_ci	}
76362306a36Sopenharmony_ci
76462306a36Sopenharmony_ci	prng_reseed_limit = limit;
76562306a36Sopenharmony_ci
76662306a36Sopenharmony_ci	return count;
76762306a36Sopenharmony_ci}
76862306a36Sopenharmony_cistatic DEVICE_ATTR(reseed_limit, 0644,
76962306a36Sopenharmony_ci		   prng_reseed_limit_show, prng_reseed_limit_store);
77062306a36Sopenharmony_ci
77162306a36Sopenharmony_ci/* strength attribute (ro) */
77262306a36Sopenharmony_cistatic ssize_t prng_strength_show(struct device *dev,
77362306a36Sopenharmony_ci				  struct device_attribute *attr,
77462306a36Sopenharmony_ci				  char *buf)
77562306a36Sopenharmony_ci{
77662306a36Sopenharmony_ci	return scnprintf(buf, PAGE_SIZE, "256\n");
77762306a36Sopenharmony_ci}
77862306a36Sopenharmony_cistatic DEVICE_ATTR(strength, 0444, prng_strength_show, NULL);
77962306a36Sopenharmony_ci
78062306a36Sopenharmony_cistatic struct attribute *prng_sha512_dev_attrs[] = {
78162306a36Sopenharmony_ci	&dev_attr_errorflag.attr,
78262306a36Sopenharmony_ci	&dev_attr_chunksize.attr,
78362306a36Sopenharmony_ci	&dev_attr_byte_counter.attr,
78462306a36Sopenharmony_ci	&dev_attr_mode.attr,
78562306a36Sopenharmony_ci	&dev_attr_reseed.attr,
78662306a36Sopenharmony_ci	&dev_attr_reseed_limit.attr,
78762306a36Sopenharmony_ci	&dev_attr_strength.attr,
78862306a36Sopenharmony_ci	NULL
78962306a36Sopenharmony_ci};
79062306a36Sopenharmony_ciATTRIBUTE_GROUPS(prng_sha512_dev);
79162306a36Sopenharmony_ci
79262306a36Sopenharmony_cistatic struct attribute *prng_tdes_dev_attrs[] = {
79362306a36Sopenharmony_ci	&dev_attr_chunksize.attr,
79462306a36Sopenharmony_ci	&dev_attr_byte_counter.attr,
79562306a36Sopenharmony_ci	&dev_attr_mode.attr,
79662306a36Sopenharmony_ci	NULL
79762306a36Sopenharmony_ci};
79862306a36Sopenharmony_ciATTRIBUTE_GROUPS(prng_tdes_dev);
79962306a36Sopenharmony_ci
80062306a36Sopenharmony_cistatic struct miscdevice prng_sha512_dev = {
80162306a36Sopenharmony_ci	.name	= "prandom",
80262306a36Sopenharmony_ci	.minor	= MISC_DYNAMIC_MINOR,
80362306a36Sopenharmony_ci	.mode	= 0644,
80462306a36Sopenharmony_ci	.fops	= &prng_sha512_fops,
80562306a36Sopenharmony_ci	.groups = prng_sha512_dev_groups,
80662306a36Sopenharmony_ci};
80762306a36Sopenharmony_ci
80862306a36Sopenharmony_cistatic struct miscdevice prng_tdes_dev = {
80962306a36Sopenharmony_ci	.name	= "prandom",
81062306a36Sopenharmony_ci	.minor	= MISC_DYNAMIC_MINOR,
81162306a36Sopenharmony_ci	.mode	= 0644,
81262306a36Sopenharmony_ci	.fops	= &prng_tdes_fops,
81362306a36Sopenharmony_ci	.groups = prng_tdes_dev_groups,
81462306a36Sopenharmony_ci};
81562306a36Sopenharmony_ci
81662306a36Sopenharmony_ci
81762306a36Sopenharmony_ci/*** module init and exit ***/
81862306a36Sopenharmony_ci
81962306a36Sopenharmony_cistatic int __init prng_init(void)
82062306a36Sopenharmony_ci{
82162306a36Sopenharmony_ci	int ret;
82262306a36Sopenharmony_ci
82362306a36Sopenharmony_ci	/* check if the CPU has a PRNG */
82462306a36Sopenharmony_ci	if (!cpacf_query_func(CPACF_KMC, CPACF_KMC_PRNG))
82562306a36Sopenharmony_ci		return -ENODEV;
82662306a36Sopenharmony_ci
82762306a36Sopenharmony_ci	/* check if TRNG subfunction is available */
82862306a36Sopenharmony_ci	if (cpacf_query_func(CPACF_PRNO, CPACF_PRNO_TRNG))
82962306a36Sopenharmony_ci		trng_available = true;
83062306a36Sopenharmony_ci
83162306a36Sopenharmony_ci	/* choose prng mode */
83262306a36Sopenharmony_ci	if (prng_mode != PRNG_MODE_TDES) {
83362306a36Sopenharmony_ci		/* check for MSA5 support for PRNO operations */
83462306a36Sopenharmony_ci		if (!cpacf_query_func(CPACF_PRNO, CPACF_PRNO_SHA512_DRNG_GEN)) {
83562306a36Sopenharmony_ci			if (prng_mode == PRNG_MODE_SHA512) {
83662306a36Sopenharmony_ci				pr_err("The prng module cannot "
83762306a36Sopenharmony_ci				       "start in SHA-512 mode\n");
83862306a36Sopenharmony_ci				return -ENODEV;
83962306a36Sopenharmony_ci			}
84062306a36Sopenharmony_ci			prng_mode = PRNG_MODE_TDES;
84162306a36Sopenharmony_ci		} else
84262306a36Sopenharmony_ci			prng_mode = PRNG_MODE_SHA512;
84362306a36Sopenharmony_ci	}
84462306a36Sopenharmony_ci
84562306a36Sopenharmony_ci	if (prng_mode == PRNG_MODE_SHA512) {
84662306a36Sopenharmony_ci
84762306a36Sopenharmony_ci		/* SHA512 mode */
84862306a36Sopenharmony_ci
84962306a36Sopenharmony_ci		if (prng_chunk_size < PRNG_CHUNKSIZE_SHA512_MIN
85062306a36Sopenharmony_ci		    || prng_chunk_size > PRNG_CHUNKSIZE_SHA512_MAX)
85162306a36Sopenharmony_ci			return -EINVAL;
85262306a36Sopenharmony_ci		prng_chunk_size = (prng_chunk_size + 0x3f) & ~0x3f;
85362306a36Sopenharmony_ci
85462306a36Sopenharmony_ci		if (prng_reseed_limit == 0)
85562306a36Sopenharmony_ci			prng_reseed_limit = PRNG_RESEED_LIMIT_SHA512;
85662306a36Sopenharmony_ci		else if (prng_reseed_limit < PRNG_RESEED_LIMIT_SHA512_LOWER)
85762306a36Sopenharmony_ci			return -EINVAL;
85862306a36Sopenharmony_ci
85962306a36Sopenharmony_ci		ret = prng_sha512_instantiate();
86062306a36Sopenharmony_ci		if (ret)
86162306a36Sopenharmony_ci			goto out;
86262306a36Sopenharmony_ci
86362306a36Sopenharmony_ci		ret = misc_register(&prng_sha512_dev);
86462306a36Sopenharmony_ci		if (ret) {
86562306a36Sopenharmony_ci			prng_sha512_deinstantiate();
86662306a36Sopenharmony_ci			goto out;
86762306a36Sopenharmony_ci		}
86862306a36Sopenharmony_ci
86962306a36Sopenharmony_ci	} else {
87062306a36Sopenharmony_ci
87162306a36Sopenharmony_ci		/* TDES mode */
87262306a36Sopenharmony_ci
87362306a36Sopenharmony_ci		if (prng_chunk_size < PRNG_CHUNKSIZE_TDES_MIN
87462306a36Sopenharmony_ci		    || prng_chunk_size > PRNG_CHUNKSIZE_TDES_MAX)
87562306a36Sopenharmony_ci			return -EINVAL;
87662306a36Sopenharmony_ci		prng_chunk_size = (prng_chunk_size + 0x07) & ~0x07;
87762306a36Sopenharmony_ci
87862306a36Sopenharmony_ci		if (prng_reseed_limit == 0)
87962306a36Sopenharmony_ci			prng_reseed_limit = PRNG_RESEED_LIMIT_TDES;
88062306a36Sopenharmony_ci		else if (prng_reseed_limit < PRNG_RESEED_LIMIT_TDES_LOWER)
88162306a36Sopenharmony_ci			return -EINVAL;
88262306a36Sopenharmony_ci
88362306a36Sopenharmony_ci		ret = prng_tdes_instantiate();
88462306a36Sopenharmony_ci		if (ret)
88562306a36Sopenharmony_ci			goto out;
88662306a36Sopenharmony_ci
88762306a36Sopenharmony_ci		ret = misc_register(&prng_tdes_dev);
88862306a36Sopenharmony_ci		if (ret) {
88962306a36Sopenharmony_ci			prng_tdes_deinstantiate();
89062306a36Sopenharmony_ci			goto out;
89162306a36Sopenharmony_ci		}
89262306a36Sopenharmony_ci	}
89362306a36Sopenharmony_ci
89462306a36Sopenharmony_ciout:
89562306a36Sopenharmony_ci	return ret;
89662306a36Sopenharmony_ci}
89762306a36Sopenharmony_ci
89862306a36Sopenharmony_ci
89962306a36Sopenharmony_cistatic void __exit prng_exit(void)
90062306a36Sopenharmony_ci{
90162306a36Sopenharmony_ci	if (prng_mode == PRNG_MODE_SHA512) {
90262306a36Sopenharmony_ci		misc_deregister(&prng_sha512_dev);
90362306a36Sopenharmony_ci		prng_sha512_deinstantiate();
90462306a36Sopenharmony_ci	} else {
90562306a36Sopenharmony_ci		misc_deregister(&prng_tdes_dev);
90662306a36Sopenharmony_ci		prng_tdes_deinstantiate();
90762306a36Sopenharmony_ci	}
90862306a36Sopenharmony_ci}
90962306a36Sopenharmony_ci
91062306a36Sopenharmony_cimodule_cpu_feature_match(S390_CPU_FEATURE_MSA, prng_init);
91162306a36Sopenharmony_cimodule_exit(prng_exit);
912