120a884f5SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
21b278294SJan Glauber /*
357127645SHarald Freudenberger * Copyright IBM Corp. 2006, 2015
41b278294SJan Glauber * Author(s): Jan Glauber <jan.glauber@de.ibm.com>
557127645SHarald Freudenberger * Harald Freudenberger <freude@de.ibm.com>
61b278294SJan Glauber * Driver for the s390 pseudo random number generator
71b278294SJan Glauber */
857127645SHarald Freudenberger
957127645SHarald Freudenberger #define KMSG_COMPONENT "prng"
1057127645SHarald Freudenberger #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
1157127645SHarald Freudenberger
121b278294SJan Glauber #include <linux/fs.h>
1357127645SHarald Freudenberger #include <linux/fips.h>
141b278294SJan Glauber #include <linux/init.h>
151b278294SJan Glauber #include <linux/kernel.h>
1657127645SHarald Freudenberger #include <linux/device.h>
171b278294SJan Glauber #include <linux/miscdevice.h>
181b278294SJan Glauber #include <linux/module.h>
191b278294SJan Glauber #include <linux/moduleparam.h>
2057127645SHarald Freudenberger #include <linux/mutex.h>
21d05377c1SHendrik Brueckner #include <linux/cpufeature.h>
221b278294SJan Glauber #include <linux/random.h>
235a0e3ad6STejun Heo #include <linux/slab.h>
24174cd4b1SIngo Molnar #include <linux/sched/signal.h>
25174cd4b1SIngo Molnar
261b278294SJan Glauber #include <asm/debug.h>
277c0f6ba6SLinus Torvalds #include <linux/uaccess.h>
2857127645SHarald Freudenberger #include <asm/timex.h>
29c7d4d259SMartin Schwidefsky #include <asm/cpacf.h>
301b278294SJan Glauber
311b278294SJan Glauber MODULE_LICENSE("GPL");
3257127645SHarald Freudenberger MODULE_AUTHOR("IBM Corporation");
331b278294SJan Glauber MODULE_DESCRIPTION("s390 PRNG interface");
341b278294SJan Glauber
3557127645SHarald Freudenberger
3657127645SHarald Freudenberger #define PRNG_MODE_AUTO 0
3757127645SHarald Freudenberger #define PRNG_MODE_TDES 1
3857127645SHarald Freudenberger #define PRNG_MODE_SHA512 2
3957127645SHarald Freudenberger
4057127645SHarald Freudenberger static unsigned int prng_mode = PRNG_MODE_AUTO;
4157127645SHarald Freudenberger module_param_named(mode, prng_mode, int, 0);
4257127645SHarald Freudenberger MODULE_PARM_DESC(prng_mode, "PRNG mode: 0 - auto, 1 - TDES, 2 - SHA512");
4357127645SHarald Freudenberger
4457127645SHarald Freudenberger
4557127645SHarald Freudenberger #define PRNG_CHUNKSIZE_TDES_MIN 8
4657127645SHarald Freudenberger #define PRNG_CHUNKSIZE_TDES_MAX (64*1024)
4757127645SHarald Freudenberger #define PRNG_CHUNKSIZE_SHA512_MIN 64
4857127645SHarald Freudenberger #define PRNG_CHUNKSIZE_SHA512_MAX (64*1024)
4957127645SHarald Freudenberger
5057127645SHarald Freudenberger static unsigned int prng_chunk_size = 256;
5157127645SHarald Freudenberger module_param_named(chunksize, prng_chunk_size, int, 0);
521b278294SJan Glauber MODULE_PARM_DESC(prng_chunk_size, "PRNG read chunk size in bytes");
531b278294SJan Glauber
5457127645SHarald Freudenberger
5557127645SHarald Freudenberger #define PRNG_RESEED_LIMIT_TDES 4096
5657127645SHarald Freudenberger #define PRNG_RESEED_LIMIT_TDES_LOWER 4096
5757127645SHarald Freudenberger #define PRNG_RESEED_LIMIT_SHA512 100000
5857127645SHarald Freudenberger #define PRNG_RESEED_LIMIT_SHA512_LOWER 10000
5957127645SHarald Freudenberger
6057127645SHarald Freudenberger static unsigned int prng_reseed_limit;
6157127645SHarald Freudenberger module_param_named(reseed_limit, prng_reseed_limit, int, 0);
6257127645SHarald Freudenberger MODULE_PARM_DESC(prng_reseed_limit, "PRNG reseed limit");
6357127645SHarald Freudenberger
64769f020bSHarald Freudenberger static bool trng_available;
651b278294SJan Glauber
661b278294SJan Glauber /*
671b278294SJan Glauber * Any one who considers arithmetical methods of producing random digits is,
681b278294SJan Glauber * of course, in a state of sin. -- John von Neumann
691b278294SJan Glauber */
701b278294SJan Glauber
7157127645SHarald Freudenberger static int prng_errorflag;
7257127645SHarald Freudenberger
7357127645SHarald Freudenberger #define PRNG_GEN_ENTROPY_FAILED 1
7457127645SHarald Freudenberger #define PRNG_SELFTEST_FAILED 2
7557127645SHarald Freudenberger #define PRNG_INSTANTIATE_FAILED 3
7657127645SHarald Freudenberger #define PRNG_SEED_FAILED 4
7757127645SHarald Freudenberger #define PRNG_RESEED_FAILED 5
7857127645SHarald Freudenberger #define PRNG_GEN_FAILED 6
7957127645SHarald Freudenberger
8057127645SHarald Freudenberger struct prng_ws_s {
8157127645SHarald Freudenberger u8 parm_block[32];
8257127645SHarald Freudenberger u32 reseed_counter;
8357127645SHarald Freudenberger u64 byte_counter;
841b278294SJan Glauber };
851b278294SJan Glauber
86985a9d20SHarald Freudenberger struct prno_ws_s {
8757127645SHarald Freudenberger u32 res;
8857127645SHarald Freudenberger u32 reseed_counter;
8957127645SHarald Freudenberger u64 stream_bytes;
9057127645SHarald Freudenberger u8 V[112];
9157127645SHarald Freudenberger u8 C[112];
921b278294SJan Glauber };
931b278294SJan Glauber
9457127645SHarald Freudenberger struct prng_data_s {
9557127645SHarald Freudenberger struct mutex mutex;
9657127645SHarald Freudenberger union {
9757127645SHarald Freudenberger struct prng_ws_s prngws;
98985a9d20SHarald Freudenberger struct prno_ws_s prnows;
9957127645SHarald Freudenberger };
10057127645SHarald Freudenberger u8 *buf;
10157127645SHarald Freudenberger u32 rest;
10257127645SHarald Freudenberger u8 *prev;
10357127645SHarald Freudenberger };
10457127645SHarald Freudenberger
10557127645SHarald Freudenberger static struct prng_data_s *prng_data;
10657127645SHarald Freudenberger
10757127645SHarald Freudenberger /* initial parameter block for tdes mode, copied from libica */
10857127645SHarald Freudenberger static const u8 initial_parm_block[32] __initconst = {
10957127645SHarald Freudenberger 0x0F, 0x2B, 0x8E, 0x63, 0x8C, 0x8E, 0xD2, 0x52,
11057127645SHarald Freudenberger 0x64, 0xB7, 0xA0, 0x7B, 0x75, 0x28, 0xB8, 0xF4,
11157127645SHarald Freudenberger 0x75, 0x5F, 0xD2, 0xA6, 0x8D, 0x97, 0x11, 0xFF,
11257127645SHarald Freudenberger 0x49, 0xD8, 0x23, 0xF3, 0x7E, 0x21, 0xEC, 0xA0 };
11357127645SHarald Freudenberger
11457127645SHarald Freudenberger
11557127645SHarald Freudenberger /*** helper functions ***/
11657127645SHarald Freudenberger
117d34b1acbSHarald Freudenberger /*
118d34b1acbSHarald Freudenberger * generate_entropy:
11923d1aee9SHarald Freudenberger * This function fills a given buffer with random bytes. The entropy within
12023d1aee9SHarald Freudenberger * the random bytes given back is assumed to have at least 50% - meaning
12123d1aee9SHarald Freudenberger * a 64 bytes buffer has at least 64 * 8 / 2 = 256 bits of entropy.
12223d1aee9SHarald Freudenberger * Within the function the entropy generation is done in junks of 64 bytes.
12323d1aee9SHarald Freudenberger * So the caller should also ask for buffer fill in multiples of 64 bytes.
12423d1aee9SHarald Freudenberger * The generation of the entropy is based on the assumption that every stckf()
12523d1aee9SHarald Freudenberger * invocation produces 0.5 bits of entropy. To accumulate 256 bits of entropy
12623d1aee9SHarald Freudenberger * at least 512 stckf() values are needed. The entropy relevant part of the
12723d1aee9SHarald Freudenberger * stckf value is bit 51 (counting starts at the left with bit nr 0) so
12823d1aee9SHarald Freudenberger * here we use the lower 4 bytes and exor the values into 2k of bufferspace.
12923d1aee9SHarald Freudenberger * To be on the save side, if there is ever a problem with stckf() the
13023d1aee9SHarald Freudenberger * other half of the page buffer is filled with bytes from urandom via
13123d1aee9SHarald Freudenberger * get_random_bytes(), so this function consumes 2k of urandom for each
13223d1aee9SHarald Freudenberger * requested 64 bytes output data. Finally the buffer page is condensed into
13323d1aee9SHarald Freudenberger * a 64 byte value by hashing with a SHA512 hash.
134d34b1acbSHarald Freudenberger */
generate_entropy(u8 * ebuf,size_t nbytes)13557127645SHarald Freudenberger static int generate_entropy(u8 *ebuf, size_t nbytes)
1361b278294SJan Glauber {
13757127645SHarald Freudenberger int n, ret = 0;
13823d1aee9SHarald Freudenberger u8 *pg, pblock[80] = {
13923d1aee9SHarald Freudenberger /* 8 x 64 bit init values */
14023d1aee9SHarald Freudenberger 0x6A, 0x09, 0xE6, 0x67, 0xF3, 0xBC, 0xC9, 0x08,
14123d1aee9SHarald Freudenberger 0xBB, 0x67, 0xAE, 0x85, 0x84, 0xCA, 0xA7, 0x3B,
14223d1aee9SHarald Freudenberger 0x3C, 0x6E, 0xF3, 0x72, 0xFE, 0x94, 0xF8, 0x2B,
14323d1aee9SHarald Freudenberger 0xA5, 0x4F, 0xF5, 0x3A, 0x5F, 0x1D, 0x36, 0xF1,
14423d1aee9SHarald Freudenberger 0x51, 0x0E, 0x52, 0x7F, 0xAD, 0xE6, 0x82, 0xD1,
14523d1aee9SHarald Freudenberger 0x9B, 0x05, 0x68, 0x8C, 0x2B, 0x3E, 0x6C, 0x1F,
14623d1aee9SHarald Freudenberger 0x1F, 0x83, 0xD9, 0xAB, 0xFB, 0x41, 0xBD, 0x6B,
14723d1aee9SHarald Freudenberger 0x5B, 0xE0, 0xCD, 0x19, 0x13, 0x7E, 0x21, 0x79,
14823d1aee9SHarald Freudenberger /* 128 bit counter total message bit length */
14923d1aee9SHarald Freudenberger 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
15023d1aee9SHarald Freudenberger 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00 };
15157127645SHarald Freudenberger
15223d1aee9SHarald Freudenberger /* allocate one page stckf buffer */
15323d1aee9SHarald Freudenberger pg = (u8 *) __get_free_page(GFP_KERNEL);
15457127645SHarald Freudenberger if (!pg) {
15557127645SHarald Freudenberger prng_errorflag = PRNG_GEN_ENTROPY_FAILED;
15657127645SHarald Freudenberger return -ENOMEM;
1571b278294SJan Glauber }
1581b278294SJan Glauber
15923d1aee9SHarald Freudenberger /* fill the ebuf in chunks of 64 byte each */
16057127645SHarald Freudenberger while (nbytes) {
16123d1aee9SHarald Freudenberger /* fill lower 2k with urandom bytes */
16223d1aee9SHarald Freudenberger get_random_bytes(pg, PAGE_SIZE / 2);
16323d1aee9SHarald Freudenberger /* exor upper 2k with 512 stckf values, offset 4 bytes each */
16423d1aee9SHarald Freudenberger for (n = 0; n < 512; n++) {
16523d1aee9SHarald Freudenberger int offset = (PAGE_SIZE / 2) + (n * 4) - 4;
16623d1aee9SHarald Freudenberger u64 *p = (u64 *)(pg + offset);
16757127645SHarald Freudenberger *p ^= get_tod_clock_fast();
16857127645SHarald Freudenberger }
16923d1aee9SHarald Freudenberger /* hash over the filled page */
17023d1aee9SHarald Freudenberger cpacf_klmd(CPACF_KLMD_SHA_512, pblock, pg, PAGE_SIZE);
17123d1aee9SHarald Freudenberger n = (nbytes < 64) ? nbytes : 64;
17223d1aee9SHarald Freudenberger memcpy(ebuf, pblock, n);
17357127645SHarald Freudenberger ret += n;
17457127645SHarald Freudenberger ebuf += n;
17557127645SHarald Freudenberger nbytes -= n;
17657127645SHarald Freudenberger }
17757127645SHarald Freudenberger
17823d1aee9SHarald Freudenberger memzero_explicit(pblock, sizeof(pblock));
17923d1aee9SHarald Freudenberger memzero_explicit(pg, PAGE_SIZE);
18023d1aee9SHarald Freudenberger free_page((unsigned long)pg);
18157127645SHarald Freudenberger return ret;
18257127645SHarald Freudenberger }
18357127645SHarald Freudenberger
18457127645SHarald Freudenberger
18557127645SHarald Freudenberger /*** tdes functions ***/
18657127645SHarald Freudenberger
prng_tdes_add_entropy(void)18757127645SHarald Freudenberger static void prng_tdes_add_entropy(void)
1881b278294SJan Glauber {
1891b278294SJan Glauber __u64 entropy[4];
1901b278294SJan Glauber unsigned int i;
1911b278294SJan Glauber
1921b278294SJan Glauber for (i = 0; i < 16; i++) {
1930177db01SMartin Schwidefsky cpacf_kmc(CPACF_KMC_PRNG, prng_data->prngws.parm_block,
19457127645SHarald Freudenberger (char *) entropy, (char *) entropy,
19557127645SHarald Freudenberger sizeof(entropy));
19657127645SHarald Freudenberger memcpy(prng_data->prngws.parm_block, entropy, sizeof(entropy));
1971b278294SJan Glauber }
1981b278294SJan Glauber }
1991b278294SJan Glauber
20057127645SHarald Freudenberger
prng_tdes_seed(int nbytes)20157127645SHarald Freudenberger static void prng_tdes_seed(int nbytes)
2021b278294SJan Glauber {
2031b278294SJan Glauber char buf[16];
2041b278294SJan Glauber int i = 0;
2051b278294SJan Glauber
20657127645SHarald Freudenberger BUG_ON(nbytes > sizeof(buf));
20757127645SHarald Freudenberger
2081b278294SJan Glauber get_random_bytes(buf, nbytes);
2091b278294SJan Glauber
2101b278294SJan Glauber /* Add the entropy */
2111b278294SJan Glauber while (nbytes >= 8) {
21257127645SHarald Freudenberger *((__u64 *)prng_data->prngws.parm_block) ^= *((__u64 *)(buf+i));
21357127645SHarald Freudenberger prng_tdes_add_entropy();
2141b278294SJan Glauber i += 8;
2151b278294SJan Glauber nbytes -= 8;
2161b278294SJan Glauber }
21757127645SHarald Freudenberger prng_tdes_add_entropy();
21857127645SHarald Freudenberger prng_data->prngws.reseed_counter = 0;
2191b278294SJan Glauber }
2201b278294SJan Glauber
2211b278294SJan Glauber
prng_tdes_instantiate(void)22257127645SHarald Freudenberger static int __init prng_tdes_instantiate(void)
22357127645SHarald Freudenberger {
22457127645SHarald Freudenberger int datalen;
22557127645SHarald Freudenberger
22657127645SHarald Freudenberger pr_debug("prng runs in TDES mode with "
22757127645SHarald Freudenberger "chunksize=%d and reseed_limit=%u\n",
22857127645SHarald Freudenberger prng_chunk_size, prng_reseed_limit);
22957127645SHarald Freudenberger
23057127645SHarald Freudenberger /* memory allocation, prng_data struct init, mutex init */
23157127645SHarald Freudenberger datalen = sizeof(struct prng_data_s) + prng_chunk_size;
23257127645SHarald Freudenberger prng_data = kzalloc(datalen, GFP_KERNEL);
23357127645SHarald Freudenberger if (!prng_data) {
23457127645SHarald Freudenberger prng_errorflag = PRNG_INSTANTIATE_FAILED;
23557127645SHarald Freudenberger return -ENOMEM;
23657127645SHarald Freudenberger }
23757127645SHarald Freudenberger mutex_init(&prng_data->mutex);
23857127645SHarald Freudenberger prng_data->buf = ((u8 *)prng_data) + sizeof(struct prng_data_s);
23957127645SHarald Freudenberger memcpy(prng_data->prngws.parm_block, initial_parm_block, 32);
24057127645SHarald Freudenberger
24157127645SHarald Freudenberger /* initialize the PRNG, add 128 bits of entropy */
24257127645SHarald Freudenberger prng_tdes_seed(16);
24357127645SHarald Freudenberger
24457127645SHarald Freudenberger return 0;
24557127645SHarald Freudenberger }
24657127645SHarald Freudenberger
24757127645SHarald Freudenberger
prng_tdes_deinstantiate(void)24857127645SHarald Freudenberger static void prng_tdes_deinstantiate(void)
24957127645SHarald Freudenberger {
25057127645SHarald Freudenberger pr_debug("The prng module stopped "
25157127645SHarald Freudenberger "after running in triple DES mode\n");
252453431a5SWaiman Long kfree_sensitive(prng_data);
25357127645SHarald Freudenberger }
25457127645SHarald Freudenberger
25557127645SHarald Freudenberger
25657127645SHarald Freudenberger /*** sha512 functions ***/
25757127645SHarald Freudenberger
prng_sha512_selftest(void)25857127645SHarald Freudenberger static int __init prng_sha512_selftest(void)
25957127645SHarald Freudenberger {
26057127645SHarald Freudenberger /* NIST DRBG testvector for Hash Drbg, Sha-512, Count #0 */
26157127645SHarald Freudenberger static const u8 seed[] __initconst = {
26257127645SHarald Freudenberger 0x6b, 0x50, 0xa7, 0xd8, 0xf8, 0xa5, 0x5d, 0x7a,
26357127645SHarald Freudenberger 0x3d, 0xf8, 0xbb, 0x40, 0xbc, 0xc3, 0xb7, 0x22,
26457127645SHarald Freudenberger 0xd8, 0x70, 0x8d, 0xe6, 0x7f, 0xda, 0x01, 0x0b,
26557127645SHarald Freudenberger 0x03, 0xc4, 0xc8, 0x4d, 0x72, 0x09, 0x6f, 0x8c,
26657127645SHarald Freudenberger 0x3e, 0xc6, 0x49, 0xcc, 0x62, 0x56, 0xd9, 0xfa,
26757127645SHarald Freudenberger 0x31, 0xdb, 0x7a, 0x29, 0x04, 0xaa, 0xf0, 0x25 };
26857127645SHarald Freudenberger static const u8 V0[] __initconst = {
26957127645SHarald Freudenberger 0x00, 0xad, 0xe3, 0x6f, 0x9a, 0x01, 0xc7, 0x76,
27057127645SHarald Freudenberger 0x61, 0x34, 0x35, 0xf5, 0x4e, 0x24, 0x74, 0x22,
27157127645SHarald Freudenberger 0x21, 0x9a, 0x29, 0x89, 0xc7, 0x93, 0x2e, 0x60,
27257127645SHarald Freudenberger 0x1e, 0xe8, 0x14, 0x24, 0x8d, 0xd5, 0x03, 0xf1,
27357127645SHarald Freudenberger 0x65, 0x5d, 0x08, 0x22, 0x72, 0xd5, 0xad, 0x95,
27457127645SHarald Freudenberger 0xe1, 0x23, 0x1e, 0x8a, 0xa7, 0x13, 0xd9, 0x2b,
27557127645SHarald Freudenberger 0x5e, 0xbc, 0xbb, 0x80, 0xab, 0x8d, 0xe5, 0x79,
27657127645SHarald Freudenberger 0xab, 0x5b, 0x47, 0x4e, 0xdd, 0xee, 0x6b, 0x03,
27757127645SHarald Freudenberger 0x8f, 0x0f, 0x5c, 0x5e, 0xa9, 0x1a, 0x83, 0xdd,
27857127645SHarald Freudenberger 0xd3, 0x88, 0xb2, 0x75, 0x4b, 0xce, 0x83, 0x36,
27957127645SHarald Freudenberger 0x57, 0x4b, 0xf1, 0x5c, 0xca, 0x7e, 0x09, 0xc0,
28057127645SHarald Freudenberger 0xd3, 0x89, 0xc6, 0xe0, 0xda, 0xc4, 0x81, 0x7e,
28157127645SHarald Freudenberger 0x5b, 0xf9, 0xe1, 0x01, 0xc1, 0x92, 0x05, 0xea,
28257127645SHarald Freudenberger 0xf5, 0x2f, 0xc6, 0xc6, 0xc7, 0x8f, 0xbc, 0xf4 };
28357127645SHarald Freudenberger static const u8 C0[] __initconst = {
28457127645SHarald Freudenberger 0x00, 0xf4, 0xa3, 0xe5, 0xa0, 0x72, 0x63, 0x95,
28557127645SHarald Freudenberger 0xc6, 0x4f, 0x48, 0xd0, 0x8b, 0x5b, 0x5f, 0x8e,
28657127645SHarald Freudenberger 0x6b, 0x96, 0x1f, 0x16, 0xed, 0xbc, 0x66, 0x94,
28757127645SHarald Freudenberger 0x45, 0x31, 0xd7, 0x47, 0x73, 0x22, 0xa5, 0x86,
28857127645SHarald Freudenberger 0xce, 0xc0, 0x4c, 0xac, 0x63, 0xb8, 0x39, 0x50,
28957127645SHarald Freudenberger 0xbf, 0xe6, 0x59, 0x6c, 0x38, 0x58, 0x99, 0x1f,
29057127645SHarald Freudenberger 0x27, 0xa7, 0x9d, 0x71, 0x2a, 0xb3, 0x7b, 0xf9,
29157127645SHarald Freudenberger 0xfb, 0x17, 0x86, 0xaa, 0x99, 0x81, 0xaa, 0x43,
29257127645SHarald Freudenberger 0xe4, 0x37, 0xd3, 0x1e, 0x6e, 0xe5, 0xe6, 0xee,
29357127645SHarald Freudenberger 0xc2, 0xed, 0x95, 0x4f, 0x53, 0x0e, 0x46, 0x8a,
29457127645SHarald Freudenberger 0xcc, 0x45, 0xa5, 0xdb, 0x69, 0x0d, 0x81, 0xc9,
29557127645SHarald Freudenberger 0x32, 0x92, 0xbc, 0x8f, 0x33, 0xe6, 0xf6, 0x09,
29657127645SHarald Freudenberger 0x7c, 0x8e, 0x05, 0x19, 0x0d, 0xf1, 0xb6, 0xcc,
29757127645SHarald Freudenberger 0xf3, 0x02, 0x21, 0x90, 0x25, 0xec, 0xed, 0x0e };
29857127645SHarald Freudenberger static const u8 random[] __initconst = {
29957127645SHarald Freudenberger 0x95, 0xb7, 0xf1, 0x7e, 0x98, 0x02, 0xd3, 0x57,
30057127645SHarald Freudenberger 0x73, 0x92, 0xc6, 0xa9, 0xc0, 0x80, 0x83, 0xb6,
30157127645SHarald Freudenberger 0x7d, 0xd1, 0x29, 0x22, 0x65, 0xb5, 0xf4, 0x2d,
30257127645SHarald Freudenberger 0x23, 0x7f, 0x1c, 0x55, 0xbb, 0x9b, 0x10, 0xbf,
30357127645SHarald Freudenberger 0xcf, 0xd8, 0x2c, 0x77, 0xa3, 0x78, 0xb8, 0x26,
30457127645SHarald Freudenberger 0x6a, 0x00, 0x99, 0x14, 0x3b, 0x3c, 0x2d, 0x64,
30557127645SHarald Freudenberger 0x61, 0x1e, 0xee, 0xb6, 0x9a, 0xcd, 0xc0, 0x55,
30657127645SHarald Freudenberger 0x95, 0x7c, 0x13, 0x9e, 0x8b, 0x19, 0x0c, 0x7a,
30757127645SHarald Freudenberger 0x06, 0x95, 0x5f, 0x2c, 0x79, 0x7c, 0x27, 0x78,
30857127645SHarald Freudenberger 0xde, 0x94, 0x03, 0x96, 0xa5, 0x01, 0xf4, 0x0e,
30957127645SHarald Freudenberger 0x91, 0x39, 0x6a, 0xcf, 0x8d, 0x7e, 0x45, 0xeb,
31057127645SHarald Freudenberger 0xdb, 0xb5, 0x3b, 0xbf, 0x8c, 0x97, 0x52, 0x30,
31157127645SHarald Freudenberger 0xd2, 0xf0, 0xff, 0x91, 0x06, 0xc7, 0x61, 0x19,
31257127645SHarald Freudenberger 0xae, 0x49, 0x8e, 0x7f, 0xbc, 0x03, 0xd9, 0x0f,
31357127645SHarald Freudenberger 0x8e, 0x4c, 0x51, 0x62, 0x7a, 0xed, 0x5c, 0x8d,
31457127645SHarald Freudenberger 0x42, 0x63, 0xd5, 0xd2, 0xb9, 0x78, 0x87, 0x3a,
31557127645SHarald Freudenberger 0x0d, 0xe5, 0x96, 0xee, 0x6d, 0xc7, 0xf7, 0xc2,
31657127645SHarald Freudenberger 0x9e, 0x37, 0xee, 0xe8, 0xb3, 0x4c, 0x90, 0xdd,
31757127645SHarald Freudenberger 0x1c, 0xf6, 0xa9, 0xdd, 0xb2, 0x2b, 0x4c, 0xbd,
31857127645SHarald Freudenberger 0x08, 0x6b, 0x14, 0xb3, 0x5d, 0xe9, 0x3d, 0xa2,
31957127645SHarald Freudenberger 0xd5, 0xcb, 0x18, 0x06, 0x69, 0x8c, 0xbd, 0x7b,
32057127645SHarald Freudenberger 0xbb, 0x67, 0xbf, 0xe3, 0xd3, 0x1f, 0xd2, 0xd1,
32157127645SHarald Freudenberger 0xdb, 0xd2, 0xa1, 0xe0, 0x58, 0xa3, 0xeb, 0x99,
32257127645SHarald Freudenberger 0xd7, 0xe5, 0x1f, 0x1a, 0x93, 0x8e, 0xed, 0x5e,
32357127645SHarald Freudenberger 0x1c, 0x1d, 0xe2, 0x3a, 0x6b, 0x43, 0x45, 0xd3,
32457127645SHarald Freudenberger 0x19, 0x14, 0x09, 0xf9, 0x2f, 0x39, 0xb3, 0x67,
32557127645SHarald Freudenberger 0x0d, 0x8d, 0xbf, 0xb6, 0x35, 0xd8, 0xe6, 0xa3,
32657127645SHarald Freudenberger 0x69, 0x32, 0xd8, 0x10, 0x33, 0xd1, 0x44, 0x8d,
32757127645SHarald Freudenberger 0x63, 0xb4, 0x03, 0xdd, 0xf8, 0x8e, 0x12, 0x1b,
32857127645SHarald Freudenberger 0x6e, 0x81, 0x9a, 0xc3, 0x81, 0x22, 0x6c, 0x13,
32957127645SHarald Freudenberger 0x21, 0xe4, 0xb0, 0x86, 0x44, 0xf6, 0x72, 0x7c,
33057127645SHarald Freudenberger 0x36, 0x8c, 0x5a, 0x9f, 0x7a, 0x4b, 0x3e, 0xe2 };
33157127645SHarald Freudenberger
33257127645SHarald Freudenberger u8 buf[sizeof(random)];
333985a9d20SHarald Freudenberger struct prno_ws_s ws;
33457127645SHarald Freudenberger
33557127645SHarald Freudenberger memset(&ws, 0, sizeof(ws));
33657127645SHarald Freudenberger
33757127645SHarald Freudenberger /* initial seed */
338985a9d20SHarald Freudenberger cpacf_prno(CPACF_PRNO_SHA512_DRNG_SEED,
3390177db01SMartin Schwidefsky &ws, NULL, 0, seed, sizeof(seed));
34057127645SHarald Freudenberger
34157127645SHarald Freudenberger /* check working states V and C */
34257127645SHarald Freudenberger if (memcmp(ws.V, V0, sizeof(V0)) != 0
34357127645SHarald Freudenberger || memcmp(ws.C, C0, sizeof(C0)) != 0) {
34457127645SHarald Freudenberger pr_err("The prng self test state test "
34557127645SHarald Freudenberger "for the SHA-512 mode failed\n");
34657127645SHarald Freudenberger prng_errorflag = PRNG_SELFTEST_FAILED;
34757127645SHarald Freudenberger return -EIO;
34857127645SHarald Freudenberger }
34957127645SHarald Freudenberger
35057127645SHarald Freudenberger /* generate random bytes */
351985a9d20SHarald Freudenberger cpacf_prno(CPACF_PRNO_SHA512_DRNG_GEN,
352c7d4d259SMartin Schwidefsky &ws, buf, sizeof(buf), NULL, 0);
353985a9d20SHarald Freudenberger cpacf_prno(CPACF_PRNO_SHA512_DRNG_GEN,
354c7d4d259SMartin Schwidefsky &ws, buf, sizeof(buf), NULL, 0);
35557127645SHarald Freudenberger
35657127645SHarald Freudenberger /* check against expected data */
35757127645SHarald Freudenberger if (memcmp(buf, random, sizeof(random)) != 0) {
35857127645SHarald Freudenberger pr_err("The prng self test data test "
35957127645SHarald Freudenberger "for the SHA-512 mode failed\n");
36057127645SHarald Freudenberger prng_errorflag = PRNG_SELFTEST_FAILED;
36157127645SHarald Freudenberger return -EIO;
36257127645SHarald Freudenberger }
36357127645SHarald Freudenberger
36457127645SHarald Freudenberger return 0;
36557127645SHarald Freudenberger }
36657127645SHarald Freudenberger
36757127645SHarald Freudenberger
prng_sha512_instantiate(void)36857127645SHarald Freudenberger static int __init prng_sha512_instantiate(void)
36957127645SHarald Freudenberger {
370769f020bSHarald Freudenberger int ret, datalen, seedlen;
37123d1aee9SHarald Freudenberger u8 seed[128 + 16];
37257127645SHarald Freudenberger
37357127645SHarald Freudenberger pr_debug("prng runs in SHA-512 mode "
37457127645SHarald Freudenberger "with chunksize=%d and reseed_limit=%u\n",
37557127645SHarald Freudenberger prng_chunk_size, prng_reseed_limit);
37657127645SHarald Freudenberger
37757127645SHarald Freudenberger /* memory allocation, prng_data struct init, mutex init */
37857127645SHarald Freudenberger datalen = sizeof(struct prng_data_s) + prng_chunk_size;
37957127645SHarald Freudenberger if (fips_enabled)
38057127645SHarald Freudenberger datalen += prng_chunk_size;
38157127645SHarald Freudenberger prng_data = kzalloc(datalen, GFP_KERNEL);
38257127645SHarald Freudenberger if (!prng_data) {
38357127645SHarald Freudenberger prng_errorflag = PRNG_INSTANTIATE_FAILED;
38457127645SHarald Freudenberger return -ENOMEM;
38557127645SHarald Freudenberger }
38657127645SHarald Freudenberger mutex_init(&prng_data->mutex);
38757127645SHarald Freudenberger prng_data->buf = ((u8 *)prng_data) + sizeof(struct prng_data_s);
38857127645SHarald Freudenberger
38957127645SHarald Freudenberger /* selftest */
39057127645SHarald Freudenberger ret = prng_sha512_selftest();
39157127645SHarald Freudenberger if (ret)
39257127645SHarald Freudenberger goto outfree;
39357127645SHarald Freudenberger
394769f020bSHarald Freudenberger /* generate initial seed, we need at least 256 + 128 bits entropy. */
395769f020bSHarald Freudenberger if (trng_available) {
39623d1aee9SHarald Freudenberger /*
397769f020bSHarald Freudenberger * Trng available, so use it. The trng works in chunks of
398769f020bSHarald Freudenberger * 32 bytes and produces 100% entropy. So we pull 64 bytes
399769f020bSHarald Freudenberger * which gives us 512 bits entropy.
40023d1aee9SHarald Freudenberger */
401769f020bSHarald Freudenberger seedlen = 2 * 32;
402769f020bSHarald Freudenberger cpacf_trng(NULL, 0, seed, seedlen);
403769f020bSHarald Freudenberger } else {
404769f020bSHarald Freudenberger /*
405769f020bSHarald Freudenberger * No trng available, so use the generate_entropy() function.
406769f020bSHarald Freudenberger * This function works in 64 byte junks and produces
407769f020bSHarald Freudenberger * 50% entropy. So we pull 2*64 bytes which gives us 512 bits
408769f020bSHarald Freudenberger * of entropy.
409769f020bSHarald Freudenberger */
410769f020bSHarald Freudenberger seedlen = 2 * 64;
411769f020bSHarald Freudenberger ret = generate_entropy(seed, seedlen);
412769f020bSHarald Freudenberger if (ret != seedlen)
41357127645SHarald Freudenberger goto outfree;
414769f020bSHarald Freudenberger }
41557127645SHarald Freudenberger
416769f020bSHarald Freudenberger /* append the seed by 16 bytes of unique nonce */
417fc4a925fSHeiko Carstens store_tod_clock_ext((union tod_clock *)(seed + seedlen));
418769f020bSHarald Freudenberger seedlen += 16;
419769f020bSHarald Freudenberger
420769f020bSHarald Freudenberger /* now initial seed of the prno drng */
421985a9d20SHarald Freudenberger cpacf_prno(CPACF_PRNO_SHA512_DRNG_SEED,
422769f020bSHarald Freudenberger &prng_data->prnows, NULL, 0, seed, seedlen);
42323d1aee9SHarald Freudenberger memzero_explicit(seed, sizeof(seed));
42457127645SHarald Freudenberger
42557127645SHarald Freudenberger /* if fips mode is enabled, generate a first block of random
42657127645SHarald Freudenberger bytes for the FIPS 140-2 Conditional Self Test */
42757127645SHarald Freudenberger if (fips_enabled) {
42857127645SHarald Freudenberger prng_data->prev = prng_data->buf + prng_chunk_size;
429985a9d20SHarald Freudenberger cpacf_prno(CPACF_PRNO_SHA512_DRNG_GEN,
430985a9d20SHarald Freudenberger &prng_data->prnows,
431c7d4d259SMartin Schwidefsky prng_data->prev, prng_chunk_size, NULL, 0);
43257127645SHarald Freudenberger }
43357127645SHarald Freudenberger
43457127645SHarald Freudenberger return 0;
43557127645SHarald Freudenberger
43657127645SHarald Freudenberger outfree:
43757127645SHarald Freudenberger kfree(prng_data);
43857127645SHarald Freudenberger return ret;
43957127645SHarald Freudenberger }
44057127645SHarald Freudenberger
44157127645SHarald Freudenberger
prng_sha512_deinstantiate(void)44257127645SHarald Freudenberger static void prng_sha512_deinstantiate(void)
44357127645SHarald Freudenberger {
44457127645SHarald Freudenberger pr_debug("The prng module stopped after running in SHA-512 mode\n");
445453431a5SWaiman Long kfree_sensitive(prng_data);
44657127645SHarald Freudenberger }
44757127645SHarald Freudenberger
44857127645SHarald Freudenberger
prng_sha512_reseed(void)44957127645SHarald Freudenberger static int prng_sha512_reseed(void)
45057127645SHarald Freudenberger {
451769f020bSHarald Freudenberger int ret, seedlen;
452d34b1acbSHarald Freudenberger u8 seed[64];
45357127645SHarald Freudenberger
454769f020bSHarald Freudenberger /* We need at least 256 bits of fresh entropy for reseeding */
455769f020bSHarald Freudenberger if (trng_available) {
456769f020bSHarald Freudenberger /* trng produces 256 bits entropy in 32 bytes */
457769f020bSHarald Freudenberger seedlen = 32;
458769f020bSHarald Freudenberger cpacf_trng(NULL, 0, seed, seedlen);
459769f020bSHarald Freudenberger } else {
460769f020bSHarald Freudenberger /* generate_entropy() produces 256 bits entropy in 64 bytes */
461769f020bSHarald Freudenberger seedlen = 64;
462769f020bSHarald Freudenberger ret = generate_entropy(seed, seedlen);
46357127645SHarald Freudenberger if (ret != sizeof(seed))
46457127645SHarald Freudenberger return ret;
465769f020bSHarald Freudenberger }
46657127645SHarald Freudenberger
467985a9d20SHarald Freudenberger /* do a reseed of the prno drng with this bytestring */
468985a9d20SHarald Freudenberger cpacf_prno(CPACF_PRNO_SHA512_DRNG_SEED,
469769f020bSHarald Freudenberger &prng_data->prnows, NULL, 0, seed, seedlen);
47023d1aee9SHarald Freudenberger memzero_explicit(seed, sizeof(seed));
47157127645SHarald Freudenberger
47257127645SHarald Freudenberger return 0;
47357127645SHarald Freudenberger }
47457127645SHarald Freudenberger
47557127645SHarald Freudenberger
prng_sha512_generate(u8 * buf,size_t nbytes)47657127645SHarald Freudenberger static int prng_sha512_generate(u8 *buf, size_t nbytes)
47757127645SHarald Freudenberger {
47857127645SHarald Freudenberger int ret;
47957127645SHarald Freudenberger
48057127645SHarald Freudenberger /* reseed needed ? */
481985a9d20SHarald Freudenberger if (prng_data->prnows.reseed_counter > prng_reseed_limit) {
48257127645SHarald Freudenberger ret = prng_sha512_reseed();
48357127645SHarald Freudenberger if (ret)
48457127645SHarald Freudenberger return ret;
48557127645SHarald Freudenberger }
48657127645SHarald Freudenberger
487985a9d20SHarald Freudenberger /* PRNO generate */
488985a9d20SHarald Freudenberger cpacf_prno(CPACF_PRNO_SHA512_DRNG_GEN,
489985a9d20SHarald Freudenberger &prng_data->prnows, buf, nbytes, NULL, 0);
49057127645SHarald Freudenberger
49157127645SHarald Freudenberger /* FIPS 140-2 Conditional Self Test */
49257127645SHarald Freudenberger if (fips_enabled) {
49357127645SHarald Freudenberger if (!memcmp(prng_data->prev, buf, nbytes)) {
49457127645SHarald Freudenberger prng_errorflag = PRNG_GEN_FAILED;
49557127645SHarald Freudenberger return -EILSEQ;
49657127645SHarald Freudenberger }
49757127645SHarald Freudenberger memcpy(prng_data->prev, buf, nbytes);
49857127645SHarald Freudenberger }
49957127645SHarald Freudenberger
5006512391aSColin Ian King return nbytes;
50157127645SHarald Freudenberger }
50257127645SHarald Freudenberger
50357127645SHarald Freudenberger
50457127645SHarald Freudenberger /*** file io functions ***/
50557127645SHarald Freudenberger
prng_open(struct inode * inode,struct file * file)50657127645SHarald Freudenberger static int prng_open(struct inode *inode, struct file *file)
50757127645SHarald Freudenberger {
50857127645SHarald Freudenberger return nonseekable_open(inode, file);
50957127645SHarald Freudenberger }
51057127645SHarald Freudenberger
51157127645SHarald Freudenberger
prng_tdes_read(struct file * file,char __user * ubuf,size_t nbytes,loff_t * ppos)51257127645SHarald Freudenberger static ssize_t prng_tdes_read(struct file *file, char __user *ubuf,
51357127645SHarald Freudenberger size_t nbytes, loff_t *ppos)
51457127645SHarald Freudenberger {
5150177db01SMartin Schwidefsky int chunk, n, ret = 0;
51657127645SHarald Freudenberger
51757127645SHarald Freudenberger /* lock prng_data struct */
51857127645SHarald Freudenberger if (mutex_lock_interruptible(&prng_data->mutex))
51957127645SHarald Freudenberger return -ERESTARTSYS;
52057127645SHarald Freudenberger
5211b278294SJan Glauber while (nbytes) {
5221b278294SJan Glauber if (need_resched()) {
5231b278294SJan Glauber if (signal_pending(current)) {
5241b278294SJan Glauber if (ret == 0)
5251b278294SJan Glauber ret = -ERESTARTSYS;
5261b278294SJan Glauber break;
5271b278294SJan Glauber }
52857127645SHarald Freudenberger /* give mutex free before calling schedule() */
52957127645SHarald Freudenberger mutex_unlock(&prng_data->mutex);
5301b278294SJan Glauber schedule();
5314b03b3eeSJulia Lawall /* occupy mutex again */
53257127645SHarald Freudenberger if (mutex_lock_interruptible(&prng_data->mutex)) {
53357127645SHarald Freudenberger if (ret == 0)
53457127645SHarald Freudenberger ret = -ERESTARTSYS;
53557127645SHarald Freudenberger return ret;
53657127645SHarald Freudenberger }
5371b278294SJan Glauber }
5381b278294SJan Glauber
5391b278294SJan Glauber /*
5401b278294SJan Glauber * we lose some random bytes if an attacker issues
5411b278294SJan Glauber * reads < 8 bytes, but we don't care
5421b278294SJan Glauber */
5431b278294SJan Glauber chunk = min_t(int, nbytes, prng_chunk_size);
5441b278294SJan Glauber
5451b278294SJan Glauber /* PRNG only likes multiples of 8 bytes */
5461b278294SJan Glauber n = (chunk + 7) & -8;
5471b278294SJan Glauber
54857127645SHarald Freudenberger if (prng_data->prngws.reseed_counter > prng_reseed_limit)
54957127645SHarald Freudenberger prng_tdes_seed(8);
5501b278294SJan Glauber
5511b278294SJan Glauber /* if the CPU supports PRNG stckf is present too */
55257127645SHarald Freudenberger *((unsigned long long *)prng_data->buf) = get_tod_clock_fast();
5531b278294SJan Glauber
5541b278294SJan Glauber /*
5551b278294SJan Glauber * Beside the STCKF the input for the TDES-EDE is the output
5561b278294SJan Glauber * of the last operation. We differ here from X9.17 since we
5571b278294SJan Glauber * only store one timestamp into the buffer. Padding the whole
5581b278294SJan Glauber * buffer with timestamps does not improve security, since
5591b278294SJan Glauber * successive stckf have nearly constant offsets.
5601b278294SJan Glauber * If an attacker knows the first timestamp it would be
5611b278294SJan Glauber * trivial to guess the additional values. One timestamp
5621b278294SJan Glauber * is therefore enough and still guarantees unique input values.
5631b278294SJan Glauber *
5641b278294SJan Glauber * Note: you can still get strict X9.17 conformity by setting
5651b278294SJan Glauber * prng_chunk_size to 8 bytes.
5661b278294SJan Glauber */
5670177db01SMartin Schwidefsky cpacf_kmc(CPACF_KMC_PRNG, prng_data->prngws.parm_block,
56857127645SHarald Freudenberger prng_data->buf, prng_data->buf, n);
5691b278294SJan Glauber
57057127645SHarald Freudenberger prng_data->prngws.byte_counter += n;
57157127645SHarald Freudenberger prng_data->prngws.reseed_counter += n;
5721b278294SJan Glauber
5739e6e7c74SDan Carpenter if (copy_to_user(ubuf, prng_data->buf, chunk)) {
5749e6e7c74SDan Carpenter ret = -EFAULT;
5759e6e7c74SDan Carpenter break;
5769e6e7c74SDan Carpenter }
5771b278294SJan Glauber
5781b278294SJan Glauber nbytes -= chunk;
5791b278294SJan Glauber ret += chunk;
5801b278294SJan Glauber ubuf += chunk;
5811b278294SJan Glauber }
58257127645SHarald Freudenberger
58357127645SHarald Freudenberger /* unlock prng_data struct */
58457127645SHarald Freudenberger mutex_unlock(&prng_data->mutex);
58557127645SHarald Freudenberger
5861b278294SJan Glauber return ret;
5871b278294SJan Glauber }
5881b278294SJan Glauber
58957127645SHarald Freudenberger
prng_sha512_read(struct file * file,char __user * ubuf,size_t nbytes,loff_t * ppos)59057127645SHarald Freudenberger static ssize_t prng_sha512_read(struct file *file, char __user *ubuf,
59157127645SHarald Freudenberger size_t nbytes, loff_t *ppos)
59257127645SHarald Freudenberger {
59357127645SHarald Freudenberger int n, ret = 0;
59457127645SHarald Freudenberger u8 *p;
59557127645SHarald Freudenberger
59657127645SHarald Freudenberger /* if errorflag is set do nothing and return 'broken pipe' */
59757127645SHarald Freudenberger if (prng_errorflag)
59857127645SHarald Freudenberger return -EPIPE;
59957127645SHarald Freudenberger
60057127645SHarald Freudenberger /* lock prng_data struct */
60157127645SHarald Freudenberger if (mutex_lock_interruptible(&prng_data->mutex))
60257127645SHarald Freudenberger return -ERESTARTSYS;
60357127645SHarald Freudenberger
60457127645SHarald Freudenberger while (nbytes) {
60557127645SHarald Freudenberger if (need_resched()) {
60657127645SHarald Freudenberger if (signal_pending(current)) {
60757127645SHarald Freudenberger if (ret == 0)
60857127645SHarald Freudenberger ret = -ERESTARTSYS;
60957127645SHarald Freudenberger break;
61057127645SHarald Freudenberger }
61157127645SHarald Freudenberger /* give mutex free before calling schedule() */
61257127645SHarald Freudenberger mutex_unlock(&prng_data->mutex);
61357127645SHarald Freudenberger schedule();
61457127645SHarald Freudenberger /* occopy mutex again */
61557127645SHarald Freudenberger if (mutex_lock_interruptible(&prng_data->mutex)) {
61657127645SHarald Freudenberger if (ret == 0)
61757127645SHarald Freudenberger ret = -ERESTARTSYS;
61857127645SHarald Freudenberger return ret;
61957127645SHarald Freudenberger }
62057127645SHarald Freudenberger }
62157127645SHarald Freudenberger if (prng_data->rest) {
62257127645SHarald Freudenberger /* push left over random bytes from the previous read */
62357127645SHarald Freudenberger p = prng_data->buf + prng_chunk_size - prng_data->rest;
62457127645SHarald Freudenberger n = (nbytes < prng_data->rest) ?
62557127645SHarald Freudenberger nbytes : prng_data->rest;
62657127645SHarald Freudenberger prng_data->rest -= n;
62757127645SHarald Freudenberger } else {
62857127645SHarald Freudenberger /* generate one chunk of random bytes into read buf */
62957127645SHarald Freudenberger p = prng_data->buf;
63057127645SHarald Freudenberger n = prng_sha512_generate(p, prng_chunk_size);
63157127645SHarald Freudenberger if (n < 0) {
63257127645SHarald Freudenberger ret = n;
63357127645SHarald Freudenberger break;
63457127645SHarald Freudenberger }
63557127645SHarald Freudenberger if (nbytes < prng_chunk_size) {
63657127645SHarald Freudenberger n = nbytes;
63757127645SHarald Freudenberger prng_data->rest = prng_chunk_size - n;
63857127645SHarald Freudenberger } else {
63957127645SHarald Freudenberger n = prng_chunk_size;
64057127645SHarald Freudenberger prng_data->rest = 0;
64157127645SHarald Freudenberger }
64257127645SHarald Freudenberger }
64357127645SHarald Freudenberger if (copy_to_user(ubuf, p, n)) {
64457127645SHarald Freudenberger ret = -EFAULT;
64557127645SHarald Freudenberger break;
64657127645SHarald Freudenberger }
64723d1aee9SHarald Freudenberger memzero_explicit(p, n);
64857127645SHarald Freudenberger ubuf += n;
64957127645SHarald Freudenberger nbytes -= n;
65057127645SHarald Freudenberger ret += n;
65157127645SHarald Freudenberger }
65257127645SHarald Freudenberger
65357127645SHarald Freudenberger /* unlock prng_data struct */
65457127645SHarald Freudenberger mutex_unlock(&prng_data->mutex);
65557127645SHarald Freudenberger
65657127645SHarald Freudenberger return ret;
65757127645SHarald Freudenberger }
65857127645SHarald Freudenberger
65957127645SHarald Freudenberger
66057127645SHarald Freudenberger /*** sysfs stuff ***/
66157127645SHarald Freudenberger
66257127645SHarald Freudenberger static const struct file_operations prng_sha512_fops = {
6631b278294SJan Glauber .owner = THIS_MODULE,
6641b278294SJan Glauber .open = &prng_open,
6651b278294SJan Glauber .release = NULL,
66657127645SHarald Freudenberger .read = &prng_sha512_read,
66757127645SHarald Freudenberger .llseek = noop_llseek,
66857127645SHarald Freudenberger };
66957127645SHarald Freudenberger static const struct file_operations prng_tdes_fops = {
67057127645SHarald Freudenberger .owner = THIS_MODULE,
67157127645SHarald Freudenberger .open = &prng_open,
67257127645SHarald Freudenberger .release = NULL,
67357127645SHarald Freudenberger .read = &prng_tdes_read,
6746038f373SArnd Bergmann .llseek = noop_llseek,
6751b278294SJan Glauber };
6761b278294SJan Glauber
67757127645SHarald Freudenberger /* chunksize attribute (ro) */
prng_chunksize_show(struct device * dev,struct device_attribute * attr,char * buf)67857127645SHarald Freudenberger static ssize_t prng_chunksize_show(struct device *dev,
67957127645SHarald Freudenberger struct device_attribute *attr,
68057127645SHarald Freudenberger char *buf)
68157127645SHarald Freudenberger {
682df8cea2aSChen Zhou return scnprintf(buf, PAGE_SIZE, "%u\n", prng_chunk_size);
68357127645SHarald Freudenberger }
68457127645SHarald Freudenberger static DEVICE_ATTR(chunksize, 0444, prng_chunksize_show, NULL);
68557127645SHarald Freudenberger
68657127645SHarald Freudenberger /* counter attribute (ro) */
prng_counter_show(struct device * dev,struct device_attribute * attr,char * buf)68757127645SHarald Freudenberger static ssize_t prng_counter_show(struct device *dev,
68857127645SHarald Freudenberger struct device_attribute *attr,
68957127645SHarald Freudenberger char *buf)
69057127645SHarald Freudenberger {
69157127645SHarald Freudenberger u64 counter;
69257127645SHarald Freudenberger
69357127645SHarald Freudenberger if (mutex_lock_interruptible(&prng_data->mutex))
69457127645SHarald Freudenberger return -ERESTARTSYS;
69557127645SHarald Freudenberger if (prng_mode == PRNG_MODE_SHA512)
696985a9d20SHarald Freudenberger counter = prng_data->prnows.stream_bytes;
69757127645SHarald Freudenberger else
69857127645SHarald Freudenberger counter = prng_data->prngws.byte_counter;
69957127645SHarald Freudenberger mutex_unlock(&prng_data->mutex);
70057127645SHarald Freudenberger
701df8cea2aSChen Zhou return scnprintf(buf, PAGE_SIZE, "%llu\n", counter);
70257127645SHarald Freudenberger }
70357127645SHarald Freudenberger static DEVICE_ATTR(byte_counter, 0444, prng_counter_show, NULL);
70457127645SHarald Freudenberger
70557127645SHarald Freudenberger /* errorflag attribute (ro) */
prng_errorflag_show(struct device * dev,struct device_attribute * attr,char * buf)70657127645SHarald Freudenberger static ssize_t prng_errorflag_show(struct device *dev,
70757127645SHarald Freudenberger struct device_attribute *attr,
70857127645SHarald Freudenberger char *buf)
70957127645SHarald Freudenberger {
710df8cea2aSChen Zhou return scnprintf(buf, PAGE_SIZE, "%d\n", prng_errorflag);
71157127645SHarald Freudenberger }
71257127645SHarald Freudenberger static DEVICE_ATTR(errorflag, 0444, prng_errorflag_show, NULL);
71357127645SHarald Freudenberger
71457127645SHarald Freudenberger /* mode attribute (ro) */
prng_mode_show(struct device * dev,struct device_attribute * attr,char * buf)71557127645SHarald Freudenberger static ssize_t prng_mode_show(struct device *dev,
71657127645SHarald Freudenberger struct device_attribute *attr,
71757127645SHarald Freudenberger char *buf)
71857127645SHarald Freudenberger {
71957127645SHarald Freudenberger if (prng_mode == PRNG_MODE_TDES)
720df8cea2aSChen Zhou return scnprintf(buf, PAGE_SIZE, "TDES\n");
72157127645SHarald Freudenberger else
722df8cea2aSChen Zhou return scnprintf(buf, PAGE_SIZE, "SHA512\n");
72357127645SHarald Freudenberger }
72457127645SHarald Freudenberger static DEVICE_ATTR(mode, 0444, prng_mode_show, NULL);
72557127645SHarald Freudenberger
72657127645SHarald Freudenberger /* reseed attribute (w) */
prng_reseed_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)72757127645SHarald Freudenberger static ssize_t prng_reseed_store(struct device *dev,
72857127645SHarald Freudenberger struct device_attribute *attr,
72957127645SHarald Freudenberger const char *buf, size_t count)
73057127645SHarald Freudenberger {
73157127645SHarald Freudenberger if (mutex_lock_interruptible(&prng_data->mutex))
73257127645SHarald Freudenberger return -ERESTARTSYS;
73357127645SHarald Freudenberger prng_sha512_reseed();
73457127645SHarald Freudenberger mutex_unlock(&prng_data->mutex);
73557127645SHarald Freudenberger
73657127645SHarald Freudenberger return count;
73757127645SHarald Freudenberger }
73857127645SHarald Freudenberger static DEVICE_ATTR(reseed, 0200, NULL, prng_reseed_store);
73957127645SHarald Freudenberger
74057127645SHarald Freudenberger /* reseed limit attribute (rw) */
prng_reseed_limit_show(struct device * dev,struct device_attribute * attr,char * buf)74157127645SHarald Freudenberger static ssize_t prng_reseed_limit_show(struct device *dev,
74257127645SHarald Freudenberger struct device_attribute *attr,
74357127645SHarald Freudenberger char *buf)
74457127645SHarald Freudenberger {
745df8cea2aSChen Zhou return scnprintf(buf, PAGE_SIZE, "%u\n", prng_reseed_limit);
74657127645SHarald Freudenberger }
prng_reseed_limit_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)74757127645SHarald Freudenberger static ssize_t prng_reseed_limit_store(struct device *dev,
74857127645SHarald Freudenberger struct device_attribute *attr,
74957127645SHarald Freudenberger const char *buf, size_t count)
75057127645SHarald Freudenberger {
75157127645SHarald Freudenberger unsigned limit;
75257127645SHarald Freudenberger
75357127645SHarald Freudenberger if (sscanf(buf, "%u\n", &limit) != 1)
75457127645SHarald Freudenberger return -EINVAL;
75557127645SHarald Freudenberger
75657127645SHarald Freudenberger if (prng_mode == PRNG_MODE_SHA512) {
75757127645SHarald Freudenberger if (limit < PRNG_RESEED_LIMIT_SHA512_LOWER)
75857127645SHarald Freudenberger return -EINVAL;
75957127645SHarald Freudenberger } else {
76057127645SHarald Freudenberger if (limit < PRNG_RESEED_LIMIT_TDES_LOWER)
76157127645SHarald Freudenberger return -EINVAL;
76257127645SHarald Freudenberger }
76357127645SHarald Freudenberger
76457127645SHarald Freudenberger prng_reseed_limit = limit;
76557127645SHarald Freudenberger
76657127645SHarald Freudenberger return count;
76757127645SHarald Freudenberger }
76857127645SHarald Freudenberger static DEVICE_ATTR(reseed_limit, 0644,
76957127645SHarald Freudenberger prng_reseed_limit_show, prng_reseed_limit_store);
77057127645SHarald Freudenberger
77157127645SHarald Freudenberger /* strength attribute (ro) */
prng_strength_show(struct device * dev,struct device_attribute * attr,char * buf)77257127645SHarald Freudenberger static ssize_t prng_strength_show(struct device *dev,
77357127645SHarald Freudenberger struct device_attribute *attr,
77457127645SHarald Freudenberger char *buf)
77557127645SHarald Freudenberger {
776df8cea2aSChen Zhou return scnprintf(buf, PAGE_SIZE, "256\n");
77757127645SHarald Freudenberger }
77857127645SHarald Freudenberger static DEVICE_ATTR(strength, 0444, prng_strength_show, NULL);
77957127645SHarald Freudenberger
78057127645SHarald Freudenberger static struct attribute *prng_sha512_dev_attrs[] = {
78157127645SHarald Freudenberger &dev_attr_errorflag.attr,
78257127645SHarald Freudenberger &dev_attr_chunksize.attr,
78357127645SHarald Freudenberger &dev_attr_byte_counter.attr,
78457127645SHarald Freudenberger &dev_attr_mode.attr,
78557127645SHarald Freudenberger &dev_attr_reseed.attr,
78657127645SHarald Freudenberger &dev_attr_reseed_limit.attr,
78757127645SHarald Freudenberger &dev_attr_strength.attr,
78857127645SHarald Freudenberger NULL
78957127645SHarald Freudenberger };
7901e632eaaSJulian Wiedmann ATTRIBUTE_GROUPS(prng_sha512_dev);
7911e632eaaSJulian Wiedmann
79257127645SHarald Freudenberger static struct attribute *prng_tdes_dev_attrs[] = {
79357127645SHarald Freudenberger &dev_attr_chunksize.attr,
79457127645SHarald Freudenberger &dev_attr_byte_counter.attr,
79557127645SHarald Freudenberger &dev_attr_mode.attr,
79657127645SHarald Freudenberger NULL
79757127645SHarald Freudenberger };
7981e632eaaSJulian Wiedmann ATTRIBUTE_GROUPS(prng_tdes_dev);
79957127645SHarald Freudenberger
8001e632eaaSJulian Wiedmann static struct miscdevice prng_sha512_dev = {
8011e632eaaSJulian Wiedmann .name = "prandom",
8021e632eaaSJulian Wiedmann .minor = MISC_DYNAMIC_MINOR,
8031e632eaaSJulian Wiedmann .mode = 0644,
8041e632eaaSJulian Wiedmann .fops = &prng_sha512_fops,
8051e632eaaSJulian Wiedmann .groups = prng_sha512_dev_groups,
80657127645SHarald Freudenberger };
8071e632eaaSJulian Wiedmann
8081e632eaaSJulian Wiedmann static struct miscdevice prng_tdes_dev = {
8091e632eaaSJulian Wiedmann .name = "prandom",
8101e632eaaSJulian Wiedmann .minor = MISC_DYNAMIC_MINOR,
8111e632eaaSJulian Wiedmann .mode = 0644,
8121e632eaaSJulian Wiedmann .fops = &prng_tdes_fops,
8131e632eaaSJulian Wiedmann .groups = prng_tdes_dev_groups,
81457127645SHarald Freudenberger };
81557127645SHarald Freudenberger
81657127645SHarald Freudenberger
81757127645SHarald Freudenberger /*** module init and exit ***/
8181b278294SJan Glauber
prng_init(void)8191b278294SJan Glauber static int __init prng_init(void)
8201b278294SJan Glauber {
8211b278294SJan Glauber int ret;
8221b278294SJan Glauber
8231b278294SJan Glauber /* check if the CPU has a PRNG */
82469c0e360SMartin Schwidefsky if (!cpacf_query_func(CPACF_KMC, CPACF_KMC_PRNG))
825ba6a98feSDavid Hildenbrand return -ENODEV;
8261b278294SJan Glauber
827769f020bSHarald Freudenberger /* check if TRNG subfunction is available */
828769f020bSHarald Freudenberger if (cpacf_query_func(CPACF_PRNO, CPACF_PRNO_TRNG))
829769f020bSHarald Freudenberger trng_available = true;
830769f020bSHarald Freudenberger
83157127645SHarald Freudenberger /* choose prng mode */
83257127645SHarald Freudenberger if (prng_mode != PRNG_MODE_TDES) {
833985a9d20SHarald Freudenberger /* check for MSA5 support for PRNO operations */
834985a9d20SHarald Freudenberger if (!cpacf_query_func(CPACF_PRNO, CPACF_PRNO_SHA512_DRNG_GEN)) {
83557127645SHarald Freudenberger if (prng_mode == PRNG_MODE_SHA512) {
83657127645SHarald Freudenberger pr_err("The prng module cannot "
83757127645SHarald Freudenberger "start in SHA-512 mode\n");
838ba6a98feSDavid Hildenbrand return -ENODEV;
83957127645SHarald Freudenberger }
84057127645SHarald Freudenberger prng_mode = PRNG_MODE_TDES;
84157127645SHarald Freudenberger } else
84257127645SHarald Freudenberger prng_mode = PRNG_MODE_SHA512;
8431b278294SJan Glauber }
8441b278294SJan Glauber
84557127645SHarald Freudenberger if (prng_mode == PRNG_MODE_SHA512) {
8461b278294SJan Glauber
84757127645SHarald Freudenberger /* SHA512 mode */
84857127645SHarald Freudenberger
84957127645SHarald Freudenberger if (prng_chunk_size < PRNG_CHUNKSIZE_SHA512_MIN
85057127645SHarald Freudenberger || prng_chunk_size > PRNG_CHUNKSIZE_SHA512_MAX)
85157127645SHarald Freudenberger return -EINVAL;
85257127645SHarald Freudenberger prng_chunk_size = (prng_chunk_size + 0x3f) & ~0x3f;
85357127645SHarald Freudenberger
85457127645SHarald Freudenberger if (prng_reseed_limit == 0)
85557127645SHarald Freudenberger prng_reseed_limit = PRNG_RESEED_LIMIT_SHA512;
85657127645SHarald Freudenberger else if (prng_reseed_limit < PRNG_RESEED_LIMIT_SHA512_LOWER)
85757127645SHarald Freudenberger return -EINVAL;
85857127645SHarald Freudenberger
85957127645SHarald Freudenberger ret = prng_sha512_instantiate();
860d4ebabe8SJan Glauber if (ret)
86157127645SHarald Freudenberger goto out;
8621b278294SJan Glauber
86357127645SHarald Freudenberger ret = misc_register(&prng_sha512_dev);
86457127645SHarald Freudenberger if (ret) {
86557127645SHarald Freudenberger prng_sha512_deinstantiate();
86657127645SHarald Freudenberger goto out;
86757127645SHarald Freudenberger }
86857127645SHarald Freudenberger
86957127645SHarald Freudenberger } else {
87057127645SHarald Freudenberger
87157127645SHarald Freudenberger /* TDES mode */
87257127645SHarald Freudenberger
87357127645SHarald Freudenberger if (prng_chunk_size < PRNG_CHUNKSIZE_TDES_MIN
87457127645SHarald Freudenberger || prng_chunk_size > PRNG_CHUNKSIZE_TDES_MAX)
87557127645SHarald Freudenberger return -EINVAL;
87657127645SHarald Freudenberger prng_chunk_size = (prng_chunk_size + 0x07) & ~0x07;
87757127645SHarald Freudenberger
87857127645SHarald Freudenberger if (prng_reseed_limit == 0)
87957127645SHarald Freudenberger prng_reseed_limit = PRNG_RESEED_LIMIT_TDES;
88057127645SHarald Freudenberger else if (prng_reseed_limit < PRNG_RESEED_LIMIT_TDES_LOWER)
88157127645SHarald Freudenberger return -EINVAL;
88257127645SHarald Freudenberger
88357127645SHarald Freudenberger ret = prng_tdes_instantiate();
88457127645SHarald Freudenberger if (ret)
88557127645SHarald Freudenberger goto out;
88657127645SHarald Freudenberger
88757127645SHarald Freudenberger ret = misc_register(&prng_tdes_dev);
88857127645SHarald Freudenberger if (ret) {
88957127645SHarald Freudenberger prng_tdes_deinstantiate();
89057127645SHarald Freudenberger goto out;
89157127645SHarald Freudenberger }
89257127645SHarald Freudenberger }
89357127645SHarald Freudenberger
89457127645SHarald Freudenberger out:
8951b278294SJan Glauber return ret;
8961b278294SJan Glauber }
8971b278294SJan Glauber
89857127645SHarald Freudenberger
prng_exit(void)8991b278294SJan Glauber static void __exit prng_exit(void)
9001b278294SJan Glauber {
90157127645SHarald Freudenberger if (prng_mode == PRNG_MODE_SHA512) {
90257127645SHarald Freudenberger misc_deregister(&prng_sha512_dev);
90357127645SHarald Freudenberger prng_sha512_deinstantiate();
90457127645SHarald Freudenberger } else {
90557127645SHarald Freudenberger misc_deregister(&prng_tdes_dev);
90657127645SHarald Freudenberger prng_tdes_deinstantiate();
9071b278294SJan Glauber }
90857127645SHarald Freudenberger }
90957127645SHarald Freudenberger
910*0a5f9b38SHeiko Carstens module_cpu_feature_match(S390_CPU_FEATURE_MSA, prng_init);
9111b278294SJan Glauber module_exit(prng_exit);
912