summaryrefslogtreecommitdiffstats
path: root/arch/s390/crypto
diff options
context:
space:
mode:
authorHarald Freudenberger <freude@linux.ibm.com>2019-04-16 07:41:26 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2019-04-25 09:34:09 -0400
commit769f020b6c9283d61c59de3559375ec7e961a424 (patch)
treeef30000786f61ce3e0fc434d3ffa82a6ac7769b8 /arch/s390/crypto
parent23d1aee92b42587e696ab48a9da774819ecd3718 (diff)
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: Harald Freudenberger <freude@linux.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390/crypto')
-rw-r--r--arch/s390/crypto/prng.c67
1 files changed, 47 insertions, 20 deletions
diff --git a/arch/s390/crypto/prng.c b/arch/s390/crypto/prng.c
index fba37906045b..12cca467af7d 100644
--- a/arch/s390/crypto/prng.c
+++ b/arch/s390/crypto/prng.c
@@ -61,6 +61,7 @@ static unsigned int prng_reseed_limit;
61module_param_named(reseed_limit, prng_reseed_limit, int, 0); 61module_param_named(reseed_limit, prng_reseed_limit, int, 0);
62MODULE_PARM_DESC(prng_reseed_limit, "PRNG reseed limit"); 62MODULE_PARM_DESC(prng_reseed_limit, "PRNG reseed limit");
63 63
64static bool trng_available;
64 65
65/* 66/*
66 * Any one who considers arithmetical methods of producing random digits is, 67 * Any one who considers arithmetical methods of producing random digits is,
@@ -366,7 +367,7 @@ static int __init prng_sha512_selftest(void)
366 367
367static int __init prng_sha512_instantiate(void) 368static int __init prng_sha512_instantiate(void)
368{ 369{
369 int ret, datalen; 370 int ret, datalen, seedlen;
370 u8 seed[128 + 16]; 371 u8 seed[128 + 16];
371 372
372 pr_debug("prng runs in SHA-512 mode " 373 pr_debug("prng runs in SHA-512 mode "
@@ -390,21 +391,35 @@ static int __init prng_sha512_instantiate(void)
390 if (ret) 391 if (ret)
391 goto outfree; 392 goto outfree;
392 393
393 /* 394 /* generate initial seed, we need at least 256 + 128 bits entropy. */
394 * generate initial seed bytestring, we need at least 395 if (trng_available) {
395 * 256 + 128 bits entropy. However, the generate_entropy() 396 /*
396 * function anyway works in 64 byte junks so we pull 397 * Trng available, so use it. The trng works in chunks of
397 * 2*64 bytes here. 398 * 32 bytes and produces 100% entropy. So we pull 64 bytes
398 */ 399 * which gives us 512 bits entropy.
399 ret = generate_entropy(seed, 128); 400 */
400 if (ret != 128) 401 seedlen = 2 * 32;
401 goto outfree; 402 cpacf_trng(NULL, 0, seed, seedlen);
402 /* followed by 16 bytes of unique nonce */ 403 } else {
403 get_tod_clock_ext(seed + 128); 404 /*
405 * No trng available, so use the generate_entropy() function.
406 * This function works in 64 byte junks and produces
407 * 50% entropy. So we pull 2*64 bytes which gives us 512 bits
408 * of entropy.
409 */
410 seedlen = 2 * 64;
411 ret = generate_entropy(seed, seedlen);
412 if (ret != seedlen)
413 goto outfree;
414 }
404 415
405 /* initial seed of the prno drng */ 416 /* append the seed by 16 bytes of unique nonce */
417 get_tod_clock_ext(seed + seedlen);
418 seedlen += 16;
419
420 /* now initial seed of the prno drng */
406 cpacf_prno(CPACF_PRNO_SHA512_DRNG_SEED, 421 cpacf_prno(CPACF_PRNO_SHA512_DRNG_SEED,
407 &prng_data->prnows, NULL, 0, seed, sizeof(seed)); 422 &prng_data->prnows, NULL, 0, seed, seedlen);
408 memzero_explicit(seed, sizeof(seed)); 423 memzero_explicit(seed, sizeof(seed));
409 424
410 /* if fips mode is enabled, generate a first block of random 425 /* if fips mode is enabled, generate a first block of random
@@ -433,17 +448,25 @@ static void prng_sha512_deinstantiate(void)
433 448
434static int prng_sha512_reseed(void) 449static int prng_sha512_reseed(void)
435{ 450{
436 int ret; 451 int ret, seedlen;
437 u8 seed[64]; 452 u8 seed[64];
438 453
439 /* fetch 256 bits of fresh entropy */ 454 /* We need at least 256 bits of fresh entropy for reseeding */
440 ret = generate_entropy(seed, sizeof(seed)); 455 if (trng_available) {
441 if (ret != sizeof(seed)) 456 /* trng produces 256 bits entropy in 32 bytes */
442 return ret; 457 seedlen = 32;
458 cpacf_trng(NULL, 0, seed, seedlen);
459 } else {
460 /* generate_entropy() produces 256 bits entropy in 64 bytes */
461 seedlen = 64;
462 ret = generate_entropy(seed, seedlen);
463 if (ret != sizeof(seed))
464 return ret;
465 }
443 466
444 /* do a reseed of the prno drng with this bytestring */ 467 /* do a reseed of the prno drng with this bytestring */
445 cpacf_prno(CPACF_PRNO_SHA512_DRNG_SEED, 468 cpacf_prno(CPACF_PRNO_SHA512_DRNG_SEED,
446 &prng_data->prnows, NULL, 0, seed, sizeof(seed)); 469 &prng_data->prnows, NULL, 0, seed, seedlen);
447 memzero_explicit(seed, sizeof(seed)); 470 memzero_explicit(seed, sizeof(seed));
448 471
449 return 0; 472 return 0;
@@ -803,6 +826,10 @@ static int __init prng_init(void)
803 if (!cpacf_query_func(CPACF_KMC, CPACF_KMC_PRNG)) 826 if (!cpacf_query_func(CPACF_KMC, CPACF_KMC_PRNG))
804 return -EOPNOTSUPP; 827 return -EOPNOTSUPP;
805 828
829 /* check if TRNG subfunction is available */
830 if (cpacf_query_func(CPACF_PRNO, CPACF_PRNO_TRNG))
831 trng_available = true;
832
806 /* choose prng mode */ 833 /* choose prng mode */
807 if (prng_mode != PRNG_MODE_TDES) { 834 if (prng_mode != PRNG_MODE_TDES) {
808 /* check for MSA5 support for PRNO operations */ 835 /* check for MSA5 support for PRNO operations */