aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteffen Klassert <steffen.klassert@secunet.com>2012-03-29 03:03:47 -0400
committerHerbert Xu <herbert@gondor.apana.org.au>2012-03-29 07:52:47 -0400
commit1e1229940045a537c61fb69f86010a8774e576d0 (patch)
tree3a594eef2d1cda7e49f7b62f70853d6f6a021d61
parentfbf0ca1bf852fe224cec5400a69cd755ddc4ddcb (diff)
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>
-rw-r--r--crypto/ablkcipher.c4
-rw-r--r--crypto/aead.c4
-rw-r--r--crypto/crypto_user.c72
-rw-r--r--include/crypto/internal/aead.h2
-rw-r--r--include/crypto/internal/skcipher.h2
5 files changed, 79 insertions, 5 deletions
diff --git a/crypto/ablkcipher.c b/crypto/ablkcipher.c
index a0f768c1d9a..8d3a056ebee 100644
--- a/crypto/ablkcipher.c
+++ b/crypto/ablkcipher.c
@@ -613,8 +613,7 @@ out:
613 return err; 613 return err;
614} 614}
615 615
616static struct crypto_alg *crypto_lookup_skcipher(const char *name, u32 type, 616struct crypto_alg *crypto_lookup_skcipher(const char *name, u32 type, u32 mask)
617 u32 mask)
618{ 617{
619 struct crypto_alg *alg; 618 struct crypto_alg *alg;
620 619
@@ -652,6 +651,7 @@ static struct crypto_alg *crypto_lookup_skcipher(const char *name, u32 type,
652 651
653 return ERR_PTR(crypto_givcipher_default(alg, type, mask)); 652 return ERR_PTR(crypto_givcipher_default(alg, type, mask));
654} 653}
654EXPORT_SYMBOL_GPL(crypto_lookup_skcipher);
655 655
656int crypto_grab_skcipher(struct crypto_skcipher_spawn *spawn, const char *name, 656int crypto_grab_skcipher(struct crypto_skcipher_spawn *spawn, const char *name,
657 u32 type, u32 mask) 657 u32 type, u32 mask)
diff --git a/crypto/aead.c b/crypto/aead.c
index 04add3dca6f..e4cb35159be 100644
--- a/crypto/aead.c
+++ b/crypto/aead.c
@@ -470,8 +470,7 @@ out:
470 return err; 470 return err;
471} 471}
472 472
473static struct crypto_alg *crypto_lookup_aead(const char *name, u32 type, 473struct crypto_alg *crypto_lookup_aead(const char *name, u32 type, u32 mask)
474 u32 mask)
475{ 474{
476 struct crypto_alg *alg; 475 struct crypto_alg *alg;
477 476
@@ -503,6 +502,7 @@ static struct crypto_alg *crypto_lookup_aead(const char *name, u32 type,
503 502
504 return ERR_PTR(crypto_nivaead_default(alg, type, mask)); 503 return ERR_PTR(crypto_nivaead_default(alg, type, mask));
505} 504}
505EXPORT_SYMBOL_GPL(crypto_lookup_aead);
506 506
507int crypto_grab_aead(struct crypto_aead_spawn *spawn, const char *name, 507int crypto_grab_aead(struct crypto_aead_spawn *spawn, const char *name,
508 u32 type, u32 mask) 508 u32 type, u32 mask)
diff --git a/crypto/crypto_user.c b/crypto/crypto_user.c
index f76e42bcc6e..e91c16111ed 100644
--- a/crypto/crypto_user.c
+++ b/crypto/crypto_user.c
@@ -21,9 +21,13 @@
21#include <linux/module.h> 21#include <linux/module.h>
22#include <linux/crypto.h> 22#include <linux/crypto.h>
23#include <linux/cryptouser.h> 23#include <linux/cryptouser.h>
24#include <linux/sched.h>
24#include <net/netlink.h> 25#include <net/netlink.h>
25#include <linux/security.h> 26#include <linux/security.h>
26#include <net/net_namespace.h> 27#include <net/net_namespace.h>
28#include <crypto/internal/aead.h>
29#include <crypto/internal/skcipher.h>
30
27#include "internal.h" 31#include "internal.h"
28 32
29DEFINE_MUTEX(crypto_cfg_mutex); 33DEFINE_MUTEX(crypto_cfg_mutex);
@@ -301,6 +305,60 @@ static int crypto_del_alg(struct sk_buff *skb, struct nlmsghdr *nlh,
301 return crypto_unregister_instance(alg); 305 return crypto_unregister_instance(alg);
302} 306}
303 307
308static struct crypto_alg *crypto_user_skcipher_alg(const char *name, u32 type,
309 u32 mask)
310{
311 int err;
312 struct crypto_alg *alg;
313
314 type = crypto_skcipher_type(type);
315 mask = crypto_skcipher_mask(mask);
316
317 for (;;) {
318 alg = crypto_lookup_skcipher(name, type, mask);
319 if (!IS_ERR(alg))
320 return alg;
321
322 err = PTR_ERR(alg);
323 if (err != -EAGAIN)
324 break;
325 if (signal_pending(current)) {
326 err = -EINTR;
327 break;
328 }
329 }
330
331 return ERR_PTR(err);
332}
333
334static struct crypto_alg *crypto_user_aead_alg(const char *name, u32 type,
335 u32 mask)
336{
337 int err;
338 struct crypto_alg *alg;
339
340 type &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV);
341 type |= CRYPTO_ALG_TYPE_AEAD;
342 mask &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV);
343 mask |= CRYPTO_ALG_TYPE_MASK;
344
345 for (;;) {
346 alg = crypto_lookup_aead(name, type, mask);
347 if (!IS_ERR(alg))
348 return alg;
349
350 err = PTR_ERR(alg);
351 if (err != -EAGAIN)
352 break;
353 if (signal_pending(current)) {
354 err = -EINTR;
355 break;
356 }
357 }
358
359 return ERR_PTR(err);
360}
361
304static int crypto_add_alg(struct sk_buff *skb, struct nlmsghdr *nlh, 362static int crypto_add_alg(struct sk_buff *skb, struct nlmsghdr *nlh,
305 struct nlattr **attrs) 363 struct nlattr **attrs)
306{ 364{
@@ -325,7 +383,19 @@ static int crypto_add_alg(struct sk_buff *skb, struct nlmsghdr *nlh,
325 else 383 else
326 name = p->cru_name; 384 name = p->cru_name;
327 385
328 alg = crypto_alg_mod_lookup(name, p->cru_type, p->cru_mask); 386 switch (p->cru_type & p->cru_mask & CRYPTO_ALG_TYPE_MASK) {
387 case CRYPTO_ALG_TYPE_AEAD:
388 alg = crypto_user_aead_alg(name, p->cru_type, p->cru_mask);
389 break;
390 case CRYPTO_ALG_TYPE_GIVCIPHER:
391 case CRYPTO_ALG_TYPE_BLKCIPHER:
392 case CRYPTO_ALG_TYPE_ABLKCIPHER:
393 alg = crypto_user_skcipher_alg(name, p->cru_type, p->cru_mask);
394 break;
395 default:
396 alg = crypto_alg_mod_lookup(name, p->cru_type, p->cru_mask);
397 }
398
329 if (IS_ERR(alg)) 399 if (IS_ERR(alg))
330 return PTR_ERR(alg); 400 return PTR_ERR(alg);
331 401
diff --git a/include/crypto/internal/aead.h b/include/crypto/internal/aead.h
index d838c945575..2eba340230a 100644
--- a/include/crypto/internal/aead.h
+++ b/include/crypto/internal/aead.h
@@ -31,6 +31,8 @@ static inline void crypto_set_aead_spawn(
31 crypto_set_spawn(&spawn->base, inst); 31 crypto_set_spawn(&spawn->base, inst);
32} 32}
33 33
34struct crypto_alg *crypto_lookup_aead(const char *name, u32 type, u32 mask);
35
34int crypto_grab_aead(struct crypto_aead_spawn *spawn, const char *name, 36int crypto_grab_aead(struct crypto_aead_spawn *spawn, const char *name,
35 u32 type, u32 mask); 37 u32 type, u32 mask);
36 38
diff --git a/include/crypto/internal/skcipher.h b/include/crypto/internal/skcipher.h
index 3a748a6bf77..06e8b32d541 100644
--- a/include/crypto/internal/skcipher.h
+++ b/include/crypto/internal/skcipher.h
@@ -34,6 +34,8 @@ static inline void crypto_set_skcipher_spawn(
34int crypto_grab_skcipher(struct crypto_skcipher_spawn *spawn, const char *name, 34int crypto_grab_skcipher(struct crypto_skcipher_spawn *spawn, const char *name,
35 u32 type, u32 mask); 35 u32 type, u32 mask);
36 36
37struct crypto_alg *crypto_lookup_skcipher(const char *name, u32 type, u32 mask);
38
37static inline void crypto_drop_skcipher(struct crypto_skcipher_spawn *spawn) 39static inline void crypto_drop_skcipher(struct crypto_skcipher_spawn *spawn)
38{ 40{
39 crypto_drop_spawn(&spawn->base); 41 crypto_drop_spawn(&spawn->base);