2007-08-30 08:41:54

by Herbert Xu

[permalink] [raw]
Subject: [PATCH 8/8] [CRYPTO] aead: Add authenc

[CRYPTO] aead: Add authenc

This patch adds the authenc algorithm which constructs an AEAD algorithm
from an asynchronous block cipher and a hash. The construction is done
by concatenating the encrypted result from the cipher with the output
from the hash, as is used by the IPsec ESP protocol.

The authenc algorithm exists as a template with four parameters:

authenc(auth, authsize, enc, enckeylen).

The authentication algorithm, the authentication size (i.e., truncating
the output of the authentication algorithm), the encryption algorithm,
and the encryption key length. Both the size field and the key length
field are in bytes. For example, AES-128 with SHA1-HMAC would be
represented by

authenc(hmac(sha1), 12, cbc(aes), 16)

The key for the authenc algorithm is the concatenation of the keys for
the authentication algorithm with the encryption algorithm. For the
above example, if a key of length 36 bytes is given, then hmac(sha1)
would receive the first 20 bytes while the last 16 would be given to
cbc(aes).

Signed-off-by: Herbert Xu <[email protected]>
---

crypto/Kconfig | 8
crypto/Makefile | 1
crypto/algapi.c | 23 ++
crypto/authenc.c | 400 ++++++++++++++++++++++++++++++++++++++++++++++++
include/crypto/algapi.h | 44 +++++
5 files changed, 472 insertions(+), 4 deletions(-)

diff --git a/crypto/Kconfig b/crypto/Kconfig
index a83d349..71bfa51 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -469,6 +469,14 @@ config CRYPTO_TEST
help
Quick & dirty crypto test module.

+config CRYPTO_AUTHENC
+ tristate "Authenc support"
+ select CRYPTO_AEAD
+ select CRYPTO_MANAGER
+ help
+ Authenc: Combined mode wrapper for IPsec.
+ This is required for IPSec.
+
source "drivers/crypto/Kconfig"

endif # if CRYPTO
diff --git a/crypto/Makefile b/crypto/Makefile
index 5c015cc..ba8841e 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -49,6 +49,7 @@ obj-$(CONFIG_CRYPTO_ANUBIS) += anubis.o
obj-$(CONFIG_CRYPTO_DEFLATE) += deflate.o
obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o
obj-$(CONFIG_CRYPTO_CRC32C) += crc32c.o
+obj-$(CONFIG_CRYPTO_AUTHENC) += authenc.o

obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o

diff --git a/crypto/algapi.c b/crypto/algapi.c
index d955960..d891f56 100644
--- a/crypto/algapi.c
+++ b/crypto/algapi.c
@@ -470,9 +470,8 @@ int crypto_check_attr_type(struct rtattr **tb, u32 type)
}
EXPORT_SYMBOL_GPL(crypto_check_attr_type);

-struct crypto_alg *crypto_get_attr_alg(struct rtattr **tb, u32 type, u32 mask)
+struct crypto_alg *crypto_attr_alg(struct rtattr *rta, u32 type, u32 mask)
{
- struct rtattr *rta = tb[1];
struct crypto_attr_alg *alga;

if (!rta)
@@ -487,7 +486,25 @@ struct crypto_alg *crypto_get_attr_alg(struct rtattr **tb, u32 type, u32 mask)

return crypto_alg_mod_lookup(alga->name, type, mask);
}
-EXPORT_SYMBOL_GPL(crypto_get_attr_alg);
+EXPORT_SYMBOL_GPL(crypto_attr_alg);
+
+int crypto_attr_u32(struct rtattr *rta, u32 *num)
+{
+ struct crypto_attr_u32 *nu32;
+
+ if (!rta)
+ return -ENOENT;
+ if (RTA_PAYLOAD(rta) < sizeof(*nu32))
+ return -EINVAL;
+ if (rta->rta_type != CRYPTOA_U32)
+ return -EINVAL;
+
+ nu32 = RTA_DATA(rta);
+ *num = nu32->num;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(crypto_attr_u32);

struct crypto_instance *crypto_alloc_instance(const char *name,
struct crypto_alg *alg)
diff --git a/crypto/authenc.c b/crypto/authenc.c
new file mode 100644
index 0000000..86b3ac8
--- /dev/null
+++ b/crypto/authenc.c
@@ -0,0 +1,400 @@
+/*
+ * Authenc: Simple AEAD wrapper for IPsec
+ *
+ * Copyright (c) 2007 Herbert Xu <[email protected]>
+ *
+ * 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.
+ *
+ */
+
+#include <crypto/algapi.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#include "scatterwalk.h"
+
+struct authenc_instance_ctx {
+ struct crypto_spawn auth;
+ struct crypto_spawn enc;
+
+ unsigned int authsize;
+ unsigned int enckeylen;
+};
+
+struct crypto_authenc_ctx {
+ spinlock_t auth_lock;
+ struct crypto_hash *auth;
+ struct crypto_ablkcipher *enc;
+};
+
+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;
+ struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
+ struct crypto_hash *auth = ctx->auth;
+ struct crypto_ablkcipher *enc = ctx->enc;
+ int err = -EINVAL;
+
+ if (keylen < enckeylen) {
+ crypto_aead_set_flags(authenc, CRYPTO_TFM_RES_BAD_KEY_LEN);
+ goto out;
+ }
+ authkeylen = keylen - enckeylen;
+
+ crypto_hash_clear_flags(auth, CRYPTO_TFM_REQ_MASK);
+ crypto_hash_set_flags(auth, crypto_aead_get_flags(authenc) &
+ CRYPTO_TFM_REQ_MASK);
+ err = crypto_hash_setkey(auth, key, authkeylen);
+ crypto_aead_set_flags(authenc, crypto_hash_get_flags(auth) &
+ CRYPTO_TFM_RES_MASK);
+
+ if (err)
+ goto out;
+
+ crypto_ablkcipher_clear_flags(enc, CRYPTO_TFM_REQ_MASK);
+ crypto_ablkcipher_set_flags(enc, crypto_aead_get_flags(authenc) &
+ CRYPTO_TFM_REQ_MASK);
+ err = crypto_ablkcipher_setkey(enc, key + authkeylen, enckeylen);
+ crypto_aead_set_flags(authenc, crypto_ablkcipher_get_flags(enc) &
+ CRYPTO_TFM_RES_MASK);
+
+out:
+ return err;
+}
+
+static int crypto_authenc_hash(struct aead_request *req)
+{
+ struct crypto_aead *authenc = crypto_aead_reqtfm(req);
+ struct authenc_instance_ctx *ictx =
+ crypto_instance_ctx(crypto_aead_alg_instance(authenc));
+ struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
+ struct crypto_hash *auth = ctx->auth;
+ struct hash_desc desc = {
+ .tfm = auth,
+ };
+ u8 *hash = aead_request_ctx(req);
+ struct scatterlist *dst;
+ unsigned int cryptlen;
+ int err;
+
+ hash = (u8 *)ALIGN((unsigned long)hash + crypto_hash_alignmask(auth),
+ crypto_hash_alignmask(auth) + 1);
+
+ spin_lock_bh(&ctx->auth_lock);
+ err = crypto_hash_init(&desc);
+ if (err)
+ goto auth_unlock;
+
+ err = crypto_hash_update(&desc, req->assoc, req->assoclen);
+ if (err)
+ goto auth_unlock;
+
+ cryptlen = req->cryptlen;
+ dst = req->dst;
+ err = crypto_hash_update(&desc, dst, cryptlen);
+ if (err)
+ goto auth_unlock;
+
+ err = crypto_hash_final(&desc, hash);
+auth_unlock:
+ spin_unlock_bh(&ctx->auth_lock);
+
+ if (err)
+ return err;
+
+ scatterwalk_map_and_copy(hash, dst, cryptlen, ictx->authsize, 1);
+ return 0;
+}
+
+static void crypto_authenc_encrypt_done(struct crypto_async_request *req,
+ int err)
+{
+ if (!err)
+ err = crypto_authenc_hash(req->data);
+
+ aead_request_complete(req->data, err);
+}
+
+static int crypto_authenc_encrypt(struct aead_request *req)
+{
+ struct crypto_aead *authenc = crypto_aead_reqtfm(req);
+ struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
+ struct ablkcipher_request *abreq = aead_request_ctx(req);
+ int err;
+
+ ablkcipher_request_set_tfm(abreq, ctx->enc);
+ ablkcipher_request_set_callback(abreq, aead_request_flags(req),
+ crypto_authenc_encrypt_done, req);
+ ablkcipher_request_set_crypt(abreq, req->src, req->dst, req->cryptlen,
+ req->iv);
+
+ err = crypto_ablkcipher_encrypt(abreq);
+ if (err)
+ return err;
+
+ return crypto_authenc_hash(req);
+}
+
+static int crypto_authenc_verify(struct aead_request *req)
+{
+ struct crypto_aead *authenc = crypto_aead_reqtfm(req);
+ struct authenc_instance_ctx *ictx =
+ crypto_instance_ctx(crypto_aead_alg_instance(authenc));
+ struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
+ struct crypto_hash *auth = ctx->auth;
+ struct hash_desc desc = {
+ .tfm = auth,
+ .flags = aead_request_flags(req),
+ };
+ u8 *ohash = aead_request_ctx(req);
+ u8 *ihash;
+ struct scatterlist *src;
+ unsigned int cryptlen;
+ unsigned int authsize;
+ int err;
+
+ ohash = (u8 *)ALIGN((unsigned long)ohash + crypto_hash_alignmask(auth),
+ crypto_hash_alignmask(auth) + 1);
+ ihash = ohash + crypto_hash_digestsize(auth);
+
+ spin_lock_bh(&ctx->auth_lock);
+ err = crypto_hash_init(&desc);
+ if (err)
+ goto auth_unlock;
+
+ err = crypto_hash_update(&desc, req->assoc, req->assoclen);
+ if (err)
+ goto auth_unlock;
+
+ cryptlen = req->cryptlen;
+ src = req->src;
+ err = crypto_hash_update(&desc, src, cryptlen);
+ if (err)
+ goto auth_unlock;
+
+ err = crypto_hash_final(&desc, ohash);
+auth_unlock:
+ spin_unlock_bh(&ctx->auth_lock);
+
+ if (err)
+ return err;
+
+ authsize = ictx->authsize;
+ scatterwalk_map_and_copy(ihash, src, cryptlen, authsize, 0);
+ return memcmp(ihash, ohash, authsize) ? -EINVAL : 0;
+}
+
+static void crypto_authenc_decrypt_done(struct crypto_async_request *req,
+ int err)
+{
+ aead_request_complete(req->data, err);
+}
+
+static int crypto_authenc_decrypt(struct aead_request *req)
+{
+ struct crypto_aead *authenc = crypto_aead_reqtfm(req);
+ struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
+ struct ablkcipher_request *abreq = aead_request_ctx(req);
+ int err;
+
+ err = crypto_authenc_verify(req);
+ if (err)
+ return err;
+
+ ablkcipher_request_set_tfm(abreq, ctx->enc);
+ ablkcipher_request_set_callback(abreq, aead_request_flags(req),
+ crypto_authenc_decrypt_done, req);
+ ablkcipher_request_set_crypt(abreq, req->src, req->dst, req->cryptlen,
+ req->iv);
+
+ return crypto_ablkcipher_decrypt(abreq);
+}
+
+static int crypto_authenc_init_tfm(struct crypto_tfm *tfm)
+{
+ struct crypto_instance *inst = (void *)tfm->__crt_alg;
+ struct authenc_instance_ctx *ictx = crypto_instance_ctx(inst);
+ struct crypto_authenc_ctx *ctx = crypto_tfm_ctx(tfm);
+ struct crypto_hash *auth;
+ struct crypto_ablkcipher *enc;
+ unsigned int digestsize;
+ int err;
+
+ auth = crypto_spawn_hash(&ictx->auth);
+ if (IS_ERR(auth))
+ return PTR_ERR(auth);
+
+ err = -EINVAL;
+ digestsize = crypto_hash_digestsize(auth);
+ if (ictx->authsize > digestsize)
+ goto err_free_hash;
+
+ enc = crypto_spawn_ablkcipher(&ictx->enc);
+ err = PTR_ERR(enc);
+ if (IS_ERR(enc))
+ goto err_free_hash;
+
+ ctx->auth = auth;
+ ctx->enc = enc;
+ tfm->crt_aead.reqsize = max_t(unsigned int,
+ (crypto_hash_alignmask(auth) &
+ ~(crypto_tfm_ctx_alignment() - 1)) +
+ digestsize * 2,
+ sizeof(struct ablkcipher_request) +
+ crypto_ablkcipher_reqsize(enc));
+
+ spin_lock_init(&ctx->auth_lock);
+
+ return 0;
+
+err_free_hash:
+ crypto_free_hash(auth);
+ return err;
+}
+
+static void crypto_authenc_exit_tfm(struct crypto_tfm *tfm)
+{
+ struct crypto_authenc_ctx *ctx = crypto_tfm_ctx(tfm);
+
+ crypto_free_hash(ctx->auth);
+ crypto_free_ablkcipher(ctx->enc);
+}
+
+static struct crypto_instance *crypto_authenc_alloc(struct rtattr **tb)
+{
+ struct crypto_instance *inst;
+ struct crypto_alg *auth;
+ struct crypto_alg *enc;
+ struct authenc_instance_ctx *ctx;
+ unsigned int authsize;
+ unsigned int enckeylen;
+ int err;
+
+ err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_AEAD);
+ if (err)
+ return ERR_PTR(err);
+
+ auth = crypto_attr_alg(tb[1], CRYPTO_ALG_TYPE_HASH,
+ CRYPTO_ALG_TYPE_HASH_MASK);
+ if (IS_ERR(auth))
+ return ERR_PTR(PTR_ERR(auth));
+
+ err = crypto_attr_u32(tb[2], &authsize);
+ inst = ERR_PTR(err);
+ if (err)
+ goto out_put_auth;
+
+ enc = crypto_attr_alg(tb[3], CRYPTO_ALG_TYPE_BLKCIPHER,
+ CRYPTO_ALG_TYPE_MASK);
+ inst = ERR_PTR(PTR_ERR(enc));
+ if (IS_ERR(enc))
+ goto out_put_auth;
+
+ err = crypto_attr_u32(tb[4], &enckeylen);
+ if (err)
+ goto out_put_enc;
+
+ inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL);
+ err = -ENOMEM;
+ if (!inst)
+ goto out_put_enc;
+
+ err = -ENAMETOOLONG;
+ if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME,
+ "authenc(%s, %u, %s, %u)", auth->cra_name, authsize,
+ enc->cra_name, enckeylen) >= CRYPTO_MAX_ALG_NAME)
+ goto err_free_inst;
+
+ if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
+ "authenc(%s, %u, %s, %u)", auth->cra_driver_name,
+ authsize, enc->cra_driver_name, enckeylen) >=
+ CRYPTO_MAX_ALG_NAME)
+ goto err_free_inst;
+
+ ctx = crypto_instance_ctx(inst);
+ ctx->authsize = authsize;
+ ctx->enckeylen = enckeylen;
+
+ err = crypto_init_spawn(&ctx->auth, auth, inst, CRYPTO_ALG_TYPE_MASK);
+ if (err)
+ goto err_free_inst;
+
+ err = crypto_init_spawn(&ctx->enc, enc, inst, CRYPTO_ALG_TYPE_MASK);
+ if (err)
+ goto err_drop_auth;
+
+ inst->alg.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC;
+ inst->alg.cra_priority = enc->cra_priority * 10 + auth->cra_priority;
+ inst->alg.cra_blocksize = enc->cra_blocksize;
+ inst->alg.cra_alignmask = max(auth->cra_alignmask, enc->cra_alignmask);
+ inst->alg.cra_type = &crypto_aead_type;
+
+ inst->alg.cra_aead.ivsize = enc->cra_blkcipher.ivsize;
+ inst->alg.cra_aead.authsize = authsize;
+
+ inst->alg.cra_ctxsize = sizeof(struct crypto_authenc_ctx);
+
+ inst->alg.cra_init = crypto_authenc_init_tfm;
+ inst->alg.cra_exit = crypto_authenc_exit_tfm;
+
+ inst->alg.cra_aead.setkey = crypto_authenc_setkey;
+ inst->alg.cra_aead.encrypt = crypto_authenc_encrypt;
+ inst->alg.cra_aead.decrypt = crypto_authenc_decrypt;
+
+out:
+ crypto_mod_put(enc);
+out_put_auth:
+ crypto_mod_put(auth);
+ return inst;
+
+err_drop_auth:
+ crypto_drop_spawn(&ctx->auth);
+err_free_inst:
+ kfree(inst);
+out_put_enc:
+ inst = ERR_PTR(err);
+ goto out;
+}
+
+static void crypto_authenc_free(struct crypto_instance *inst)
+{
+ struct authenc_instance_ctx *ctx = crypto_instance_ctx(inst);
+
+ crypto_drop_spawn(&ctx->enc);
+ crypto_drop_spawn(&ctx->auth);
+ kfree(inst);
+}
+
+static struct crypto_template crypto_authenc_tmpl = {
+ .name = "authenc",
+ .alloc = crypto_authenc_alloc,
+ .free = crypto_authenc_free,
+ .module = THIS_MODULE,
+};
+
+static int __init crypto_authenc_module_init(void)
+{
+ return crypto_register_template(&crypto_authenc_tmpl);
+}
+
+static void __exit crypto_authenc_module_exit(void)
+{
+ crypto_unregister_template(&crypto_authenc_tmpl);
+}
+
+module_init(crypto_authenc_module_init);
+module_exit(crypto_authenc_module_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Simple AEAD wrapper for IPsec");
diff --git a/include/crypto/algapi.h b/include/crypto/algapi.h
index cd721a7..4af72dc 100644
--- a/include/crypto/algapi.h
+++ b/include/crypto/algapi.h
@@ -112,7 +112,8 @@ struct crypto_tfm *crypto_spawn_tfm(struct crypto_spawn *spawn, u32 type,

struct crypto_attr_type *crypto_get_attr_type(struct rtattr **tb);
int crypto_check_attr_type(struct rtattr **tb, u32 type);
-struct crypto_alg *crypto_get_attr_alg(struct rtattr **tb, u32 type, u32 mask);
+struct crypto_alg *crypto_attr_alg(struct rtattr *rta, u32 type, u32 mask);
+int crypto_attr_u32(struct rtattr *rta, u32 *num);
struct crypto_instance *crypto_alloc_instance(const char *name,
struct crypto_alg *alg);

@@ -171,6 +172,26 @@ static inline struct aead_alg *crypto_aead_alg(struct crypto_aead *tfm)
return &crypto_aead_tfm(tfm)->__crt_alg->cra_aead;
}

+static inline void *crypto_aead_ctx(struct crypto_aead *tfm)
+{
+ return crypto_tfm_ctx(&tfm->base);
+}
+
+static inline struct crypto_instance *crypto_aead_alg_instance(
+ struct crypto_aead *aead)
+{
+ return crypto_tfm_alg_instance(&aead->base);
+}
+
+static inline struct crypto_ablkcipher *crypto_spawn_ablkcipher(
+ struct crypto_spawn *spawn)
+{
+ u32 type = CRYPTO_ALG_TYPE_BLKCIPHER;
+ u32 mask = CRYPTO_ALG_TYPE_MASK;
+
+ return __crypto_ablkcipher_cast(crypto_spawn_tfm(spawn, type, mask));
+}
+
static inline struct crypto_blkcipher *crypto_spawn_blkcipher(
struct crypto_spawn *spawn)
{
@@ -257,5 +278,26 @@ static inline int ablkcipher_tfm_in_queue(struct crypto_queue *queue,
return crypto_tfm_in_queue(queue, crypto_ablkcipher_tfm(tfm));
}

+static inline void *aead_request_ctx(struct aead_request *req)
+{
+ return req->__ctx;
+}
+
+static inline void aead_request_complete(struct aead_request *req, int err)
+{
+ req->base.complete(&req->base, err);
+}
+
+static inline u32 aead_request_flags(struct aead_request *req)
+{
+ return req->base.flags;
+}
+
+static inline struct crypto_alg *crypto_get_attr_alg(struct rtattr **tb,
+ u32 type, u32 mask)
+{
+ return crypto_attr_alg(tb[1], type, mask);
+}
+
#endif /* _CRYPTO_ALGAPI_H */



2007-08-30 11:01:58

by Ronen Shitrit

[permalink] [raw]
Subject: RE: [PATCH 8/8] [CRYPTO] aead: Add authenc

Hi

That was quick :)

This patch is a wrapper for the encryption and hash operations, which
mean the HW engine will do the encryption, and then the SW will do the
hash.

Is this the combined mode that was discussed on the mailing list before?
Is there a plan to add support for HW engines that can run the
encryption and authentication as one operation?

BTW: will the kernel IPsec patch that uses this AEAD API will be
submitted on this mailing list as well?

Thanks
Ronen Shitrit


> -----Original Message-----
> From: [email protected] [mailto:linux-crypto-
> [email protected]] On Behalf Of Herbert Xu
> Sent: Thursday, August 30, 2007 11:42 AM
> To: Linux Crypto Mailing List; Thomas Graf; Herbgert Xu
> Subject: [PATCH 8/8] [CRYPTO] aead: Add authenc
>
> [CRYPTO] aead: Add authenc
>
> This patch adds the authenc algorithm which constructs an AEAD
algorithm
> from an asynchronous block cipher and a hash. The construction is
done
> by concatenating the encrypted result from the cipher with the output
> from the hash, as is used by the IPsec ESP protocol.
>
> The authenc algorithm exists as a template with four parameters:
>
> authenc(auth, authsize, enc, enckeylen).
>
> The authentication algorithm, the authentication size (i.e.,
truncating
> the output of the authentication algorithm), the encryption algorithm,
> and the encryption key length. Both the size field and the key length
> field are in bytes. For example, AES-128 with SHA1-HMAC would be
> represented by
>
> authenc(hmac(sha1), 12, cbc(aes), 16)
>
> The key for the authenc algorithm is the concatenation of the keys for
> the authentication algorithm with the encryption algorithm. For the
> above example, if a key of length 36 bytes is given, then hmac(sha1)
> would receive the first 20 bytes while the last 16 would be given to
> cbc(aes).
>

2007-08-30 11:13:10

by Herbert Xu

[permalink] [raw]
Subject: Re: [PATCH 8/8] [CRYPTO] aead: Add authenc

On Thu, Aug 30, 2007 at 02:00:43PM +0300, Ronen Shitrit wrote:
>
> Is this the combined mode that was discussed on the mailing list before?

Authenc is just the first user of the crypto_aead interface.
Once IPsec moves across we will add others such as the CCM
algorithm.

> Is there a plan to add support for HW engines that can run the
> encryption and authentication as one operation?

Yep this interface will support those hardware engines.

> BTW: will the kernel IPsec patch that uses this AEAD API will be
> submitted on this mailing list as well?

It'll be submitted on [email protected].

Cheers,
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

2007-09-27 22:32:54

by Joy Latten

[permalink] [raw]
Subject: Re: [PATCH 8/8] [CRYPTO] aead: Add authenc

Again, sorry for the late notice, but this just came
to my attention.

+static struct crypto_instance *crypto_authenc_alloc(struct rtattr **tb)
+{
+ struct crypto_instance *inst;
+ struct crypto_alg *auth;
+ struct crypto_alg *enc;
+ struct authenc_instance_ctx *ctx;
+ unsigned int authsize;
+ unsigned int enckeylen;
+ int err;
+
+ err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_AEAD);
+ if (err)
+ return ERR_PTR(err);
+
+ auth = crypto_attr_alg(tb[1], CRYPTO_ALG_TYPE_HASH,
+ CRYPTO_ALG_TYPE_HASH_MASK);
+ if (IS_ERR(auth))
+ return ERR_PTR(PTR_ERR(auth));
+
+ err = crypto_attr_u32(tb[2], &authsize);
+ inst = ERR_PTR(err);
+ if (err)
+ goto out_put_auth;
+
+ enc = crypto_attr_alg(tb[3], CRYPTO_ALG_TYPE_BLKCIPHER,
+ CRYPTO_ALG_TYPE_MASK);
+ inst = ERR_PTR(PTR_ERR(enc));
+ if (IS_ERR(enc))
+ goto out_put_auth;
+
+ err = crypto_attr_u32(tb[4], &enckeylen);
+ if (err)
+ goto out_put_enc;
+
+ inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL);
+ err = -ENOMEM;
+ if (!inst)
+ goto out_put_enc;
+
+ err = -ENAMETOOLONG;
+ if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME,
+ "authenc(%s, %u, %s, %u)", auth->cra_name, authsize,

The parsing routine in cryptomg_schedule_probe() does
not appear to accomodate whitespaces in the template.

Thus if user enters template without whitespaces,
then the above would cause a problem because the
name in the template would not match up with the name
in the instance above.

I have not tested this with authenc, but did with
ctr(aes,4,8) as opposed to ctr(aes, 4, 8).
With whitespaces, it failed. Without whitespaces
in either template or instance, it worked.

+ enc->cra_name, enckeylen) >= CRYPTO_MAX_ALG_NAME)
+ goto err_free_inst;
+
+ if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
+ "authenc(%s, %u, %s, %u)", auth->cra_driver_name,

Same thing...

+ authsize, enc->cra_driver_name, enckeylen) >=
+ CRYPTO_MAX_ALG_NAME)
+ goto err_free_inst;
+

Regards,
Joy

2007-09-28 01:10:25

by Herbert Xu

[permalink] [raw]
Subject: Re: [PATCH 8/8] [CRYPTO] aead: Add authenc

On Thu, Sep 27, 2007 at 05:29:04PM -0500, Joy Latten wrote:
>
> Thus if user enters template without whitespaces,
> then the above would cause a problem because the
> name in the template would not match up with the name
> in the instance above.

Indeed, white spaces are not allowed so they should go from
these prints. I've fixed it in my tree as below.

Thanks,
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
--
diff --git a/crypto/authenc.c b/crypto/authenc.c
index 86b3ac8..0b29a6a 100644
--- a/crypto/authenc.c
+++ b/crypto/authenc.c
@@ -312,12 +312,12 @@ static struct crypto_instance *crypto_authenc_alloc(struct rtattr **tb)

err = -ENAMETOOLONG;
if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME,
- "authenc(%s, %u, %s, %u)", auth->cra_name, authsize,
+ "authenc(%s,%u,%s,%u)", auth->cra_name, authsize,
enc->cra_name, enckeylen) >= CRYPTO_MAX_ALG_NAME)
goto err_free_inst;

if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
- "authenc(%s, %u, %s, %u)", auth->cra_driver_name,
+ "authenc(%s,%u,%s,%u)", auth->cra_driver_name,
authsize, enc->cra_driver_name, enckeylen) >=
CRYPTO_MAX_ALG_NAME)
goto err_free_inst;