linux/crypto/ansi_cprng.c

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * PRNG: Pseudo Random Number Generator
 *       Based on NIST Recommended PRNG From ANSI X9.31 Appendix A.2.4 using
 *       AES 128 cipher
 *
 *  (C) Neil Horman <[email protected]>
 */

#include <crypto/internal/cipher.h>
#include <crypto/internal/rng.h>
#include <linux/err.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/string.h>

#define DEFAULT_PRNG_KEY
#define DEFAULT_PRNG_KSZ
#define DEFAULT_BLK_SZ
#define DEFAULT_V_SEED

/*
 * Flags for the prng_context flags field
 */

#define PRNG_FIXED_SIZE
#define PRNG_NEED_RESET

/*
 * Note: DT is our counter value
 *	 I is our intermediate value
 *	 V is our seed vector
 * See http://csrc.nist.gov/groups/STM/cavp/documents/rng/931rngext.pdf
 * for implementation details
 */


struct prng_context {};

static int dbg;

static void hexdump(char *note, unsigned char *buf, unsigned int len)
{}

#define dbgprint(format, args...)

static void xor_vectors(unsigned char *in1, unsigned char *in2,
			unsigned char *out, unsigned int size)
{}
/*
 * Returns DEFAULT_BLK_SZ bytes of random data per call
 * returns 0 if generation succeeded, <0 if something went wrong
 */
static int _get_more_prng_bytes(struct prng_context *ctx, int cont_test)
{}

/* Our exported functions */
static int get_prng_bytes(char *buf, size_t nbytes, struct prng_context *ctx,
				int do_cont_test)
{}

static void free_prng_context(struct prng_context *ctx)
{}

static int reset_prng_context(struct prng_context *ctx,
			      const unsigned char *key, size_t klen,
			      const unsigned char *V, const unsigned char *DT)
{}

static int cprng_init(struct crypto_tfm *tfm)
{}

static void cprng_exit(struct crypto_tfm *tfm)
{}

static int cprng_get_random(struct crypto_rng *tfm,
			    const u8 *src, unsigned int slen,
			    u8 *rdata, unsigned int dlen)
{}

/*
 *  This is the cprng_registered reset method the seed value is
 *  interpreted as the tuple { V KEY DT}
 *  V and KEY are required during reset, and DT is optional, detected
 *  as being present by testing the length of the seed
 */
static int cprng_reset(struct crypto_rng *tfm,
		       const u8 *seed, unsigned int slen)
{}

#ifdef CONFIG_CRYPTO_FIPS
static int fips_cprng_get_random(struct crypto_rng *tfm,
				 const u8 *src, unsigned int slen,
				 u8 *rdata, unsigned int dlen)
{
	struct prng_context *prng = crypto_rng_ctx(tfm);

	return get_prng_bytes(rdata, dlen, prng, 1);
}

static int fips_cprng_reset(struct crypto_rng *tfm,
			    const u8 *seed, unsigned int slen)
{
	u8 rdata[DEFAULT_BLK_SZ];
	const u8 *key = seed + DEFAULT_BLK_SZ;
	int rc;

	struct prng_context *prng = crypto_rng_ctx(tfm);

	if (slen < DEFAULT_PRNG_KSZ + DEFAULT_BLK_SZ)
		return -EINVAL;

	/* fips strictly requires seed != key */
	if (!memcmp(seed, key, DEFAULT_PRNG_KSZ))
		return -EINVAL;

	rc = cprng_reset(tfm, seed, slen);

	if (!rc)
		goto out;

	/* this primes our continuity test */
	rc = get_prng_bytes(rdata, DEFAULT_BLK_SZ, prng, 0);
	prng->rand_data_valid = DEFAULT_BLK_SZ;

out:
	return rc;
}
#endif

static struct rng_alg rng_algs[] =;

/* Module initalization */
static int __init prng_mod_init(void)
{}

static void __exit prng_mod_fini(void)
{}

MODULE_LICENSE();
MODULE_DESCRIPTION();
MODULE_AUTHOR();
module_param(dbg, int, 0);
MODULE_PARM_DESC();
subsys_initcall(prng_mod_init);
module_exit(prng_mod_fini);
MODULE_ALIAS_CRYPTO();
MODULE_ALIAS_CRYPTO();
MODULE_IMPORT_NS();