static int __init prng_init()

in crypto/prng.c [819:896]


static int __init prng_init(void)
{
	int ret;

	/* check if the CPU has a PRNG */
	if (!cpacf_query_func(CPACF_KMC, CPACF_KMC_PRNG))
		return -ENODEV;

	/* check if TRNG subfunction is available */
	if (cpacf_query_func(CPACF_PRNO, CPACF_PRNO_TRNG))
		trng_available = true;

	/* choose prng mode */
	if (prng_mode != PRNG_MODE_TDES) {
		/* check for MSA5 support for PRNO operations */
		if (!cpacf_query_func(CPACF_PRNO, CPACF_PRNO_SHA512_DRNG_GEN)) {
			if (prng_mode == PRNG_MODE_SHA512) {
				pr_err("The prng module cannot "
				       "start in SHA-512 mode\n");
				return -ENODEV;
			}
			prng_mode = PRNG_MODE_TDES;
		} else
			prng_mode = PRNG_MODE_SHA512;
	}

	if (prng_mode == PRNG_MODE_SHA512) {

		/* SHA512 mode */

		if (prng_chunk_size < PRNG_CHUNKSIZE_SHA512_MIN
		    || prng_chunk_size > PRNG_CHUNKSIZE_SHA512_MAX)
			return -EINVAL;
		prng_chunk_size = (prng_chunk_size + 0x3f) & ~0x3f;

		if (prng_reseed_limit == 0)
			prng_reseed_limit = PRNG_RESEED_LIMIT_SHA512;
		else if (prng_reseed_limit < PRNG_RESEED_LIMIT_SHA512_LOWER)
			return -EINVAL;

		ret = prng_sha512_instantiate();
		if (ret)
			goto out;

		ret = misc_register(&prng_sha512_dev);
		if (ret) {
			prng_sha512_deinstantiate();
			goto out;
		}

	} else {

		/* TDES mode */

		if (prng_chunk_size < PRNG_CHUNKSIZE_TDES_MIN
		    || prng_chunk_size > PRNG_CHUNKSIZE_TDES_MAX)
			return -EINVAL;
		prng_chunk_size = (prng_chunk_size + 0x07) & ~0x07;

		if (prng_reseed_limit == 0)
			prng_reseed_limit = PRNG_RESEED_LIMIT_TDES;
		else if (prng_reseed_limit < PRNG_RESEED_LIMIT_TDES_LOWER)
			return -EINVAL;

		ret = prng_tdes_instantiate();
		if (ret)
			goto out;

		ret = misc_register(&prng_tdes_dev);
		if (ret) {
			prng_tdes_deinstantiate();
			goto out;
		}
	}

out:
	return ret;
}