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 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 <steffen.klassert@secunet.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
This commit is contained in:
parent
fbf0ca1bf8
commit
1e12299400
|
@ -613,8 +613,7 @@ out:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct crypto_alg *crypto_lookup_skcipher(const char *name, u32 type,
|
struct crypto_alg *crypto_lookup_skcipher(const char *name, u32 type, u32 mask)
|
||||||
u32 mask)
|
|
||||||
{
|
{
|
||||||
struct crypto_alg *alg;
|
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));
|
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,
|
int crypto_grab_skcipher(struct crypto_skcipher_spawn *spawn, const char *name,
|
||||||
u32 type, u32 mask)
|
u32 type, u32 mask)
|
||||||
|
|
|
@ -470,8 +470,7 @@ out:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct crypto_alg *crypto_lookup_aead(const char *name, u32 type,
|
struct crypto_alg *crypto_lookup_aead(const char *name, u32 type, u32 mask)
|
||||||
u32 mask)
|
|
||||||
{
|
{
|
||||||
struct crypto_alg *alg;
|
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));
|
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,
|
int crypto_grab_aead(struct crypto_aead_spawn *spawn, const char *name,
|
||||||
u32 type, u32 mask)
|
u32 type, u32 mask)
|
||||||
|
|
|
@ -21,9 +21,13 @@
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/crypto.h>
|
#include <linux/crypto.h>
|
||||||
#include <linux/cryptouser.h>
|
#include <linux/cryptouser.h>
|
||||||
|
#include <linux/sched.h>
|
||||||
#include <net/netlink.h>
|
#include <net/netlink.h>
|
||||||
#include <linux/security.h>
|
#include <linux/security.h>
|
||||||
#include <net/net_namespace.h>
|
#include <net/net_namespace.h>
|
||||||
|
#include <crypto/internal/aead.h>
|
||||||
|
#include <crypto/internal/skcipher.h>
|
||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
DEFINE_MUTEX(crypto_cfg_mutex);
|
DEFINE_MUTEX(crypto_cfg_mutex);
|
||||||
|
@ -301,6 +305,60 @@ static int crypto_del_alg(struct sk_buff *skb, struct nlmsghdr *nlh,
|
||||||
return crypto_unregister_instance(alg);
|
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,
|
static int crypto_add_alg(struct sk_buff *skb, struct nlmsghdr *nlh,
|
||||||
struct nlattr **attrs)
|
struct nlattr **attrs)
|
||||||
{
|
{
|
||||||
|
@ -325,7 +383,19 @@ static int crypto_add_alg(struct sk_buff *skb, struct nlmsghdr *nlh,
|
||||||
else
|
else
|
||||||
name = p->cru_name;
|
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))
|
if (IS_ERR(alg))
|
||||||
return PTR_ERR(alg);
|
return PTR_ERR(alg);
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,8 @@ static inline void crypto_set_aead_spawn(
|
||||||
crypto_set_spawn(&spawn->base, inst);
|
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,
|
int crypto_grab_aead(struct crypto_aead_spawn *spawn, const char *name,
|
||||||
u32 type, u32 mask);
|
u32 type, u32 mask);
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,8 @@ static inline void crypto_set_skcipher_spawn(
|
||||||
int crypto_grab_skcipher(struct crypto_skcipher_spawn *spawn, const char *name,
|
int crypto_grab_skcipher(struct crypto_skcipher_spawn *spawn, const char *name,
|
||||||
u32 type, u32 mask);
|
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)
|
static inline void crypto_drop_skcipher(struct crypto_skcipher_spawn *spawn)
|
||||||
{
|
{
|
||||||
crypto_drop_spawn(&spawn->base);
|
crypto_drop_spawn(&spawn->base);
|
||||||
|
|
Loading…
Reference in New Issue