diff mbox

[v3,1/4] crypto: add template handling for RNGs

Message ID 2944776.2qGGKJgDkv@positron.chronox.de (mailing list archive)
State Changes Requested
Delegated to: Herbert Xu
Headers show

Commit Message

Stephan Mueller July 12, 2016, 9:07 a.m. UTC
This patch adds the ability to register templates for RNGs. RNGs are
"meta" mechanisms using raw cipher primitives. Thus, RNGs can now be
implemented as templates to allow the complete flexibility the kernel
crypto API provides.

Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 crypto/rng.c         | 31 +++++++++++++++++++++++++++++++
 include/crypto/rng.h | 39 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 70 insertions(+)

Comments

Herbert Xu July 18, 2016, 7:14 a.m. UTC | #1
Stephan Mueller <smueller@chronox.de> wrote:
> This patch adds the ability to register templates for RNGs. RNGs are
> "meta" mechanisms using raw cipher primitives. Thus, RNGs can now be
> implemented as templates to allow the complete flexibility the kernel
> crypto API provides.
> 
> Signed-off-by: Stephan Mueller <smueller@chronox.de>
> ---
> crypto/rng.c         | 31 +++++++++++++++++++++++++++++++
> include/crypto/rng.h | 39 +++++++++++++++++++++++++++++++++++++++
> 2 files changed, 70 insertions(+)
> 
> diff --git a/crypto/rng.c b/crypto/rng.c
> index b81cffb..92cc02a 100644
> --- a/crypto/rng.c
> +++ b/crypto/rng.c
> @@ -232,5 +232,36 @@ void crypto_unregister_rngs(struct rng_alg *algs, int count)
> }
> EXPORT_SYMBOL_GPL(crypto_unregister_rngs);
> 
> +void rng_free_instance(struct crypto_instance *inst)
> +{
> +       crypto_drop_spawn(crypto_instance_ctx(inst));
> +       kfree(rng_instance(inst));
> +}

Please use the new free interface, i.e.,

void rng_free_instance(struct rng_instance *inst)

and then

inst->free = rng_free_instance;

> +static inline struct rng_alg *__crypto_rng_alg(struct crypto_alg *alg)
> +{
> +       return container_of(alg, struct rng_alg, base);
> +}
> +
> +static inline struct rng_instance *rng_instance(
> +       struct crypto_instance *inst)
> +{
> +       return container_of(__crypto_rng_alg(&inst->alg),
> +                           struct rng_instance, alg);
> +}

These two can then be deleted.

Thanks,
Stephan Mueller July 18, 2016, 7:18 a.m. UTC | #2
Am Montag, 18. Juli 2016, 15:14:17 schrieb Herbert Xu:

Hi Herbert,
> > 
> > diff --git a/crypto/rng.c b/crypto/rng.c
> > index b81cffb..92cc02a 100644
> > --- a/crypto/rng.c
> > +++ b/crypto/rng.c
> > @@ -232,5 +232,36 @@ void crypto_unregister_rngs(struct rng_alg *algs, int
> > count) }
> > EXPORT_SYMBOL_GPL(crypto_unregister_rngs);
> > 
> > +void rng_free_instance(struct crypto_instance *inst)
> > +{
> > +       crypto_drop_spawn(crypto_instance_ctx(inst));
> > +       kfree(rng_instance(inst));
> > +}
> 
> Please use the new free interface, i.e.,
> 
> void rng_free_instance(struct rng_instance *inst)
> 
> and then
> 
> inst->free = rng_free_instance;
> 
> > +static inline struct rng_alg *__crypto_rng_alg(struct crypto_alg *alg)
> > +{
> > +       return container_of(alg, struct rng_alg, base);
> > +}
> > +
> > +static inline struct rng_instance *rng_instance(
> > +       struct crypto_instance *inst)
> > +{
> > +       return container_of(__crypto_rng_alg(&inst->alg),
> > +                           struct rng_instance, alg);
> > +}
> 
> These two can then be deleted.

Thanks. I will add that to the next round.
> 
> Thanks,


Ciao
Stephan
--
To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sandy Harris July 18, 2016, 3:23 p.m. UTC | #3
On Mon, Jul 18, 2016 at 3:14 AM, Herbert Xu <herbert@gondor.apana.org.au> wrote:
> Stephan Mueller <smueller@chronox.de> wrote:

>> This patch adds the ability to register templates for RNGs. RNGs are
>> "meta" mechanisms using raw cipher primitives. Thus, RNGs can now be
>> implemented as templates to allow the complete flexibility the kernel
>> crypto API provides.

I do not see why this might be desirable, let alone necessary.
Security-critical code should be kept as simple as possible.
Don't we need just one good RNG?
--
To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Stephan Mueller July 18, 2016, 3:37 p.m. UTC | #4
Am Montag, 18. Juli 2016, 11:23:26 schrieb Sandy Harris:

Hi Sandy,

> On Mon, Jul 18, 2016 at 3:14 AM, Herbert Xu <herbert@gondor.apana.org.au> 
wrote:
> > Stephan Mueller <smueller@chronox.de> wrote:
> >> This patch adds the ability to register templates for RNGs. RNGs are
> >> "meta" mechanisms using raw cipher primitives. Thus, RNGs can now be
> >> implemented as templates to allow the complete flexibility the kernel
> >> crypto API provides.
> 
> I do not see why this might be desirable, let alone necessary.
> Security-critical code should be kept as simple as possible.
> Don't we need just one good RNG?

Well, why do we have multiple symmetric ciphers, hashes, or asymmetric 
ciphers? This allows different users to pick the cipher he likes. Maybe there 
is an issue found in one of them and having multiple at the disposal, allows 
an immediate fixing of issues.

Furthermore, the kernel crypto API supports hardware implementations. So, on 
one arch, you may have an accelerated SHA256 whereas on another you have an 
accelerated SHA512. And accelerated implementations are not only useful for 
speed improvements, but for security purposes as well (like cache-attack 
resistance).

This applies to RNGs too. Furthermore, I think an SP800-90A DRBG is a good 
one. But many people find this standard smelly just because of the Dual EC 
fiasco. Or it is smelly because it was developed by the US organization called 
NIST.

At the level of the kernel crypto API, no policies should be enforced. 
Policies (such as what is the "right" cipher) should be defined outside the 
kernel.

Furthermore, the RNG approach shall be usable for mechanisms that act RNG-like 
but are no real RNGs. The prime example as given with the patch set is the 
KDF. A KDF acts like an RNG, but is not considered as one. Now, there are many 
different types of KDFs out there. SP800-108 is one (defining three types), 
SP800-56A defines more.

For the KDF implementation I did not want to hard-wire the KDF logic with a 
defined cipher like SHA-256, but allow the caller to define the used hash. 
Thus I need the plumbing code do to that.

Ciao
Stephan
--
To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/crypto/rng.c b/crypto/rng.c
index b81cffb..92cc02a 100644
--- a/crypto/rng.c
+++ b/crypto/rng.c
@@ -232,5 +232,36 @@  void crypto_unregister_rngs(struct rng_alg *algs, int count)
 }
 EXPORT_SYMBOL_GPL(crypto_unregister_rngs);
 
+void rng_free_instance(struct crypto_instance *inst)
+{
+	crypto_drop_spawn(crypto_instance_ctx(inst));
+	kfree(rng_instance(inst));
+}
+EXPORT_SYMBOL_GPL(rng_free_instance);
+
+static int rng_prepare_alg(struct rng_alg *alg)
+{
+	struct crypto_alg *base = &alg->base;
+
+	base->cra_type = &crypto_rng_type;
+	base->cra_flags &= ~CRYPTO_ALG_TYPE_MASK;
+	base->cra_flags |= CRYPTO_ALG_TYPE_RNG;
+
+	return 0;
+}
+
+int rng_register_instance(struct crypto_template *tmpl,
+			  struct rng_instance *inst)
+{
+	int err;
+
+	err = rng_prepare_alg(&inst->alg);
+	if (err)
+		return err;
+
+	return crypto_register_instance(tmpl, rng_crypto_instance(inst));
+}
+EXPORT_SYMBOL_GPL(rng_register_instance);
+
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Random Number Generator");
diff --git a/include/crypto/rng.h b/include/crypto/rng.h
index b95ede3..b8a6ea3 100644
--- a/include/crypto/rng.h
+++ b/include/crypto/rng.h
@@ -15,6 +15,7 @@ 
 #define _CRYPTO_RNG_H
 
 #include <linux/crypto.h>
+#include <crypto/algapi.h>
 
 struct crypto_rng;
 
@@ -197,4 +198,42 @@  static inline int crypto_rng_seedsize(struct crypto_rng *tfm)
 	return crypto_rng_alg(tfm)->seedsize;
 }
 
+struct rng_instance {
+	struct rng_alg alg;
+};
+
+static inline struct rng_instance *rng_alloc_instance(
+	const char *name, struct crypto_alg *alg)
+{
+	return crypto_alloc_instance2(name, alg,
+				      sizeof(struct rng_alg) - sizeof(*alg));
+}
+
+static inline struct crypto_instance *rng_crypto_instance(
+	struct rng_instance *inst)
+{
+	return container_of(&inst->alg.base, struct crypto_instance, alg);
+}
+
+static inline void *rng_instance_ctx(struct rng_instance *inst)
+{
+	return crypto_instance_ctx(rng_crypto_instance(inst));
+}
+
+static inline struct rng_alg *__crypto_rng_alg(struct crypto_alg *alg)
+{
+	return container_of(alg, struct rng_alg, base);
+}
+
+static inline struct rng_instance *rng_instance(
+	struct crypto_instance *inst)
+{
+	return container_of(__crypto_rng_alg(&inst->alg),
+			    struct rng_instance, alg);
+}
+
+int rng_register_instance(struct crypto_template *tmpl,
+			  struct rng_instance *inst);
+void rng_free_instance(struct crypto_instance *inst);
+
 #endif