|
@@ -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);
|
|
@@ -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)
|
|
|
{
|
|
@@ -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);
|
|
|
|