From 6756f31534e071d9915d1f7da7eb316c170f764d Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Mon, 20 Apr 2015 13:39:03 +0800 Subject: crypto: rng - Convert crypto_rng to new style crypto_type This patch converts the top-level crypto_rng to the "new" style. It was the last algorithm type added before we switched over to the new way of doing things exemplified by shash. All users will automatically switch over to the new interface. Note that this patch does not touch the low-level interface to rng implementations. Signed-off-by: Herbert Xu --- crypto/rng.c | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) (limited to 'crypto/rng.c') diff --git a/crypto/rng.c b/crypto/rng.c index e0a25c24..87fa2f49 100644 --- a/crypto/rng.c +++ b/crypto/rng.c @@ -24,11 +24,18 @@ #include #include +#include "internal.h" + static DEFINE_MUTEX(crypto_default_rng_lock); struct crypto_rng *crypto_default_rng; EXPORT_SYMBOL_GPL(crypto_default_rng); static int crypto_default_rng_refcnt; +static inline struct crypto_rng *__crypto_rng_cast(struct crypto_tfm *tfm) +{ + return container_of(tfm, struct crypto_rng, base); +} + static int rngapi_reset(struct crypto_rng *tfm, u8 *seed, unsigned int slen) { u8 *buf = NULL; @@ -49,13 +56,13 @@ static int rngapi_reset(struct crypto_rng *tfm, u8 *seed, unsigned int slen) return err; } -static int crypto_init_rng_ops(struct crypto_tfm *tfm, u32 type, u32 mask) +static int crypto_rng_init_tfm(struct crypto_tfm *tfm) { + struct crypto_rng *rng = __crypto_rng_cast(tfm); struct rng_alg *alg = &tfm->__crt_alg->cra_rng; - struct rng_tfm *ops = &tfm->crt_rng; - ops->rng_gen_random = alg->rng_make_random; - ops->rng_reset = rngapi_reset; + rng->generate = alg->rng_make_random; + rng->seed = rngapi_reset; return 0; } @@ -92,22 +99,26 @@ static void crypto_rng_show(struct seq_file *m, struct crypto_alg *alg) seq_printf(m, "seedsize : %u\n", alg->cra_rng.seedsize); } -static unsigned int crypto_rng_ctxsize(struct crypto_alg *alg, u32 type, - u32 mask) -{ - return alg->cra_ctxsize; -} - const struct crypto_type crypto_rng_type = { - .ctxsize = crypto_rng_ctxsize, - .init = crypto_init_rng_ops, + .extsize = crypto_alg_extsize, + .init_tfm = crypto_rng_init_tfm, #ifdef CONFIG_PROC_FS .show = crypto_rng_show, #endif .report = crypto_rng_report, + .maskclear = ~CRYPTO_ALG_TYPE_MASK, + .maskset = CRYPTO_ALG_TYPE_MASK, + .type = CRYPTO_ALG_TYPE_RNG, + .tfmsize = offsetof(struct crypto_rng, base), }; EXPORT_SYMBOL_GPL(crypto_rng_type); +struct crypto_rng *crypto_alloc_rng(const char *alg_name, u32 type, u32 mask) +{ + return crypto_alloc_tfm(alg_name, &crypto_rng_type, type, mask); +} +EXPORT_SYMBOL_GPL(crypto_alloc_rng); + int crypto_get_default_rng(void) { struct crypto_rng *rng; -- cgit v1.2.3 From b1faf983dac9bd3067a5ed12462bc514292c5549 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Mon, 20 Apr 2015 13:39:04 +0800 Subject: crypto: rng - Introduce crypto_rng_generate This patch adds the new top-level function crypto_rng_generate which generates random numbers with additional input. It also extends the mid-level rng_gen_random function to take additional data as input. Signed-off-by: Herbert Xu --- crypto/rng.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'crypto/rng.c') diff --git a/crypto/rng.c b/crypto/rng.c index 87fa2f49..4514d375 100644 --- a/crypto/rng.c +++ b/crypto/rng.c @@ -36,6 +36,12 @@ static inline struct crypto_rng *__crypto_rng_cast(struct crypto_tfm *tfm) return container_of(tfm, struct crypto_rng, base); } +static int generate(struct crypto_rng *tfm, const u8 *src, unsigned int slen, + u8 *dst, unsigned int dlen) +{ + return crypto_rng_alg(tfm)->rng_make_random(tfm, dst, dlen); +} + static int rngapi_reset(struct crypto_rng *tfm, u8 *seed, unsigned int slen) { u8 *buf = NULL; @@ -59,9 +65,8 @@ static int rngapi_reset(struct crypto_rng *tfm, u8 *seed, unsigned int slen) static int crypto_rng_init_tfm(struct crypto_tfm *tfm) { struct crypto_rng *rng = __crypto_rng_cast(tfm); - struct rng_alg *alg = &tfm->__crt_alg->cra_rng; - rng->generate = alg->rng_make_random; + rng->generate = generate; rng->seed = rngapi_reset; return 0; -- cgit v1.2.3 From 3e1a4d829fecfd7d9127b9ca24e0b58ad68b4d08 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Tue, 21 Apr 2015 10:46:37 +0800 Subject: crypto: rng - Mark crypto_rng_reset seed as const There is no reason why crypto_rng_reset should modify the seed so this patch marks it as const. Since our algorithms don't export a const seed function yet we have to go through some contortions for now. Signed-off-by: Herbert Xu --- crypto/rng.c | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) (limited to 'crypto/rng.c') diff --git a/crypto/rng.c b/crypto/rng.c index 4514d375..f1d64948 100644 --- a/crypto/rng.c +++ b/crypto/rng.c @@ -42,7 +42,29 @@ static int generate(struct crypto_rng *tfm, const u8 *src, unsigned int slen, return crypto_rng_alg(tfm)->rng_make_random(tfm, dst, dlen); } -static int rngapi_reset(struct crypto_rng *tfm, u8 *seed, unsigned int slen) +static int rngapi_reset(struct crypto_rng *tfm, const u8 *seed, + unsigned int slen) +{ + u8 *buf = NULL; + u8 *src = (u8 *)seed; + int err; + + if (slen) { + buf = kmalloc(slen, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + memcpy(buf, seed, slen); + src = buf; + } + + err = crypto_rng_alg(tfm)->rng_reset(tfm, src, slen); + + kzfree(buf); + return err; +} + +int crypto_rng_reset(struct crypto_rng *tfm, const u8 *seed, unsigned int slen) { u8 *buf = NULL; int err; @@ -56,11 +78,12 @@ static int rngapi_reset(struct crypto_rng *tfm, u8 *seed, unsigned int slen) seed = buf; } - err = crypto_rng_alg(tfm)->rng_reset(tfm, seed, slen); + err = tfm->seed(tfm, seed, slen); kfree(buf); return err; } +EXPORT_SYMBOL_GPL(crypto_rng_reset); static int crypto_rng_init_tfm(struct crypto_tfm *tfm) { -- cgit v1.2.3 From 67ea60f16b21a872f5563d8343cd0098fb5c7964 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Tue, 21 Apr 2015 10:46:38 +0800 Subject: crypto: rng - Convert low-level crypto_rng to new style This patch converts the low-level crypto_rng interface to the "new" style. This allows existing implementations to be converted over one- by-one. Once that is complete we can then remove the old rng interface. Signed-off-by: Herbert Xu --- crypto/rng.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 50 insertions(+), 6 deletions(-) (limited to 'crypto/rng.c') diff --git a/crypto/rng.c b/crypto/rng.c index f1d64948..5e0425a2 100644 --- a/crypto/rng.c +++ b/crypto/rng.c @@ -36,10 +36,15 @@ static inline struct crypto_rng *__crypto_rng_cast(struct crypto_tfm *tfm) return container_of(tfm, struct crypto_rng, base); } +static inline struct old_rng_alg *crypto_old_rng_alg(struct crypto_rng *tfm) +{ + return &crypto_rng_tfm(tfm)->__crt_alg->cra_rng; +} + static int generate(struct crypto_rng *tfm, const u8 *src, unsigned int slen, u8 *dst, unsigned int dlen) { - return crypto_rng_alg(tfm)->rng_make_random(tfm, dst, dlen); + return crypto_old_rng_alg(tfm)->rng_make_random(tfm, dst, dlen); } static int rngapi_reset(struct crypto_rng *tfm, const u8 *seed, @@ -58,7 +63,7 @@ static int rngapi_reset(struct crypto_rng *tfm, const u8 *seed, src = buf; } - err = crypto_rng_alg(tfm)->rng_reset(tfm, src, slen); + err = crypto_old_rng_alg(tfm)->rng_reset(tfm, src, slen); kzfree(buf); return err; @@ -88,13 +93,31 @@ EXPORT_SYMBOL_GPL(crypto_rng_reset); static int crypto_rng_init_tfm(struct crypto_tfm *tfm) { struct crypto_rng *rng = __crypto_rng_cast(tfm); + struct rng_alg *alg = crypto_rng_alg(rng); + struct old_rng_alg *oalg = crypto_old_rng_alg(rng); + + if (oalg->rng_make_random) { + rng->generate = generate; + rng->seed = rngapi_reset; + rng->seedsize = oalg->seedsize; + return 0; + } - rng->generate = generate; - rng->seed = rngapi_reset; + rng->generate = alg->generate; + rng->seed = alg->seed; + rng->seedsize = alg->seedsize; return 0; } +static unsigned int seedsize(struct crypto_alg *alg) +{ + struct rng_alg *ralg = container_of(alg, struct rng_alg, base); + + return alg->cra_rng.rng_make_random ? + alg->cra_rng.seedsize : ralg->seedsize; +} + #ifdef CONFIG_NET static int crypto_rng_report(struct sk_buff *skb, struct crypto_alg *alg) { @@ -102,7 +125,7 @@ static int crypto_rng_report(struct sk_buff *skb, struct crypto_alg *alg) strncpy(rrng.type, "rng", sizeof(rrng.type)); - rrng.seedsize = alg->cra_rng.seedsize; + rrng.seedsize = seedsize(alg); if (nla_put(skb, CRYPTOCFGA_REPORT_RNG, sizeof(struct crypto_report_rng), &rrng)) @@ -124,7 +147,7 @@ static void crypto_rng_show(struct seq_file *m, struct crypto_alg *alg) static void crypto_rng_show(struct seq_file *m, struct crypto_alg *alg) { seq_printf(m, "type : rng\n"); - seq_printf(m, "seedsize : %u\n", alg->cra_rng.seedsize); + seq_printf(m, "seedsize : %u\n", seedsize(alg)); } const struct crypto_type crypto_rng_type = { @@ -189,5 +212,26 @@ void crypto_put_default_rng(void) } EXPORT_SYMBOL_GPL(crypto_put_default_rng); +int crypto_register_rng(struct rng_alg *alg) +{ + struct crypto_alg *base = &alg->base; + + if (alg->seedsize > PAGE_SIZE / 8) + return -EINVAL; + + base->cra_type = &crypto_rng_type; + base->cra_flags &= ~CRYPTO_ALG_TYPE_MASK; + base->cra_flags |= CRYPTO_ALG_TYPE_RNG; + + return crypto_register_alg(base); +} +EXPORT_SYMBOL_GPL(crypto_register_rng); + +void crypto_unregister_rng(struct rng_alg *alg) +{ + crypto_unregister_alg(&alg->base); +} +EXPORT_SYMBOL_GPL(crypto_unregister_rng); + MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Random Number Generator"); -- cgit v1.2.3 From ad9488be606afa90da985e7023c0afbb03bd32c6 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Tue, 21 Apr 2015 10:46:40 +0800 Subject: crypto: rng - Add multiple algorithm registration interface This patch adds the helpers that allow the registration and removal of multiple RNG algorithms. Signed-off-by: Herbert Xu --- crypto/rng.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'crypto/rng.c') diff --git a/crypto/rng.c b/crypto/rng.c index 5e0425a2..e98ce1ca 100644 --- a/crypto/rng.c +++ b/crypto/rng.c @@ -233,5 +233,34 @@ void crypto_unregister_rng(struct rng_alg *alg) } EXPORT_SYMBOL_GPL(crypto_unregister_rng); +int crypto_register_rngs(struct rng_alg *algs, int count) +{ + int i, ret; + + for (i = 0; i < count; i++) { + ret = crypto_register_rng(algs + i); + if (ret) + goto err; + } + + return 0; + +err: + for (--i; i >= 0; --i) + crypto_unregister_rng(algs + i); + + return ret; +} +EXPORT_SYMBOL_GPL(crypto_register_rngs); + +void crypto_unregister_rngs(struct rng_alg *algs, int count) +{ + int i; + + for (i = count - 1; i >= 0; --i) + crypto_unregister_rng(algs + i); +} +EXPORT_SYMBOL_GPL(crypto_unregister_rngs); + MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Random Number Generator"); -- cgit v1.2.3 From f7da2d8decf2c87176db5a50558e0bc92369e3e1 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Tue, 21 Apr 2015 10:46:46 +0800 Subject: crypto: rng - Remove old low-level rng interface Now that all rng implementations have switched over to the new interface, we can remove the old low-level interface. Signed-off-by: Herbert Xu --- crypto/rng.c | 57 ++++----------------------------------------------------- 1 file changed, 4 insertions(+), 53 deletions(-) (limited to 'crypto/rng.c') diff --git a/crypto/rng.c b/crypto/rng.c index e98ce1ca..055e2764 100644 --- a/crypto/rng.c +++ b/crypto/rng.c @@ -4,6 +4,7 @@ * RNG operations. * * Copyright (c) 2008 Neil Horman + * Copyright (c) 2015 Herbert Xu * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -36,39 +37,6 @@ static inline struct crypto_rng *__crypto_rng_cast(struct crypto_tfm *tfm) return container_of(tfm, struct crypto_rng, base); } -static inline struct old_rng_alg *crypto_old_rng_alg(struct crypto_rng *tfm) -{ - return &crypto_rng_tfm(tfm)->__crt_alg->cra_rng; -} - -static int generate(struct crypto_rng *tfm, const u8 *src, unsigned int slen, - u8 *dst, unsigned int dlen) -{ - return crypto_old_rng_alg(tfm)->rng_make_random(tfm, dst, dlen); -} - -static int rngapi_reset(struct crypto_rng *tfm, const u8 *seed, - unsigned int slen) -{ - u8 *buf = NULL; - u8 *src = (u8 *)seed; - int err; - - if (slen) { - buf = kmalloc(slen, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - memcpy(buf, seed, slen); - src = buf; - } - - err = crypto_old_rng_alg(tfm)->rng_reset(tfm, src, slen); - - kzfree(buf); - return err; -} - int crypto_rng_reset(struct crypto_rng *tfm, const u8 *seed, unsigned int slen) { u8 *buf = NULL; @@ -83,7 +51,7 @@ int crypto_rng_reset(struct crypto_rng *tfm, const u8 *seed, unsigned int slen) seed = buf; } - err = tfm->seed(tfm, seed, slen); + err = crypto_rng_alg(tfm)->seed(tfm, seed, slen); kfree(buf); return err; @@ -92,21 +60,6 @@ EXPORT_SYMBOL_GPL(crypto_rng_reset); static int crypto_rng_init_tfm(struct crypto_tfm *tfm) { - struct crypto_rng *rng = __crypto_rng_cast(tfm); - struct rng_alg *alg = crypto_rng_alg(rng); - struct old_rng_alg *oalg = crypto_old_rng_alg(rng); - - if (oalg->rng_make_random) { - rng->generate = generate; - rng->seed = rngapi_reset; - rng->seedsize = oalg->seedsize; - return 0; - } - - rng->generate = alg->generate; - rng->seed = alg->seed; - rng->seedsize = alg->seedsize; - return 0; } @@ -114,8 +67,7 @@ static unsigned int seedsize(struct crypto_alg *alg) { struct rng_alg *ralg = container_of(alg, struct rng_alg, base); - return alg->cra_rng.rng_make_random ? - alg->cra_rng.seedsize : ralg->seedsize; + return ralg->seedsize; } #ifdef CONFIG_NET @@ -150,7 +102,7 @@ static void crypto_rng_show(struct seq_file *m, struct crypto_alg *alg) seq_printf(m, "seedsize : %u\n", seedsize(alg)); } -const struct crypto_type crypto_rng_type = { +static const struct crypto_type crypto_rng_type = { .extsize = crypto_alg_extsize, .init_tfm = crypto_rng_init_tfm, #ifdef CONFIG_PROC_FS @@ -162,7 +114,6 @@ const struct crypto_type crypto_rng_type = { .type = CRYPTO_ALG_TYPE_RNG, .tfmsize = offsetof(struct crypto_rng, base), }; -EXPORT_SYMBOL_GPL(crypto_rng_type); struct crypto_rng *crypto_alloc_rng(const char *alg_name, u32 type, u32 mask) { -- cgit v1.2.3 From 866a50cce1f2f8f56910b4a4168f019eef9dac7e Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Tue, 21 Apr 2015 10:46:49 +0800 Subject: crypto: rng - Zero seed in crypto_rng_reset If we allocate a seed on behalf ot the user in crypto_rng_reset, we must ensure that it is zeroed afterwards or the RNG may be compromised. Reported-by: Stephan Mueller Signed-off-by: Herbert Xu --- crypto/rng.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'crypto/rng.c') diff --git a/crypto/rng.c b/crypto/rng.c index 055e2764..13155058 100644 --- a/crypto/rng.c +++ b/crypto/rng.c @@ -53,7 +53,7 @@ int crypto_rng_reset(struct crypto_rng *tfm, const u8 *seed, unsigned int slen) err = crypto_rng_alg(tfm)->seed(tfm, seed, slen); - kfree(buf); + kzfree(buf); return err; } EXPORT_SYMBOL_GPL(crypto_rng_reset); -- cgit v1.2.3 From 68932e3c35878466fb98ef8007457a2b839f1874 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sun, 21 Jun 2015 19:11:43 +0800 Subject: crypto: rng - Do not free default RNG when it becomes unused Currently we free the default RNG when its use count hits zero. This was OK when the IV generators would latch onto the RNG at instance creation time and keep it until the instance is torn down. Now that IV generators only keep the RNG reference during init time this scheme causes the default RNG to come and go at a high frequencey. This is highly undesirable as we want to keep a single RNG in use unless the admin wants it to be removed. This patch changes the scheme so that the system RNG once allocated is never removed unless a specifically requested. Signed-off-by: Herbert Xu --- crypto/rng.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) (limited to 'crypto/rng.c') diff --git a/crypto/rng.c b/crypto/rng.c index 13155058..b81cffb1 100644 --- a/crypto/rng.c +++ b/crypto/rng.c @@ -155,14 +155,33 @@ EXPORT_SYMBOL_GPL(crypto_get_default_rng); void crypto_put_default_rng(void) { mutex_lock(&crypto_default_rng_lock); - if (!--crypto_default_rng_refcnt) { - crypto_free_rng(crypto_default_rng); - crypto_default_rng = NULL; - } + crypto_default_rng_refcnt--; mutex_unlock(&crypto_default_rng_lock); } EXPORT_SYMBOL_GPL(crypto_put_default_rng); +#if defined(CONFIG_CRYPTO_RNG) || defined(CONFIG_CRYPTO_RNG_MODULE) +int crypto_del_default_rng(void) +{ + int err = -EBUSY; + + mutex_lock(&crypto_default_rng_lock); + if (crypto_default_rng_refcnt) + goto out; + + crypto_free_rng(crypto_default_rng); + crypto_default_rng = NULL; + + err = 0; + +out: + mutex_unlock(&crypto_default_rng_lock); + + return err; +} +EXPORT_SYMBOL_GPL(crypto_del_default_rng); +#endif + int crypto_register_rng(struct rng_alg *alg) { struct crypto_alg *base = &alg->base; -- cgit v1.2.3