Commit 769f020b authored by Harald Freudenberger's avatar Harald Freudenberger Committed by Martin Schwidefsky

s390/crypto: use TRNG for seeding/reseeding

With the z14 machine there came also a CPACF hardware extension
which provides a True Random Number Generator. This TRNG can
be accessed with a new subfunction code within the CPACF prno
instruction and provides random data with very high entropy.

So if there is a TRNG available, let's use it for initial seeding
and reseeding instead of the current implementation which tries
to generate entropy based on stckf (store clock fast) jitters.

For details about the amount of data needed and pulled for
seeding and reseeding there can be explaining comments in the
code found.
Signed-off-by: default avatarHarald Freudenberger <freude@linux.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent 23d1aee9
...@@ -61,6 +61,7 @@ static unsigned int prng_reseed_limit; ...@@ -61,6 +61,7 @@ static unsigned int prng_reseed_limit;
module_param_named(reseed_limit, prng_reseed_limit, int, 0); module_param_named(reseed_limit, prng_reseed_limit, int, 0);
MODULE_PARM_DESC(prng_reseed_limit, "PRNG reseed limit"); MODULE_PARM_DESC(prng_reseed_limit, "PRNG reseed limit");
static bool trng_available;
/* /*
* Any one who considers arithmetical methods of producing random digits is, * Any one who considers arithmetical methods of producing random digits is,
...@@ -366,7 +367,7 @@ static int __init prng_sha512_selftest(void) ...@@ -366,7 +367,7 @@ static int __init prng_sha512_selftest(void)
static int __init prng_sha512_instantiate(void) static int __init prng_sha512_instantiate(void)
{ {
int ret, datalen; int ret, datalen, seedlen;
u8 seed[128 + 16]; u8 seed[128 + 16];
pr_debug("prng runs in SHA-512 mode " pr_debug("prng runs in SHA-512 mode "
...@@ -390,21 +391,35 @@ static int __init prng_sha512_instantiate(void) ...@@ -390,21 +391,35 @@ static int __init prng_sha512_instantiate(void)
if (ret) if (ret)
goto outfree; goto outfree;
/* generate initial seed, we need at least 256 + 128 bits entropy. */
if (trng_available) {
/* /*
* generate initial seed bytestring, we need at least * Trng available, so use it. The trng works in chunks of
* 256 + 128 bits entropy. However, the generate_entropy() * 32 bytes and produces 100% entropy. So we pull 64 bytes
* function anyway works in 64 byte junks so we pull * which gives us 512 bits entropy.
* 2*64 bytes here.
*/ */
ret = generate_entropy(seed, 128); seedlen = 2 * 32;
if (ret != 128) cpacf_trng(NULL, 0, seed, seedlen);
} else {
/*
* No trng available, so use the generate_entropy() function.
* This function works in 64 byte junks and produces
* 50% entropy. So we pull 2*64 bytes which gives us 512 bits
* of entropy.
*/
seedlen = 2 * 64;
ret = generate_entropy(seed, seedlen);
if (ret != seedlen)
goto outfree; goto outfree;
/* followed by 16 bytes of unique nonce */ }
get_tod_clock_ext(seed + 128);
/* append the seed by 16 bytes of unique nonce */
get_tod_clock_ext(seed + seedlen);
seedlen += 16;
/* initial seed of the prno drng */ /* now initial seed of the prno drng */
cpacf_prno(CPACF_PRNO_SHA512_DRNG_SEED, cpacf_prno(CPACF_PRNO_SHA512_DRNG_SEED,
&prng_data->prnows, NULL, 0, seed, sizeof(seed)); &prng_data->prnows, NULL, 0, seed, seedlen);
memzero_explicit(seed, sizeof(seed)); memzero_explicit(seed, sizeof(seed));
/* if fips mode is enabled, generate a first block of random /* if fips mode is enabled, generate a first block of random
...@@ -433,17 +448,25 @@ static void prng_sha512_deinstantiate(void) ...@@ -433,17 +448,25 @@ static void prng_sha512_deinstantiate(void)
static int prng_sha512_reseed(void) static int prng_sha512_reseed(void)
{ {
int ret; int ret, seedlen;
u8 seed[64]; u8 seed[64];
/* fetch 256 bits of fresh entropy */ /* We need at least 256 bits of fresh entropy for reseeding */
ret = generate_entropy(seed, sizeof(seed)); if (trng_available) {
/* trng produces 256 bits entropy in 32 bytes */
seedlen = 32;
cpacf_trng(NULL, 0, seed, seedlen);
} else {
/* generate_entropy() produces 256 bits entropy in 64 bytes */
seedlen = 64;
ret = generate_entropy(seed, seedlen);
if (ret != sizeof(seed)) if (ret != sizeof(seed))
return ret; return ret;
}
/* do a reseed of the prno drng with this bytestring */ /* do a reseed of the prno drng with this bytestring */
cpacf_prno(CPACF_PRNO_SHA512_DRNG_SEED, cpacf_prno(CPACF_PRNO_SHA512_DRNG_SEED,
&prng_data->prnows, NULL, 0, seed, sizeof(seed)); &prng_data->prnows, NULL, 0, seed, seedlen);
memzero_explicit(seed, sizeof(seed)); memzero_explicit(seed, sizeof(seed));
return 0; return 0;
...@@ -803,6 +826,10 @@ static int __init prng_init(void) ...@@ -803,6 +826,10 @@ static int __init prng_init(void)
if (!cpacf_query_func(CPACF_KMC, CPACF_KMC_PRNG)) if (!cpacf_query_func(CPACF_KMC, CPACF_KMC_PRNG))
return -EOPNOTSUPP; return -EOPNOTSUPP;
/* check if TRNG subfunction is available */
if (cpacf_query_func(CPACF_PRNO, CPACF_PRNO_TRNG))
trng_available = true;
/* choose prng mode */ /* choose prng mode */
if (prng_mode != PRNG_MODE_TDES) { if (prng_mode != PRNG_MODE_TDES) {
/* check for MSA5 support for PRNO operations */ /* check for MSA5 support for PRNO operations */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment