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

[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 <herbert@gondor.apana.org.au>

+58 -22
+31 -22
crypto/authenc.c
··· 11 11 */ 12 12 13 13 #include <crypto/algapi.h> 14 + #include <crypto/authenc.h> 14 15 #include <linux/err.h> 15 16 #include <linux/init.h> 16 17 #include <linux/kernel.h> 17 18 #include <linux/module.h> 19 + #include <linux/rtnetlink.h> 18 20 #include <linux/slab.h> 19 21 #include <linux/spinlock.h> 20 22 ··· 25 23 struct authenc_instance_ctx { 26 24 struct crypto_spawn auth; 27 25 struct crypto_spawn enc; 28 - 29 - unsigned int enckeylen; 30 26 }; 31 27 32 28 struct crypto_authenc_ctx { ··· 36 36 static int crypto_authenc_setkey(struct crypto_aead *authenc, const u8 *key, 37 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 39 unsigned int authkeylen; 40 + unsigned int enckeylen; 43 41 struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc); 44 42 struct crypto_hash *auth = ctx->auth; 45 43 struct crypto_ablkcipher *enc = ctx->enc; 44 + struct rtattr *rta = (void *)key; 45 + struct crypto_authenc_key_param *param; 46 46 int err = -EINVAL; 47 47 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 + 52 64 authkeylen = keylen - enckeylen; 53 65 54 66 crypto_hash_clear_flags(auth, CRYPTO_TFM_REQ_MASK); ··· 82 70 83 71 out: 84 72 return err; 73 + 74 + badkey: 75 + crypto_aead_set_flags(authenc, CRYPTO_TFM_RES_BAD_KEY_LEN); 76 + goto out; 85 77 } 86 78 87 79 static int crypto_authenc_hash(struct aead_request *req) ··· 279 263 struct crypto_alg *auth; 280 264 struct crypto_alg *enc; 281 265 struct authenc_instance_ctx *ctx; 282 - unsigned int enckeylen; 283 266 int err; 284 267 285 268 err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_AEAD); ··· 296 281 if (IS_ERR(enc)) 297 282 goto out_put_auth; 298 283 299 - err = crypto_attr_u32(tb[3], &enckeylen); 300 - if (err) 301 - goto out_put_enc; 302 - 303 284 inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL); 304 285 err = -ENOMEM; 305 286 if (!inst) ··· 303 292 304 293 err = -ENAMETOOLONG; 305 294 if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME, 306 - "authenc(%s,%s,%u)", auth->cra_name, 307 - enc->cra_name, enckeylen) >= CRYPTO_MAX_ALG_NAME) 308 - goto err_free_inst; 309 - 310 - if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME, 311 - "authenc(%s,%s,%u)", auth->cra_driver_name, 312 - enc->cra_driver_name, enckeylen) >= 295 + "authenc(%s,%s)", auth->cra_name, enc->cra_name) >= 313 296 CRYPTO_MAX_ALG_NAME) 314 297 goto err_free_inst; 315 298 299 + if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME, 300 + "authenc(%s,%s)", auth->cra_driver_name, 301 + enc->cra_driver_name) >= CRYPTO_MAX_ALG_NAME) 302 + goto err_free_inst; 303 + 316 304 ctx = crypto_instance_ctx(inst); 317 - ctx->enckeylen = enckeylen; 318 305 319 306 err = crypto_init_spawn(&ctx->auth, auth, inst, CRYPTO_ALG_TYPE_MASK); 320 307 if (err)
+27
include/crypto/authenc.h
··· 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 + 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 +