Skip to content

Commit e236d4a

Browse files
committed
[CRYPTO] authenc: Move enckeylen into key itself
Having enckeylen as a template parameter makes it a pain for hardware devices that implement ciphers with many key sizes since each one would have to be registered separately. Since the authenc algorithm is mainly used for legacy purposes where its key is going to be constructed out of two separate keys, we can in fact embed this value into the key itself. This patch does this by prepending an rtnetlink header to the key that contains the encryption key length. Signed-off-by: Herbert Xu <[email protected]>
1 parent 7ba683a commit e236d4a

File tree

2 files changed

+56
-20
lines changed

2 files changed

+56
-20
lines changed

crypto/authenc.c

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,12 @@
1111
*/
1212

1313
#include <crypto/algapi.h>
14+
#include <crypto/authenc.h>
1415
#include <linux/err.h>
1516
#include <linux/init.h>
1617
#include <linux/kernel.h>
1718
#include <linux/module.h>
19+
#include <linux/rtnetlink.h>
1820
#include <linux/slab.h>
1921
#include <linux/spinlock.h>
2022

@@ -23,8 +25,6 @@
2325
struct authenc_instance_ctx {
2426
struct crypto_spawn auth;
2527
struct crypto_spawn enc;
26-
27-
unsigned int enckeylen;
2828
};
2929

3030
struct crypto_authenc_ctx {
@@ -36,19 +36,31 @@ struct crypto_authenc_ctx {
3636
static int crypto_authenc_setkey(struct crypto_aead *authenc, const u8 *key,
3737
unsigned int keylen)
3838
{
39-
struct authenc_instance_ctx *ictx =
40-
crypto_instance_ctx(crypto_aead_alg_instance(authenc));
41-
unsigned int enckeylen = ictx->enckeylen;
4239
unsigned int authkeylen;
40+
unsigned int enckeylen;
4341
struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
4442
struct crypto_hash *auth = ctx->auth;
4543
struct crypto_ablkcipher *enc = ctx->enc;
44+
struct rtattr *rta = (void *)key;
45+
struct crypto_authenc_key_param *param;
4646
int err = -EINVAL;
4747

48-
if (keylen < enckeylen) {
49-
crypto_aead_set_flags(authenc, CRYPTO_TFM_RES_BAD_KEY_LEN);
50-
goto out;
51-
}
48+
if (keylen < sizeof(*rta))
49+
goto badkey;
50+
if (rta->rta_type != CRYPTO_AUTHENC_KEYA_PARAM)
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+
5264
authkeylen = keylen - enckeylen;
5365

5466
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,
7082

7183
out:
7284
return err;
85+
86+
badkey:
87+
crypto_aead_set_flags(authenc, CRYPTO_TFM_RES_BAD_KEY_LEN);
88+
goto out;
7389
}
7490

7591
static int crypto_authenc_hash(struct aead_request *req)
@@ -263,7 +279,6 @@ static struct crypto_instance *crypto_authenc_alloc(struct rtattr **tb)
263279
struct crypto_alg *auth;
264280
struct crypto_alg *enc;
265281
struct authenc_instance_ctx *ctx;
266-
unsigned int enckeylen;
267282
int err;
268283

269284
err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_AEAD);
@@ -281,29 +296,23 @@ static struct crypto_instance *crypto_authenc_alloc(struct rtattr **tb)
281296
if (IS_ERR(enc))
282297
goto out_put_auth;
283298

284-
err = crypto_attr_u32(tb[3], &enckeylen);
285-
if (err)
286-
goto out_put_enc;
287-
288299
inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL);
289300
err = -ENOMEM;
290301
if (!inst)
291302
goto out_put_enc;
292303

293304
err = -ENAMETOOLONG;
294305
if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME,
295-
"authenc(%s,%s,%u)", auth->cra_name,
296-
enc->cra_name, enckeylen) >= CRYPTO_MAX_ALG_NAME)
306+
"authenc(%s,%s)", auth->cra_name, enc->cra_name) >=
307+
CRYPTO_MAX_ALG_NAME)
297308
goto err_free_inst;
298309

299310
if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
300-
"authenc(%s,%s,%u)", auth->cra_driver_name,
301-
enc->cra_driver_name, enckeylen) >=
302-
CRYPTO_MAX_ALG_NAME)
311+
"authenc(%s,%s)", auth->cra_driver_name,
312+
enc->cra_driver_name) >= CRYPTO_MAX_ALG_NAME)
303313
goto err_free_inst;
304314

305315
ctx = crypto_instance_ctx(inst);
306-
ctx->enckeylen = enckeylen;
307316

308317
err = crypto_init_spawn(&ctx->auth, auth, inst, CRYPTO_ALG_TYPE_MASK);
309318
if (err)

include/crypto/authenc.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* Authenc: Simple AEAD wrapper for IPsec
3+
*
4+
* Copyright (c) 2007 Herbert Xu <[email protected]>
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+
17+
enum {
18+
CRYPTO_AUTHENC_KEYA_UNSPEC,
19+
CRYPTO_AUTHENC_KEYA_PARAM,
20+
};
21+
22+
struct crypto_authenc_key_param {
23+
__be32 enckeylen;
24+
};
25+
26+
#endif /* _CRYPTO_AUTHENC_H */
27+

0 commit comments

Comments
 (0)