Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Steffen Klassert and committed by
Herbert Xu
1e122994 fbf0ca1b

+79 -5
+2 -2
crypto/ablkcipher.c
··· 613 613 return err; 614 614 } 615 615 616 - static struct crypto_alg *crypto_lookup_skcipher(const char *name, u32 type, 617 - u32 mask) 616 + struct crypto_alg *crypto_lookup_skcipher(const char *name, u32 type, u32 mask) 618 617 { 619 618 struct crypto_alg *alg; 620 619 ··· 651 652 652 653 return ERR_PTR(crypto_givcipher_default(alg, type, mask)); 653 654 } 655 + EXPORT_SYMBOL_GPL(crypto_lookup_skcipher); 654 656 655 657 int crypto_grab_skcipher(struct crypto_skcipher_spawn *spawn, const char *name, 656 658 u32 type, u32 mask)
+2 -2
crypto/aead.c
··· 470 470 return err; 471 471 } 472 472 473 - static struct crypto_alg *crypto_lookup_aead(const char *name, u32 type, 474 - u32 mask) 473 + struct crypto_alg *crypto_lookup_aead(const char *name, u32 type, u32 mask) 475 474 { 476 475 struct crypto_alg *alg; 477 476 ··· 502 503 503 504 return ERR_PTR(crypto_nivaead_default(alg, type, mask)); 504 505 } 506 + EXPORT_SYMBOL_GPL(crypto_lookup_aead); 505 507 506 508 int crypto_grab_aead(struct crypto_aead_spawn *spawn, const char *name, 507 509 u32 type, u32 mask)
+71 -1
crypto/crypto_user.c
··· 21 21 #include <linux/module.h> 22 22 #include <linux/crypto.h> 23 23 #include <linux/cryptouser.h> 24 + #include <linux/sched.h> 24 25 #include <net/netlink.h> 25 26 #include <linux/security.h> 26 27 #include <net/net_namespace.h> 28 + #include <crypto/internal/aead.h> 29 + #include <crypto/internal/skcipher.h> 30 + 27 31 #include "internal.h" 28 32 29 33 DEFINE_MUTEX(crypto_cfg_mutex); ··· 305 301 return crypto_unregister_instance(alg); 306 302 } 307 303 304 + static struct crypto_alg *crypto_user_skcipher_alg(const char *name, u32 type, 305 + u32 mask) 306 + { 307 + int err; 308 + struct crypto_alg *alg; 309 + 310 + type = crypto_skcipher_type(type); 311 + mask = crypto_skcipher_mask(mask); 312 + 313 + for (;;) { 314 + alg = crypto_lookup_skcipher(name, type, mask); 315 + if (!IS_ERR(alg)) 316 + return alg; 317 + 318 + err = PTR_ERR(alg); 319 + if (err != -EAGAIN) 320 + break; 321 + if (signal_pending(current)) { 322 + err = -EINTR; 323 + break; 324 + } 325 + } 326 + 327 + return ERR_PTR(err); 328 + } 329 + 330 + static struct crypto_alg *crypto_user_aead_alg(const char *name, u32 type, 331 + u32 mask) 332 + { 333 + int err; 334 + struct crypto_alg *alg; 335 + 336 + type &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV); 337 + type |= CRYPTO_ALG_TYPE_AEAD; 338 + mask &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV); 339 + mask |= CRYPTO_ALG_TYPE_MASK; 340 + 341 + for (;;) { 342 + alg = crypto_lookup_aead(name, type, mask); 343 + if (!IS_ERR(alg)) 344 + return alg; 345 + 346 + err = PTR_ERR(alg); 347 + if (err != -EAGAIN) 348 + break; 349 + if (signal_pending(current)) { 350 + err = -EINTR; 351 + break; 352 + } 353 + } 354 + 355 + return ERR_PTR(err); 356 + } 357 + 308 358 static int crypto_add_alg(struct sk_buff *skb, struct nlmsghdr *nlh, 309 359 struct nlattr **attrs) 310 360 { ··· 383 325 else 384 326 name = p->cru_name; 385 327 386 - alg = crypto_alg_mod_lookup(name, p->cru_type, p->cru_mask); 328 + switch (p->cru_type & p->cru_mask & CRYPTO_ALG_TYPE_MASK) { 329 + case CRYPTO_ALG_TYPE_AEAD: 330 + alg = crypto_user_aead_alg(name, p->cru_type, p->cru_mask); 331 + break; 332 + case CRYPTO_ALG_TYPE_GIVCIPHER: 333 + case CRYPTO_ALG_TYPE_BLKCIPHER: 334 + case CRYPTO_ALG_TYPE_ABLKCIPHER: 335 + alg = crypto_user_skcipher_alg(name, p->cru_type, p->cru_mask); 336 + break; 337 + default: 338 + alg = crypto_alg_mod_lookup(name, p->cru_type, p->cru_mask); 339 + } 340 + 387 341 if (IS_ERR(alg)) 388 342 return PTR_ERR(alg); 389 343
+2
include/crypto/internal/aead.h
··· 31 31 crypto_set_spawn(&spawn->base, inst); 32 32 } 33 33 34 + struct crypto_alg *crypto_lookup_aead(const char *name, u32 type, u32 mask); 35 + 34 36 int crypto_grab_aead(struct crypto_aead_spawn *spawn, const char *name, 35 37 u32 type, u32 mask); 36 38
+2
include/crypto/internal/skcipher.h
··· 34 34 int crypto_grab_skcipher(struct crypto_skcipher_spawn *spawn, const char *name, 35 35 u32 type, u32 mask); 36 36 37 + struct crypto_alg *crypto_lookup_skcipher(const char *name, u32 type, u32 mask); 38 + 37 39 static inline void crypto_drop_skcipher(struct crypto_skcipher_spawn *spawn) 38 40 { 39 41 crypto_drop_spawn(&spawn->base);