crypto: drbg - Convert to new rng interface
This patch converts the DRBG implementation to the new low-level rng interface. This allows us to get rid of struct drbg_gen by using the new RNG API instead. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Acked-by: Stephan Mueller <smueller@chronox.de>
This commit is contained in:
parent
881cd6c570
commit
8fded5925d
121
crypto/drbg.c
121
crypto/drbg.c
|
@ -235,7 +235,7 @@ static bool drbg_fips_continuous_test(struct drbg_state *drbg,
|
||||||
#ifdef CONFIG_CRYPTO_FIPS
|
#ifdef CONFIG_CRYPTO_FIPS
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
/* skip test if we test the overall system */
|
/* skip test if we test the overall system */
|
||||||
if (drbg->test_data)
|
if (list_empty(&drbg->test_data.list))
|
||||||
return true;
|
return true;
|
||||||
/* only perform test in FIPS mode */
|
/* only perform test in FIPS mode */
|
||||||
if (0 == fips_enabled)
|
if (0 == fips_enabled)
|
||||||
|
@ -1068,9 +1068,9 @@ static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (drbg->test_data && drbg->test_data->testentropy) {
|
if (list_empty(&drbg->test_data.list)) {
|
||||||
drbg_string_fill(&data1, drbg->test_data->testentropy->buf,
|
drbg_string_fill(&data1, drbg->test_data.buf,
|
||||||
drbg->test_data->testentropy->len);
|
drbg->test_data.len);
|
||||||
pr_devel("DRBG: using test entropy\n");
|
pr_devel("DRBG: using test entropy\n");
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
|
@ -1471,15 +1471,16 @@ static int drbg_uninstantiate(struct drbg_state *drbg)
|
||||||
* Helper function for setting the test data in the DRBG
|
* Helper function for setting the test data in the DRBG
|
||||||
*
|
*
|
||||||
* @drbg DRBG state handle
|
* @drbg DRBG state handle
|
||||||
* @test_data test data to sets
|
* @data test data
|
||||||
|
* @len test data length
|
||||||
*/
|
*/
|
||||||
static inline void drbg_set_testdata(struct drbg_state *drbg,
|
static void drbg_kcapi_set_entropy(struct crypto_rng *tfm,
|
||||||
struct drbg_test_data *test_data)
|
const u8 *data, unsigned int len)
|
||||||
{
|
{
|
||||||
if (!test_data || !test_data->testentropy)
|
struct drbg_state *drbg = crypto_rng_ctx(tfm);
|
||||||
return;
|
|
||||||
mutex_lock(&drbg->drbg_mutex);;
|
mutex_lock(&drbg->drbg_mutex);
|
||||||
drbg->test_data = test_data;
|
drbg_string_fill(&drbg->test_data, data, len);
|
||||||
mutex_unlock(&drbg->drbg_mutex);
|
mutex_unlock(&drbg->drbg_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1645,63 +1646,49 @@ static void drbg_kcapi_cleanup(struct crypto_tfm *tfm)
|
||||||
* Generate random numbers invoked by the kernel crypto API:
|
* Generate random numbers invoked by the kernel crypto API:
|
||||||
* The API of the kernel crypto API is extended as follows:
|
* The API of the kernel crypto API is extended as follows:
|
||||||
*
|
*
|
||||||
* If dlen is larger than zero, rdata is interpreted as the output buffer
|
* src is additional input supplied to the RNG.
|
||||||
* where random data is to be stored.
|
* slen is the length of src.
|
||||||
*
|
* dst is the output buffer where random data is to be stored.
|
||||||
* If dlen is zero, rdata is interpreted as a pointer to a struct drbg_gen
|
* dlen is the length of dst.
|
||||||
* which holds the additional information string that is used for the
|
|
||||||
* DRBG generation process. The output buffer that is to be used to store
|
|
||||||
* data is also pointed to by struct drbg_gen.
|
|
||||||
*/
|
*/
|
||||||
static int drbg_kcapi_random(struct crypto_rng *tfm, u8 *rdata,
|
static int drbg_kcapi_random(struct crypto_rng *tfm,
|
||||||
unsigned int dlen)
|
const u8 *src, unsigned int slen,
|
||||||
|
u8 *dst, unsigned int dlen)
|
||||||
{
|
{
|
||||||
struct drbg_state *drbg = crypto_rng_ctx(tfm);
|
struct drbg_state *drbg = crypto_rng_ctx(tfm);
|
||||||
if (0 < dlen) {
|
struct drbg_string *addtl = NULL;
|
||||||
return drbg_generate_long(drbg, rdata, dlen, NULL);
|
struct drbg_string string;
|
||||||
} else {
|
|
||||||
struct drbg_gen *data = (struct drbg_gen *)rdata;
|
if (slen) {
|
||||||
struct drbg_string addtl;
|
|
||||||
/* catch NULL pointer */
|
|
||||||
if (!data)
|
|
||||||
return 0;
|
|
||||||
drbg_set_testdata(drbg, data->test_data);
|
|
||||||
/* linked list variable is now local to allow modification */
|
/* linked list variable is now local to allow modification */
|
||||||
drbg_string_fill(&addtl, data->addtl->buf, data->addtl->len);
|
drbg_string_fill(&string, src, slen);
|
||||||
return drbg_generate_long(drbg, data->outbuf, data->outlen,
|
addtl = &string;
|
||||||
&addtl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return drbg_generate_long(drbg, dst, dlen, addtl);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Seed the DRBG invoked by the kernel crypto API
|
* Seed the DRBG invoked by the kernel crypto API
|
||||||
* Similar to the generate function of drbg_kcapi_random, this
|
|
||||||
* function extends the kernel crypto API interface with struct drbg_gen
|
|
||||||
*/
|
*/
|
||||||
static int drbg_kcapi_reset(struct crypto_rng *tfm, u8 *seed, unsigned int slen)
|
static int drbg_kcapi_seed(struct crypto_rng *tfm,
|
||||||
|
const u8 *seed, unsigned int slen)
|
||||||
{
|
{
|
||||||
struct drbg_state *drbg = crypto_rng_ctx(tfm);
|
struct drbg_state *drbg = crypto_rng_ctx(tfm);
|
||||||
struct crypto_tfm *tfm_base = crypto_rng_tfm(tfm);
|
struct crypto_tfm *tfm_base = crypto_rng_tfm(tfm);
|
||||||
bool pr = false;
|
bool pr = false;
|
||||||
struct drbg_string seed_string;
|
struct drbg_string string;
|
||||||
|
struct drbg_string *seed_string = NULL;
|
||||||
int coreref = 0;
|
int coreref = 0;
|
||||||
|
|
||||||
drbg_convert_tfm_core(crypto_tfm_alg_driver_name(tfm_base), &coreref,
|
drbg_convert_tfm_core(crypto_tfm_alg_driver_name(tfm_base), &coreref,
|
||||||
&pr);
|
&pr);
|
||||||
if (0 < slen) {
|
if (0 < slen) {
|
||||||
drbg_string_fill(&seed_string, seed, slen);
|
drbg_string_fill(&string, seed, slen);
|
||||||
return drbg_instantiate(drbg, &seed_string, coreref, pr);
|
seed_string = &string;
|
||||||
} else {
|
|
||||||
struct drbg_gen *data = (struct drbg_gen *)seed;
|
|
||||||
/* allow invocation of API call with NULL, 0 */
|
|
||||||
if (!data)
|
|
||||||
return drbg_instantiate(drbg, NULL, coreref, pr);
|
|
||||||
drbg_set_testdata(drbg, data->test_data);
|
|
||||||
/* linked list variable is now local to allow modification */
|
|
||||||
drbg_string_fill(&seed_string, data->addtl->buf,
|
|
||||||
data->addtl->len);
|
|
||||||
return drbg_instantiate(drbg, &seed_string, coreref, pr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return drbg_instantiate(drbg, seed_string, coreref, pr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************
|
/***************************************************************
|
||||||
|
@ -1793,32 +1780,31 @@ outbuf:
|
||||||
#endif /* CONFIG_CRYPTO_FIPS */
|
#endif /* CONFIG_CRYPTO_FIPS */
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct crypto_alg drbg_algs[22];
|
static struct rng_alg drbg_algs[22];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Fill the array drbg_algs used to register the different DRBGs
|
* Fill the array drbg_algs used to register the different DRBGs
|
||||||
* with the kernel crypto API. To fill the array, the information
|
* with the kernel crypto API. To fill the array, the information
|
||||||
* from drbg_cores[] is used.
|
* from drbg_cores[] is used.
|
||||||
*/
|
*/
|
||||||
static inline void __init drbg_fill_array(struct crypto_alg *alg,
|
static inline void __init drbg_fill_array(struct rng_alg *alg,
|
||||||
const struct drbg_core *core, int pr)
|
const struct drbg_core *core, int pr)
|
||||||
{
|
{
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
static int priority = 100;
|
static int priority = 100;
|
||||||
|
|
||||||
memset(alg, 0, sizeof(struct crypto_alg));
|
memcpy(alg->base.cra_name, "stdrng", 6);
|
||||||
memcpy(alg->cra_name, "stdrng", 6);
|
|
||||||
if (pr) {
|
if (pr) {
|
||||||
memcpy(alg->cra_driver_name, "drbg_pr_", 8);
|
memcpy(alg->base.cra_driver_name, "drbg_pr_", 8);
|
||||||
pos = 8;
|
pos = 8;
|
||||||
} else {
|
} else {
|
||||||
memcpy(alg->cra_driver_name, "drbg_nopr_", 10);
|
memcpy(alg->base.cra_driver_name, "drbg_nopr_", 10);
|
||||||
pos = 10;
|
pos = 10;
|
||||||
}
|
}
|
||||||
memcpy(alg->cra_driver_name + pos, core->cra_name,
|
memcpy(alg->base.cra_driver_name + pos, core->cra_name,
|
||||||
strlen(core->cra_name));
|
strlen(core->cra_name));
|
||||||
|
|
||||||
alg->cra_priority = priority;
|
alg->base.cra_priority = priority;
|
||||||
priority++;
|
priority++;
|
||||||
/*
|
/*
|
||||||
* If FIPS mode enabled, the selected DRBG shall have the
|
* If FIPS mode enabled, the selected DRBG shall have the
|
||||||
|
@ -1826,17 +1812,16 @@ static inline void __init drbg_fill_array(struct crypto_alg *alg,
|
||||||
* it is selected.
|
* it is selected.
|
||||||
*/
|
*/
|
||||||
if (fips_enabled)
|
if (fips_enabled)
|
||||||
alg->cra_priority += 200;
|
alg->base.cra_priority += 200;
|
||||||
|
|
||||||
alg->cra_flags = CRYPTO_ALG_TYPE_RNG;
|
alg->base.cra_ctxsize = sizeof(struct drbg_state);
|
||||||
alg->cra_ctxsize = sizeof(struct drbg_state);
|
alg->base.cra_module = THIS_MODULE;
|
||||||
alg->cra_type = &crypto_rng_type;
|
alg->base.cra_init = drbg_kcapi_init;
|
||||||
alg->cra_module = THIS_MODULE;
|
alg->base.cra_exit = drbg_kcapi_cleanup;
|
||||||
alg->cra_init = drbg_kcapi_init;
|
alg->generate = drbg_kcapi_random;
|
||||||
alg->cra_exit = drbg_kcapi_cleanup;
|
alg->seed = drbg_kcapi_seed;
|
||||||
alg->cra_u.rng.rng_make_random = drbg_kcapi_random;
|
alg->set_ent = drbg_kcapi_set_entropy;
|
||||||
alg->cra_u.rng.rng_reset = drbg_kcapi_reset;
|
alg->seedsize = 0;
|
||||||
alg->cra_u.rng.seedsize = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init drbg_init(void)
|
static int __init drbg_init(void)
|
||||||
|
@ -1869,12 +1854,12 @@ static int __init drbg_init(void)
|
||||||
drbg_fill_array(&drbg_algs[i], &drbg_cores[j], 1);
|
drbg_fill_array(&drbg_algs[i], &drbg_cores[j], 1);
|
||||||
for (j = 0; ARRAY_SIZE(drbg_cores) > j; j++, i++)
|
for (j = 0; ARRAY_SIZE(drbg_cores) > j; j++, i++)
|
||||||
drbg_fill_array(&drbg_algs[i], &drbg_cores[j], 0);
|
drbg_fill_array(&drbg_algs[i], &drbg_cores[j], 0);
|
||||||
return crypto_register_algs(drbg_algs, (ARRAY_SIZE(drbg_cores) * 2));
|
return crypto_register_rngs(drbg_algs, (ARRAY_SIZE(drbg_cores) * 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __exit drbg_exit(void)
|
static void __exit drbg_exit(void)
|
||||||
{
|
{
|
||||||
crypto_unregister_algs(drbg_algs, (ARRAY_SIZE(drbg_cores) * 2));
|
crypto_unregister_rngs(drbg_algs, (ARRAY_SIZE(drbg_cores) * 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
module_init(drbg_init);
|
module_init(drbg_init);
|
||||||
|
|
|
@ -121,7 +121,7 @@ struct drbg_state {
|
||||||
#endif
|
#endif
|
||||||
const struct drbg_state_ops *d_ops;
|
const struct drbg_state_ops *d_ops;
|
||||||
const struct drbg_core *core;
|
const struct drbg_core *core;
|
||||||
struct drbg_test_data *test_data;
|
struct drbg_string test_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline __u8 drbg_statelen(struct drbg_state *drbg)
|
static inline __u8 drbg_statelen(struct drbg_state *drbg)
|
||||||
|
@ -176,20 +176,9 @@ static inline size_t drbg_max_requests(struct drbg_state *drbg)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* kernel crypto API input data structure for DRBG generate in case dlen
|
|
||||||
* is set to 0
|
|
||||||
*/
|
|
||||||
struct drbg_gen {
|
|
||||||
unsigned char *outbuf; /* output buffer for random numbers */
|
|
||||||
unsigned int outlen; /* size of output buffer */
|
|
||||||
struct drbg_string *addtl; /* additional information string */
|
|
||||||
struct drbg_test_data *test_data; /* test data */
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is a wrapper to the kernel crypto API function of
|
* This is a wrapper to the kernel crypto API function of
|
||||||
* crypto_rng_get_bytes() to allow the caller to provide additional data.
|
* crypto_rng_generate() to allow the caller to provide additional data.
|
||||||
*
|
*
|
||||||
* @drng DRBG handle -- see crypto_rng_get_bytes
|
* @drng DRBG handle -- see crypto_rng_get_bytes
|
||||||
* @outbuf output buffer -- see crypto_rng_get_bytes
|
* @outbuf output buffer -- see crypto_rng_get_bytes
|
||||||
|
@ -204,21 +193,15 @@ static inline int crypto_drbg_get_bytes_addtl(struct crypto_rng *drng,
|
||||||
unsigned char *outbuf, unsigned int outlen,
|
unsigned char *outbuf, unsigned int outlen,
|
||||||
struct drbg_string *addtl)
|
struct drbg_string *addtl)
|
||||||
{
|
{
|
||||||
int ret;
|
return crypto_rng_generate(drng, addtl->buf, addtl->len,
|
||||||
struct drbg_gen genbuf;
|
outbuf, outlen);
|
||||||
genbuf.outbuf = outbuf;
|
|
||||||
genbuf.outlen = outlen;
|
|
||||||
genbuf.addtl = addtl;
|
|
||||||
genbuf.test_data = NULL;
|
|
||||||
ret = crypto_rng_get_bytes(drng, (u8 *)&genbuf, 0);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TEST code
|
* TEST code
|
||||||
*
|
*
|
||||||
* This is a wrapper to the kernel crypto API function of
|
* This is a wrapper to the kernel crypto API function of
|
||||||
* crypto_rng_get_bytes() to allow the caller to provide additional data and
|
* crypto_rng_generate() to allow the caller to provide additional data and
|
||||||
* allow furnishing of test_data
|
* allow furnishing of test_data
|
||||||
*
|
*
|
||||||
* @drng DRBG handle -- see crypto_rng_get_bytes
|
* @drng DRBG handle -- see crypto_rng_get_bytes
|
||||||
|
@ -236,14 +219,10 @@ static inline int crypto_drbg_get_bytes_addtl_test(struct crypto_rng *drng,
|
||||||
struct drbg_string *addtl,
|
struct drbg_string *addtl,
|
||||||
struct drbg_test_data *test_data)
|
struct drbg_test_data *test_data)
|
||||||
{
|
{
|
||||||
int ret;
|
crypto_rng_set_entropy(drng, test_data->testentropy->buf,
|
||||||
struct drbg_gen genbuf;
|
test_data->testentropy->len);
|
||||||
genbuf.outbuf = outbuf;
|
return crypto_rng_generate(drng, addtl->buf, addtl->len,
|
||||||
genbuf.outlen = outlen;
|
outbuf, outlen);
|
||||||
genbuf.addtl = addtl;
|
|
||||||
genbuf.test_data = test_data;
|
|
||||||
ret = crypto_rng_get_bytes(drng, (u8 *)&genbuf, 0);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -264,14 +243,9 @@ static inline int crypto_drbg_reset_test(struct crypto_rng *drng,
|
||||||
struct drbg_string *pers,
|
struct drbg_string *pers,
|
||||||
struct drbg_test_data *test_data)
|
struct drbg_test_data *test_data)
|
||||||
{
|
{
|
||||||
int ret;
|
crypto_rng_set_entropy(drng, test_data->testentropy->buf,
|
||||||
struct drbg_gen genbuf;
|
test_data->testentropy->len);
|
||||||
genbuf.outbuf = NULL;
|
return crypto_rng_reset(drng, pers->buf, pers->len);
|
||||||
genbuf.outlen = 0;
|
|
||||||
genbuf.addtl = pers;
|
|
||||||
genbuf.test_data = test_data;
|
|
||||||
ret = crypto_rng_reset(drng, (u8 *)&genbuf, 0);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* DRBG type flags */
|
/* DRBG type flags */
|
||||||
|
|
Loading…
Reference in New Issue