diff --git a/crypto/algapi.c b/crypto/algapi.c
index f7d2185b2c8fbac94cf6f6736b5f1a965f224bb9..491205e11cbe4bf1316c25544385abda90b5590f 100644
--- a/crypto/algapi.c
+++ b/crypto/algapi.c
@@ -425,15 +425,45 @@ int crypto_unregister_notifier(struct notifier_block *nb)
 }
 EXPORT_SYMBOL_GPL(crypto_unregister_notifier);
 
-struct crypto_alg *crypto_get_attr_alg(void *param, unsigned int len,
-				       u32 type, u32 mask)
+struct crypto_attr_type *crypto_get_attr_type(struct rtattr **tb)
 {
-	struct rtattr *rta = param;
+	struct rtattr *rta = tb[CRYPTOA_TYPE - 1];
+	struct crypto_attr_type *algt;
+
+	if (!rta)
+		return ERR_PTR(-ENOENT);
+	if (RTA_PAYLOAD(rta) < sizeof(*algt))
+		return ERR_PTR(-EINVAL);
+
+	algt = RTA_DATA(rta);
+
+	return algt;
+}
+EXPORT_SYMBOL_GPL(crypto_get_attr_type);
+
+int crypto_check_attr_type(struct rtattr **tb, u32 type)
+{
+	struct crypto_attr_type *algt;
+
+	algt = crypto_get_attr_type(tb);
+	if (IS_ERR(algt))
+		return PTR_ERR(algt);
+
+	if ((algt->type ^ type) & algt->mask)
+		return -EINVAL;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(crypto_check_attr_type);
+
+struct crypto_alg *crypto_get_attr_alg(struct rtattr **tb, u32 type, u32 mask)
+{
+	struct rtattr *rta = tb[CRYPTOA_ALG - 1];
 	struct crypto_attr_alg *alga;
 
-	if (!RTA_OK(rta, len))
-		return ERR_PTR(-EBADR);
-	if (rta->rta_type != CRYPTOA_ALG || RTA_PAYLOAD(rta) < sizeof(*alga))
+	if (!rta)
+		return ERR_PTR(-ENOENT);
+	if (RTA_PAYLOAD(rta) < sizeof(*alga))
 		return ERR_PTR(-EINVAL);
 
 	alga = RTA_DATA(rta);
diff --git a/crypto/cbc.c b/crypto/cbc.c
index 136fea7e700095542c585cbb7cae9c16b64eb667..1f2649e13b4266ebc1354bd701c6b98d23c83d2e 100644
--- a/crypto/cbc.c
+++ b/crypto/cbc.c
@@ -275,13 +275,18 @@ static void crypto_cbc_exit_tfm(struct crypto_tfm *tfm)
 	crypto_free_cipher(ctx->child);
 }
 
-static struct crypto_instance *crypto_cbc_alloc(void *param, unsigned int len)
+static struct crypto_instance *crypto_cbc_alloc(struct rtattr **tb)
 {
 	struct crypto_instance *inst;
 	struct crypto_alg *alg;
+	int err;
+
+	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_BLKCIPHER);
+	if (err)
+		return ERR_PTR(err);
 
-	alg = crypto_get_attr_alg(param, len, CRYPTO_ALG_TYPE_CIPHER,
-				  CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC);
+	alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_CIPHER,
+				  CRYPTO_ALG_TYPE_MASK);
 	if (IS_ERR(alg))
 		return ERR_PTR(PTR_ERR(alg));
 
diff --git a/crypto/cryptomgr.c b/crypto/cryptomgr.c
index 2ebffb84f1d99552bc707162eeb26a9d08f4277f..7a3df9b4121881a65bd723ee7ef883baaec0e80f 100644
--- a/crypto/cryptomgr.c
+++ b/crypto/cryptomgr.c
@@ -26,14 +26,19 @@
 struct cryptomgr_param {
 	struct work_struct work;
 
+	struct rtattr *tb[CRYPTOA_MAX];
+
+	struct {
+		struct rtattr attr;
+		struct crypto_attr_type data;
+	} type;
+
 	struct {
 		struct rtattr attr;
 		struct crypto_attr_alg data;
 	} alg;
 
 	struct {
-		u32 type;
-		u32 mask;
 		char name[CRYPTO_MAX_ALG_NAME];
 	} larval;
 
@@ -53,7 +58,7 @@ static void cryptomgr_probe(struct work_struct *work)
 		goto err;
 
 	do {
-		inst = tmpl->alloc(&param->alg, sizeof(param->alg));
+		inst = tmpl->alloc(param->tb);
 		if (IS_ERR(inst))
 			err = PTR_ERR(inst);
 		else if ((err = crypto_register_instance(tmpl, inst)))
@@ -70,8 +75,8 @@ static void cryptomgr_probe(struct work_struct *work)
 	return;
 
 err:
-	crypto_larval_error(param->larval.name, param->larval.type,
-			    param->larval.mask);
+	crypto_larval_error(param->larval.name, param->type.data.type,
+			    param->type.data.mask);
 	goto out;
 }
 
@@ -82,7 +87,7 @@ static int cryptomgr_schedule_probe(struct crypto_larval *larval)
 	const char *p;
 	unsigned int len;
 
-	param = kmalloc(sizeof(*param), GFP_KERNEL);
+	param = kzalloc(sizeof(*param), GFP_KERNEL);
 	if (!param)
 		goto err;
 
@@ -94,7 +99,6 @@ static int cryptomgr_schedule_probe(struct crypto_larval *larval)
 		goto err_free_param;
 
 	memcpy(param->template, name, len);
-	param->template[len] = 0;
 
 	name = p + 1;
 	for (p = name; isalnum(*p) || *p == '-' || *p == '_'; p++)
@@ -104,14 +108,18 @@ static int cryptomgr_schedule_probe(struct crypto_larval *larval)
 	if (!len || *p != ')' || p[1])
 		goto err_free_param;
 
+	param->type.attr.rta_len = sizeof(param->type);
+	param->type.attr.rta_type = CRYPTOA_TYPE;
+	param->type.data.type = larval->alg.cra_flags;
+	param->type.data.mask = larval->mask;
+	param->tb[CRYPTOA_TYPE - 1] = &param->type.attr;
+
 	param->alg.attr.rta_len = sizeof(param->alg);
 	param->alg.attr.rta_type = CRYPTOA_ALG;
 	memcpy(param->alg.data.name, name, len);
-	param->alg.data.name[len] = 0;
+	param->tb[CRYPTOA_ALG - 1] = &param->alg.attr;
 
 	memcpy(param->larval.name, larval->alg.cra_name, CRYPTO_MAX_ALG_NAME);
-	param->larval.type = larval->alg.cra_flags;
-	param->larval.mask = larval->mask;
 
 	INIT_WORK(&param->work, cryptomgr_probe);
 	schedule_work(&param->work);
diff --git a/crypto/ecb.c b/crypto/ecb.c
index 839a0aed8c229c26631ff56032165a19295a0531..6310387a872c6c4df4dd538a3d60f25c70391590 100644
--- a/crypto/ecb.c
+++ b/crypto/ecb.c
@@ -115,13 +115,18 @@ static void crypto_ecb_exit_tfm(struct crypto_tfm *tfm)
 	crypto_free_cipher(ctx->child);
 }
 
-static struct crypto_instance *crypto_ecb_alloc(void *param, unsigned int len)
+static struct crypto_instance *crypto_ecb_alloc(struct rtattr **tb)
 {
 	struct crypto_instance *inst;
 	struct crypto_alg *alg;
+	int err;
+
+	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_BLKCIPHER);
+	if (err)
+		return ERR_PTR(err);
 
-	alg = crypto_get_attr_alg(param, len, CRYPTO_ALG_TYPE_CIPHER,
-				  CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC);
+	alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_CIPHER,
+				  CRYPTO_ALG_TYPE_MASK);
 	if (IS_ERR(alg))
 		return ERR_PTR(PTR_ERR(alg));
 
diff --git a/crypto/hmac.c b/crypto/hmac.c
index 44187c5ee5933cbf9195ec799d337053ef0e0b8e..8802fb6dd5a6c857e4d78880944d5f9c3cc6c9d4 100644
--- a/crypto/hmac.c
+++ b/crypto/hmac.c
@@ -197,13 +197,18 @@ static void hmac_free(struct crypto_instance *inst)
 	kfree(inst);
 }
 
-static struct crypto_instance *hmac_alloc(void *param, unsigned int len)
+static struct crypto_instance *hmac_alloc(struct rtattr **tb)
 {
 	struct crypto_instance *inst;
 	struct crypto_alg *alg;
+	int err;
+
+	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_HASH);
+	if (err)
+		return ERR_PTR(err);
 
-	alg = crypto_get_attr_alg(param, len, CRYPTO_ALG_TYPE_HASH,
-				  CRYPTO_ALG_TYPE_HASH_MASK | CRYPTO_ALG_ASYNC);
+	alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_HASH,
+				  CRYPTO_ALG_TYPE_HASH_MASK);
 	if (IS_ERR(alg))
 		return ERR_PTR(PTR_ERR(alg));
 
diff --git a/crypto/lrw.c b/crypto/lrw.c
index b4105080ac7aa9d5886ea28772cfea6101197d27..621095db28b354fa314acb44528f514baf026cf5 100644
--- a/crypto/lrw.c
+++ b/crypto/lrw.c
@@ -228,13 +228,18 @@ static void exit_tfm(struct crypto_tfm *tfm)
 	crypto_free_cipher(ctx->child);
 }
 
-static struct crypto_instance *alloc(void *param, unsigned int len)
+static struct crypto_instance *alloc(struct rtattr **tb)
 {
 	struct crypto_instance *inst;
 	struct crypto_alg *alg;
+	int err;
+
+	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_BLKCIPHER);
+	if (err)
+		return ERR_PTR(err);
 
-	alg = crypto_get_attr_alg(param, len, CRYPTO_ALG_TYPE_CIPHER,
-				  CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC);
+	alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_CIPHER,
+				  CRYPTO_ALG_TYPE_MASK);
 	if (IS_ERR(alg))
 		return ERR_PTR(PTR_ERR(alg));
 
diff --git a/crypto/pcbc.c b/crypto/pcbc.c
index 5174d7fdad6e20f2d3051d60d3c764dfeb8dbaf1..c3ed8a1c9f4616022ad1e80525875c8f5ce776d0 100644
--- a/crypto/pcbc.c
+++ b/crypto/pcbc.c
@@ -279,13 +279,18 @@ static void crypto_pcbc_exit_tfm(struct crypto_tfm *tfm)
 	crypto_free_cipher(ctx->child);
 }
 
-static struct crypto_instance *crypto_pcbc_alloc(void *param, unsigned int len)
+static struct crypto_instance *crypto_pcbc_alloc(struct rtattr **tb)
 {
 	struct crypto_instance *inst;
 	struct crypto_alg *alg;
+	int err;
+
+	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_BLKCIPHER);
+	if (err)
+		return ERR_PTR(err);
 
-	alg = crypto_get_attr_alg(param, len, CRYPTO_ALG_TYPE_CIPHER,
-				  CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC);
+	alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_CIPHER,
+				  CRYPTO_ALG_TYPE_MASK);
 	if (IS_ERR(alg))
 		return ERR_PTR(PTR_ERR(alg));
 
diff --git a/crypto/xcbc.c b/crypto/xcbc.c
index 53e8ccbf0f5f514d9023431d9e15a47e53ed705e..9f502b86e0ea563ac04b31fbf96dcd534367e05a 100644
--- a/crypto/xcbc.c
+++ b/crypto/xcbc.c
@@ -288,12 +288,18 @@ static void xcbc_exit_tfm(struct crypto_tfm *tfm)
 	crypto_free_cipher(ctx->child);
 }
 
-static struct crypto_instance *xcbc_alloc(void *param, unsigned int len)
+static struct crypto_instance *xcbc_alloc(struct rtattr **tb)
 {
 	struct crypto_instance *inst;
 	struct crypto_alg *alg;
-	alg = crypto_get_attr_alg(param, len, CRYPTO_ALG_TYPE_CIPHER,
-				  CRYPTO_ALG_TYPE_HASH_MASK | CRYPTO_ALG_ASYNC);
+	int err;
+
+	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_HASH);
+	if (err)
+		return ERR_PTR(err);
+
+	alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_CIPHER,
+				  CRYPTO_ALG_TYPE_MASK);
 	if (IS_ERR(alg))
 		return ERR_PTR(PTR_ERR(alg));
 
diff --git a/include/crypto/algapi.h b/include/crypto/algapi.h
index 4e05e93ff6811248002485475e8a624fa1209cf1..d0c190b4d02fb439b1884c3130459af9047ad0ab 100644
--- a/include/crypto/algapi.h
+++ b/include/crypto/algapi.h
@@ -15,6 +15,7 @@
 #include <linux/crypto.h>
 
 struct module;
+struct rtattr;
 struct seq_file;
 
 struct crypto_type {
@@ -38,7 +39,7 @@ struct crypto_template {
 	struct hlist_head instances;
 	struct module *module;
 
-	struct crypto_instance *(*alloc)(void *param, unsigned int len);
+	struct crypto_instance *(*alloc)(struct rtattr **tb);
 	void (*free)(struct crypto_instance *inst);
 
 	char name[CRYPTO_MAX_ALG_NAME];
@@ -96,8 +97,9 @@ void crypto_drop_spawn(struct crypto_spawn *spawn);
 struct crypto_tfm *crypto_spawn_tfm(struct crypto_spawn *spawn, u32 type,
 				    u32 mask);
 
-struct crypto_alg *crypto_get_attr_alg(void *param, unsigned int len,
-				       u32 type, u32 mask);
+struct crypto_attr_type *crypto_get_attr_type(struct rtattr **tb);
+int crypto_check_attr_type(struct rtattr **tb, u32 type);
+struct crypto_alg *crypto_get_attr_alg(struct rtattr **tb, u32 type, u32 mask);
 struct crypto_instance *crypto_alloc_instance(const char *name,
 					      struct crypto_alg *alg);
 
diff --git a/include/linux/crypto.h b/include/linux/crypto.h
index d4d05313280c5643a4c0b05e2f388d901bb581f1..67830e7c2c318e2d75d43e3ae587a65719835506 100644
--- a/include/linux/crypto.h
+++ b/include/linux/crypto.h
@@ -372,12 +372,21 @@ struct crypto_hash {
 enum {
 	CRYPTOA_UNSPEC,
 	CRYPTOA_ALG,
+	CRYPTOA_TYPE,
+	__CRYPTOA_MAX,
 };
 
+#define CRYPTOA_MAX (__CRYPTOA_MAX - 1)
+
 struct crypto_attr_alg {
 	char name[CRYPTO_MAX_ALG_NAME];
 };
 
+struct crypto_attr_type {
+	u32 type;
+	u32 mask;
+};
+
 /* 
  * Transform user interface.
  */