diff options
author | Steffen Klassert <steffen.klassert@secunet.com> | 2012-03-29 03:03:47 -0400 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2012-03-29 07:52:47 -0400 |
commit | 1e1229940045a537c61fb69f86010a8774e576d0 (patch) | |
tree | 3a594eef2d1cda7e49f7b62f70853d6f6a021d61 /crypto/crypto_user.c | |
parent | fbf0ca1bf852fe224cec5400a69cd755ddc4ddcb (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>
Diffstat (limited to 'crypto/crypto_user.c')
-rw-r--r-- | crypto/crypto_user.c | 72 |
1 files changed, 71 insertions, 1 deletions
diff --git a/crypto/crypto_user.c b/crypto/crypto_user.c index f76e42bcc6e7..e91c16111ed3 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 | ||
29 | DEFINE_MUTEX(crypto_cfg_mutex); | 33 | DEFINE_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 | ||
308 | static 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 | |||
334 | static 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 | |||
304 | static int crypto_add_alg(struct sk_buff *skb, struct nlmsghdr *nlh, | 362 | static 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 | ||