// SPDX-License-Identifier: GPL-2.0 /* * Copyright IBM Corp. 2006, 2015 * Author(s): Jan Glauber <jan.glauber@de.ibm.com> * Harald Freudenberger <freude@de.ibm.com> * Driver for the s390 pseudo random number generator
*/
/* * generate_entropy: * This function fills a given buffer with random bytes. The entropy within * the random bytes given back is assumed to have at least 50% - meaning * a 64 bytes buffer has at least 64 * 8 / 2 = 256 bits of entropy. * Within the function the entropy generation is done in junks of 64 bytes. * So the caller should also ask for buffer fill in multiples of 64 bytes. * The generation of the entropy is based on the assumption that every stckf() * invocation produces 0.5 bits of entropy. To accumulate 256 bits of entropy * at least 512 stckf() values are needed. The entropy relevant part of the * stckf value is bit 51 (counting starts at the left with bit nr 0) so * here we use the lower 4 bytes and exor the values into 2k of bufferspace. * To be on the save side, if there is ever a problem with stckf() the * other half of the page buffer is filled with bytes from urandom via * get_random_bytes(), so this function consumes 2k of urandom for each * requested 64 bytes output data. Finally the buffer page is condensed into * a 64 byte value by hashing with a SHA512 hash.
*/ staticint generate_entropy(u8 *ebuf, size_t nbytes)
{ int n, ret = 0;
u8 *pg, pblock[80] = { /* 8 x 64 bit init values */
0x6A, 0x09, 0xE6, 0x67, 0xF3, 0xBC, 0xC9, 0x08,
0xBB, 0x67, 0xAE, 0x85, 0x84, 0xCA, 0xA7, 0x3B,
0x3C, 0x6E, 0xF3, 0x72, 0xFE, 0x94, 0xF8, 0x2B,
0xA5, 0x4F, 0xF5, 0x3A, 0x5F, 0x1D, 0x36, 0xF1,
0x51, 0x0E, 0x52, 0x7F, 0xAD, 0xE6, 0x82, 0xD1,
0x9B, 0x05, 0x68, 0x8C, 0x2B, 0x3E, 0x6C, 0x1F,
0x1F, 0x83, 0xD9, 0xAB, 0xFB, 0x41, 0xBD, 0x6B,
0x5B, 0xE0, 0xCD, 0x19, 0x13, 0x7E, 0x21, 0x79, /* 128 bit counter total message bit length */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00 };
/* check working states V and C */ if (memcmp(ws.V, V0, sizeof(V0)) != 0
|| memcmp(ws.C, C0, sizeof(C0)) != 0) {
pr_err("The prng self test state test " "for the SHA-512 mode failed\n");
prng_errorflag = PRNG_SELFTEST_FAILED; return -EIO;
}
/* check against expected data */ if (memcmp(buf, random, sizeof(random)) != 0) {
pr_err("The prng self test data test " "for the SHA-512 mode failed\n");
prng_errorflag = PRNG_SELFTEST_FAILED; return -EIO;
}
/* selftest */
ret = prng_sha512_selftest(); if (ret) goto outfree;
/* generate initial seed, we need at least 256 + 128 bits entropy. */ if (trng_available) { /* * Trng available, so use it. The trng works in chunks of * 32 bytes and produces 100% entropy. So we pull 64 bytes * which gives us 512 bits entropy.
*/
seedlen = 2 * 32;
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;
}
/* append the seed by 16 bytes of unique nonce */
store_tod_clock_ext((union tod_clock *)(seed + seedlen));
seedlen += 16;
/* now initial seed of the prno drng */
cpacf_prno(CPACF_PRNO_SHA512_DRNG_SEED,
&prng_data->prnows, NULL, 0, seed, seedlen);
memzero_explicit(seed, sizeof(seed));
/* if fips mode is enabled, generate a first block of random
bytes for the FIPS 140-2 Conditional Self Test */ if (fips_enabled) {
prng_data->prev = prng_data->buf + prng_chunk_size;
cpacf_prno(CPACF_PRNO_SHA512_DRNG_GEN,
&prng_data->prnows,
prng_data->prev, prng_chunk_size, NULL, 0);
}
return 0;
outfree:
kfree(prng_data); return ret;
}
staticvoid prng_sha512_deinstantiate(void)
{
pr_debug("The prng module stopped after running in SHA-512 mode\n");
kfree_sensitive(prng_data);
}
staticint prng_sha512_reseed(void)
{ int ret, seedlen;
u8 seed[64];
/* We need at least 256 bits of fresh entropy for reseeding */ 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)) return ret;
}
/* do a reseed of the prno drng with this bytestring */
cpacf_prno(CPACF_PRNO_SHA512_DRNG_SEED,
&prng_data->prnows, NULL, 0, seed, seedlen);
memzero_explicit(seed, sizeof(seed));
return 0;
}
staticint prng_sha512_generate(u8 *buf, size_t nbytes)
{ int ret;
/* reseed needed ? */ if (prng_data->prnows.reseed_counter > prng_reseed_limit) {
ret = prng_sha512_reseed(); if (ret) return ret;
}
static ssize_t prng_tdes_read(struct file *file, char __user *ubuf,
size_t nbytes, loff_t *ppos)
{ int chunk, n, ret = 0;
/* lock prng_data struct */ if (mutex_lock_interruptible(&prng_data->mutex)) return -ERESTARTSYS;
while (nbytes) { if (need_resched()) { if (signal_pending(current)) { if (ret == 0)
ret = -ERESTARTSYS; break;
} /* give mutex free before calling schedule() */
mutex_unlock(&prng_data->mutex);
schedule(); /* occupy mutex again */ if (mutex_lock_interruptible(&prng_data->mutex)) { if (ret == 0)
ret = -ERESTARTSYS; return ret;
}
}
/* * we lose some random bytes if an attacker issues * reads < 8 bytes, but we don't care
*/
chunk = min_t(int, nbytes, prng_chunk_size);
/* PRNG only likes multiples of 8 bytes */
n = (chunk + 7) & -8;
if (prng_data->prngws.reseed_counter > prng_reseed_limit)
prng_tdes_seed(8);
/* if the CPU supports PRNG stckf is present too */
*((unsignedlonglong *)prng_data->buf) = get_tod_clock_fast();
/* * Beside the STCKF the input for the TDES-EDE is the output * of the last operation. We differ here from X9.17 since we * only store one timestamp into the buffer. Padding the whole * buffer with timestamps does not improve security, since * successive stckf have nearly constant offsets. * If an attacker knows the first timestamp it would be * trivial to guess the additional values. One timestamp * is therefore enough and still guarantees unique input values. * * Note: you can still get strict X9.17 conformity by setting * prng_chunk_size to 8 bytes.
*/
cpacf_kmc(CPACF_KMC_PRNG, prng_data->prngws.parm_block,
prng_data->buf, prng_data->buf, n);
static ssize_t prng_sha512_read(struct file *file, char __user *ubuf,
size_t nbytes, loff_t *ppos)
{ int n, ret = 0;
u8 *p;
/* if errorflag is set do nothing and return 'broken pipe' */ if (prng_errorflag) return -EPIPE;
/* lock prng_data struct */ if (mutex_lock_interruptible(&prng_data->mutex)) return -ERESTARTSYS;
while (nbytes) { if (need_resched()) { if (signal_pending(current)) { if (ret == 0)
ret = -ERESTARTSYS; break;
} /* give mutex free before calling schedule() */
mutex_unlock(&prng_data->mutex);
schedule(); /* occopy mutex again */ if (mutex_lock_interruptible(&prng_data->mutex)) { if (ret == 0)
ret = -ERESTARTSYS; return ret;
}
} if (prng_data->rest) { /* push left over random bytes from the previous read */
p = prng_data->buf + prng_chunk_size - prng_data->rest;
n = (nbytes < prng_data->rest) ?
nbytes : prng_data->rest;
prng_data->rest -= n;
} else { /* generate one chunk of random bytes into read buf */
p = prng_data->buf;
n = prng_sha512_generate(p, prng_chunk_size); if (n < 0) {
ret = n; break;
} if (nbytes < prng_chunk_size) {
n = nbytes;
prng_data->rest = prng_chunk_size - n;
} else {
n = prng_chunk_size;
prng_data->rest = 0;
}
} if (copy_to_user(ubuf, p, n)) {
ret = -EFAULT; break;
}
memzero_explicit(p, n);
ubuf += n;
nbytes -= n;
ret += n;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.