Sorry I omitted the patch. Here it is.

On Nov 13, 2007 3:59 AM, Tan Swee Heng <[EMAIL PROTECTED]> wrote:
> This patch implements a template that wraps around an eSTREAM cipher
> algorithm and its ivsize.
>
> For example, an eSTREAM cipher with the name CIPHERNAME and ivsize
> IVSIZE will be instantiated as "stream(CIPHERNAME,IVSIZE)" in
> cryptomgr. It uses blkcipher to walk over the memory it
> encrypts/decrypts. It has been modified to use the crypto_estream_*
> type instead of crypto_cipher_*.
>
diff --git a/crypto/Kconfig b/crypto/Kconfig
index 4ad25fd..27a802f 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -211,6 +211,16 @@ config CRYPTO_CTR
          CTR: Counter mode
          This block cipher algorithm is required for IPSec.
 
+config CRYPTO_STREAM
+       tristate "STREAM: Wrapper for eSTREAM ciphers (EXPERIMENTAL)"
+       depends on EXPERIMENTAL
+       select CRYPTO_BLKCIPHER
+       select CRYPTO_MANAGER
+       select CRYPTO_ESTREAM
+       help
+         STREAM: Wrapper for eSTREAM ciphers
+         This wrapper is used by stream ciphers submitted to eSTREAM.
+
 config CRYPTO_CRYPTD
        tristate "Software async crypto daemon"
        select CRYPTO_ABLKCIPHER
diff --git a/crypto/Makefile b/crypto/Makefile
index 14afa34..f95206b 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -34,6 +34,7 @@ obj-$(CONFIG_CRYPTO_PCBC) += pcbc.o
 obj-$(CONFIG_CRYPTO_LRW) += lrw.o
 obj-$(CONFIG_CRYPTO_XTS) += xts.o
 obj-$(CONFIG_CRYPTO_CTR) += ctr.o
+obj-$(CONFIG_CRYPTO_STREAM) += stream.o
 obj-$(CONFIG_CRYPTO_CRYPTD) += cryptd.o
 obj-$(CONFIG_CRYPTO_DES) += des_generic.o
 obj-$(CONFIG_CRYPTO_FCRYPT) += fcrypt.o
diff --git a/crypto/stream.c b/crypto/stream.c
new file mode 100644
index 0000000..0c2ffc7
--- /dev/null
+++ b/crypto/stream.c
@@ -0,0 +1,241 @@
+/*
+ * STREAM: Wrapper for eSTREAM ciphers
+ *
+ * Copyright (c) 2007 Tan Swee Heng <[EMAIL PROTECTED]>
+ *
+ * Derived from
+ * - cbc.c: Copyright (c) 2006 Herbert Xu <[EMAIL PROTECTED]>
+ * - ctr.c: Copyright (c) IBM Corp. 2007 Joy Latten <[EMAIL PROTECTED]>
+ *
+ * Stream ciphers submitted to eSTREAM, the ECRYPT Stream Cipher Project,
+ * requires both key size and IV size in the key setup. This is different
+ * from standard block ciphers. This wrapper provides the necessary glue
+ * tp work with such eSTREAM ciphers.
+ *
+ * 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/scatterlist.h>
+#include <linux/slab.h>
+
+struct stream_instance_ctx {
+       struct crypto_spawn alg;
+       unsigned int ivsize;
+};
+
+struct crypto_stream_ctx {
+       struct crypto_estream *child;
+};
+
+static int crypto_stream_setkey(struct crypto_tfm *parent, const u8 *key,
+                               unsigned int keysize)
+{
+       struct crypto_stream_ctx *ctx = crypto_tfm_ctx(parent);
+       struct crypto_estream *child = ctx->child;
+       struct stream_instance_ctx *ictx =
+               crypto_instance_ctx(crypto_tfm_alg_instance(parent));
+       int err;
+
+       crypto_estream_clear_flags(child, CRYPTO_TFM_REQ_MASK);
+       crypto_estream_set_flags(child, crypto_tfm_get_flags(parent) &
+                                CRYPTO_TFM_REQ_MASK);
+       err = crypto_estream_setkey(child, key, keysize, ictx->ivsize);
+       crypto_tfm_set_flags(parent, crypto_estream_get_flags(child) &
+                            CRYPTO_TFM_RES_MASK);
+       return err;
+}
+
+static int crypto_stream_crypt_walk(struct blkcipher_walk *walk,
+                                   struct crypto_estream *tfm)
+{
+       unsigned int bsize = crypto_estream_blocksize(tfm);
+       unsigned int nbytes = walk->nbytes;
+       u8 *src = walk->src.virt.addr;
+       u8 *dst = walk->dst.virt.addr;
+       u8 *iv = walk->iv;
+       u8 *ks;
+
+       crypto_estream_setiv(tfm, iv);
+       while (nbytes >= bsize) {
+               crypto_estream_encrypt_block(tfm, dst, src);
+               dst += bsize;
+               src += bsize;
+               nbytes -= bsize;
+       }
+       if (nbytes > 0) {
+               ks = kzalloc(bsize, GFP_KERNEL);
+               memcpy(ks, src, nbytes);
+               crypto_estream_encrypt_block(tfm, ks, ks);
+               memcpy(dst, ks, nbytes);
+               kfree(ks);
+       }
+
+       return 0;
+}
+
+static int crypto_stream_crypt(struct blkcipher_desc *desc,
+                              struct scatterlist *dst,
+                              struct scatterlist *src,
+                              unsigned int nbytes)
+{
+       struct blkcipher_walk walk;
+       struct crypto_blkcipher *tfm = desc->tfm;
+       struct crypto_stream_ctx *ctx = crypto_blkcipher_ctx(tfm);
+       struct crypto_estream *child = ctx->child;
+       int err;
+
+       blkcipher_walk_init(&walk, dst, src, nbytes);
+       err = blkcipher_walk_virt(desc, &walk);
+
+       while (walk.nbytes) {
+               nbytes = crypto_stream_crypt_walk(&walk, child);
+               err = blkcipher_walk_done(desc, &walk, nbytes);
+       }
+
+       return err;
+}
+
+
+static int crypto_stream_init_tfm(struct crypto_tfm *tfm)
+{
+       struct crypto_instance *inst = (void *)tfm->__crt_alg;
+       struct stream_instance_ctx *ictx = crypto_instance_ctx(inst);
+       struct crypto_stream_ctx *ctx = crypto_tfm_ctx(tfm);
+       struct crypto_estream *estream;
+
+       estream = crypto_spawn_estream(&ictx->alg);
+       if (IS_ERR(estream))
+               return PTR_ERR(estream);
+
+       ctx->child = estream;
+       return 0;
+}
+
+static void crypto_stream_exit_tfm(struct crypto_tfm *tfm)
+{
+       struct crypto_stream_ctx *ctx = crypto_tfm_ctx(tfm);
+       crypto_free_estream(ctx->child);
+}
+
+static struct crypto_instance *crypto_stream_alloc(struct rtattr **tb)
+{
+       struct crypto_instance *inst;
+       struct crypto_alg *alg;
+       struct stream_instance_ctx *ictx;
+       unsigned int ivsize;
+       int err;
+
+       err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_BLKCIPHER);
+       if (err)
+               return ERR_PTR(err);
+
+       alg = crypto_attr_alg(tb[1], CRYPTO_ALG_TYPE_ESTREAM,
+                             CRYPTO_ALG_TYPE_MASK);
+       if (IS_ERR(alg))
+               return ERR_PTR(PTR_ERR(alg));
+
+       err = crypto_attr_u32(tb[2], &ivsize);
+       if (err)
+               goto out_put_alg;
+
+       err = -EINVAL;
+       if ((ivsize < alg->cra_estream.min_ivsize) ||
+               (ivsize > alg->cra_estream.max_ivsize))
+               goto out_put_alg;
+
+       inst = kzalloc(sizeof(*inst) + sizeof(*ictx), GFP_KERNEL);
+       err = -ENOMEM;
+       if (!inst)
+               goto out_put_alg;
+
+       err = - ENAMETOOLONG;
+       if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME,
+                    "stream(%s,%u)", alg->cra_name,
+                    ivsize) >=  CRYPTO_MAX_ALG_NAME) {
+               goto err_free_inst;
+       }
+
+       if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
+                    "stream(%s,%u)", alg->cra_driver_name,
+                    ivsize) >=  CRYPTO_MAX_ALG_NAME) {
+               goto err_free_inst;
+       }
+
+       ictx = crypto_instance_ctx(inst);
+       ictx->ivsize = ivsize;
+
+       err = crypto_init_spawn(&ictx->alg, alg, inst,
+                               CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC);
+       if (err)
+               goto err_free_inst;
+
+       err = 0;
+       inst->alg.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER;
+       inst->alg.cra_priority = alg->cra_priority;
+       inst->alg.cra_blocksize = 1;
+       inst->alg.cra_alignmask = alg->cra_alignmask;
+       inst->alg.cra_type = &crypto_blkcipher_type;
+
+       inst->alg.cra_blkcipher.ivsize = ivsize;
+       inst->alg.cra_blkcipher.min_keysize = alg->cra_estream.min_keysize;
+       inst->alg.cra_blkcipher.max_keysize = alg->cra_estream.max_keysize;
+
+       inst->alg.cra_ctxsize = sizeof(struct crypto_stream_ctx);
+
+       inst->alg.cra_init = crypto_stream_init_tfm;
+       inst->alg.cra_exit = crypto_stream_exit_tfm;
+
+       inst->alg.cra_blkcipher.setkey = crypto_stream_setkey;
+       inst->alg.cra_blkcipher.encrypt = crypto_stream_crypt;
+       inst->alg.cra_blkcipher.decrypt = crypto_stream_crypt;
+
+err_free_inst:
+       if (err)
+               kfree(inst);
+
+out_put_alg:
+       crypto_mod_put(alg);
+
+       if(err)
+               inst = ERR_PTR(err);
+
+       return inst;
+}
+
+static void crypto_stream_free(struct crypto_instance *inst)
+{
+       crypto_drop_spawn(crypto_instance_ctx(inst));
+       kfree(inst);
+}
+
+static struct crypto_template crypto_stream_tmpl = {
+       .name = "stream",
+       .alloc = crypto_stream_alloc,
+       .free = crypto_stream_free,
+       .module = THIS_MODULE,
+};
+
+static int __init crypto_stream_module_init(void)
+{
+       return crypto_register_template(&crypto_stream_tmpl);
+}
+
+static void __exit crypto_stream_module_exit(void)
+{
+       crypto_unregister_template(&crypto_stream_tmpl);
+}
+
+module_init(crypto_stream_module_init);
+module_exit(crypto_stream_module_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Wrapper for eSTREAM ciphers");

Reply via email to