*/
#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>
struct authenc_instance_ctx {
struct crypto_spawn auth;
struct crypto_spawn enc;
-
- unsigned int enckeylen;
};
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);
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)
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);
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)
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)
--- /dev/null
+/*
+ * Authenc: Simple AEAD wrapper for IPsec
+ *
+ * Copyright (c) 2007 Herbert Xu <herbert@gondor.apana.org.au>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ */
+#ifndef _CRYPTO_AUTHENC_H
+#define _CRYPTO_AUTHENC_H
+
+#include <linux/types.h>
+
+enum {
+ CRYPTO_AUTHENC_KEYA_UNSPEC,
+ CRYPTO_AUTHENC_KEYA_PARAM,
+};
+
+struct crypto_authenc_key_param {
+ __be32 enckeylen;
+};
+
+#endif /* _CRYPTO_AUTHENC_H */
+