2012-03-26 07:27:36

by Steffen Klassert

[permalink] [raw]
Subject: [PATCH 1/2] crypto: user - Fix lookup of algorithms with IV generator

We lookup algorithms with crypto_alg_mod_lookup() when instantiating via
crypto_add_alg(). However, algorithms that are wrapped by an IV genearator
(e.g. aead or givcipher type algorithms) need special care. The userspace
process hangs until it gets a timeout when we use crypto_alg_mod_lookup()
to lookup these algorithms. So export the lookup functions for these
algorithms and use them when instantiating via crypto_add_alg().

Signed-off-by: Steffen Klassert <[email protected]>
---
crypto/ablkcipher.c | 4 +-
crypto/aead.c | 4 +-
crypto/crypto_user.c | 71 +++++++++++++++++++++++++++++++++++-
include/crypto/internal/aead.h | 2 +
include/crypto/internal/skcipher.h | 2 +
5 files changed, 78 insertions(+), 5 deletions(-)

diff --git a/crypto/ablkcipher.c b/crypto/ablkcipher.c
index a0f768c..8d3a056 100644
--- a/crypto/ablkcipher.c
+++ b/crypto/ablkcipher.c
@@ -613,8 +613,7 @@ out:
return err;
}

-static struct crypto_alg *crypto_lookup_skcipher(const char *name, u32 type,
- u32 mask)
+struct crypto_alg *crypto_lookup_skcipher(const char *name, u32 type, u32 mask)
{
struct crypto_alg *alg;

@@ -652,6 +651,7 @@ static struct crypto_alg *crypto_lookup_skcipher(const char *name, u32 type,

return ERR_PTR(crypto_givcipher_default(alg, type, mask));
}
+EXPORT_SYMBOL_GPL(crypto_lookup_skcipher);

int crypto_grab_skcipher(struct crypto_skcipher_spawn *spawn, const char *name,
u32 type, u32 mask)
diff --git a/crypto/aead.c b/crypto/aead.c
index 04add3d..e4cb351 100644
--- a/crypto/aead.c
+++ b/crypto/aead.c
@@ -470,8 +470,7 @@ out:
return err;
}

-static struct crypto_alg *crypto_lookup_aead(const char *name, u32 type,
- u32 mask)
+struct crypto_alg *crypto_lookup_aead(const char *name, u32 type, u32 mask)
{
struct crypto_alg *alg;

@@ -503,6 +502,7 @@ static struct crypto_alg *crypto_lookup_aead(const char *name, u32 type,

return ERR_PTR(crypto_nivaead_default(alg, type, mask));
}
+EXPORT_SYMBOL_GPL(crypto_lookup_aead);

int crypto_grab_aead(struct crypto_aead_spawn *spawn, const char *name,
u32 type, u32 mask)
diff --git a/crypto/crypto_user.c b/crypto/crypto_user.c
index 3e61cc1..38534aa 100644
--- a/crypto/crypto_user.c
+++ b/crypto/crypto_user.c
@@ -24,6 +24,9 @@
#include <net/netlink.h>
#include <linux/security.h>
#include <net/net_namespace.h>
+#include <crypto/internal/aead.h>
+#include <crypto/internal/skcipher.h>
+
#include "internal.h"

DEFINE_MUTEX(crypto_cfg_mutex);
@@ -301,6 +304,60 @@ static int crypto_del_alg(struct sk_buff *skb, struct nlmsghdr *nlh,
return crypto_unregister_instance(alg);
}

+static struct crypto_alg *crypto_user_skcipher_alg(const char *name, u32 type,
+ u32 mask)
+{
+ int err;
+ struct crypto_alg *alg;
+
+ type = crypto_skcipher_type(type);
+ mask = crypto_skcipher_mask(mask);
+
+ for (;;) {
+ alg = crypto_lookup_skcipher(name, type, mask);
+ if (!IS_ERR(alg))
+ return alg;
+
+ err = PTR_ERR(alg);
+ if (err != -EAGAIN)
+ break;
+ if (signal_pending(current)) {
+ err = -EINTR;
+ break;
+ }
+ }
+
+ return ERR_PTR(err);
+}
+
+static struct crypto_alg *crypto_user_aead_alg(const char *name, u32 type,
+ u32 mask)
+{
+ int err;
+ struct crypto_alg *alg;
+
+ type &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV);
+ type |= CRYPTO_ALG_TYPE_AEAD;
+ mask &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV);
+ mask |= CRYPTO_ALG_TYPE_MASK;
+
+ for (;;) {
+ alg = crypto_lookup_aead(name, type, mask);
+ if (!IS_ERR(alg))
+ return alg;
+
+ err = PTR_ERR(alg);
+ if (err != -EAGAIN)
+ break;
+ if (signal_pending(current)) {
+ err = -EINTR;
+ break;
+ }
+ }
+
+ return ERR_PTR(err);
+}
+
static int crypto_add_alg(struct sk_buff *skb, struct nlmsghdr *nlh,
struct nlattr **attrs)
{
@@ -325,7 +382,19 @@ static int crypto_add_alg(struct sk_buff *skb, struct nlmsghdr *nlh,
else
name = p->cru_name;

- alg = crypto_alg_mod_lookup(name, p->cru_type, p->cru_mask);
+ switch (p->cru_type & p->cru_mask & CRYPTO_ALG_TYPE_MASK) {
+ case CRYPTO_ALG_TYPE_AEAD:
+ alg = crypto_user_aead_alg(name, p->cru_type, p->cru_mask);
+ break;
+ case CRYPTO_ALG_TYPE_GIVCIPHER:
+ case CRYPTO_ALG_TYPE_BLKCIPHER:
+ case CRYPTO_ALG_TYPE_ABLKCIPHER:
+ alg = crypto_user_skcipher_alg(name, p->cru_type, p->cru_mask);
+ break;
+ default:
+ alg = crypto_alg_mod_lookup(name, p->cru_type, p->cru_mask);
+ }
+
if (IS_ERR(alg))
return PTR_ERR(alg);

diff --git a/include/crypto/internal/aead.h b/include/crypto/internal/aead.h
index d838c94..2eba340 100644
--- a/include/crypto/internal/aead.h
+++ b/include/crypto/internal/aead.h
@@ -31,6 +31,8 @@ static inline void crypto_set_aead_spawn(
crypto_set_spawn(&spawn->base, inst);
}

+struct crypto_alg *crypto_lookup_aead(const char *name, u32 type, u32 mask);
+
int crypto_grab_aead(struct crypto_aead_spawn *spawn, const char *name,
u32 type, u32 mask);

diff --git a/include/crypto/internal/skcipher.h b/include/crypto/internal/skcipher.h
index 3a748a6..06e8b32 100644
--- a/include/crypto/internal/skcipher.h
+++ b/include/crypto/internal/skcipher.h
@@ -34,6 +34,8 @@ static inline void crypto_set_skcipher_spawn(
int crypto_grab_skcipher(struct crypto_skcipher_spawn *spawn, const char *name,
u32 type, u32 mask);

+struct crypto_alg *crypto_lookup_skcipher(const char *name, u32 type, u32 mask);
+
static inline void crypto_drop_skcipher(struct crypto_skcipher_spawn *spawn)
{
crypto_drop_spawn(&spawn->base);
--
1.7.0.4


2012-03-26 07:28:33

by Steffen Klassert

[permalink] [raw]
Subject: [PATCH 2/2] crypto: user - Fix size of netlink dump message

The default netlink message size limit might be exceeded when dumping a
lot of algorithms to userspace. As a result, not all of the instantiated
algorithms dumped to userspace. So calculate an upper bound on the message
size and call netlink_dump_start() with that value.

Signed-off-by: Steffen Klassert <[email protected]>
---
crypto/crypto_user.c | 8 +++++++-
include/linux/cryptouser.h | 3 +++
2 files changed, 10 insertions(+), 1 deletions(-)

diff --git a/crypto/crypto_user.c b/crypto/crypto_user.c
index 38534aa..7fca04c 100644
--- a/crypto/crypto_user.c
+++ b/crypto/crypto_user.c
@@ -456,11 +456,17 @@ static int crypto_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)

if ((type == (CRYPTO_MSG_GETALG - CRYPTO_MSG_BASE) &&
(nlh->nlmsg_flags & NLM_F_DUMP))) {
+ struct crypto_alg *alg;
+ u16 dump_alloc = 0;
+
if (link->dump == NULL)
return -EINVAL;

+ list_for_each_entry(alg, &crypto_alg_list, cra_list)
+ dump_alloc += CRYPTO_REPORT_MAXSIZE;
+
return netlink_dump_start(crypto_nlsk, skb, nlh,
- link->dump, link->done, 0);
+ link->dump, link->done, dump_alloc);
}

err = nlmsg_parse(nlh, crypto_msg_min[type], attrs, CRYPTOCFGA_MAX,
diff --git a/include/linux/cryptouser.h b/include/linux/cryptouser.h
index 532fb58..4abf2ea 100644
--- a/include/linux/cryptouser.h
+++ b/include/linux/cryptouser.h
@@ -100,3 +100,6 @@ struct crypto_report_rng {
char type[CRYPTO_MAX_NAME];
unsigned int seedsize;
};
+
+#define CRYPTO_REPORT_MAXSIZE (sizeof(struct crypto_user_alg) + \
+ sizeof(struct crypto_report_blkcipher))
--
1.7.0.4

2012-03-29 05:45:10

by Steffen Klassert

[permalink] [raw]
Subject: Re: [PATCH 2/2] crypto: user - Fix size of netlink dump message

On Mon, Mar 26, 2012 at 09:28:27AM +0200, Steffen Klassert wrote:
> +
> return netlink_dump_start(crypto_nlsk, skb, nlh,
> - link->dump, link->done, 0);
> + link->dump, link->done, dump_alloc);

I've just noticed that the interface to netlink_dump_start() changed in
the mainline (with commit 80d326fab534a5380e8f6e509a0b9076655a9670), so
this will cause a conflict. The crypto-2.6 tree is way behind the mainline
(v3.2 + some patches). Could you please update the crypto-2.6 tree so that
I can respin this patch?

Thanks!

2012-03-29 05:46:28

by Herbert Xu

[permalink] [raw]
Subject: Re: [PATCH 2/2] crypto: user - Fix size of netlink dump message

On Thu, Mar 29, 2012 at 07:45:04AM +0200, Steffen Klassert wrote:
> On Mon, Mar 26, 2012 at 09:28:27AM +0200, Steffen Klassert wrote:
> > +
> > return netlink_dump_start(crypto_nlsk, skb, nlh,
> > - link->dump, link->done, 0);
> > + link->dump, link->done, dump_alloc);
>
> I've just noticed that the interface to netlink_dump_start() changed in
> the mainline (with commit 80d326fab534a5380e8f6e509a0b9076655a9670), so
> this will cause a conflict. The crypto-2.6 tree is way behind the mainline
> (v3.2 + some patches). Could you please update the crypto-2.6 tree so that
> I can respin this patch?


As long as your patch is against mainline it should be fine. I will
rebase cryptodev before applying any patches for the next release.

Cheers,
--
Email: Herbert Xu <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

2012-03-29 05:53:33

by Steffen Klassert

[permalink] [raw]
Subject: Re: [PATCH 2/2] crypto: user - Fix size of netlink dump message

On Thu, Mar 29, 2012 at 01:46:26PM +0800, Herbert Xu wrote:
> On Thu, Mar 29, 2012 at 07:45:04AM +0200, Steffen Klassert wrote:
> > On Mon, Mar 26, 2012 at 09:28:27AM +0200, Steffen Klassert wrote:
> > > +
> > > return netlink_dump_start(crypto_nlsk, skb, nlh,
> > > - link->dump, link->done, 0);
> > > + link->dump, link->done, dump_alloc);
> >
> > I've just noticed that the interface to netlink_dump_start() changed in
> > the mainline (with commit 80d326fab534a5380e8f6e509a0b9076655a9670), so
> > this will cause a conflict. The crypto-2.6 tree is way behind the mainline
> > (v3.2 + some patches). Could you please update the crypto-2.6 tree so that
> > I can respin this patch?
>
>
> As long as your patch is against mainline it should be fine. I will
> rebase cryptodev before applying any patches for the next release.
>

Ok, so I'll respin this one to the mainline and resend.
Anyway, would be nice to see this fix in v3.4.

2012-03-29 06:58:31

by Steffen Klassert

[permalink] [raw]
Subject: Re: [PATCH 2/2] crypto: user - Fix size of netlink dump message

On Thu, Mar 29, 2012 at 07:53:30AM +0200, Steffen Klassert wrote:
>
> Ok, so I'll respin this one to the mainline and resend.

I'll resend the whole patchset, please ignore this one.

Thanks!