aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crypto/authenc.c49
-rw-r--r--include/crypto/authenc.h27
2 files changed, 56 insertions, 20 deletions
diff --git a/crypto/authenc.c b/crypto/authenc.c
index 5df5fb169cbe..a61dea1c2fe6 100644
--- a/crypto/authenc.c
+++ b/crypto/authenc.c
@@ -11,10 +11,12 @@
11 */ 11 */
12 12
13#include <crypto/algapi.h> 13#include <crypto/algapi.h>
14#include <crypto/authenc.h>
14#include <linux/err.h> 15#include <linux/err.h>
15#include <linux/init.h> 16#include <linux/init.h>
16#include <linux/kernel.h> 17#include <linux/kernel.h>
17#include <linux/module.h> 18#include <linux/module.h>
19#include <linux/rtnetlink.h>
18#include <linux/slab.h> 20#include <linux/slab.h>
19#include <linux/spinlock.h> 21#include <linux/spinlock.h>
20 22
@@ -23,8 +25,6 @@
23struct authenc_instance_ctx { 25struct authenc_instance_ctx {
24 struct crypto_spawn auth; 26 struct crypto_spawn auth;
25 struct crypto_spawn enc; 27 struct crypto_spawn enc;
26
27 unsigned int enckeylen;
28}; 28};
29 29
30struct crypto_authenc_ctx { 30struct crypto_authenc_ctx {
@@ -36,19 +36,31 @@ struct crypto_authenc_ctx {
36static int crypto_authenc_setkey(struct crypto_aead *authenc, const u8 *key, 36static int crypto_authenc_setkey(struct crypto_aead *authenc, const u8 *key,
37 unsigned int keylen) 37 unsigned int keylen)
38{ 38{
39 struct authenc_instance_ctx *ictx =
40 crypto_instance_ctx(crypto_aead_alg_instance(authenc));
41 unsigned int enckeylen = ictx->enckeylen;
42 unsigned int authkeylen; 39 unsigned int authkeylen;
40 unsigned int enckeylen;
43 struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc); 41 struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
44 struct crypto_hash *auth = ctx->auth; 42 struct crypto_hash *auth = ctx->auth;
45 struct crypto_ablkcipher *enc = ctx->enc; 43 struct crypto_ablkcipher *enc = ctx->enc;
44 struct rtattr *rta = (void *)key;
45 struct crypto_authenc_key_param *param;
46 int err = -EINVAL; 46 int err = -EINVAL;
47 47
48 if (keylen < enckeylen) { 48 if (keylen < sizeof(*rta))
49 crypto_aead_set_flags(authenc, CRYPTO_TFM_RES_BAD_KEY_LEN); 49 goto badkey;
50 goto out; 50 if (rta->rta_type != CRYPTO_AUTHENC_KEYA_PARAM)
51 } 51 goto badkey;
52 if (RTA_PAYLOAD(rta) < sizeof(*param))
53 goto badkey;
54
55 param = RTA_DATA(rta);
56 enckeylen = be32_to_cpu(param->enckeylen);
57
58 key += RTA_ALIGN(rta->rta_len);
59 keylen -= RTA_ALIGN(rta->rta_len);
60
61 if (keylen < enckeylen)
62 goto badkey;
63
52 authkeylen = keylen - enckeylen; 64 authkeylen = keylen - enckeylen;
53 65
54 crypto_hash_clear_flags(auth, CRYPTO_TFM_REQ_MASK); 66 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,
70 82
71out: 83out:
72 return err; 84 return err;
85
86badkey:
87 crypto_aead_set_flags(authenc, CRYPTO_TFM_RES_BAD_KEY_LEN);
88 goto out;
73} 89}
74 90
75static int crypto_authenc_hash(struct aead_request *req) 91static int crypto_authenc_hash(struct aead_request *req)
@@ -263,7 +279,6 @@ static struct crypto_instance *crypto_authenc_alloc(struct rtattr **tb)
263 struct crypto_alg *auth; 279 struct crypto_alg *auth;
264 struct crypto_alg *enc; 280 struct crypto_alg *enc;
265 struct authenc_instance_ctx *ctx; 281 struct authenc_instance_ctx *ctx;
266 unsigned int enckeylen;
267 int err; 282 int err;
268 283
269 err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_AEAD); 284 err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_AEAD);
@@ -281,10 +296,6 @@ static struct crypto_instance *crypto_authenc_alloc(struct rtattr **tb)
281 if (IS_ERR(enc)) 296 if (IS_ERR(enc))
282 goto out_put_auth; 297 goto out_put_auth;
283 298
284 err = crypto_attr_u32(tb[3], &enckeylen);
285 if (err)
286 goto out_put_enc;
287
288 inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL); 299 inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL);
289 err = -ENOMEM; 300 err = -ENOMEM;
290 if (!inst) 301 if (!inst)
@@ -292,18 +303,16 @@ static struct crypto_instance *crypto_authenc_alloc(struct rtattr **tb)
292 303
293 err = -ENAMETOOLONG; 304 err = -ENAMETOOLONG;
294 if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME, 305 if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME,
295 "authenc(%s,%s,%u)", auth->cra_name, 306 "authenc(%s,%s)", auth->cra_name, enc->cra_name) >=
296 enc->cra_name, enckeylen) >= CRYPTO_MAX_ALG_NAME) 307 CRYPTO_MAX_ALG_NAME)
297 goto err_free_inst; 308 goto err_free_inst;
298 309
299 if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME, 310 if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
300 "authenc(%s,%s,%u)", auth->cra_driver_name, 311 "authenc(%s,%s)", auth->cra_driver_name,
301 enc->cra_driver_name, enckeylen) >= 312 enc->cra_driver_name) >= CRYPTO_MAX_ALG_NAME)
302 CRYPTO_MAX_ALG_NAME)
303 goto err_free_inst; 313 goto err_free_inst;
304 314
305 ctx = crypto_instance_ctx(inst); 315 ctx = crypto_instance_ctx(inst);
306 ctx->enckeylen = enckeylen;
307 316
308 err = crypto_init_spawn(&ctx->auth, auth, inst, CRYPTO_ALG_TYPE_MASK); 317 err = crypto_init_spawn(&ctx->auth, auth, inst, CRYPTO_ALG_TYPE_MASK);
309 if (err) 318 if (err)
diff --git a/include/crypto/authenc.h b/include/crypto/authenc.h
new file mode 100644
index 000000000000..e47b044929a8
--- /dev/null
+++ b/include/crypto/authenc.h
@@ -0,0 +1,27 @@
1/*
2 * Authenc: Simple AEAD wrapper for IPsec
3 *
4 * Copyright (c) 2007 Herbert Xu <herbert@gondor.apana.org.au>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation; either version 2 of the License, or (at your option)
9 * any later version.
10 *
11 */
12#ifndef _CRYPTO_AUTHENC_H
13#define _CRYPTO_AUTHENC_H
14
15#include <linux/types.h>
16
17enum {
18 CRYPTO_AUTHENC_KEYA_UNSPEC,
19 CRYPTO_AUTHENC_KEYA_PARAM,
20};
21
22struct crypto_authenc_key_param {
23 __be32 enckeylen;
24};
25
26#endif /* _CRYPTO_AUTHENC_H */
27