[CRYPTO] authenc: Move enckeylen into key itself
[linux-3.10.git] / crypto / authenc.c
index 5df5fb169cbe3cee3e944290796238cfb9f67801..a61dea1c2fe680ff6d776f4a08c5bb470986b7ab 100644 (file)
  */
 
 #include <crypto/algapi.h>
+#include <crypto/authenc.h>
 #include <linux/err.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/rtnetlink.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 
@@ -23,8 +25,6 @@
 struct authenc_instance_ctx {
        struct crypto_spawn auth;
        struct crypto_spawn enc;
-
-       unsigned int enckeylen;
 };
 
 struct crypto_authenc_ctx {
@@ -36,19 +36,31 @@ struct crypto_authenc_ctx {
 static int crypto_authenc_setkey(struct crypto_aead *authenc, const u8 *key,
                                 unsigned int keylen)
 {
-       struct authenc_instance_ctx *ictx =
-               crypto_instance_ctx(crypto_aead_alg_instance(authenc));
-       unsigned int enckeylen = ictx->enckeylen;
        unsigned int authkeylen;
+       unsigned int enckeylen;
        struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
        struct crypto_hash *auth = ctx->auth;
        struct crypto_ablkcipher *enc = ctx->enc;
+       struct rtattr *rta = (void *)key;
+       struct crypto_authenc_key_param *param;
        int err = -EINVAL;
 
-       if (keylen < enckeylen) {
-               crypto_aead_set_flags(authenc, CRYPTO_TFM_RES_BAD_KEY_LEN);
-               goto out;
-       }
+       if (keylen < sizeof(*rta))
+               goto badkey;
+       if (rta->rta_type != CRYPTO_AUTHENC_KEYA_PARAM)
+               goto badkey;
+       if (RTA_PAYLOAD(rta) < sizeof(*param))
+               goto badkey;
+
+       param = RTA_DATA(rta);
+       enckeylen = be32_to_cpu(param->enckeylen);
+
+       key += RTA_ALIGN(rta->rta_len);
+       keylen -= RTA_ALIGN(rta->rta_len);
+
+       if (keylen < enckeylen)
+               goto badkey;
+
        authkeylen = keylen - enckeylen;
 
        crypto_hash_clear_flags(auth, CRYPTO_TFM_REQ_MASK);
@@ -70,6 +82,10 @@ static int crypto_authenc_setkey(struct crypto_aead *authenc, const u8 *key,
 
 out:
        return err;
+
+badkey:
+       crypto_aead_set_flags(authenc, CRYPTO_TFM_RES_BAD_KEY_LEN);
+       goto out;
 }
 
 static int crypto_authenc_hash(struct aead_request *req)
@@ -263,7 +279,6 @@ static struct crypto_instance *crypto_authenc_alloc(struct rtattr **tb)
        struct crypto_alg *auth;
        struct crypto_alg *enc;
        struct authenc_instance_ctx *ctx;
-       unsigned int enckeylen;
        int err;
 
        err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_AEAD);
@@ -281,10 +296,6 @@ static struct crypto_instance *crypto_authenc_alloc(struct rtattr **tb)
        if (IS_ERR(enc))
                goto out_put_auth;
 
-       err = crypto_attr_u32(tb[3], &enckeylen);
-       if (err)
-               goto out_put_enc;
-
        inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL);
        err = -ENOMEM;
        if (!inst)
@@ -292,18 +303,16 @@ static struct crypto_instance *crypto_authenc_alloc(struct rtattr **tb)
 
        err = -ENAMETOOLONG;
        if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME,
-                    "authenc(%s,%s,%u)", auth->cra_name,
-                    enc->cra_name, enckeylen) >= CRYPTO_MAX_ALG_NAME)
+                    "authenc(%s,%s)", auth->cra_name, enc->cra_name) >=
+           CRYPTO_MAX_ALG_NAME)
                goto err_free_inst;
 
        if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
-                    "authenc(%s,%s,%u)", auth->cra_driver_name,
-                    enc->cra_driver_name, enckeylen) >=
-           CRYPTO_MAX_ALG_NAME)
+                    "authenc(%s,%s)", auth->cra_driver_name,
+                    enc->cra_driver_name) >= CRYPTO_MAX_ALG_NAME)
                goto err_free_inst;
 
        ctx = crypto_instance_ctx(inst);
-       ctx->enckeylen = enckeylen;
 
        err = crypto_init_spawn(&ctx->auth, auth, inst, CRYPTO_ALG_TYPE_MASK);
        if (err)