Skip to content

Commit

Permalink
crypto: user - Fix lookup of algorithms with IV generator
Browse files Browse the repository at this point in the history
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 genicv 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 in crypto_add_alg().

Signed-off-by: Steffen Klassert <[email protected]>
Signed-off-by: Herbert Xu <[email protected]>
  • Loading branch information
klassert authored and herbertx committed Mar 29, 2012
1 parent fbf0ca1 commit 1e12299
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 5 deletions.
4 changes: 2 additions & 2 deletions crypto/ablkcipher.c
Original file line number Diff line number Diff line change
Expand Up @@ -613,8 +613,7 @@ static int crypto_givcipher_default(struct crypto_alg *alg, u32 type, u32 mask)
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;

Expand Down Expand Up @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions crypto/aead.c
Original file line number Diff line number Diff line change
Expand Up @@ -470,8 +470,7 @@ static int crypto_nivaead_default(struct crypto_alg *alg, u32 type, u32 mask)
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;

Expand Down Expand Up @@ -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)
Expand Down
72 changes: 71 additions & 1 deletion crypto/crypto_user.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,13 @@
#include <linux/module.h>
#include <linux/crypto.h>
#include <linux/cryptouser.h>
#include <linux/sched.h>
#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);
Expand Down Expand Up @@ -301,6 +305,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)
{
Expand All @@ -325,7 +383,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);

Expand Down
2 changes: 2 additions & 0 deletions include/crypto/internal/aead.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
2 changes: 2 additions & 0 deletions include/crypto/internal/skcipher.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit 1e12299

Please sign in to comment.